Repository: nevermoe/unity_metadata_loader Branch: v24 Commit: 1e8841c50549 Files: 846 Total size: 5.4 MB Directory structure: gitextract_80tw_glg/ ├── .gitignore ├── LICENSE ├── README.md ├── unity_decoder/ │ ├── core.h │ ├── libil2cpp/ │ │ ├── CMakeLists.txt │ │ ├── UnityAdsStubs.cpp │ │ ├── blob.h │ │ ├── char-conversions.cpp │ │ ├── char-conversions.h │ │ ├── class-internals.cpp │ │ ├── class-internals.h │ │ ├── codegen/ │ │ │ ├── il2cpp-codegen-common.h │ │ │ ├── il2cpp-codegen-il2cpp.h │ │ │ ├── il2cpp-codegen-mono.h │ │ │ └── il2cpp-codegen.h │ │ ├── debugger/ │ │ │ ├── agent.cpp │ │ │ ├── agent.h │ │ │ ├── command-line-parser.cpp │ │ │ ├── command-line-parser.h │ │ │ ├── common.h │ │ │ ├── data-buffer.cpp │ │ │ ├── data-buffer.h │ │ │ ├── event-request.cpp │ │ │ ├── event-request.h │ │ │ ├── handlers/ │ │ │ │ ├── app-domain.cpp │ │ │ │ ├── array-ref.cpp │ │ │ │ ├── assembly.cpp │ │ │ │ ├── event-request.cpp │ │ │ │ ├── event.cpp │ │ │ │ ├── internal-error.cpp │ │ │ │ ├── method.cpp │ │ │ │ ├── module.cpp │ │ │ │ ├── object-ref.cpp │ │ │ │ ├── stack-frame.cpp │ │ │ │ ├── string-ref.cpp │ │ │ │ ├── thread.cpp │ │ │ │ ├── type.cpp │ │ │ │ └── vm.cpp │ │ │ ├── id-bank.h │ │ │ ├── id-brank.cpp │ │ │ ├── il2cpp-api-test-forwarder.cpp │ │ │ ├── il2cpp-api-test-forwarder.h │ │ │ ├── meta.h │ │ │ ├── protocol/ │ │ │ │ ├── commands/ │ │ │ │ │ ├── app-domain.cpp │ │ │ │ │ ├── app-domain.h │ │ │ │ │ ├── array-ref.cpp │ │ │ │ │ ├── array-ref.h │ │ │ │ │ ├── assembly.cpp │ │ │ │ │ ├── assembly.h │ │ │ │ │ ├── event-request.cpp │ │ │ │ │ ├── event-request.h │ │ │ │ │ ├── event.cpp │ │ │ │ │ ├── event.h │ │ │ │ │ ├── internal-error.cpp │ │ │ │ │ ├── internal-error.h │ │ │ │ │ ├── method.cpp │ │ │ │ │ ├── method.h │ │ │ │ │ ├── module.cpp │ │ │ │ │ ├── module.h │ │ │ │ │ ├── object-ref.cpp │ │ │ │ │ ├── object-ref.h │ │ │ │ │ ├── stack-frame.cpp │ │ │ │ │ ├── stack-frame.h │ │ │ │ │ ├── string-ref.cpp │ │ │ │ │ ├── string-ref.h │ │ │ │ │ ├── thread.cpp │ │ │ │ │ ├── thread.h │ │ │ │ │ ├── type.cpp │ │ │ │ │ ├── type.h │ │ │ │ │ ├── vm.cpp │ │ │ │ │ └── vm.h │ │ │ │ ├── events.cpp │ │ │ │ ├── events.h │ │ │ │ ├── globals.h │ │ │ │ ├── protocol-utils.h │ │ │ │ ├── protocol.cpp │ │ │ │ ├── protocol.h │ │ │ │ ├── utils.cpp │ │ │ │ └── utils.h │ │ │ ├── thread-data.cpp │ │ │ ├── thread-data.h │ │ │ ├── transport-tcp.cpp │ │ │ ├── transport-tcp.h │ │ │ ├── transport.h │ │ │ ├── variant.cpp │ │ │ └── variant.h │ │ ├── external/ │ │ │ ├── google/ │ │ │ │ └── sparsehash/ │ │ │ │ ├── dense_hash_map.h │ │ │ │ ├── dense_hash_set.h │ │ │ │ ├── densehashtable.h │ │ │ │ └── type_traits.h │ │ │ ├── xamarin-android/ │ │ │ │ ├── README │ │ │ │ ├── logger.h │ │ │ │ ├── monodroid.h │ │ │ │ ├── xamarin_getifaddrs.c │ │ │ │ └── xamarin_getifaddrs.h │ │ │ └── zlib/ │ │ │ ├── adler32.c │ │ │ ├── compress.c │ │ │ ├── crc32.c │ │ │ ├── crc32.h │ │ │ ├── deflate.c │ │ │ ├── deflate.h │ │ │ ├── gzio.c │ │ │ ├── infback.c │ │ │ ├── inffast.c │ │ │ ├── inffast.h │ │ │ ├── inffixed.h │ │ │ ├── inflate.c │ │ │ ├── inflate.h │ │ │ ├── inftrees.c │ │ │ ├── inftrees.h │ │ │ ├── trees.c │ │ │ ├── trees.h │ │ │ ├── uncompr.c │ │ │ ├── zconf.h │ │ │ ├── zlib.h │ │ │ ├── zutil.c │ │ │ └── zutil.h │ │ ├── externals/ │ │ │ ├── MonoPosixHelper.cpp │ │ │ └── MonoPosixHelper.h │ │ ├── gc/ │ │ │ ├── Allocator.h │ │ │ ├── AppendOnlyGCHashMap.h │ │ │ ├── BoehmGC.cpp │ │ │ ├── GCHandle.cpp │ │ │ ├── GCHandle.h │ │ │ ├── GarbageCollector.cpp │ │ │ ├── GarbageCollector.h │ │ │ ├── NullGC.cpp │ │ │ ├── WriteBarrier.cpp │ │ │ ├── WriteBarrier.h │ │ │ └── gc_wrapper.h │ │ ├── icallincludes.h │ │ ├── icalls/ │ │ │ ├── System/ │ │ │ │ ├── Microsoft.Win32/ │ │ │ │ │ ├── NativeMethods.cpp │ │ │ │ │ └── NativeMethods.h │ │ │ │ ├── Mono.Net.Security/ │ │ │ │ │ ├── MonoTlsProviderFactory.cpp │ │ │ │ │ └── MonoTlsProviderFactory.h │ │ │ │ ├── System/ │ │ │ │ │ ├── IOSelector.cpp │ │ │ │ │ └── IOSelector.h │ │ │ │ ├── System.ComponentModel/ │ │ │ │ │ ├── Win32Exception.cpp │ │ │ │ │ └── Win32Exception.h │ │ │ │ ├── System.Configuration/ │ │ │ │ │ ├── DefaultConfig.cpp │ │ │ │ │ ├── DefaultConfig.h │ │ │ │ │ ├── InternalConfigurationHost.cpp │ │ │ │ │ └── InternalConfigurationHost.h │ │ │ │ ├── System.Diagnostics/ │ │ │ │ │ ├── DefaultTraceListener.cpp │ │ │ │ │ ├── DefaultTraceListener.h │ │ │ │ │ ├── FileVersionInfo.cpp │ │ │ │ │ ├── FileVersionInfo.h │ │ │ │ │ ├── PerformanceCounter.cpp │ │ │ │ │ ├── PerformanceCounter.h │ │ │ │ │ ├── PerformanceCounterCategory.cpp │ │ │ │ │ ├── PerformanceCounterCategory.h │ │ │ │ │ ├── PerformanceCounterUtils.cpp │ │ │ │ │ ├── PerformanceCounterUtils.h │ │ │ │ │ ├── Process.cpp │ │ │ │ │ ├── Process.h │ │ │ │ │ ├── Stopwatch.cpp │ │ │ │ │ ├── Stopwatch.h │ │ │ │ │ └── perfcounters-def.h │ │ │ │ ├── System.IO/ │ │ │ │ │ ├── FAMWatcher.cpp │ │ │ │ │ ├── FAMWatcher.h │ │ │ │ │ ├── FileSystemWatcher.cpp │ │ │ │ │ ├── FileSystemWatcher.h │ │ │ │ │ ├── InotifyWatcher.cpp │ │ │ │ │ ├── InotifyWatcher.h │ │ │ │ │ ├── KqueueMonitor.cpp │ │ │ │ │ └── KqueueMonitor.h │ │ │ │ ├── System.Net/ │ │ │ │ │ ├── Dns.cpp │ │ │ │ │ └── Dns.h │ │ │ │ ├── System.Net.NetworkInformation/ │ │ │ │ │ ├── LinuxNetworkInterface.cpp │ │ │ │ │ ├── LinuxNetworkInterface.h │ │ │ │ │ ├── MacOsIPInterfaceProperties.cpp │ │ │ │ │ └── MacOsIPInterfaceProperties.h │ │ │ │ ├── System.Net.Sockets/ │ │ │ │ │ ├── Socket.cpp │ │ │ │ │ ├── Socket.h │ │ │ │ │ ├── SocketException.cpp │ │ │ │ │ └── SocketException.h │ │ │ │ └── System.Threading/ │ │ │ │ ├── Semaphore.cpp │ │ │ │ └── Semaphore.h │ │ │ ├── System.Configuration/ │ │ │ │ └── System.Configuration/ │ │ │ │ ├── InternalConfigurationHost.cpp │ │ │ │ └── InternalConfigurationHost.h │ │ │ ├── System.Core/ │ │ │ │ └── System.IO.MemoryMappedFiles/ │ │ │ │ ├── MemoryMapImpl.cpp │ │ │ │ └── MemoryMapImpl.h │ │ │ └── mscorlib/ │ │ │ ├── Mono/ │ │ │ │ ├── Runtime.cpp │ │ │ │ ├── Runtime.h │ │ │ │ ├── RuntimeClassHandle.cpp │ │ │ │ ├── RuntimeClassHandle.h │ │ │ │ ├── RuntimeGPtrArrayHandle.cpp │ │ │ │ ├── RuntimeGPtrArrayHandle.h │ │ │ │ ├── RuntimeMarshal.cpp │ │ │ │ ├── RuntimeMarshal.h │ │ │ │ ├── SafeStringMarshal.cpp │ │ │ │ └── SafeStringMarshal.h │ │ │ ├── Mono.Globalization.Unicode/ │ │ │ │ ├── Normalization.cpp │ │ │ │ └── Normalization.h │ │ │ ├── Mono.Interop/ │ │ │ │ ├── ComInteropProxy.cpp │ │ │ │ └── ComInteropProxy.h │ │ │ ├── Mono.Security.Cryptography/ │ │ │ │ ├── KeyPairPersistence.cpp │ │ │ │ └── KeyPairPersistence.h │ │ │ ├── System/ │ │ │ │ ├── Activator.cpp │ │ │ │ ├── Activator.h │ │ │ │ ├── AppDomain.cpp │ │ │ │ ├── AppDomain.h │ │ │ │ ├── ArgIterator.cpp │ │ │ │ ├── ArgIterator.h │ │ │ │ ├── Array.cpp │ │ │ │ ├── Array.h │ │ │ │ ├── Buffer.cpp │ │ │ │ ├── Buffer.h │ │ │ │ ├── CLRConfig.cpp │ │ │ │ ├── CLRConfig.h │ │ │ │ ├── Char.cpp │ │ │ │ ├── Char.h │ │ │ │ ├── ConsoleDriver.cpp │ │ │ │ ├── ConsoleDriver.h │ │ │ │ ├── Convert.cpp │ │ │ │ ├── Convert.h │ │ │ │ ├── CurrentSystemTimeZone.cpp │ │ │ │ ├── CurrentSystemTimeZone.h │ │ │ │ ├── DateTime.cpp │ │ │ │ ├── DateTime.h │ │ │ │ ├── Decimal.cpp │ │ │ │ ├── Decimal.h │ │ │ │ ├── Delegate.cpp │ │ │ │ ├── Delegate.h │ │ │ │ ├── Double.cpp │ │ │ │ ├── Double.h │ │ │ │ ├── Enum.cpp │ │ │ │ ├── Enum.h │ │ │ │ ├── Environment.cpp │ │ │ │ ├── Environment.h │ │ │ │ ├── Exception.cpp │ │ │ │ ├── Exception.h │ │ │ │ ├── GC.cpp │ │ │ │ ├── GC.h │ │ │ │ ├── Math.cpp │ │ │ │ ├── Math.h │ │ │ │ ├── MissingMemberException.cpp │ │ │ │ ├── MissingMemberException.h │ │ │ │ ├── MonoCustomAttrs.cpp │ │ │ │ ├── MonoCustomAttrs.h │ │ │ │ ├── MonoEnumInfo.cpp │ │ │ │ ├── MonoEnumInfo.h │ │ │ │ ├── MonoType.cpp │ │ │ │ ├── MonoType.h │ │ │ │ ├── Number.cpp │ │ │ │ ├── Number.h │ │ │ │ ├── NumberFormatter.cpp │ │ │ │ ├── NumberFormatter.h │ │ │ │ ├── Object.cpp │ │ │ │ ├── Object.h │ │ │ │ ├── RuntimeFieldHandle.cpp │ │ │ │ ├── RuntimeFieldHandle.h │ │ │ │ ├── RuntimeMethodHandle.cpp │ │ │ │ ├── RuntimeMethodHandle.h │ │ │ │ ├── RuntimeType.cpp │ │ │ │ ├── RuntimeType.h │ │ │ │ ├── RuntimeTypeHandle.cpp │ │ │ │ ├── RuntimeTypeHandle.h │ │ │ │ ├── SizedReference.cpp │ │ │ │ ├── SizedReference.h │ │ │ │ ├── String.cpp │ │ │ │ ├── String.h │ │ │ │ ├── TimeSpan.cpp │ │ │ │ ├── TimeSpan.h │ │ │ │ ├── TimeZoneInfo.h │ │ │ │ ├── Type.cpp │ │ │ │ ├── Type.h │ │ │ │ ├── TypedReference.cpp │ │ │ │ ├── TypedReference.h │ │ │ │ ├── ValueType.cpp │ │ │ │ ├── ValueType.h │ │ │ │ ├── __ComObject.cpp │ │ │ │ └── __ComObject.h │ │ │ ├── System.Diagnostics/ │ │ │ │ ├── Assert.cpp │ │ │ │ ├── Assert.h │ │ │ │ ├── Debugger.cpp │ │ │ │ ├── Debugger.h │ │ │ │ ├── StackFrame.cpp │ │ │ │ ├── StackFrame.h │ │ │ │ ├── StackTrace.cpp │ │ │ │ └── StackTrace.h │ │ │ ├── System.Globalization/ │ │ │ │ ├── CalendarData.cpp │ │ │ │ ├── CalendarData.h │ │ │ │ ├── CompareInfo.cpp │ │ │ │ ├── CompareInfo.h │ │ │ │ ├── CompareOptions.h │ │ │ │ ├── CultureData.cpp │ │ │ │ ├── CultureData.h │ │ │ │ ├── CultureInfo.cpp │ │ │ │ ├── CultureInfo.h │ │ │ │ ├── CultureInfoInternals.h │ │ │ │ ├── CultureInfoTables.h │ │ │ │ ├── RegionInfo.cpp │ │ │ │ └── RegionInfo.h │ │ │ ├── System.IO/ │ │ │ │ ├── DriveInfo.cpp │ │ │ │ ├── DriveInfo.h │ │ │ │ ├── MonoIO.cpp │ │ │ │ ├── MonoIO.h │ │ │ │ ├── Path.cpp │ │ │ │ └── Path.h │ │ │ ├── System.Reflection/ │ │ │ │ ├── Assembly.cpp │ │ │ │ ├── Assembly.h │ │ │ │ ├── AssemblyName.cpp │ │ │ │ ├── AssemblyName.h │ │ │ │ ├── CustomAttributeData.cpp │ │ │ │ ├── CustomAttributeData.h │ │ │ │ ├── EventInfo.cpp │ │ │ │ ├── EventInfo.h │ │ │ │ ├── FieldInfo.cpp │ │ │ │ ├── FieldInfo.h │ │ │ │ ├── MemberInfo.cpp │ │ │ │ ├── MemberInfo.h │ │ │ │ ├── MethodBase.cpp │ │ │ │ ├── MethodBase.h │ │ │ │ ├── Module.cpp │ │ │ │ ├── Module.h │ │ │ │ ├── MonoCMethod.cpp │ │ │ │ ├── MonoCMethod.h │ │ │ │ ├── MonoEventInfo.cpp │ │ │ │ ├── MonoEventInfo.h │ │ │ │ ├── MonoField.cpp │ │ │ │ ├── MonoField.h │ │ │ │ ├── MonoGenericCMethod.cpp │ │ │ │ ├── MonoGenericCMethod.h │ │ │ │ ├── MonoGenericClass.cpp │ │ │ │ ├── MonoGenericClass.h │ │ │ │ ├── MonoGenericMethod.cpp │ │ │ │ ├── MonoGenericMethod.h │ │ │ │ ├── MonoMethod.cpp │ │ │ │ ├── MonoMethod.h │ │ │ │ ├── MonoMethodInfo.cpp │ │ │ │ ├── MonoMethodInfo.h │ │ │ │ ├── MonoPropertyInfo.cpp │ │ │ │ ├── MonoPropertyInfo.h │ │ │ │ ├── ParameterInfo.cpp │ │ │ │ ├── ParameterInfo.h │ │ │ │ ├── PropertyInfo.cpp │ │ │ │ ├── PropertyInfo.h │ │ │ │ ├── RtFieldInfo.cpp │ │ │ │ └── RtFieldInfo.h │ │ │ ├── System.Reflection.Emit/ │ │ │ │ ├── AssemblyBuilder.cpp │ │ │ │ ├── AssemblyBuilder.h │ │ │ │ ├── CustomAttributeBuilder.cpp │ │ │ │ ├── CustomAttributeBuilder.h │ │ │ │ ├── DerivedType.cpp │ │ │ │ ├── DerivedType.h │ │ │ │ ├── DynamicMethod.cpp │ │ │ │ ├── DynamicMethod.h │ │ │ │ ├── EnumBuilder.cpp │ │ │ │ ├── EnumBuilder.h │ │ │ │ ├── GenericTypeParameterBuilder.cpp │ │ │ │ ├── GenericTypeParameterBuilder.h │ │ │ │ ├── MethodBuilder.cpp │ │ │ │ ├── MethodBuilder.h │ │ │ │ ├── ModuleBuilder.cpp │ │ │ │ ├── ModuleBuilder.h │ │ │ │ ├── SignatureHelper.cpp │ │ │ │ ├── SignatureHelper.h │ │ │ │ ├── SymbolType.cpp │ │ │ │ ├── SymbolType.h │ │ │ │ ├── TypeBuilder.cpp │ │ │ │ └── TypeBuilder.h │ │ │ ├── System.Runtime.CompilerServices/ │ │ │ │ ├── RuntimeHelpers.cpp │ │ │ │ └── RuntimeHelpers.h │ │ │ ├── System.Runtime.InteropServices/ │ │ │ │ ├── GCHandle.cpp │ │ │ │ ├── GCHandle.h │ │ │ │ ├── Marshal.cpp │ │ │ │ └── Marshal.h │ │ │ ├── System.Runtime.InteropServices.WindowsRuntime/ │ │ │ │ ├── UnsafeNativeMethods.cpp │ │ │ │ └── UnsafeNativeMethods.h │ │ │ ├── System.Runtime.Remoting/ │ │ │ │ ├── RemotingServices.cpp │ │ │ │ └── RemotingServices.h │ │ │ ├── System.Runtime.Remoting.Activation/ │ │ │ │ ├── ActivationServices.cpp │ │ │ │ └── ActivationServices.h │ │ │ ├── System.Runtime.Remoting.Contexts/ │ │ │ │ ├── Context.cpp │ │ │ │ └── Context.h │ │ │ ├── System.Runtime.Remoting.Messaging/ │ │ │ │ ├── AsyncResult.cpp │ │ │ │ ├── AsyncResult.h │ │ │ │ ├── MonoMethodMessage.cpp │ │ │ │ └── MonoMethodMessage.h │ │ │ ├── System.Runtime.Remoting.Proxies/ │ │ │ │ ├── RealProxy.cpp │ │ │ │ └── RealProxy.h │ │ │ ├── System.Runtime.Versioning/ │ │ │ │ ├── VersioningHelper.cpp │ │ │ │ └── VersioningHelper.h │ │ │ ├── System.Security/ │ │ │ │ ├── SecurityFrame.cpp │ │ │ │ ├── SecurityFrame.h │ │ │ │ ├── SecurityManager.cpp │ │ │ │ └── SecurityManager.h │ │ │ ├── System.Security.Cryptography/ │ │ │ │ ├── RNGCryptoServiceProvider.cpp │ │ │ │ └── RNGCryptoServiceProvider.h │ │ │ ├── System.Security.Policy/ │ │ │ │ ├── Evidence.cpp │ │ │ │ └── Evidence.h │ │ │ ├── System.Security.Principal/ │ │ │ │ ├── WindowsIdentity.cpp │ │ │ │ ├── WindowsIdentity.h │ │ │ │ ├── WindowsImpersonationContext.cpp │ │ │ │ ├── WindowsImpersonationContext.h │ │ │ │ ├── WindowsPrincipal.cpp │ │ │ │ └── WindowsPrincipal.h │ │ │ ├── System.Text/ │ │ │ │ ├── Encoding.cpp │ │ │ │ ├── Encoding.h │ │ │ │ ├── EncodingHelper.cpp │ │ │ │ ├── EncodingHelper.h │ │ │ │ ├── Normalization.cpp │ │ │ │ └── Normalization.h │ │ │ └── System.Threading/ │ │ │ ├── Interlocked.cpp │ │ │ ├── Interlocked.h │ │ │ ├── InternalThread.cpp │ │ │ ├── InternalThread.h │ │ │ ├── Monitor.cpp │ │ │ ├── Monitor.h │ │ │ ├── Mutex.cpp │ │ │ ├── Mutex.h │ │ │ ├── NativeEventCalls.cpp │ │ │ ├── NativeEventCalls.h │ │ │ ├── Thread.cpp │ │ │ ├── Thread.h │ │ │ ├── ThreadPool.cpp │ │ │ ├── ThreadPool.h │ │ │ ├── Timer.cpp │ │ │ ├── Timer.h │ │ │ ├── WaitHandle.cpp │ │ │ └── WaitHandle.h │ │ ├── il2cpp-api-functions.h │ │ ├── il2cpp-api-types.h │ │ ├── il2cpp-api.cpp │ │ ├── il2cpp-api.h │ │ ├── il2cpp-config.h │ │ ├── il2cpp-debugger.cpp │ │ ├── il2cpp-debugger.h │ │ ├── il2cpp-metadata.h │ │ ├── il2cpp-string-types.h │ │ ├── il2cpp-vm-support.h │ │ ├── libil2cpp.def │ │ ├── libil2cpp.icalls │ │ ├── libil2cpp.vcxproj │ │ ├── libil2cpp.vcxproj.filters │ │ ├── metadata/ │ │ │ ├── ArrayMetadata.cpp │ │ │ ├── ArrayMetadata.h │ │ │ ├── FieldLayout.cpp │ │ │ ├── FieldLayout.h │ │ │ ├── GenericMetadata.cpp │ │ │ ├── GenericMetadata.h │ │ │ ├── GenericMethod.cpp │ │ │ ├── GenericMethod.h │ │ │ ├── GenericSharing.cpp │ │ │ ├── GenericSharing.h │ │ │ ├── Il2CppGenericClassCompare.cpp │ │ │ ├── Il2CppGenericClassCompare.h │ │ │ ├── Il2CppGenericClassHash.cpp │ │ │ ├── Il2CppGenericClassHash.h │ │ │ ├── Il2CppGenericContextCompare.cpp │ │ │ ├── Il2CppGenericContextCompare.h │ │ │ ├── Il2CppGenericContextHash.cpp │ │ │ ├── Il2CppGenericContextHash.h │ │ │ ├── Il2CppGenericInstCompare.cpp │ │ │ ├── Il2CppGenericInstCompare.h │ │ │ ├── Il2CppGenericInstHash.cpp │ │ │ ├── Il2CppGenericInstHash.h │ │ │ ├── Il2CppGenericMethodCompare.cpp │ │ │ ├── Il2CppGenericMethodCompare.h │ │ │ ├── Il2CppGenericMethodHash.cpp │ │ │ ├── Il2CppGenericMethodHash.h │ │ │ ├── Il2CppSignatureCompare.cpp │ │ │ ├── Il2CppSignatureCompare.h │ │ │ ├── Il2CppSignatureHash.cpp │ │ │ ├── Il2CppSignatureHash.h │ │ │ ├── Il2CppTypeCompare.cpp │ │ │ ├── Il2CppTypeCompare.h │ │ │ ├── Il2CppTypeHash.cpp │ │ │ ├── Il2CppTypeHash.h │ │ │ └── Il2CppTypeVector.h │ │ ├── metadata.h │ │ ├── mono/ │ │ │ └── ThreadPool/ │ │ │ ├── ThreadPoolDataStructures.h │ │ │ ├── ThreadPoolMacros.h │ │ │ ├── ThreadPoolMonitorThread.cpp │ │ │ ├── ThreadPoolMonitorThread.h │ │ │ ├── ThreadPoolWorkerThread.cpp │ │ │ ├── ThreadPoolWorkerThread.h │ │ │ ├── threadpool-ms-io-poll.cpp │ │ │ ├── threadpool-ms-io-poll.h │ │ │ ├── threadpool-ms-io.cpp │ │ │ ├── threadpool-ms-io.h │ │ │ ├── threadpool-ms.cpp │ │ │ └── threadpool-ms.h │ │ ├── mono-runtime/ │ │ │ ├── il2cpp-callbacks.cpp │ │ │ ├── il2cpp-callbacks.h │ │ │ ├── il2cpp-mapping.h │ │ │ ├── il2cpp-mono-support.cpp │ │ │ └── il2cpp-mono-support.h │ │ ├── mono-structs.cpp │ │ ├── mono-structs.h │ │ ├── normalization-tables.h │ │ ├── number-formatter.h │ │ ├── object-internals.h │ │ ├── os/ │ │ │ ├── Android/ │ │ │ │ └── StackTrace.cpp │ │ │ ├── Atomic.h │ │ │ ├── COM.h │ │ │ ├── ConditionVariable.cpp │ │ │ ├── ConditionVariable.h │ │ │ ├── Console.h │ │ │ ├── CpuInfo.h │ │ │ ├── Cryptography.h │ │ │ ├── Debug.cpp │ │ │ ├── Debug.h │ │ │ ├── Directory.h │ │ │ ├── Encoding.h │ │ │ ├── Environment.h │ │ │ ├── Error.cpp │ │ │ ├── Error.h │ │ │ ├── ErrorCodes.h │ │ │ ├── Event.cpp │ │ │ ├── Event.h │ │ │ ├── File.h │ │ │ ├── FileSystemWatcher.h │ │ │ ├── Generic/ │ │ │ │ ├── COM.cpp │ │ │ │ ├── Environment.cpp │ │ │ │ ├── Initialize.cpp │ │ │ │ ├── MarshalStringAlloc.cpp │ │ │ │ ├── MemoryMappedFile.cpp │ │ │ │ ├── SocketImpl.cpp │ │ │ │ ├── SocketImpl.h │ │ │ │ └── WindowsRuntime.cpp │ │ │ ├── Handle.h │ │ │ ├── Image.h │ │ │ ├── Initialize.h │ │ │ ├── LastError.h │ │ │ ├── LibraryLoader.h │ │ │ ├── Locale.h │ │ │ ├── MarshalAlloc.h │ │ │ ├── MarshalStringAlloc.h │ │ │ ├── Memory.h │ │ │ ├── MemoryMappedFile.h │ │ │ ├── Messages.cpp │ │ │ ├── Messages.h │ │ │ ├── Mutex.cpp │ │ │ ├── Mutex.h │ │ │ ├── NativeMethods.h │ │ │ ├── OSGlobalEnums.h │ │ │ ├── OSX/ │ │ │ │ ├── Image.cpp │ │ │ │ └── Process.cpp │ │ │ ├── Path.cpp │ │ │ ├── Path.h │ │ │ ├── Posix/ │ │ │ │ ├── AtomicImpl.h │ │ │ │ ├── ConditionVariableImpl.cpp │ │ │ │ ├── ConditionVariableImpl.h │ │ │ │ ├── Console.cpp │ │ │ │ ├── CpuInfo.cpp │ │ │ │ ├── Cryptography.cpp │ │ │ │ ├── Directory.cpp │ │ │ │ ├── Encoding.cpp │ │ │ │ ├── Environment.cpp │ │ │ │ ├── Error.cpp │ │ │ │ ├── Error.h │ │ │ │ ├── EventImpl.cpp │ │ │ │ ├── EventImpl.h │ │ │ │ ├── File.cpp │ │ │ │ ├── FileHandle.h │ │ │ │ ├── FileSystemWatcher.cpp │ │ │ │ ├── Image.cpp │ │ │ │ ├── LastError.cpp │ │ │ │ ├── LibraryLoader.cpp │ │ │ │ ├── Locale.cpp │ │ │ │ ├── MarshalAlloc.cpp │ │ │ │ ├── Memory.cpp │ │ │ │ ├── MemoryMappedFile.cpp │ │ │ │ ├── MutexImpl.cpp │ │ │ │ ├── MutexImpl.h │ │ │ │ ├── NativeMethods.cpp │ │ │ │ ├── Path.cpp │ │ │ │ ├── PosixHelpers.cpp │ │ │ │ ├── PosixHelpers.h │ │ │ │ ├── PosixWaitObject.cpp │ │ │ │ ├── PosixWaitObject.h │ │ │ │ ├── Process.cpp │ │ │ │ ├── SemaphoreImpl.cpp │ │ │ │ ├── SemaphoreImpl.h │ │ │ │ ├── SocketImpl.cpp │ │ │ │ ├── SocketImpl.h │ │ │ │ ├── StackTrace.cpp │ │ │ │ ├── ThreadImpl.cpp │ │ │ │ ├── ThreadImpl.h │ │ │ │ ├── ThreadLocalValueImpl.cpp │ │ │ │ ├── ThreadLocalValueImpl.h │ │ │ │ ├── Time.cpp │ │ │ │ └── TimeZone.cpp │ │ │ ├── Process.h │ │ │ ├── Semaphore.cpp │ │ │ ├── Semaphore.h │ │ │ ├── Socket.cpp │ │ │ ├── Socket.h │ │ │ ├── StackTrace.h │ │ │ ├── Std/ │ │ │ │ ├── ThreadImpl.cpp │ │ │ │ └── ThreadImpl.h │ │ │ ├── Thread.cpp │ │ │ ├── Thread.h │ │ │ ├── ThreadLocalValue.cpp │ │ │ ├── ThreadLocalValue.h │ │ │ ├── Time.h │ │ │ ├── TimeZone.h │ │ │ ├── Tizen/ │ │ │ │ └── ExtendedAtomicOps.h │ │ │ ├── Unity/ │ │ │ │ ├── AtomicQueue.cpp │ │ │ │ ├── AtomicQueue.h │ │ │ │ ├── ExtendedAtomicOps-arm.h │ │ │ │ ├── ExtendedAtomicOps-arm64.h │ │ │ │ ├── ExtendedAtomicOps-x86-64.h │ │ │ │ ├── ExtendedAtomicOps-x86.h │ │ │ │ ├── ExtendedAtomicOps.h │ │ │ │ ├── ExtendedAtomicTypes.h │ │ │ │ └── UnityPlatformConfigure.h │ │ │ ├── WaitStatus.h │ │ │ ├── Win32/ │ │ │ │ ├── AtomicImpl.h │ │ │ │ ├── COM.cpp │ │ │ │ ├── ConditionVariableImpl.cpp │ │ │ │ ├── ConditionVariableImpl.h │ │ │ │ ├── Console.cpp │ │ │ │ ├── CpuInfo.cpp │ │ │ │ ├── Cryptography.cpp │ │ │ │ ├── Debug.cpp │ │ │ │ ├── Directory.cpp │ │ │ │ ├── Encoding.cpp │ │ │ │ ├── Environment.cpp │ │ │ │ ├── EventImpl.cpp │ │ │ │ ├── EventImpl.h │ │ │ │ ├── File.cpp │ │ │ │ ├── FileSystemWatcher.cpp │ │ │ │ ├── Image.cpp │ │ │ │ ├── Initialize.cpp │ │ │ │ ├── LastError.cpp │ │ │ │ ├── LibraryLoader.cpp │ │ │ │ ├── Locale.cpp │ │ │ │ ├── MarshalAlloc.cpp │ │ │ │ ├── MarshalStringAlloc.cpp │ │ │ │ ├── Memory.cpp │ │ │ │ ├── MemoryMappedFile.cpp │ │ │ │ ├── MutexImpl.cpp │ │ │ │ ├── MutexImpl.h │ │ │ │ ├── NativeMethods.cpp │ │ │ │ ├── Path.cpp │ │ │ │ ├── Process.cpp │ │ │ │ ├── SemaphoreImpl.cpp │ │ │ │ ├── SemaphoreImpl.h │ │ │ │ ├── SocketImpl.cpp │ │ │ │ ├── SocketImpl.h │ │ │ │ ├── StackTrace.cpp │ │ │ │ ├── ThreadImpl.cpp │ │ │ │ ├── ThreadImpl.h │ │ │ │ ├── ThreadLocalValueImpl.cpp │ │ │ │ ├── ThreadLocalValueImpl.h │ │ │ │ ├── Time.cpp │ │ │ │ ├── TimeZone.cpp │ │ │ │ ├── WindowsHeaders.h │ │ │ │ ├── WindowsHelpers.cpp │ │ │ │ ├── WindowsHelpers.h │ │ │ │ └── WindowsRuntime.cpp │ │ │ ├── WinRT/ │ │ │ │ ├── Cryptography.cpp │ │ │ │ ├── Environment.cpp │ │ │ │ ├── File.cpp │ │ │ │ ├── Initialize.cpp │ │ │ │ ├── Locale.cpp │ │ │ │ ├── Process.cpp │ │ │ │ ├── SynchronousOperation.h │ │ │ │ ├── Win32ApiSharedEmulation.cpp │ │ │ │ ├── Win32ApiSharedEmulation.h │ │ │ │ ├── Win32ApiWinRTEmulation.cpp │ │ │ │ └── Win32ApiWinRTEmulation.h │ │ │ ├── WindowsRuntime.h │ │ │ └── c-api/ │ │ │ ├── Allocator.cpp │ │ │ ├── Allocator.h │ │ │ ├── File-c-api.h │ │ │ ├── File.cpp │ │ │ ├── NativeMethods-c-api.h │ │ │ ├── NativeMethods.cpp │ │ │ ├── Path-c-api.h │ │ │ ├── Path.cpp │ │ │ ├── Process-c-api.h │ │ │ ├── Process.cpp │ │ │ ├── Time-c-api.h │ │ │ ├── Time.cpp │ │ │ ├── TimeZone-c-api.h │ │ │ ├── TimeZone.cpp │ │ │ └── tests/ │ │ │ ├── FileTests.cpp │ │ │ ├── MainTestRunner.cpp │ │ │ ├── NativeMethodsTests.cpp │ │ │ ├── PathTests.cpp │ │ │ ├── ProcessTests.cpp │ │ │ ├── TimeTests.cpp │ │ │ ├── TimeZoneTests.cpp │ │ │ ├── libil2cpp-c-api-tests.vcxproj │ │ │ └── libil2cpp-c-api-tests.vcxproj.filters │ │ ├── tabledefs.h │ │ ├── utils/ │ │ │ ├── CallOnce.h │ │ │ ├── Collections.h │ │ │ ├── DirectoryUtils.cpp │ │ │ ├── DirectoryUtils.h │ │ │ ├── Environment.cpp │ │ │ ├── Environment.h │ │ │ ├── Exception.cpp │ │ │ ├── Exception.h │ │ │ ├── Functional.h │ │ │ ├── HashUtils.h │ │ │ ├── Il2CppHStringReference.h │ │ │ ├── Il2CppHashMap.h │ │ │ ├── Il2CppHashSet.h │ │ │ ├── KeyWrapper.h │ │ │ ├── Logging.cpp │ │ │ ├── Logging.h │ │ │ ├── MarshalingUtils.cpp │ │ │ ├── MarshalingUtils.h │ │ │ ├── MathUtils.h │ │ │ ├── Memory.cpp │ │ │ ├── Memory.h │ │ │ ├── MemoryPool.cpp │ │ │ ├── MemoryPool.h │ │ │ ├── MemoryRead.h │ │ │ ├── NonCopyable.h │ │ │ ├── Output.cpp │ │ │ ├── Output.h │ │ │ ├── PathUtils.cpp │ │ │ ├── PathUtils.h │ │ │ ├── RegisterRuntimeInitializeAndCleanup.cpp │ │ │ ├── RegisterRuntimeInitializeAndCleanup.h │ │ │ ├── Runtime.cpp │ │ │ ├── Runtime.h │ │ │ ├── StringUtils.cpp │ │ │ ├── StringUtils.h │ │ │ ├── StringView.h │ │ │ ├── StringViewStream.h │ │ │ ├── TemplateUtils.h │ │ │ ├── ThreadSafeFreeList.h │ │ │ ├── dynamic_array.h │ │ │ └── utf8-cpp/ │ │ │ └── source/ │ │ │ ├── utf8/ │ │ │ │ ├── checked.h │ │ │ │ ├── core.h │ │ │ │ └── unchecked.h │ │ │ └── utf8.h │ │ ├── vm/ │ │ │ ├── Array.cpp │ │ │ ├── Array.h │ │ │ ├── Assembly.cpp │ │ │ ├── Assembly.h │ │ │ ├── AssemblyName.cpp │ │ │ ├── AssemblyName.h │ │ │ ├── Atomic.cpp │ │ │ ├── Atomic.h │ │ │ ├── CCW.cpp │ │ │ ├── CCW.h │ │ │ ├── COM.cpp │ │ │ ├── COM.h │ │ │ ├── CachedCCWBase.h │ │ │ ├── Class.cpp │ │ │ ├── Class.h │ │ │ ├── ComObjectBase.cpp │ │ │ ├── ComObjectBase.h │ │ │ ├── Debug.cpp │ │ │ ├── Debug.h │ │ │ ├── Domain.cpp │ │ │ ├── Domain.h │ │ │ ├── Enum.cpp │ │ │ ├── Enum.h │ │ │ ├── Event.cpp │ │ │ ├── Event.h │ │ │ ├── Exception.cpp │ │ │ ├── Exception.h │ │ │ ├── Field.cpp │ │ │ ├── Field.h │ │ │ ├── GenericClass.cpp │ │ │ ├── GenericClass.h │ │ │ ├── GenericContainer.cpp │ │ │ ├── GenericContainer.h │ │ │ ├── Image.cpp │ │ │ ├── Image.h │ │ │ ├── InternalCalls.cpp │ │ │ ├── InternalCalls.h │ │ │ ├── LastError.cpp │ │ │ ├── LastError.h │ │ │ ├── LibraryLoader.cpp │ │ │ ├── LibraryLoader.h │ │ │ ├── Liveness.cpp │ │ │ ├── Liveness.h │ │ │ ├── MarshalAlloc.cpp │ │ │ ├── MarshalAlloc.h │ │ │ ├── MemoryInformation.cpp │ │ │ ├── MemoryInformation.h │ │ │ ├── MetadataAlloc.cpp │ │ │ ├── MetadataAlloc.h │ │ │ ├── MetadataCache.cpp │ │ │ ├── MetadataCache.h │ │ │ ├── MetadataLoader.cpp │ │ │ ├── MetadataLoader.h │ │ │ ├── MetadataLock.h │ │ │ ├── Method.cpp │ │ │ ├── Method.h │ │ │ ├── Module.cpp │ │ │ ├── Module.h │ │ │ ├── Monitor.cpp │ │ │ ├── Monitor.h │ │ │ ├── NonCachedCCWBase.h │ │ │ ├── Object.cpp │ │ │ ├── Object.h │ │ │ ├── Parameter.cpp │ │ │ ├── Parameter.h │ │ │ ├── Path.cpp │ │ │ ├── Path.h │ │ │ ├── PlatformInvoke.cpp │ │ │ ├── PlatformInvoke.h │ │ │ ├── Profiler.cpp │ │ │ ├── Profiler.h │ │ │ ├── Property.cpp │ │ │ ├── Property.h │ │ │ ├── RCW.cpp │ │ │ ├── RCW.h │ │ │ ├── Random.cpp │ │ │ ├── Random.h │ │ │ ├── Reflection.cpp │ │ │ ├── Reflection.h │ │ │ ├── Runtime.cpp │ │ │ ├── Runtime.h │ │ │ ├── StackTrace.cpp │ │ │ ├── StackTrace.h │ │ │ ├── String.cpp │ │ │ ├── String.h │ │ │ ├── Thread.cpp │ │ │ ├── Thread.h │ │ │ ├── ThreadPool.cpp │ │ │ ├── ThreadPool.h │ │ │ ├── ThreadPoolMs.cpp │ │ │ ├── ThreadPoolMs.h │ │ │ ├── Type.cpp │ │ │ ├── Type.h │ │ │ ├── VisualizerHelpers.cpp │ │ │ ├── WaitHandle.cpp │ │ │ ├── WaitHandle.h │ │ │ ├── WindowsRuntime.cpp │ │ │ └── WindowsRuntime.h │ │ └── vm-utils/ │ │ ├── BlobReader.cpp │ │ ├── BlobReader.h │ │ ├── NativeDelegateMethodCache.cpp │ │ ├── NativeDelegateMethodCache.h │ │ ├── NativeSymbol.cpp │ │ ├── NativeSymbol.h │ │ ├── VmStringUtils.cpp │ │ └── VmStringUtils.h │ ├── main.cpp │ ├── unity_decoder.vcxproj │ ├── unity_decoder.vcxproj.filters │ └── unity_decoder.vcxproj.user ├── unity_decoder.sln └── unity_loader.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ *.VC.db *.VC.opendb *.sdf *.pdb *.ilk *.iobj *.ipdb *.swp unity_decoder/Debug/ /Debug/ /Debug/string_literal.txt /Debug/global-metadata.dat /Debug/global-metadata.dat-ios /Debug/global-metadata.dat-win /Debug/method_name.txt /unity_decoder/global-metadata.dat unity_decoder/Release/ .vs/ co.sh ================================================ FILE: LICENSE ================================================ 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. Copyright (C) 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. , 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: README.md ================================================ # unity_metadata_loader This project will load strings and method/class names in global-metadata.dat to IDA. ## Introduction As most game hackers may know, if you use IL2CPP to compile an Unity game, all the strings used in your original source code will be stored separately in another file call `global-metadata.dat` so that you are not able to find any strings when you load the game binary to IDA. Moreover, as the game is compiled to native assembly, all the symbols like class names or function names are removed from the binary. This significantly makes the static analysis of these games more difficult and is usually considered to be un-hackable. However, with this IDA plugin, you are able to recover all the class names, method names and string constants and mapping them to IDA. Hacking unity games becomes incredibly easy. Please refer to these two blogs for detailed information: [还原使用IL2CPP编译的unity游戏的symbol(一)](https://www.nevermoe.com/?p=572) [还原使用IL2CPP编译的unity游戏的symbol(二 )](https://www.nevermoe.com/?p=597) ## Installation & Usage **It's difficult to make a stable auto load funcition, so instead, I provide two helper function `LocateMethodPointers()` and `LocateStringLiterals()` to help you locate the address of g_MethodPointers and g_MetadataUsages. But you have to decide by yourself which adresses are the true addresses from the provided candidate** 1. Copy Release/unity_decoder.exe to the same directory as your binary to be analyzed. 2. Copy unity_loader.py to any directory. (I recommned to copy it to the same directory as your binary to be analyzed.) 3. Copy global-metadata.dat to the same directory as your binary to be analyzed. It's located in Data/Managed/Metadata/global-metadata.dat in the ipa file or apk file. 4. Double click `unity_decoder.exe` and you will get two files: `method_name.txt` and `string_literal.txt` 5. Load unity_loader.py using File->Script File. 6. Enter `LocateMethodPointers()` in IDA console. This function will give you several possible candidate location of method pointers like this: ``` candidate: 0x6f00b0, candidate end: 0x6f1fd4, method numbers: 1993 candidate: 0x70ae4c, candidate end: 0x70b224, method numbers: 246 candidate: 0x70bee8, candidate end: 0x717e60, method numbers: 12254 ``` Open the `method_name.txt` file generated at step 4, the first line is the method pointers' numbers. Find the closest number to the suggested candidate. Sometimes the method pointers are seperated to multiple candidates, then you have to add them up. 7. Navigate to the candidate address you believe to be the true address and enter `LoadMethods()` in IDA console. 8. To Load string literals, similar to loading method pointers, enter `LocateStringLiterals()` and then `LoadStringLiterals()`. ## Demo Note: The v24's binary layout is different to the following picture. Before recovering the symbols: ![before](https://www.nevermoe.com/wp-content/uploads/2016/09/before.png) After recovering the symbols: ![after](https://www.nevermoe.com/wp-content/uploads/2016/09/after.png) ## Notice Now you are able to compile this project directly because I added libil2cpp header files. This branch "v24" now only support 32bit Android build. For metadata v23 support, see this fork: [https://github.com/kenjiaiko/unity_metadata_loader](https://github.com/kenjiaiko/unity_metadata_loader) ================================================ FILE: unity_decoder/core.h ================================================ #pragma once #include ================================================ FILE: unity_decoder/libil2cpp/CMakeLists.txt ================================================ #This CMake project file for libil2cpp only exists as a convenience for working on the .cpp and .h files #for people who like to use CLion as their IDE. this is not used by il2cpp itself cmake_minimum_required(VERSION 3.4) project(libil2cpp) file(GLOB_RECURSE LIBIL2CPP_FILES {PROJECT_SOURCE_DIR} *.cpp *.h) set(BOEHMGC_FILES "../external/boehmgc/extra/gc.c") include_directories("." "../external/boehmgc/include") add_library(libil2cpp ${LIBIL2CPP_FILES} ${BOEHMGC_FILES}) ================================================ FILE: unity_decoder/libil2cpp/UnityAdsStubs.cpp ================================================ #if defined(__ANDROID__) #include #define DONTSTRIP __attribute__((used)) #define EXPORT __attribute__((visibility("default"))) extern "C" { typedef void (*UnityAdsReadyCallback)(const char * placementId); typedef void (*UnityAdsDidErrorCallback)(long rawError, const char * message); typedef void (*UnityAdsDidStartCallback)(const char * placementId); typedef void (*UnityAdsDidFinishCallback)(const char * placementId, long rawFinishState); EXPORT DONTSTRIP void UnityAdsEngineInitialize(const char * gameId, bool testMode) {} EXPORT DONTSTRIP void UnityAdsEngineShow(const char * placementId) {} EXPORT DONTSTRIP bool UnityAdsEngineGetDebugMode() { return false; } EXPORT DONTSTRIP void UnityAdsEngineSetDebugMode(bool debugMode) {} EXPORT DONTSTRIP bool UnityAdsEngineIsSupported() { return false; } EXPORT DONTSTRIP bool UnityAdsEngineIsReady(const char * placementId) { return false; } EXPORT DONTSTRIP long UnityAdsEngineGetPlacementState(const char * placementId) { return -1; } EXPORT DONTSTRIP const char * UnityAdsEngineGetVersion() { return NULL; } EXPORT DONTSTRIP bool UnityAdsEngineIsInitialized() { return false; } EXPORT DONTSTRIP void UnityAdsEngineSetMetaData(const char * category, const char * data) {} EXPORT DONTSTRIP void UnityAdsEngineSetReadyCallback(UnityAdsReadyCallback callback) {} EXPORT DONTSTRIP void UnityAdsEngineSetDidErrorCallback(UnityAdsDidErrorCallback callback) {} EXPORT DONTSTRIP void UnityAdsEngineSetDidStartCallback(UnityAdsDidStartCallback callback) {} EXPORT DONTSTRIP void UnityAdsEngineSetDidFinishCallback(UnityAdsDidFinishCallback callback) {} } #endif ================================================ FILE: unity_decoder/libil2cpp/blob.h ================================================ #pragma once // Corresponds to element type signatures // See ECMA-335, II.23.1.16 enum Il2CppTypeEnum { IL2CPP_TYPE_END = 0x00, /* End of List */ IL2CPP_TYPE_VOID = 0x01, IL2CPP_TYPE_BOOLEAN = 0x02, IL2CPP_TYPE_CHAR = 0x03, IL2CPP_TYPE_I1 = 0x04, IL2CPP_TYPE_U1 = 0x05, IL2CPP_TYPE_I2 = 0x06, IL2CPP_TYPE_U2 = 0x07, IL2CPP_TYPE_I4 = 0x08, IL2CPP_TYPE_U4 = 0x09, IL2CPP_TYPE_I8 = 0x0a, IL2CPP_TYPE_U8 = 0x0b, IL2CPP_TYPE_R4 = 0x0c, IL2CPP_TYPE_R8 = 0x0d, IL2CPP_TYPE_STRING = 0x0e, IL2CPP_TYPE_PTR = 0x0f, /* arg: token */ IL2CPP_TYPE_BYREF = 0x10, /* arg: token */ IL2CPP_TYPE_VALUETYPE = 0x11, /* arg: token */ IL2CPP_TYPE_CLASS = 0x12, /* arg: token */ IL2CPP_TYPE_VAR = 0x13, /* Generic parameter in a generic type definition, represented as number (compressed unsigned integer) number */ IL2CPP_TYPE_ARRAY = 0x14, /* type, rank, boundsCount, bound1, loCount, lo1 */ IL2CPP_TYPE_GENERICINST = 0x15, /* \x{2026} */ IL2CPP_TYPE_TYPEDBYREF = 0x16, IL2CPP_TYPE_I = 0x18, IL2CPP_TYPE_U = 0x19, IL2CPP_TYPE_FNPTR = 0x1b, /* arg: full method signature */ IL2CPP_TYPE_OBJECT = 0x1c, IL2CPP_TYPE_SZARRAY = 0x1d, /* 0-based one-dim-array */ IL2CPP_TYPE_MVAR = 0x1e, /* Generic parameter in a generic method definition, represented as number (compressed unsigned integer) */ IL2CPP_TYPE_CMOD_REQD = 0x1f, /* arg: typedef or typeref token */ IL2CPP_TYPE_CMOD_OPT = 0x20, /* optional arg: typedef or typref token */ IL2CPP_TYPE_INTERNAL = 0x21, /* CLR internal type */ IL2CPP_TYPE_MODIFIER = 0x40, /* Or with the following types */ IL2CPP_TYPE_SENTINEL = 0x41, /* Sentinel for varargs method signature */ IL2CPP_TYPE_PINNED = 0x45, /* Local var that points to pinned object */ IL2CPP_TYPE_ENUM = 0x55 /* an enumeration */ }; ================================================ FILE: unity_decoder/libil2cpp/char-conversions.cpp ================================================ #include "il2cpp-config.h" #include "char-conversions.h" uint8_t const CategoryData_v4[] = { /* Page 0, 0 indirect uses */ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 11, 24, 24, 24, 26, 24, 24, 24, 20, 21, 24, 25, 24, 19, 24, 24, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 24, 24, 25, 25, 25, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 24, 21, 27, 18, 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 25, 21, 25, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 11, 24, 26, 26, 26, 26, 28, 28, 27, 28, 1, 22, 25, 19, 28, 27, 28, 25, 10, 10, 27, 1, 28, 24, 27, 10, 1, 23, 10, 10, 10, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 25, 1, 1, 1, 1, 1, 1, 1, 1, /* Page 1, 0 indirect uses */ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 4, 0, 1, 1, 1, 4, 4, 4, 4, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, /* Page 2, 0 indirect uses */ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 27, 27, 27, 27, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 3, 3, 3, 3, 3, 27, 27, 27, 27, 27, 27, 27, 3, 27, 3, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, /* Page 3, 0 indirect uses */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 1, 0, 1, 3, 27, 0, 1, 29, 29, 3, 1, 1, 1, 24, 29, 29, 29, 29, 29, 27, 27, 0, 24, 0, 0, 0, 29, 0, 29, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 25, 0, 1, 0, 0, 1, 1, 0, 0, 0, /* Page 4, 0 indirect uses */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 28, 5, 5, 5, 5, 5, 7, 7, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, /* Page 5, 0 indirect uses */ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 29, 3, 24, 24, 24, 24, 24, 24, 29, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 29, 24, 19, 29, 29, 29, 29, 29, 29, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 19, 5, 24, 5, 5, 24, 5, 5, 24, 5, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 4, 4, 4, 24, 24, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 6, 0 indirect uses */ 15, 15, 15, 15, 29, 29, 25, 25, 25, 24, 24, 26, 24, 24, 28, 28, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 24, 29, 29, 24, 24, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 29, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 24, 24, 24, 24, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 24, 4, 5, 5, 5, 5, 5, 5, 5, 15, 7, 5, 5, 5, 5, 5, 5, 3, 3, 5, 5, 28, 5, 5, 5, 5, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 28, 28, 4, /* Page 7, 0 indirect uses */ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 29, 15, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 3, 28, 24, 24, 24, 3, 29, 29, 29, 29, 29, /* * Page 8, 3390 indirect uses: * 10500-107FF (astral_index), * 10B00-11FFF (astral_index), * 12500-1CFFF (astral_index), * 1D800-1EFFF (astral_index), * 1F100-1FFFF (astral_index), * 2A700-2F7FF (astral_index), * 2FB00-DFFFF (astral_index), * E0200-EFFFF (astral_index) */ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 9, 0 indirect uses */ 29, 5, 5, 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 5, 4, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 5, 29, 29, 4, 5, 5, 5, 5, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 24, 24, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 24, 3, 4, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 29, 5, 6, 6, 29, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 4, 4, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 29, 4, 29, 29, 29, 4, 4, 4, 4, 29, 29, 5, 4, 6, 6, 6, 5, 5, 5, 5, 29, 29, 6, 6, 29, 29, 6, 6, 5, 4, 29, 29, 29, 29, 29, 29, 29, 29, 6, 29, 29, 29, 29, 4, 4, 29, 4, 4, 4, 5, 5, 29, 29, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 26, 26, 10, 10, 10, 10, 10, 10, 28, 29, 29, 29, 29, 29, /* Page 10, 0 indirect uses */ 29, 5, 5, 6, 29, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 4, 4, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 29, 4, 4, 29, 4, 4, 29, 29, 5, 29, 6, 6, 6, 5, 5, 29, 29, 29, 29, 5, 5, 29, 29, 5, 5, 5, 29, 29, 29, 5, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 29, 4, 29, 29, 29, 29, 29, 29, 29, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 5, 5, 4, 4, 4, 5, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 5, 5, 6, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 29, 4, 4, 4, 4, 4, 29, 29, 5, 4, 6, 6, 6, 5, 5, 5, 5, 5, 29, 5, 5, 6, 29, 6, 6, 5, 29, 29, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 5, 5, 29, 29, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 29, 26, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 11, 0 indirect uses */ 29, 5, 6, 6, 29, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 4, 4, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 29, 4, 4, 4, 4, 4, 29, 29, 5, 4, 6, 5, 6, 5, 5, 5, 5, 29, 29, 6, 6, 29, 29, 6, 6, 5, 29, 29, 29, 29, 29, 29, 29, 29, 5, 6, 29, 29, 29, 29, 4, 4, 29, 4, 4, 4, 5, 5, 29, 29, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 28, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 5, 4, 29, 4, 4, 4, 4, 4, 4, 29, 29, 29, 4, 4, 4, 29, 4, 4, 4, 4, 29, 29, 29, 4, 4, 29, 4, 29, 4, 4, 29, 29, 29, 4, 4, 29, 29, 29, 4, 4, 4, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 6, 6, 5, 6, 6, 29, 29, 29, 6, 6, 6, 29, 6, 6, 6, 5, 29, 29, 4, 29, 29, 29, 29, 29, 29, 6, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 10, 10, 10, 28, 28, 28, 28, 28, 28, 26, 28, 29, 29, 29, 29, 29, /* Page 12, 0 indirect uses */ 29, 6, 6, 6, 29, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 29, 29, 29, 4, 5, 5, 5, 6, 6, 6, 6, 29, 5, 5, 5, 29, 5, 5, 5, 5, 29, 29, 29, 29, 29, 29, 29, 5, 5, 29, 4, 4, 29, 29, 29, 29, 29, 29, 4, 4, 5, 5, 29, 29, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 29, 29, 29, 29, 29, 29, 29, 29, 10, 10, 10, 10, 10, 10, 10, 28, 29, 29, 6, 6, 29, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 29, 29, 5, 4, 6, 5, 6, 6, 6, 6, 6, 29, 5, 6, 6, 29, 6, 6, 5, 5, 29, 29, 29, 29, 29, 29, 29, 6, 6, 29, 29, 29, 29, 29, 29, 29, 4, 29, 4, 4, 5, 5, 29, 29, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 29, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 13, 0 indirect uses */ 29, 29, 6, 6, 29, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 4, 6, 6, 6, 5, 5, 5, 5, 29, 6, 6, 6, 29, 6, 6, 6, 5, 29, 29, 29, 29, 29, 29, 29, 29, 29, 6, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 5, 5, 29, 29, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 29, 29, 29, 28, 4, 4, 4, 4, 4, 4, 29, 29, 6, 6, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 29, 29, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 5, 29, 29, 29, 29, 6, 6, 6, 5, 5, 5, 29, 5, 29, 6, 6, 6, 6, 6, 6, 6, 6, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 6, 6, 24, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 14, 0 indirect uses */ 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 4, 4, 5, 5, 5, 5, 5, 5, 5, 29, 29, 29, 29, 26, 4, 4, 4, 4, 4, 4, 3, 5, 5, 5, 5, 5, 5, 5, 5, 24, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 24, 24, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 29, 4, 29, 29, 4, 4, 29, 4, 29, 29, 4, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 29, 4, 29, 4, 29, 29, 4, 4, 29, 4, 4, 4, 4, 5, 4, 4, 5, 5, 5, 5, 5, 5, 29, 5, 5, 4, 29, 29, 4, 4, 4, 4, 4, 29, 3, 29, 5, 5, 5, 5, 5, 5, 29, 29, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 29, 29, 4, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 15, 0 indirect uses */ 4, 28, 28, 28, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 28, 28, 28, 28, 28, 5, 5, 28, 28, 28, 28, 28, 28, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 28, 5, 28, 5, 28, 5, 20, 21, 20, 21, 6, 6, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 24, 5, 5, 4, 4, 4, 4, 29, 29, 29, 29, 5, 5, 5, 5, 5, 5, 5, 5, 29, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 29, 28, 28, 28, 28, 28, 28, 28, 28, 5, 28, 28, 28, 28, 28, 28, 29, 28, 28, 24, 24, 24, 24, 24, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 16, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 6, 5, 5, 6, 6, 5, 5, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 24, 24, 24, 24, 24, 24, 4, 4, 4, 4, 4, 4, 6, 6, 5, 5, 4, 4, 4, 4, 5, 5, 5, 4, 6, 6, 6, 4, 4, 6, 6, 6, 6, 6, 6, 6, 4, 4, 4, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 6, 5, 5, 6, 6, 6, 6, 6, 6, 5, 4, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 29, 29, 29, 29, 28, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 24, 3, 29, 29, 29, /* Page 17, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 29, /* Page 18, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 29, 29, 4, 4, 4, 4, 4, 4, 4, 29, 4, 29, 4, 4, 4, 4, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 29, 29, 4, 4, 4, 4, 4, 4, 4, 29, 4, 29, 4, 4, 4, 4, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 19, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 5, 28, 24, 24, 24, 24, 24, 24, 24, 24, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 20, 0 indirect uses */ 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* * Page 21, 171 indirect uses: * 12000-122FF (astral_index), * 20000-2A5FF (astral_index), * 2F800-2F9FF (astral_index) */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 22, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 24, 24, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 11, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 20, 21, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 24, 24, 24, 9, 9, 9, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 23, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 5, 5, 5, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 24, 24, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 29, 5, 5, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 15, 15, 6, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 24, 24, 24, 3, 24, 24, 24, 26, 4, 5, 29, 29, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 29, 29, 29, 29, 29, 29, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 29, 29, 29, 29, 29, 29, /* Page 24, 0 indirect uses */ 24, 24, 24, 24, 24, 24, 19, 24, 24, 24, 24, 5, 5, 5, 11, 29, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 25, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 5, 5, 5, 6, 6, 6, 6, 5, 5, 6, 6, 6, 29, 29, 29, 29, 6, 6, 5, 6, 6, 6, 6, 6, 6, 5, 5, 5, 29, 29, 29, 29, 28, 29, 29, 29, 24, 24, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 29, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 4, 4, 4, 4, 4, 4, 6, 6, 29, 29, 29, 29, 29, 29, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 29, 29, 29, 29, 24, 24, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, /* Page 26, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 6, 6, 6, 29, 29, 24, 24, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 27, 0 indirect uses */ 5, 5, 5, 5, 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 5, 5, 5, 5, 5, 6, 5, 6, 6, 6, 6, 6, 5, 6, 6, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 24, 24, 24, 24, 24, 24, 24, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 5, 5, 5, 5, 5, 5, 5, 5, 5, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 5, 5, 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 5, 5, 5, 5, 6, 6, 5, 5, 6, 29, 29, 29, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 28, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 5, 5, 29, 29, 29, 24, 24, 24, 24, 24, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 29, 29, 29, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 24, 24, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 29, 0 indirect uses */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 5, 5, /* Page 30, 0 indirect uses */ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, /* Page 31, 0 indirect uses */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 29, 29, 0, 0, 0, 0, 0, 0, 29, 29, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 29, 29, 0, 0, 0, 0, 0, 0, 29, 29, 1, 1, 1, 1, 1, 1, 1, 1, 29, 0, 29, 0, 29, 0, 29, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 29, 29, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 29, 1, 1, 0, 0, 0, 0, 2, 27, 1, 27, 27, 27, 1, 1, 1, 29, 1, 1, 0, 0, 0, 0, 2, 27, 27, 27, 1, 1, 1, 1, 29, 29, 1, 1, 0, 0, 0, 0, 29, 27, 27, 27, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 27, 27, 27, 29, 29, 1, 1, 1, 29, 1, 1, 0, 0, 0, 0, 2, 27, 27, 29, /* Page 32, 0 indirect uses */ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 15, 15, 15, 15, 15, 19, 19, 19, 19, 19, 19, 24, 24, 22, 23, 20, 22, 22, 23, 20, 22, 24, 24, 24, 24, 24, 24, 24, 24, 12, 13, 15, 15, 15, 15, 15, 11, 24, 24, 24, 24, 24, 24, 24, 24, 24, 22, 23, 24, 24, 24, 24, 18, 18, 24, 24, 24, 25, 20, 21, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 24, 18, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 11, 15, 15, 15, 15, 15, 29, 29, 29, 29, 29, 15, 15, 15, 15, 15, 15, 10, 1, 29, 29, 10, 10, 10, 10, 10, 10, 25, 25, 25, 20, 21, 1, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 25, 25, 25, 20, 21, 29, 3, 3, 3, 3, 3, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 5, 7, 7, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 33, 0 indirect uses */ 28, 28, 0, 28, 28, 28, 28, 0, 28, 28, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 28, 0, 28, 28, 28, 0, 0, 0, 0, 0, 28, 28, 28, 28, 28, 28, 0, 28, 0, 28, 0, 28, 0, 0, 0, 0, 28, 1, 0, 0, 0, 0, 1, 4, 4, 4, 4, 1, 28, 28, 1, 1, 0, 0, 25, 25, 25, 25, 25, 0, 1, 1, 1, 1, 28, 25, 28, 28, 1, 28, 29, 29, 29, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 1, 9, 9, 9, 9, 29, 29, 29, 29, 29, 29, 29, 25, 25, 25, 25, 25, 28, 28, 28, 28, 28, 25, 25, 28, 28, 28, 28, 25, 28, 28, 25, 28, 28, 25, 28, 28, 28, 28, 28, 28, 28, 25, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 25, 25, 28, 28, 25, 28, 25, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, /* Page 34, 0 indirect uses */ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, /* Page 35, 0 indirect uses */ 28, 28, 28, 28, 28, 28, 28, 28, 25, 25, 25, 25, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 25, 25, 28, 28, 28, 28, 28, 28, 28, 20, 21, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 25, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 25, 25, 25, 25, 25, 25, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 36, 0 indirect uses */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, /* Page 37, 0 indirect uses */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 25, 28, 28, 28, 28, 28, 28, 28, 28, 28, 25, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 25, 25, 25, 25, 25, 25, 25, 25, /* Page 38, 0 indirect uses */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 25, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 39, 0 indirect uses */ 29, 28, 28, 28, 28, 29, 28, 28, 28, 28, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 28, 29, 28, 28, 28, 28, 29, 29, 29, 28, 29, 28, 28, 28, 28, 28, 28, 28, 29, 29, 28, 28, 28, 28, 28, 28, 28, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 28, 29, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 25, 25, 25, 25, 25, 20, 21, 25, 25, 25, 25, 29, 25, 29, 29, 29, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, /* Page 40, 0 indirect uses */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, /* Page 41, 0 indirect uses */ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 20, 21, 20, 21, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 20, 21, 25, 25, /* Page 42, 0 indirect uses */ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, /* Page 43, 0 indirect uses */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 28, 28, 25, 25, 25, 25, 25, 25, 29, 29, 29, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 44, 0 indirect uses */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 29, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 29, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 3, 29, 29, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 24, 24, 24, 24, 10, 24, 24, /* Page 45, 0 indirect uses */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 3, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 29, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, /* Page 46, 0 indirect uses */ 24, 24, 22, 23, 22, 23, 24, 24, 24, 22, 23, 24, 22, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 19, 24, 24, 19, 24, 22, 23, 24, 24, 22, 23, 20, 21, 20, 21, 20, 21, 20, 21, 24, 24, 24, 24, 24, 3, 24, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 47, 0 indirect uses */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, /* Page 48, 0 indirect uses */ 11, 24, 24, 24, 28, 3, 4, 9, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 28, 28, 20, 21, 20, 21, 20, 21, 20, 21, 19, 20, 21, 21, 28, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 5, 5, 19, 3, 3, 3, 3, 3, 28, 28, 9, 9, 9, 3, 4, 24, 28, 28, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 5, 5, 27, 27, 3, 3, 4, 19, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 24, 3, 3, 3, 4, /* Page 49, 0 indirect uses */ 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 28, 28, 10, 10, 10, 10, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 29, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 50, 0 indirect uses */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, /* Page 51, 0 indirect uses */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, /* Page 52, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 53, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 54, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 55, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 56, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 57, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 58, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 59, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 60, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 61, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 62, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 63, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 64, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 65, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 66, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 67, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 68, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 69, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 70, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 71, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 72, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 73, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 74, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 75, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 76, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 77, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, /* Page 78, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 79, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 80, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 81, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 82, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 83, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 84, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 85, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 86, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 87, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 88, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 89, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 90, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 91, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 92, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 93, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 94, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 95, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 96, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 97, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 98, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 99, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 100, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 101, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 102, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 103, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 104, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 105, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 106, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 107, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 108, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 109, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 110, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 111, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 112, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 113, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 114, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 115, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 116, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 117, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 118, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 119, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 120, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 121, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 122, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 123, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 124, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 125, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 126, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 127, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 128, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 129, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 130, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 131, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 132, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 133, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 134, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 135, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 136, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 137, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 138, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 139, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 140, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 141, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 142, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 143, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 144, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 145, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 146, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 147, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 148, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 149, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 150, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 151, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 152, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 153, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 154, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 155, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 156, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 157, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 158, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 159, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 160, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 161, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 162, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 163, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 164, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 165, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 166, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 24, 24, 24, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 29, 29, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 4, 5, 7, 7, 7, 24, 29, 29, 29, 29, 29, 29, 29, 29, 5, 5, 24, 3, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 167, 0 indirect uses */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 3, 3, 3, 3, 3, 3, 3, 3, 3, 27, 27, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 3, 27, 27, 0, 1, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, /* Page 168, 0 indirect uses */ 4, 4, 5, 4, 4, 4, 5, 4, 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 5, 5, 6, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 24, 24, 24, 24, 29, 29, 29, 29, 29, 29, 29, 29, 6, 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 29, 29, 29, 29, 29, 29, 29, 29, 29, 24, 24, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 169, 0 indirect uses */ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 24, 24, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 24, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 170, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 5, 5, 6, 6, 5, 5, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 29, 29, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 29, 29, 24, 24, 24, 24, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 171, 0 indirect uses */ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 172, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 173, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 174, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 175, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 176, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 177, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 178, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 179, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 180, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 181, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 182, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 183, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 184, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 185, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 186, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 187, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 188, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 189, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 190, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 191, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 192, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 193, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 194, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 195, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 196, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 197, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 198, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 199, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 200, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 201, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 202, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 203, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 204, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 205, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 206, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 207, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 208, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 209, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 210, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 211, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 212, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 213, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 214, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 215, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 216, 0 indirect uses */ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, /* Page 217, 0 indirect uses */ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, /* Page 218, 0 indirect uses */ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, /* Page 219, 0 indirect uses */ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, /* Page 220, 0 indirect uses */ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, /* Page 221, 0 indirect uses */ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, /* Page 222, 0 indirect uses */ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, /* Page 223, 0 indirect uses */ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, /* * Page 224, 510 indirect uses: * F0000-FFEFF (astral_index), * 100000-10FEFF (astral_index) */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 225, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 226, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 227, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 228, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 229, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 230, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 231, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 232, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 233, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 234, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 235, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 236, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 237, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 238, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 239, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 240, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 241, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 242, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 243, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 244, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 245, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 246, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 247, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 248, 0 indirect uses */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* Page 249, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 250, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 251, 0 indirect uses */ 1, 1, 1, 1, 1, 1, 1, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 1, 1, 1, 1, 1, 29, 29, 29, 29, 29, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 25, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 29, 4, 29, 4, 4, 29, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 252, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* Page 253, 0 indirect uses */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 20, 21, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 26, 28, 29, 29, /* Page 254, 0 indirect uses */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 24, 24, 24, 24, 24, 24, 24, 20, 21, 24, 29, 29, 29, 29, 29, 29, 5, 5, 5, 5, 5, 5, 5, 29, 29, 29, 29, 29, 29, 29, 29, 29, 24, 19, 19, 18, 18, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 20, 21, 24, 24, 20, 21, 24, 24, 24, 24, 18, 18, 18, 24, 24, 24, 29, 24, 24, 24, 24, 19, 20, 21, 20, 21, 20, 21, 24, 24, 24, 25, 19, 25, 25, 25, 29, 24, 26, 24, 24, 29, 29, 29, 29, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 15, /* Page 255, 0 indirect uses */ 29, 24, 24, 24, 26, 24, 24, 24, 20, 21, 24, 25, 24, 19, 24, 24, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 24, 24, 25, 25, 25, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 24, 21, 27, 18, 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 25, 21, 25, 20, 21, 24, 20, 21, 24, 24, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 4, 4, 4, 4, 4, 4, 29, 29, 4, 4, 4, 4, 4, 4, 29, 29, 4, 4, 4, 4, 4, 4, 29, 29, 4, 4, 4, 29, 29, 29, 26, 26, 25, 27, 28, 26, 26, 29, 28, 25, 25, 25, 25, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 15, 15, 15, 28, 28, 29, 29, /* Page 256, 1 indirect use: 10000-100FF (astral_index) */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, /* Page 257, 1 indirect use: 10100-101FF (astral_index) */ 24, 24, 28, 29, 29, 29, 29, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 29, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 10, 29, 29, 29, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 5, 29, 29, /* Page 258, 1 indirect use: 10200-102FF (astral_index) */ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 259, 1 indirect use: 10300-103FF (astral_index) */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 10, 10, 10, 10, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 4, 4, 4, 4, 4, 4, 4, 4, 9, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 24, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 4, 4, 4, 4, 4, 4, 4, 4, 24, 9, 9, 9, 9, 9, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 260, 1 indirect use: 10400-104FF (astral_index) */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 261, 1 indirect use: 10800-108FF (astral_index) */ 4, 4, 4, 4, 4, 4, 29, 29, 4, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 4, 4, 29, 29, 29, 4, 29, 29, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 262, 1 indirect use: 10900-109FF (astral_index) */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 10, 10, 10, 10, 29, 29, 29, 29, 29, 24, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 24, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 263, 1 indirect use: 10A00-10AFF (astral_index) */ 4, 5, 5, 5, 29, 5, 5, 29, 29, 29, 29, 29, 5, 5, 5, 5, 4, 4, 4, 4, 29, 4, 4, 4, 29, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 5, 5, 5, 29, 29, 29, 29, 5, 10, 10, 10, 10, 10, 10, 10, 10, 29, 29, 29, 29, 29, 29, 29, 29, 24, 24, 24, 24, 24, 24, 24, 24, 24, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 264, 1 indirect use: 12300-123FF (astral_index) */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 265, 1 indirect use: 12400-124FF (astral_index) */ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 24, 24, 24, 24, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 266, 1 indirect use: 1D000-1D0FF (astral_index) */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 267, 1 indirect use: 1D100-1D1FF (astral_index) */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 6, 6, 5, 5, 5, 28, 28, 28, 6, 6, 6, 6, 6, 6, 15, 15, 15, 15, 15, 15, 15, 15, 5, 5, 5, 5, 5, 5, 5, 5, 28, 28, 5, 5, 5, 5, 5, 5, 5, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 5, 5, 5, 5, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 268, 1 indirect use: 1D200-1D2FF (astral_index) */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 5, 5, 5, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 269, 1 indirect use: 1D300-1D3FF (astral_index) */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 270, 1 indirect use: 1D400-1D4FF (astral_index) */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 29, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 29, 0, 0, 29, 29, 0, 29, 29, 0, 0, 29, 29, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 29, 1, 29, 1, 1, 1, 1, 1, 1, 1, 29, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* Page 271, 1 indirect use: 1D500-1D5FF (astral_index) */ 1, 1, 1, 1, 0, 0, 29, 0, 0, 0, 0, 29, 29, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 29, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 29, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0, 29, 0, 29, 29, 29, 0, 0, 0, 0, 0, 0, 0, 29, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* Page 272, 1 indirect use: 1D600-1D6FF (astral_index) */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 29, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 25, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 1, 1, 1, 1, /* Page 273, 1 indirect use: 1D700-1D7FF (astral_index) */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 25, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 25, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 25, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 25, 1, 1, 1, 1, 1, 1, 0, 1, 29, 29, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* Page 274, 1 indirect use: 1F000-1F0FF (astral_index) */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 275, 1 indirect use: 2A600-2A6FF (astral_index) */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 276, 1 indirect use: 2FA00-2FAFF (astral_index) */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 277, 1 indirect use: E0000-E00FF (astral_index) */ 29, 15, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* Page 278, 1 indirect use: E0100-E01FF (astral_index) */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, /* * Page 279, 2 indirect uses: * FFF00-FFFFF (astral_index), * 10FF00-10FFFF (astral_index) */ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 29, 29 }; const uint8_t NumericData[] = { 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 2, 3, 57, 57, 57, 57, 57, 1, 57, 57, 44, 33, 45, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 57, 57, 57, 57, 1, 2, 3, 4, 57, 16, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 28, 30, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 33, 34, 35, 36, 37, 38, 39, 40, 41, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 21, 22, 23, 24, 25, 26, 27, 28, 32, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 17, 18, 19, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 0, 57, 57, 57, 4, 5, 6, 7, 8, 9, 57, 57, 57, 57, 57, 57, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 42, 43, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 28, 29, 30, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 28, 29, 30, 30, 31, 32, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 0, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 0, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 1, 2, 3, 4, 5, 6, 7, 8, 9, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 10, 20, 21, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 1, 2, 3, 4, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; const double NumericDataValues[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 40, 50, 60, 70, 80, 90, 100, 500, 1000, 5000, 10000, 1 / 2, 3 / 2, 5 / 2, 7 / 2, 9 / 2, 11 / 2, 13 / 2, 15 / 2, 17 / 2, 1 / 3, 2 / 3, 1 / 4, 3 / 4, 1 / 5, 2 / 5, 3 / 5, 4 / 5, 1 / 6, 5 / 6, 1 / 8, 3 / 8, 5 / 8, 7 / 8, -1 / 2, -1 }; const Il2CppChar ToLowerDataLow[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 215, 248, 249, 250, 251, 252, 253, 254, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 257, 257, 259, 259, 261, 261, 263, 263, 265, 265, 267, 267, 269, 269, 271, 271, 273, 273, 275, 275, 277, 277, 279, 279, 281, 281, 283, 283, 285, 285, 287, 287, 289, 289, 291, 291, 293, 293, 295, 295, 297, 297, 299, 299, 301, 301, 303, 303, 304, 305, 307, 307, 309, 309, 311, 311, 312, 314, 314, 316, 316, 318, 318, 320, 320, 322, 322, 324, 324, 326, 326, 328, 328, 329, 331, 331, 333, 333, 335, 335, 337, 337, 339, 339, 341, 341, 343, 343, 345, 345, 347, 347, 349, 349, 351, 351, 353, 353, 355, 355, 357, 357, 359, 359, 361, 361, 363, 363, 365, 365, 367, 367, 369, 369, 371, 371, 373, 373, 375, 375, 255, 378, 378, 380, 380, 382, 382, 383, 384, 595, 387, 387, 389, 389, 596, 392, 392, 598, 599, 396, 396, 397, 477, 601, 603, 402, 402, 608, 611, 405, 617, 616, 409, 409, 410, 411, 623, 626, 414, 629, 417, 417, 419, 419, 421, 421, 422, 424, 424, 643, 426, 427, 429, 429, 648, 432, 432, 650, 651, 436, 436, 438, 438, 658, 441, 441, 442, 443, 445, 445, 446, 447, 448, 449, 450, 451, 454, 453, 454, 457, 456, 457, 460, 459, 460, 462, 462, 464, 464, 466, 466, 468, 468, 470, 470, 472, 472, 474, 474, 476, 476, 477, 479, 479, 481, 481, 483, 483, 485, 485, 487, 487, 489, 489, 491, 491, 493, 493, 495, 495, 496, 499, 498, 499, 501, 501, 502, 503, 504, 505, 507, 507, 509, 509, 511, 511, 513, 513, 515, 515, 517, 517, 519, 519, 521, 521, 523, 523, 525, 525, 527, 527, 529, 529, 531, 531, 533, 533, 535, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 940, 903, 941, 942, 943, 907, 972, 909, 973, 974, 912, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 930, 963, 964, 965, 966, 967, 968, 969, 970, 971, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 995, 995, 997, 997, 999, 999, 1001, 1001, 1003, 1003, 1005, 1005, 1007, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1037, 1118, 1119, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1121, 1121, 1123, 1123, 1125, 1125, 1127, 1127, 1129, 1129, 1131, 1131, 1133, 1133, 1135, 1135, 1137, 1137, 1139, 1139, 1141, 1141, 1143, 1143, 1145, 1145, 1147, 1147, 1149, 1149, 1151, 1151, 1153, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161, 1162, 1163, 1164, 1165, 1166, 1167, 1169, 1169, 1171, 1171, 1173, 1173, 1175, 1175, 1177, 1177, 1179, 1179, 1181, 1181, 1183, 1183, 1185, 1185, 1187, 1187, 1189, 1189, 1191, 1191, 1193, 1193, 1195, 1195, 1197, 1197, 1199, 1199, 1201, 1201, 1203, 1203, 1205, 1205, 1207, 1207, 1209, 1209, 1211, 1211, 1213, 1213, 1215, 1215, 1216, 1218, 1218, 1220, 1220, 1221, 1222, 1224, 1224, 1225, 1226, 1228, 1228, 1229, 1230, 1231, 1233, 1233, 1235, 1235, 1237, 1237, 1239, 1239, 1241, 1241, 1243, 1243, 1245, 1245, 1247, 1247, 1249, 1249, 1251, 1251, 1253, 1253, 1255, 1255, 1257, 1257, 1259, 1259, 1260, 1261, 1263, 1263, 1265, 1265, 1267, 1267, 1269, 1269, 1270, 1271, 1273, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1322, 1323, 1324, 1325, 1326, 1327, 1328, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1367, 1368, 1369, 1370, 1371, 1372, 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415, 1416, 1417, 1418, 1419, 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437, 1438, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, 1447, 1448, 1449, 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481, 1482, 1483, 1484, 1485, 1486, 1487, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529, 1530, 1531, 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562, 1563, 1564, 1565, 1566, 1567, 1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1596, 1597, 1598, 1599, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, 1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686, 1687, 1688, 1689, 1690, 1691, 1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1700, 1701, 1702, 1703, 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721, 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, 1732, 1733, 1734, 1735, 1736, 1737, 1738, 1739, 1740, 1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765, 1766, 1767, 1768, 1769, 1770, 1771, 1772, 1773, 1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, 1782, 1783, 1784, 1785, 1786, 1787, 1788, 1789, 1790, 1791, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800, 1801, 1802, 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819, 1820, 1821, 1822, 1823, 1824, 1825, 1826, 1827, 1828, 1829, 1830, 1831, 1832, 1833, 1834, 1835, 1836, 1837, 1838, 1839, 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, 1851, 1852, 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866, 1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, 1897, 1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, 1938, 1939, 1940, 1941, 1942, 1943, 1944, 1945, 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, 2030, 2031, 2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, 2137, 2138, 2139, 2140, 2141, 2142, 2143, 2144, 2145, 2146, 2147, 2148, 2149, 2150, 2151, 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165, 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176, 2177, 2178, 2179, 2180, 2181, 2182, 2183, 2184, 2185, 2186, 2187, 2188, 2189, 2190, 2191, 2192, 2193, 2194, 2195, 2196, 2197, 2198, 2199, 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211, 2212, 2213, 2214, 2215, 2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224, 2225, 2226, 2227, 2228, 2229, 2230, 2231, 2232, 2233, 2234, 2235, 2236, 2237, 2238, 2239, 2240, 2241, 2242, 2243, 2244, 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, 2256, 2257, 2258, 2259, 2260, 2261, 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270, 2271, 2272, 2273, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2282, 2283, 2284, 2285, 2286, 2287, 2288, 2289, 2290, 2291, 2292, 2293, 2294, 2295, 2296, 2297, 2298, 2299, 2300, 2301, 2302, 2303, 2304, 2305, 2306, 2307, 2308, 2309, 2310, 2311, 2312, 2313, 2314, 2315, 2316, 2317, 2318, 2319, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2328, 2329, 2330, 2331, 2332, 2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340, 2341, 2342, 2343, 2344, 2345, 2346, 2347, 2348, 2349, 2350, 2351, 2352, 2353, 2354, 2355, 2356, 2357, 2358, 2359, 2360, 2361, 2362, 2363, 2364, 2365, 2366, 2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376, 2377, 2378, 2379, 2380, 2381, 2382, 2383, 2384, 2385, 2386, 2387, 2388, 2389, 2390, 2391, 2392, 2393, 2394, 2395, 2396, 2397, 2398, 2399, 2400, 2401, 2402, 2403, 2404, 2405, 2406, 2407, 2408, 2409, 2410, 2411, 2412, 2413, 2414, 2415, 2416, 2417, 2418, 2419, 2420, 2421, 2422, 2423, 2424, 2425, 2426, 2427, 2428, 2429, 2430, 2431, 2432, 2433, 2434, 2435, 2436, 2437, 2438, 2439, 2440, 2441, 2442, 2443, 2444, 2445, 2446, 2447, 2448, 2449, 2450, 2451, 2452, 2453, 2454, 2455, 2456, 2457, 2458, 2459, 2460, 2461, 2462, 2463, 2464, 2465, 2466, 2467, 2468, 2469, 2470, 2471, 2472, 2473, 2474, 2475, 2476, 2477, 2478, 2479, 2480, 2481, 2482, 2483, 2484, 2485, 2486, 2487, 2488, 2489, 2490, 2491, 2492, 2493, 2494, 2495, 2496, 2497, 2498, 2499, 2500, 2501, 2502, 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511, 2512, 2513, 2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, 2524, 2525, 2526, 2527, 2528, 2529, 2530, 2531, 2532, 2533, 2534, 2535, 2536, 2537, 2538, 2539, 2540, 2541, 2542, 2543, 2544, 2545, 2546, 2547, 2548, 2549, 2550, 2551, 2552, 2553, 2554, 2555, 2556, 2557, 2558, 2559, 2560, 2561, 2562, 2563, 2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, 2572, 2573, 2574, 2575, 2576, 2577, 2578, 2579, 2580, 2581, 2582, 2583, 2584, 2585, 2586, 2587, 2588, 2589, 2590, 2591, 2592, 2593, 2594, 2595, 2596, 2597, 2598, 2599, 2600, 2601, 2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611, 2612, 2613, 2614, 2615, 2616, 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626, 2627, 2628, 2629, 2630, 2631, 2632, 2633, 2634, 2635, 2636, 2637, 2638, 2639, 2640, 2641, 2642, 2643, 2644, 2645, 2646, 2647, 2648, 2649, 2650, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661, 2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676, 2677, 2678, 2679, 2680, 2681, 2682, 2683, 2684, 2685, 2686, 2687, 2688, 2689, 2690, 2691, 2692, 2693, 2694, 2695, 2696, 2697, 2698, 2699, 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, 2710, 2711, 2712, 2713, 2714, 2715, 2716, 2717, 2718, 2719, 2720, 2721, 2722, 2723, 2724, 2725, 2726, 2727, 2728, 2729, 2730, 2731, 2732, 2733, 2734, 2735, 2736, 2737, 2738, 2739, 2740, 2741, 2742, 2743, 2744, 2745, 2746, 2747, 2748, 2749, 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2760, 2761, 2762, 2763, 2764, 2765, 2766, 2767, 2768, 2769, 2770, 2771, 2772, 2773, 2774, 2775, 2776, 2777, 2778, 2779, 2780, 2781, 2782, 2783, 2784, 2785, 2786, 2787, 2788, 2789, 2790, 2791, 2792, 2793, 2794, 2795, 2796, 2797, 2798, 2799, 2800, 2801, 2802, 2803, 2804, 2805, 2806, 2807, 2808, 2809, 2810, 2811, 2812, 2813, 2814, 2815, 2816, 2817, 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825, 2826, 2827, 2828, 2829, 2830, 2831, 2832, 2833, 2834, 2835, 2836, 2837, 2838, 2839, 2840, 2841, 2842, 2843, 2844, 2845, 2846, 2847, 2848, 2849, 2850, 2851, 2852, 2853, 2854, 2855, 2856, 2857, 2858, 2859, 2860, 2861, 2862, 2863, 2864, 2865, 2866, 2867, 2868, 2869, 2870, 2871, 2872, 2873, 2874, 2875, 2876, 2877, 2878, 2879, 2880, 2881, 2882, 2883, 2884, 2885, 2886, 2887, 2888, 2889, 2890, 2891, 2892, 2893, 2894, 2895, 2896, 2897, 2898, 2899, 2900, 2901, 2902, 2903, 2904, 2905, 2906, 2907, 2908, 2909, 2910, 2911, 2912, 2913, 2914, 2915, 2916, 2917, 2918, 2919, 2920, 2921, 2922, 2923, 2924, 2925, 2926, 2927, 2928, 2929, 2930, 2931, 2932, 2933, 2934, 2935, 2936, 2937, 2938, 2939, 2940, 2941, 2942, 2943, 2944, 2945, 2946, 2947, 2948, 2949, 2950, 2951, 2952, 2953, 2954, 2955, 2956, 2957, 2958, 2959, 2960, 2961, 2962, 2963, 2964, 2965, 2966, 2967, 2968, 2969, 2970, 2971, 2972, 2973, 2974, 2975, 2976, 2977, 2978, 2979, 2980, 2981, 2982, 2983, 2984, 2985, 2986, 2987, 2988, 2989, 2990, 2991, 2992, 2993, 2994, 2995, 2996, 2997, 2998, 2999, 3000, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019, 3020, 3021, 3022, 3023, 3024, 3025, 3026, 3027, 3028, 3029, 3030, 3031, 3032, 3033, 3034, 3035, 3036, 3037, 3038, 3039, 3040, 3041, 3042, 3043, 3044, 3045, 3046, 3047, 3048, 3049, 3050, 3051, 3052, 3053, 3054, 3055, 3056, 3057, 3058, 3059, 3060, 3061, 3062, 3063, 3064, 3065, 3066, 3067, 3068, 3069, 3070, 3071, 3072, 3073, 3074, 3075, 3076, 3077, 3078, 3079, 3080, 3081, 3082, 3083, 3084, 3085, 3086, 3087, 3088, 3089, 3090, 3091, 3092, 3093, 3094, 3095, 3096, 3097, 3098, 3099, 3100, 3101, 3102, 3103, 3104, 3105, 3106, 3107, 3108, 3109, 3110, 3111, 3112, 3113, 3114, 3115, 3116, 3117, 3118, 3119, 3120, 3121, 3122, 3123, 3124, 3125, 3126, 3127, 3128, 3129, 3130, 3131, 3132, 3133, 3134, 3135, 3136, 3137, 3138, 3139, 3140, 3141, 3142, 3143, 3144, 3145, 3146, 3147, 3148, 3149, 3150, 3151, 3152, 3153, 3154, 3155, 3156, 3157, 3158, 3159, 3160, 3161, 3162, 3163, 3164, 3165, 3166, 3167, 3168, 3169, 3170, 3171, 3172, 3173, 3174, 3175, 3176, 3177, 3178, 3179, 3180, 3181, 3182, 3183, 3184, 3185, 3186, 3187, 3188, 3189, 3190, 3191, 3192, 3193, 3194, 3195, 3196, 3197, 3198, 3199, 3200, 3201, 3202, 3203, 3204, 3205, 3206, 3207, 3208, 3209, 3210, 3211, 3212, 3213, 3214, 3215, 3216, 3217, 3218, 3219, 3220, 3221, 3222, 3223, 3224, 3225, 3226, 3227, 3228, 3229, 3230, 3231, 3232, 3233, 3234, 3235, 3236, 3237, 3238, 3239, 3240, 3241, 3242, 3243, 3244, 3245, 3246, 3247, 3248, 3249, 3250, 3251, 3252, 3253, 3254, 3255, 3256, 3257, 3258, 3259, 3260, 3261, 3262, 3263, 3264, 3265, 3266, 3267, 3268, 3269, 3270, 3271, 3272, 3273, 3274, 3275, 3276, 3277, 3278, 3279, 3280, 3281, 3282, 3283, 3284, 3285, 3286, 3287, 3288, 3289, 3290, 3291, 3292, 3293, 3294, 3295, 3296, 3297, 3298, 3299, 3300, 3301, 3302, 3303, 3304, 3305, 3306, 3307, 3308, 3309, 3310, 3311, 3312, 3313, 3314, 3315, 3316, 3317, 3318, 3319, 3320, 3321, 3322, 3323, 3324, 3325, 3326, 3327, 3328, 3329, 3330, 3331, 3332, 3333, 3334, 3335, 3336, 3337, 3338, 3339, 3340, 3341, 3342, 3343, 3344, 3345, 3346, 3347, 3348, 3349, 3350, 3351, 3352, 3353, 3354, 3355, 3356, 3357, 3358, 3359, 3360, 3361, 3362, 3363, 3364, 3365, 3366, 3367, 3368, 3369, 3370, 3371, 3372, 3373, 3374, 3375, 3376, 3377, 3378, 3379, 3380, 3381, 3382, 3383, 3384, 3385, 3386, 3387, 3388, 3389, 3390, 3391, 3392, 3393, 3394, 3395, 3396, 3397, 3398, 3399, 3400, 3401, 3402, 3403, 3404, 3405, 3406, 3407, 3408, 3409, 3410, 3411, 3412, 3413, 3414, 3415, 3416, 3417, 3418, 3419, 3420, 3421, 3422, 3423, 3424, 3425, 3426, 3427, 3428, 3429, 3430, 3431, 3432, 3433, 3434, 3435, 3436, 3437, 3438, 3439, 3440, 3441, 3442, 3443, 3444, 3445, 3446, 3447, 3448, 3449, 3450, 3451, 3452, 3453, 3454, 3455, 3456, 3457, 3458, 3459, 3460, 3461, 3462, 3463, 3464, 3465, 3466, 3467, 3468, 3469, 3470, 3471, 3472, 3473, 3474, 3475, 3476, 3477, 3478, 3479, 3480, 3481, 3482, 3483, 3484, 3485, 3486, 3487, 3488, 3489, 3490, 3491, 3492, 3493, 3494, 3495, 3496, 3497, 3498, 3499, 3500, 3501, 3502, 3503, 3504, 3505, 3506, 3507, 3508, 3509, 3510, 3511, 3512, 3513, 3514, 3515, 3516, 3517, 3518, 3519, 3520, 3521, 3522, 3523, 3524, 3525, 3526, 3527, 3528, 3529, 3530, 3531, 3532, 3533, 3534, 3535, 3536, 3537, 3538, 3539, 3540, 3541, 3542, 3543, 3544, 3545, 3546, 3547, 3548, 3549, 3550, 3551, 3552, 3553, 3554, 3555, 3556, 3557, 3558, 3559, 3560, 3561, 3562, 3563, 3564, 3565, 3566, 3567, 3568, 3569, 3570, 3571, 3572, 3573, 3574, 3575, 3576, 3577, 3578, 3579, 3580, 3581, 3582, 3583, 3584, 3585, 3586, 3587, 3588, 3589, 3590, 3591, 3592, 3593, 3594, 3595, 3596, 3597, 3598, 3599, 3600, 3601, 3602, 3603, 3604, 3605, 3606, 3607, 3608, 3609, 3610, 3611, 3612, 3613, 3614, 3615, 3616, 3617, 3618, 3619, 3620, 3621, 3622, 3623, 3624, 3625, 3626, 3627, 3628, 3629, 3630, 3631, 3632, 3633, 3634, 3635, 3636, 3637, 3638, 3639, 3640, 3641, 3642, 3643, 3644, 3645, 3646, 3647, 3648, 3649, 3650, 3651, 3652, 3653, 3654, 3655, 3656, 3657, 3658, 3659, 3660, 3661, 3662, 3663, 3664, 3665, 3666, 3667, 3668, 3669, 3670, 3671, 3672, 3673, 3674, 3675, 3676, 3677, 3678, 3679, 3680, 3681, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 3696, 3697, 3698, 3699, 3700, 3701, 3702, 3703, 3704, 3705, 3706, 3707, 3708, 3709, 3710, 3711, 3712, 3713, 3714, 3715, 3716, 3717, 3718, 3719, 3720, 3721, 3722, 3723, 3724, 3725, 3726, 3727, 3728, 3729, 3730, 3731, 3732, 3733, 3734, 3735, 3736, 3737, 3738, 3739, 3740, 3741, 3742, 3743, 3744, 3745, 3746, 3747, 3748, 3749, 3750, 3751, 3752, 3753, 3754, 3755, 3756, 3757, 3758, 3759, 3760, 3761, 3762, 3763, 3764, 3765, 3766, 3767, 3768, 3769, 3770, 3771, 3772, 3773, 3774, 3775, 3776, 3777, 3778, 3779, 3780, 3781, 3782, 3783, 3784, 3785, 3786, 3787, 3788, 3789, 3790, 3791, 3792, 3793, 3794, 3795, 3796, 3797, 3798, 3799, 3800, 3801, 3802, 3803, 3804, 3805, 3806, 3807, 3808, 3809, 3810, 3811, 3812, 3813, 3814, 3815, 3816, 3817, 3818, 3819, 3820, 3821, 3822, 3823, 3824, 3825, 3826, 3827, 3828, 3829, 3830, 3831, 3832, 3833, 3834, 3835, 3836, 3837, 3838, 3839, 3840, 3841, 3842, 3843, 3844, 3845, 3846, 3847, 3848, 3849, 3850, 3851, 3852, 3853, 3854, 3855, 3856, 3857, 3858, 3859, 3860, 3861, 3862, 3863, 3864, 3865, 3866, 3867, 3868, 3869, 3870, 3871, 3872, 3873, 3874, 3875, 3876, 3877, 3878, 3879, 3880, 3881, 3882, 3883, 3884, 3885, 3886, 3887, 3888, 3889, 3890, 3891, 3892, 3893, 3894, 3895, 3896, 3897, 3898, 3899, 3900, 3901, 3902, 3903, 3904, 3905, 3906, 3907, 3908, 3909, 3910, 3911, 3912, 3913, 3914, 3915, 3916, 3917, 3918, 3919, 3920, 3921, 3922, 3923, 3924, 3925, 3926, 3927, 3928, 3929, 3930, 3931, 3932, 3933, 3934, 3935, 3936, 3937, 3938, 3939, 3940, 3941, 3942, 3943, 3944, 3945, 3946, 3947, 3948, 3949, 3950, 3951, 3952, 3953, 3954, 3955, 3956, 3957, 3958, 3959, 3960, 3961, 3962, 3963, 3964, 3965, 3966, 3967, 3968, 3969, 3970, 3971, 3972, 3973, 3974, 3975, 3976, 3977, 3978, 3979, 3980, 3981, 3982, 3983, 3984, 3985, 3986, 3987, 3988, 3989, 3990, 3991, 3992, 3993, 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4035, 4036, 4037, 4038, 4039, 4040, 4041, 4042, 4043, 4044, 4045, 4046, 4047, 4048, 4049, 4050, 4051, 4052, 4053, 4054, 4055, 4056, 4057, 4058, 4059, 4060, 4061, 4062, 4063, 4064, 4065, 4066, 4067, 4068, 4069, 4070, 4071, 4072, 4073, 4074, 4075, 4076, 4077, 4078, 4079, 4080, 4081, 4082, 4083, 4084, 4085, 4086, 4087, 4088, 4089, 4090, 4091, 4092, 4093, 4094, 4095, 4096, 4097, 4098, 4099, 4100, 4101, 4102, 4103, 4104, 4105, 4106, 4107, 4108, 4109, 4110, 4111, 4112, 4113, 4114, 4115, 4116, 4117, 4118, 4119, 4120, 4121, 4122, 4123, 4124, 4125, 4126, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4140, 4141, 4142, 4143, 4144, 4145, 4146, 4147, 4148, 4149, 4150, 4151, 4152, 4153, 4154, 4155, 4156, 4157, 4158, 4159, 4160, 4161, 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4172, 4173, 4174, 4175, 4176, 4177, 4178, 4179, 4180, 4181, 4182, 4183, 4184, 4185, 4186, 4187, 4188, 4189, 4190, 4191, 4192, 4193, 4194, 4195, 4196, 4197, 4198, 4199, 4200, 4201, 4202, 4203, 4204, 4205, 4206, 4207, 4208, 4209, 4210, 4211, 4212, 4213, 4214, 4215, 4216, 4217, 4218, 4219, 4220, 4221, 4222, 4223, 4224, 4225, 4226, 4227, 4228, 4229, 4230, 4231, 4232, 4233, 4234, 4235, 4236, 4237, 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4245, 4246, 4247, 4248, 4249, 4250, 4251, 4252, 4253, 4254, 4255, 4304, 4305, 4306, 4307, 4308, 4309, 4310, 4311, 4312, 4313, 4314, 4315, 4316, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325, 4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339, 4340, 4341, 4294, 4295, 4296, 4297, 4298, 4299, 4300, 4301, 4302, 4303, 4304, 4305, 4306, 4307, 4308, 4309, 4310, 4311, 4312, 4313, 4314, 4315, 4316, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325, 4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339, 4340, 4341, 4342, 4343, 4344, 4345, 4346, 4347, 4348, 4349, 4350, 4351, 4352, 4353, 4354, 4355, 4356, 4357, 4358, 4359, 4360, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, 4371, 4372, 4373, 4374, 4375, 4376, 4377, 4378, 4379, 4380, 4381, 4382, 4383, 4384, 4385, 4386, 4387, 4388, 4389, 4390, 4391, 4392, 4393, 4394, 4395, 4396, 4397, 4398, 4399, 4400, 4401, 4402, 4403, 4404, 4405, 4406, 4407, 4408, 4409, 4410, 4411, 4412, 4413, 4414, 4415, 4416, 4417, 4418, 4419, 4420, 4421, 4422, 4423, 4424, 4425, 4426, 4427, 4428, 4429, 4430, 4431, 4432, 4433, 4434, 4435, 4436, 4437, 4438, 4439, 4440, 4441, 4442, 4443, 4444, 4445, 4446, 4447, 4448, 4449, 4450, 4451, 4452, 4453, 4454, 4455, 4456, 4457, 4458, 4459, 4460, 4461, 4462, 4463, 4464, 4465, 4466, 4467, 4468, 4469, 4470, 4471, 4472, 4473, 4474, 4475, 4476, 4477, 4478, 4479, 4480, 4481, 4482, 4483, 4484, 4485, 4486, 4487, 4488, 4489, 4490, 4491, 4492, 4493, 4494, 4495, 4496, 4497, 4498, 4499, 4500, 4501, 4502, 4503, 4504, 4505, 4506, 4507, 4508, 4509, 4510, 4511, 4512, 4513, 4514, 4515, 4516, 4517, 4518, 4519, 4520, 4521, 4522, 4523, 4524, 4525, 4526, 4527, 4528, 4529, 4530, 4531, 4532, 4533, 4534, 4535, 4536, 4537, 4538, 4539, 4540, 4541, 4542, 4543, 4544, 4545, 4546, 4547, 4548, 4549, 4550, 4551, 4552, 4553, 4554, 4555, 4556, 4557, 4558, 4559, 4560, 4561, 4562, 4563, 4564, 4565, 4566, 4567, 4568, 4569, 4570, 4571, 4572, 4573, 4574, 4575, 4576, 4577, 4578, 4579, 4580, 4581, 4582, 4583, 4584, 4585, 4586, 4587, 4588, 4589, 4590, 4591, 4592, 4593, 4594, 4595, 4596, 4597, 4598, 4599, 4600, 4601, 4602, 4603, 4604, 4605, 4606, 4607, 4608, 4609, 4610, 4611, 4612, 4613, 4614, 4615, 4616, 4617, 4618, 4619, 4620, 4621, 4622, 4623, 4624, 4625, 4626, 4627, 4628, 4629, 4630, 4631, 4632, 4633, 4634, 4635, 4636, 4637, 4638, 4639, 4640, 4641, 4642, 4643, 4644, 4645, 4646, 4647, 4648, 4649, 4650, 4651, 4652, 4653, 4654, 4655, 4656, 4657, 4658, 4659, 4660, 4661, 4662, 4663, 4664, 4665, 4666, 4667, 4668, 4669, 4670, 4671, 4672, 4673, 4674, 4675, 4676, 4677, 4678, 4679, 4680, 4681, 4682, 4683, 4684, 4685, 4686, 4687, 4688, 4689, 4690, 4691, 4692, 4693, 4694, 4695, 4696, 4697, 4698, 4699, 4700, 4701, 4702, 4703, 4704, 4705, 4706, 4707, 4708, 4709, 4710, 4711, 4712, 4713, 4714, 4715, 4716, 4717, 4718, 4719, 4720, 4721, 4722, 4723, 4724, 4725, 4726, 4727, 4728, 4729, 4730, 4731, 4732, 4733, 4734, 4735, 4736, 4737, 4738, 4739, 4740, 4741, 4742, 4743, 4744, 4745, 4746, 4747, 4748, 4749, 4750, 4751, 4752, 4753, 4754, 4755, 4756, 4757, 4758, 4759, 4760, 4761, 4762, 4763, 4764, 4765, 4766, 4767, 4768, 4769, 4770, 4771, 4772, 4773, 4774, 4775, 4776, 4777, 4778, 4779, 4780, 4781, 4782, 4783, 4784, 4785, 4786, 4787, 4788, 4789, 4790, 4791, 4792, 4793, 4794, 4795, 4796, 4797, 4798, 4799, 4800, 4801, 4802, 4803, 4804, 4805, 4806, 4807, 4808, 4809, 4810, 4811, 4812, 4813, 4814, 4815, 4816, 4817, 4818, 4819, 4820, 4821, 4822, 4823, 4824, 4825, 4826, 4827, 4828, 4829, 4830, 4831, 4832, 4833, 4834, 4835, 4836, 4837, 4838, 4839, 4840, 4841, 4842, 4843, 4844, 4845, 4846, 4847, 4848, 4849, 4850, 4851, 4852, 4853, 4854, 4855, 4856, 4857, 4858, 4859, 4860, 4861, 4862, 4863, 4864, 4865, 4866, 4867, 4868, 4869, 4870, 4871, 4872, 4873, 4874, 4875, 4876, 4877, 4878, 4879, 4880, 4881, 4882, 4883, 4884, 4885, 4886, 4887, 4888, 4889, 4890, 4891, 4892, 4893, 4894, 4895, 4896, 4897, 4898, 4899, 4900, 4901, 4902, 4903, 4904, 4905, 4906, 4907, 4908, 4909, 4910, 4911, 4912, 4913, 4914, 4915, 4916, 4917, 4918, 4919, 4920, 4921, 4922, 4923, 4924, 4925, 4926, 4927, 4928, 4929, 4930, 4931, 4932, 4933, 4934, 4935, 4936, 4937, 4938, 4939, 4940, 4941, 4942, 4943, 4944, 4945, 4946, 4947, 4948, 4949, 4950, 4951, 4952, 4953, 4954, 4955, 4956, 4957, 4958, 4959, 4960, 4961, 4962, 4963, 4964, 4965, 4966, 4967, 4968, 4969, 4970, 4971, 4972, 4973, 4974, 4975, 4976, 4977, 4978, 4979, 4980, 4981, 4982, 4983, 4984, 4985, 4986, 4987, 4988, 4989, 4990, 4991, 4992, 4993, 4994, 4995, 4996, 4997, 4998, 4999, 5000, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012, 5013, 5014, 5015, 5016, 5017, 5018, 5019, 5020, 5021, 5022, 5023, 5024, 5025, 5026, 5027, 5028, 5029, 5030, 5031, 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042, 5043, 5044, 5045, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055, 5056, 5057, 5058, 5059, 5060, 5061, 5062, 5063, 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 5072, 5073, 5074, 5075, 5076, 5077, 5078, 5079, 5080, 5081, 5082, 5083, 5084, 5085, 5086, 5087, 5088, 5089, 5090, 5091, 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, 5100, 5101, 5102, 5103, 5104, 5105, 5106, 5107, 5108, 5109, 5110, 5111, 5112, 5113, 5114, 5115, 5116, 5117, 5118, 5119, 5120, 5121, 5122, 5123, 5124, 5125, 5126, 5127, 5128, 5129, 5130, 5131, 5132, 5133, 5134, 5135, 5136, 5137, 5138, 5139, 5140, 5141, 5142, 5143, 5144, 5145, 5146, 5147, 5148, 5149, 5150, 5151, 5152, 5153, 5154, 5155, 5156, 5157, 5158, 5159, 5160, 5161, 5162, 5163, 5164, 5165, 5166, 5167, 5168, 5169, 5170, 5171, 5172, 5173, 5174, 5175, 5176, 5177, 5178, 5179, 5180, 5181, 5182, 5183, 5184, 5185, 5186, 5187, 5188, 5189, 5190, 5191, 5192, 5193, 5194, 5195, 5196, 5197, 5198, 5199, 5200, 5201, 5202, 5203, 5204, 5205, 5206, 5207, 5208, 5209, 5210, 5211, 5212, 5213, 5214, 5215, 5216, 5217, 5218, 5219, 5220, 5221, 5222, 5223, 5224, 5225, 5226, 5227, 5228, 5229, 5230, 5231, 5232, 5233, 5234, 5235, 5236, 5237, 5238, 5239, 5240, 5241, 5242, 5243, 5244, 5245, 5246, 5247, 5248, 5249, 5250, 5251, 5252, 5253, 5254, 5255, 5256, 5257, 5258, 5259, 5260, 5261, 5262, 5263, 5264, 5265, 5266, 5267, 5268, 5269, 5270, 5271, 5272, 5273, 5274, 5275, 5276, 5277, 5278, 5279, 5280, 5281, 5282, 5283, 5284, 5285, 5286, 5287, 5288, 5289, 5290, 5291, 5292, 5293, 5294, 5295, 5296, 5297, 5298, 5299, 5300, 5301, 5302, 5303, 5304, 5305, 5306, 5307, 5308, 5309, 5310, 5311, 5312, 5313, 5314, 5315, 5316, 5317, 5318, 5319, 5320, 5321, 5322, 5323, 5324, 5325, 5326, 5327, 5328, 5329, 5330, 5331, 5332, 5333, 5334, 5335, 5336, 5337, 5338, 5339, 5340, 5341, 5342, 5343, 5344, 5345, 5346, 5347, 5348, 5349, 5350, 5351, 5352, 5353, 5354, 5355, 5356, 5357, 5358, 5359, 5360, 5361, 5362, 5363, 5364, 5365, 5366, 5367, 5368, 5369, 5370, 5371, 5372, 5373, 5374, 5375, 5376, 5377, 5378, 5379, 5380, 5381, 5382, 5383, 5384, 5385, 5386, 5387, 5388, 5389, 5390, 5391, 5392, 5393, 5394, 5395, 5396, 5397, 5398, 5399, 5400, 5401, 5402, 5403, 5404, 5405, 5406, 5407, 5408, 5409, 5410, 5411, 5412, 5413, 5414, 5415, 5416, 5417, 5418, 5419, 5420, 5421, 5422, 5423, 5424, 5425, 5426, 5427, 5428, 5429, 5430, 5431, 5432, 5433, 5434, 5435, 5436, 5437, 5438, 5439, 5440, 5441, 5442, 5443, 5444, 5445, 5446, 5447, 5448, 5449, 5450, 5451, 5452, 5453, 5454, 5455, 5456, 5457, 5458, 5459, 5460, 5461, 5462, 5463, 5464, 5465, 5466, 5467, 5468, 5469, 5470, 5471, 5472, 5473, 5474, 5475, 5476, 5477, 5478, 5479, 5480, 5481, 5482, 5483, 5484, 5485, 5486, 5487, 5488, 5489, 5490, 5491, 5492, 5493, 5494, 5495, 5496, 5497, 5498, 5499, 5500, 5501, 5502, 5503, 5504, 5505, 5506, 5507, 5508, 5509, 5510, 5511, 5512, 5513, 5514, 5515, 5516, 5517, 5518, 5519, 5520, 5521, 5522, 5523, 5524, 5525, 5526, 5527, 5528, 5529, 5530, 5531, 5532, 5533, 5534, 5535, 5536, 5537, 5538, 5539, 5540, 5541, 5542, 5543, 5544, 5545, 5546, 5547, 5548, 5549, 5550, 5551, 5552, 5553, 5554, 5555, 5556, 5557, 5558, 5559, 5560, 5561, 5562, 5563, 5564, 5565, 5566, 5567, 5568, 5569, 5570, 5571, 5572, 5573, 5574, 5575, 5576, 5577, 5578, 5579, 5580, 5581, 5582, 5583, 5584, 5585, 5586, 5587, 5588, 5589, 5590, 5591, 5592, 5593, 5594, 5595, 5596, 5597, 5598, 5599, 5600, 5601, 5602, 5603, 5604, 5605, 5606, 5607, 5608, 5609, 5610, 5611, 5612, 5613, 5614, 5615, 5616, 5617, 5618, 5619, 5620, 5621, 5622, 5623, 5624, 5625, 5626, 5627, 5628, 5629, 5630, 5631, 5632, 5633, 5634, 5635, 5636, 5637, 5638, 5639, 5640, 5641, 5642, 5643, 5644, 5645, 5646, 5647, 5648, 5649, 5650, 5651, 5652, 5653, 5654, 5655, 5656, 5657, 5658, 5659, 5660, 5661, 5662, 5663, 5664, 5665, 5666, 5667, 5668, 5669, 5670, 5671, 5672, 5673, 5674, 5675, 5676, 5677, 5678, 5679, 5680, 5681, 5682, 5683, 5684, 5685, 5686, 5687, 5688, 5689, 5690, 5691, 5692, 5693, 5694, 5695, 5696, 5697, 5698, 5699, 5700, 5701, 5702, 5703, 5704, 5705, 5706, 5707, 5708, 5709, 5710, 5711, 5712, 5713, 5714, 5715, 5716, 5717, 5718, 5719, 5720, 5721, 5722, 5723, 5724, 5725, 5726, 5727, 5728, 5729, 5730, 5731, 5732, 5733, 5734, 5735, 5736, 5737, 5738, 5739, 5740, 5741, 5742, 5743, 5744, 5745, 5746, 5747, 5748, 5749, 5750, 5751, 5752, 5753, 5754, 5755, 5756, 5757, 5758, 5759, 5760, 5761, 5762, 5763, 5764, 5765, 5766, 5767, 5768, 5769, 5770, 5771, 5772, 5773, 5774, 5775, 5776, 5777, 5778, 5779, 5780, 5781, 5782, 5783, 5784, 5785, 5786, 5787, 5788, 5789, 5790, 5791, 5792, 5793, 5794, 5795, 5796, 5797, 5798, 5799, 5800, 5801, 5802, 5803, 5804, 5805, 5806, 5807, 5808, 5809, 5810, 5811, 5812, 5813, 5814, 5815, 5816, 5817, 5818, 5819, 5820, 5821, 5822, 5823, 5824, 5825, 5826, 5827, 5828, 5829, 5830, 5831, 5832, 5833, 5834, 5835, 5836, 5837, 5838, 5839, 5840, 5841, 5842, 5843, 5844, 5845, 5846, 5847, 5848, 5849, 5850, 5851, 5852, 5853, 5854, 5855, 5856, 5857, 5858, 5859, 5860, 5861, 5862, 5863, 5864, 5865, 5866, 5867, 5868, 5869, 5870, 5871, 5872, 5873, 5874, 5875, 5876, 5877, 5878, 5879, 5880, 5881, 5882, 5883, 5884, 5885, 5886, 5887, 5888, 5889, 5890, 5891, 5892, 5893, 5894, 5895, 5896, 5897, 5898, 5899, 5900, 5901, 5902, 5903, 5904, 5905, 5906, 5907, 5908, 5909, 5910, 5911, 5912, 5913, 5914, 5915, 5916, 5917, 5918, 5919, 5920, 5921, 5922, 5923, 5924, 5925, 5926, 5927, 5928, 5929, 5930, 5931, 5932, 5933, 5934, 5935, 5936, 5937, 5938, 5939, 5940, 5941, 5942, 5943, 5944, 5945, 5946, 5947, 5948, 5949, 5950, 5951, 5952, 5953, 5954, 5955, 5956, 5957, 5958, 5959, 5960, 5961, 5962, 5963, 5964, 5965, 5966, 5967, 5968, 5969, 5970, 5971, 5972, 5973, 5974, 5975, 5976, 5977, 5978, 5979, 5980, 5981, 5982, 5983, 5984, 5985, 5986, 5987, 5988, 5989, 5990, 5991, 5992, 5993, 5994, 5995, 5996, 5997, 5998, 5999, 6000, 6001, 6002, 6003, 6004, 6005, 6006, 6007, 6008, 6009, 6010, 6011, 6012, 6013, 6014, 6015, 6016, 6017, 6018, 6019, 6020, 6021, 6022, 6023, 6024, 6025, 6026, 6027, 6028, 6029, 6030, 6031, 6032, 6033, 6034, 6035, 6036, 6037, 6038, 6039, 6040, 6041, 6042, 6043, 6044, 6045, 6046, 6047, 6048, 6049, 6050, 6051, 6052, 6053, 6054, 6055, 6056, 6057, 6058, 6059, 6060, 6061, 6062, 6063, 6064, 6065, 6066, 6067, 6068, 6069, 6070, 6071, 6072, 6073, 6074, 6075, 6076, 6077, 6078, 6079, 6080, 6081, 6082, 6083, 6084, 6085, 6086, 6087, 6088, 6089, 6090, 6091, 6092, 6093, 6094, 6095, 6096, 6097, 6098, 6099, 6100, 6101, 6102, 6103, 6104, 6105, 6106, 6107, 6108, 6109, 6110, 6111, 6112, 6113, 6114, 6115, 6116, 6117, 6118, 6119, 6120, 6121, 6122, 6123, 6124, 6125, 6126, 6127, 6128, 6129, 6130, 6131, 6132, 6133, 6134, 6135, 6136, 6137, 6138, 6139, 6140, 6141, 6142, 6143, 6144, 6145, 6146, 6147, 6148, 6149, 6150, 6151, 6152, 6153, 6154, 6155, 6156, 6157, 6158, 6159, 6160, 6161, 6162, 6163, 6164, 6165, 6166, 6167, 6168, 6169, 6170, 6171, 6172, 6173, 6174, 6175, 6176, 6177, 6178, 6179, 6180, 6181, 6182, 6183, 6184, 6185, 6186, 6187, 6188, 6189, 6190, 6191, 6192, 6193, 6194, 6195, 6196, 6197, 6198, 6199, 6200, 6201, 6202, 6203, 6204, 6205, 6206, 6207, 6208, 6209, 6210, 6211, 6212, 6213, 6214, 6215, 6216, 6217, 6218, 6219, 6220, 6221, 6222, 6223, 6224, 6225, 6226, 6227, 6228, 6229, 6230, 6231, 6232, 6233, 6234, 6235, 6236, 6237, 6238, 6239, 6240, 6241, 6242, 6243, 6244, 6245, 6246, 6247, 6248, 6249, 6250, 6251, 6252, 6253, 6254, 6255, 6256, 6257, 6258, 6259, 6260, 6261, 6262, 6263, 6264, 6265, 6266, 6267, 6268, 6269, 6270, 6271, 6272, 6273, 6274, 6275, 6276, 6277, 6278, 6279, 6280, 6281, 6282, 6283, 6284, 6285, 6286, 6287, 6288, 6289, 6290, 6291, 6292, 6293, 6294, 6295, 6296, 6297, 6298, 6299, 6300, 6301, 6302, 6303, 6304, 6305, 6306, 6307, 6308, 6309, 6310, 6311, 6312, 6313, 6314, 6315, 6316, 6317, 6318, 6319, 6320, 6321, 6322, 6323, 6324, 6325, 6326, 6327, 6328, 6329, 6330, 6331, 6332, 6333, 6334, 6335, 6336, 6337, 6338, 6339, 6340, 6341, 6342, 6343, 6344, 6345, 6346, 6347, 6348, 6349, 6350, 6351, 6352, 6353, 6354, 6355, 6356, 6357, 6358, 6359, 6360, 6361, 6362, 6363, 6364, 6365, 6366, 6367, 6368, 6369, 6370, 6371, 6372, 6373, 6374, 6375, 6376, 6377, 6378, 6379, 6380, 6381, 6382, 6383, 6384, 6385, 6386, 6387, 6388, 6389, 6390, 6391, 6392, 6393, 6394, 6395, 6396, 6397, 6398, 6399, 6400, 6401, 6402, 6403, 6404, 6405, 6406, 6407, 6408, 6409, 6410, 6411, 6412, 6413, 6414, 6415, 6416, 6417, 6418, 6419, 6420, 6421, 6422, 6423, 6424, 6425, 6426, 6427, 6428, 6429, 6430, 6431, 6432, 6433, 6434, 6435, 6436, 6437, 6438, 6439, 6440, 6441, 6442, 6443, 6444, 6445, 6446, 6447, 6448, 6449, 6450, 6451, 6452, 6453, 6454, 6455, 6456, 6457, 6458, 6459, 6460, 6461, 6462, 6463, 6464, 6465, 6466, 6467, 6468, 6469, 6470, 6471, 6472, 6473, 6474, 6475, 6476, 6477, 6478, 6479, 6480, 6481, 6482, 6483, 6484, 6485, 6486, 6487, 6488, 6489, 6490, 6491, 6492, 6493, 6494, 6495, 6496, 6497, 6498, 6499, 6500, 6501, 6502, 6503, 6504, 6505, 6506, 6507, 6508, 6509, 6510, 6511, 6512, 6513, 6514, 6515, 6516, 6517, 6518, 6519, 6520, 6521, 6522, 6523, 6524, 6525, 6526, 6527, 6528, 6529, 6530, 6531, 6532, 6533, 6534, 6535, 6536, 6537, 6538, 6539, 6540, 6541, 6542, 6543, 6544, 6545, 6546, 6547, 6548, 6549, 6550, 6551, 6552, 6553, 6554, 6555, 6556, 6557, 6558, 6559, 6560, 6561, 6562, 6563, 6564, 6565, 6566, 6567, 6568, 6569, 6570, 6571, 6572, 6573, 6574, 6575, 6576, 6577, 6578, 6579, 6580, 6581, 6582, 6583, 6584, 6585, 6586, 6587, 6588, 6589, 6590, 6591, 6592, 6593, 6594, 6595, 6596, 6597, 6598, 6599, 6600, 6601, 6602, 6603, 6604, 6605, 6606, 6607, 6608, 6609, 6610, 6611, 6612, 6613, 6614, 6615, 6616, 6617, 6618, 6619, 6620, 6621, 6622, 6623, 6624, 6625, 6626, 6627, 6628, 6629, 6630, 6631, 6632, 6633, 6634, 6635, 6636, 6637, 6638, 6639, 6640, 6641, 6642, 6643, 6644, 6645, 6646, 6647, 6648, 6649, 6650, 6651, 6652, 6653, 6654, 6655, 6656, 6657, 6658, 6659, 6660, 6661, 6662, 6663, 6664, 6665, 6666, 6667, 6668, 6669, 6670, 6671, 6672, 6673, 6674, 6675, 6676, 6677, 6678, 6679, 6680, 6681, 6682, 6683, 6684, 6685, 6686, 6687, 6688, 6689, 6690, 6691, 6692, 6693, 6694, 6695, 6696, 6697, 6698, 6699, 6700, 6701, 6702, 6703, 6704, 6705, 6706, 6707, 6708, 6709, 6710, 6711, 6712, 6713, 6714, 6715, 6716, 6717, 6718, 6719, 6720, 6721, 6722, 6723, 6724, 6725, 6726, 6727, 6728, 6729, 6730, 6731, 6732, 6733, 6734, 6735, 6736, 6737, 6738, 6739, 6740, 6741, 6742, 6743, 6744, 6745, 6746, 6747, 6748, 6749, 6750, 6751, 6752, 6753, 6754, 6755, 6756, 6757, 6758, 6759, 6760, 6761, 6762, 6763, 6764, 6765, 6766, 6767, 6768, 6769, 6770, 6771, 6772, 6773, 6774, 6775, 6776, 6777, 6778, 6779, 6780, 6781, 6782, 6783, 6784, 6785, 6786, 6787, 6788, 6789, 6790, 6791, 6792, 6793, 6794, 6795, 6796, 6797, 6798, 6799, 6800, 6801, 6802, 6803, 6804, 6805, 6806, 6807, 6808, 6809, 6810, 6811, 6812, 6813, 6814, 6815, 6816, 6817, 6818, 6819, 6820, 6821, 6822, 6823, 6824, 6825, 6826, 6827, 6828, 6829, 6830, 6831, 6832, 6833, 6834, 6835, 6836, 6837, 6838, 6839, 6840, 6841, 6842, 6843, 6844, 6845, 6846, 6847, 6848, 6849, 6850, 6851, 6852, 6853, 6854, 6855, 6856, 6857, 6858, 6859, 6860, 6861, 6862, 6863, 6864, 6865, 6866, 6867, 6868, 6869, 6870, 6871, 6872, 6873, 6874, 6875, 6876, 6877, 6878, 6879, 6880, 6881, 6882, 6883, 6884, 6885, 6886, 6887, 6888, 6889, 6890, 6891, 6892, 6893, 6894, 6895, 6896, 6897, 6898, 6899, 6900, 6901, 6902, 6903, 6904, 6905, 6906, 6907, 6908, 6909, 6910, 6911, 6912, 6913, 6914, 6915, 6916, 6917, 6918, 6919, 6920, 6921, 6922, 6923, 6924, 6925, 6926, 6927, 6928, 6929, 6930, 6931, 6932, 6933, 6934, 6935, 6936, 6937, 6938, 6939, 6940, 6941, 6942, 6943, 6944, 6945, 6946, 6947, 6948, 6949, 6950, 6951, 6952, 6953, 6954, 6955, 6956, 6957, 6958, 6959, 6960, 6961, 6962, 6963, 6964, 6965, 6966, 6967, 6968, 6969, 6970, 6971, 6972, 6973, 6974, 6975, 6976, 6977, 6978, 6979, 6980, 6981, 6982, 6983, 6984, 6985, 6986, 6987, 6988, 6989, 6990, 6991, 6992, 6993, 6994, 6995, 6996, 6997, 6998, 6999, 7000, 7001, 7002, 7003, 7004, 7005, 7006, 7007, 7008, 7009, 7010, 7011, 7012, 7013, 7014, 7015, 7016, 7017, 7018, 7019, 7020, 7021, 7022, 7023, 7024, 7025, 7026, 7027, 7028, 7029, 7030, 7031, 7032, 7033, 7034, 7035, 7036, 7037, 7038, 7039, 7040, 7041, 7042, 7043, 7044, 7045, 7046, 7047, 7048, 7049, 7050, 7051, 7052, 7053, 7054, 7055, 7056, 7057, 7058, 7059, 7060, 7061, 7062, 7063, 7064, 7065, 7066, 7067, 7068, 7069, 7070, 7071, 7072, 7073, 7074, 7075, 7076, 7077, 7078, 7079, 7080, 7081, 7082, 7083, 7084, 7085, 7086, 7087, 7088, 7089, 7090, 7091, 7092, 7093, 7094, 7095, 7096, 7097, 7098, 7099, 7100, 7101, 7102, 7103, 7104, 7105, 7106, 7107, 7108, 7109, 7110, 7111, 7112, 7113, 7114, 7115, 7116, 7117, 7118, 7119, 7120, 7121, 7122, 7123, 7124, 7125, 7126, 7127, 7128, 7129, 7130, 7131, 7132, 7133, 7134, 7135, 7136, 7137, 7138, 7139, 7140, 7141, 7142, 7143, 7144, 7145, 7146, 7147, 7148, 7149, 7150, 7151, 7152, 7153, 7154, 7155, 7156, 7157, 7158, 7159, 7160, 7161, 7162, 7163, 7164, 7165, 7166, 7167, 7168, 7169, 7170, 7171, 7172, 7173, 7174, 7175, 7176, 7177, 7178, 7179, 7180, 7181, 7182, 7183, 7184, 7185, 7186, 7187, 7188, 7189, 7190, 7191, 7192, 7193, 7194, 7195, 7196, 7197, 7198, 7199, 7200, 7201, 7202, 7203, 7204, 7205, 7206, 7207, 7208, 7209, 7210, 7211, 7212, 7213, 7214, 7215, 7216, 7217, 7218, 7219, 7220, 7221, 7222, 7223, 7224, 7225, 7226, 7227, 7228, 7229, 7230, 7231, 7232, 7233, 7234, 7235, 7236, 7237, 7238, 7239, 7240, 7241, 7242, 7243, 7244, 7245, 7246, 7247, 7248, 7249, 7250, 7251, 7252, 7253, 7254, 7255, 7256, 7257, 7258, 7259, 7260, 7261, 7262, 7263, 7264, 7265, 7266, 7267, 7268, 7269, 7270, 7271, 7272, 7273, 7274, 7275, 7276, 7277, 7278, 7279, 7280, 7281, 7282, 7283, 7284, 7285, 7286, 7287, 7288, 7289, 7290, 7291, 7292, 7293, 7294, 7295, 7296, 7297, 7298, 7299, 7300, 7301, 7302, 7303, 7304, 7305, 7306, 7307, 7308, 7309, 7310, 7311, 7312, 7313, 7314, 7315, 7316, 7317, 7318, 7319, 7320, 7321, 7322, 7323, 7324, 7325, 7326, 7327, 7328, 7329, 7330, 7331, 7332, 7333, 7334, 7335, 7336, 7337, 7338, 7339, 7340, 7341, 7342, 7343, 7344, 7345, 7346, 7347, 7348, 7349, 7350, 7351, 7352, 7353, 7354, 7355, 7356, 7357, 7358, 7359, 7360, 7361, 7362, 7363, 7364, 7365, 7366, 7367, 7368, 7369, 7370, 7371, 7372, 7373, 7374, 7375, 7376, 7377, 7378, 7379, 7380, 7381, 7382, 7383, 7384, 7385, 7386, 7387, 7388, 7389, 7390, 7391, 7392, 7393, 7394, 7395, 7396, 7397, 7398, 7399, 7400, 7401, 7402, 7403, 7404, 7405, 7406, 7407, 7408, 7409, 7410, 7411, 7412, 7413, 7414, 7415, 7416, 7417, 7418, 7419, 7420, 7421, 7422, 7423, 7424, 7425, 7426, 7427, 7428, 7429, 7430, 7431, 7432, 7433, 7434, 7435, 7436, 7437, 7438, 7439, 7440, 7441, 7442, 7443, 7444, 7445, 7446, 7447, 7448, 7449, 7450, 7451, 7452, 7453, 7454, 7455, 7456, 7457, 7458, 7459, 7460, 7461, 7462, 7463, 7464, 7465, 7466, 7467, 7468, 7469, 7470, 7471, 7472, 7473, 7474, 7475, 7476, 7477, 7478, 7479, 7480, 7481, 7482, 7483, 7484, 7485, 7486, 7487, 7488, 7489, 7490, 7491, 7492, 7493, 7494, 7495, 7496, 7497, 7498, 7499, 7500, 7501, 7502, 7503, 7504, 7505, 7506, 7507, 7508, 7509, 7510, 7511, 7512, 7513, 7514, 7515, 7516, 7517, 7518, 7519, 7520, 7521, 7522, 7523, 7524, 7525, 7526, 7527, 7528, 7529, 7530, 7531, 7532, 7533, 7534, 7535, 7536, 7537, 7538, 7539, 7540, 7541, 7542, 7543, 7544, 7545, 7546, 7547, 7548, 7549, 7550, 7551, 7552, 7553, 7554, 7555, 7556, 7557, 7558, 7559, 7560, 7561, 7562, 7563, 7564, 7565, 7566, 7567, 7568, 7569, 7570, 7571, 7572, 7573, 7574, 7575, 7576, 7577, 7578, 7579, 7580, 7581, 7582, 7583, 7584, 7585, 7586, 7587, 7588, 7589, 7590, 7591, 7592, 7593, 7594, 7595, 7596, 7597, 7598, 7599, 7600, 7601, 7602, 7603, 7604, 7605, 7606, 7607, 7608, 7609, 7610, 7611, 7612, 7613, 7614, 7615, 7616, 7617, 7618, 7619, 7620, 7621, 7622, 7623, 7624, 7625, 7626, 7627, 7628, 7629, 7630, 7631, 7632, 7633, 7634, 7635, 7636, 7637, 7638, 7639, 7640, 7641, 7642, 7643, 7644, 7645, 7646, 7647, 7648, 7649, 7650, 7651, 7652, 7653, 7654, 7655, 7656, 7657, 7658, 7659, 7660, 7661, 7662, 7663, 7664, 7665, 7666, 7667, 7668, 7669, 7670, 7671, 7672, 7673, 7674, 7675, 7676, 7677, 7678, 7679, 7681, 7681, 7683, 7683, 7685, 7685, 7687, 7687, 7689, 7689, 7691, 7691, 7693, 7693, 7695, 7695, 7697, 7697, 7699, 7699, 7701, 7701, 7703, 7703, 7705, 7705, 7707, 7707, 7709, 7709, 7711, 7711, 7713, 7713, 7715, 7715, 7717, 7717, 7719, 7719, 7721, 7721, 7723, 7723, 7725, 7725, 7727, 7727, 7729, 7729, 7731, 7731, 7733, 7733, 7735, 7735, 7737, 7737, 7739, 7739, 7741, 7741, 7743, 7743, 7745, 7745, 7747, 7747, 7749, 7749, 7751, 7751, 7753, 7753, 7755, 7755, 7757, 7757, 7759, 7759, 7761, 7761, 7763, 7763, 7765, 7765, 7767, 7767, 7769, 7769, 7771, 7771, 7773, 7773, 7775, 7775, 7777, 7777, 7779, 7779, 7781, 7781, 7783, 7783, 7785, 7785, 7787, 7787, 7789, 7789, 7791, 7791, 7793, 7793, 7795, 7795, 7797, 7797, 7799, 7799, 7801, 7801, 7803, 7803, 7805, 7805, 7807, 7807, 7809, 7809, 7811, 7811, 7813, 7813, 7815, 7815, 7817, 7817, 7819, 7819, 7821, 7821, 7823, 7823, 7825, 7825, 7827, 7827, 7829, 7829, 7830, 7831, 7832, 7833, 7834, 7835, 7836, 7837, 7838, 7839, 7841, 7841, 7843, 7843, 7845, 7845, 7847, 7847, 7849, 7849, 7851, 7851, 7853, 7853, 7855, 7855, 7857, 7857, 7859, 7859, 7861, 7861, 7863, 7863, 7865, 7865, 7867, 7867, 7869, 7869, 7871, 7871, 7873, 7873, 7875, 7875, 7877, 7877, 7879, 7879, 7881, 7881, 7883, 7883, 7885, 7885, 7887, 7887, 7889, 7889, 7891, 7891, 7893, 7893, 7895, 7895, 7897, 7897, 7899, 7899, 7901, 7901, 7903, 7903, 7905, 7905, 7907, 7907, 7909, 7909, 7911, 7911, 7913, 7913, 7915, 7915, 7917, 7917, 7919, 7919, 7921, 7921, 7923, 7923, 7925, 7925, 7927, 7927, 7929, 7929, 7930, 7931, 7932, 7933, 7934, 7935, 7936, 7937, 7938, 7939, 7940, 7941, 7942, 7943, 7936, 7937, 7938, 7939, 7940, 7941, 7942, 7943, 7952, 7953, 7954, 7955, 7956, 7957, 7958, 7959, 7952, 7953, 7954, 7955, 7956, 7957, 7966, 7967, 7968, 7969, 7970, 7971, 7972, 7973, 7974, 7975, 7968, 7969, 7970, 7971, 7972, 7973, 7974, 7975, 7984, 7985, 7986, 7987, 7988, 7989, 7990, 7991, 7984, 7985, 7986, 7987, 7988, 7989, 7990, 7991, 8000, 8001, 8002, 8003, 8004, 8005, 8006, 8007, 8000, 8001, 8002, 8003, 8004, 8005, 8014, 8015, 8016, 8017, 8018, 8019, 8020, 8021, 8022, 8023, 8024, 8017, 8026, 8019, 8028, 8021, 8030, 8023, 8032, 8033, 8034, 8035, 8036, 8037, 8038, 8039, 8032, 8033, 8034, 8035, 8036, 8037, 8038, 8039, 8048, 8049, 8050, 8051, 8052, 8053, 8054, 8055, 8056, 8057, 8058, 8059, 8060, 8061, 8062, 8063, 8064, 8065, 8066, 8067, 8068, 8069, 8070, 8071, 8072, 8073, 8074, 8075, 8076, 8077, 8078, 8079, 8080, 8081, 8082, 8083, 8084, 8085, 8086, 8087, 8088, 8089, 8090, 8091, 8092, 8093, 8094, 8095, 8096, 8097, 8098, 8099, 8100, 8101, 8102, 8103, 8104, 8105, 8106, 8107, 8108, 8109, 8110, 8111, 8112, 8113, 8114, 8115, 8116, 8117, 8118, 8119, 8112, 8113, 8048, 8049, 8124, 8125, 8126, 8127, 8128, 8129, 8130, 8131, 8132, 8133, 8134, 8135, 8050, 8051, 8052, 8053, 8140, 8141, 8142, 8143, 8144, 8145, 8146, 8147, 8148, 8149, 8150, 8151, 8144, 8145, 8054, 8055, 8156, 8157, 8158, 8159, 8160, 8161, 8162, 8163, 8164, 8165, 8166, 8167, 8160, 8161, 8058, 8059, 8165, 8173, 8174, 8175, 8176, 8177, 8178, 8179, 8180, 8181, 8182, 8183, 8056, 8057, 8060, 8061, 8188, 8189, 8190, 8191, 8192, 8193, 8194, 8195, 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8203, 8204, 8205, 8206, 8207, 8208, 8209, 8210, 8211, 8212, 8213, 8214, 8215, 8216, 8217, 8218, 8219, 8220, 8221, 8222, 8223, 8224, 8225, 8226, 8227, 8228, 8229, 8230, 8231, 8232, 8233, 8234, 8235, 8236, 8237, 8238, 8239, 8240, 8241, 8242, 8243, 8244, 8245, 8246, 8247, 8248, 8249, 8250, 8251, 8252, 8253, 8254, 8255, 8256, 8257, 8258, 8259, 8260, 8261, 8262, 8263, 8264, 8265, 8266, 8267, 8268, 8269, 8270, 8271, 8272, 8273, 8274, 8275, 8276, 8277, 8278, 8279, 8280, 8281, 8282, 8283, 8284, 8285, 8286, 8287, 8288, 8289, 8290, 8291, 8292, 8293, 8294, 8295, 8296, 8297, 8298, 8299, 8300, 8301, 8302, 8303, 8304, 8305, 8306, 8307, 8308, 8309, 8310, 8311, 8312, 8313, 8314, 8315, 8316, 8317, 8318, 8319, 8320, 8321, 8322, 8323, 8324, 8325, 8326, 8327, 8328, 8329, 8330, 8331, 8332, 8333, 8334, 8335, 8336, 8337, 8338, 8339, 8340, 8341, 8342, 8343, 8344, 8345, 8346, 8347, 8348, 8349, 8350, 8351, 8352, 8353, 8354, 8355, 8356, 8357, 8358, 8359, 8360, 8361, 8362, 8363, 8364, 8365, 8366, 8367, 8368, 8369, 8370, 8371, 8372, 8373, 8374, 8375, 8376, 8377, 8378, 8379, 8380, 8381, 8382, 8383, 8384, 8385, 8386, 8387, 8388, 8389, 8390, 8391, 8392, 8393, 8394, 8395, 8396, 8397, 8398, 8399, 8400, 8401, 8402, 8403, 8404, 8405, 8406, 8407, 8408, 8409, 8410, 8411, 8412, 8413, 8414, 8415, 8416, 8417, 8418, 8419, 8420, 8421, 8422, 8423, 8424, 8425, 8426, 8427, 8428, 8429, 8430, 8431, 8432, 8433, 8434, 8435, 8436, 8437, 8438, 8439, 8440, 8441, 8442, 8443, 8444, 8445, 8446, 8447, 8448, 8449, 8450, 8451, 8452, 8453, 8454, 8455, 8456, 8457, 8458, 8459, 8460, 8461, 8462, 8463, 8464, 8465, 8466, 8467, 8468, 8469, 8470, 8471, 8472, 8473, 8474, 8475, 8476, 8477, 8478, 8479, 8480, 8481, 8482, 8483, 8484, 8485, 8486, 8487, 8488, 8489, 8490, 8491, 8492, 8493, 8494, 8495, 8496, 8497, 8498, 8499, 8500, 8501, 8502, 8503, 8504, 8505, 8506, 8507, 8508, 8509, 8510, 8511, 8512, 8513, 8514, 8515, 8516, 8517, 8518, 8519, 8520, 8521, 8522, 8523, 8524, 8525, 8526, 8527, 8528, 8529, 8530, 8531, 8532, 8533, 8534, 8535, 8536, 8537, 8538, 8539, 8540, 8541, 8542, 8543, 8560, 8561, 8562, 8563, 8564, 8565, 8566, 8567, 8568, 8569, 8570, 8571, 8572, 8573, 8574, 8575, 8560, 8561, 8562, 8563, 8564, 8565, 8566, 8567, 8568, 8569, 8570, 8571, 8572, 8573, 8574, 8575, 8576, 8577, 8578, 8579, 8580, 8581, 8582, 8583, 8584, 8585, 8586, 8587, 8588, 8589, 8590, 8591, 8592, 8593, 8594, 8595, 8596, 8597, 8598, 8599, 8600, 8601, 8602, 8603, 8604, 8605, 8606, 8607, 8608, 8609, 8610, 8611, 8612, 8613, 8614, 8615, 8616, 8617, 8618, 8619, 8620, 8621, 8622, 8623, 8624, 8625, 8626, 8627, 8628, 8629, 8630, 8631, 8632, 8633, 8634, 8635, 8636, 8637, 8638, 8639, 8640, 8641, 8642, 8643, 8644, 8645, 8646, 8647, 8648, 8649, 8650, 8651, 8652, 8653, 8654, 8655, 8656, 8657, 8658, 8659, 8660, 8661, 8662, 8663, 8664, 8665, 8666, 8667, 8668, 8669, 8670, 8671, 8672, 8673, 8674, 8675, 8676, 8677, 8678, 8679, 8680, 8681, 8682, 8683, 8684, 8685, 8686, 8687, 8688, 8689, 8690, 8691, 8692, 8693, 8694, 8695, 8696, 8697, 8698, 8699, 8700, 8701, 8702, 8703, 8704, 8705, 8706, 8707, 8708, 8709, 8710, 8711, 8712, 8713, 8714, 8715, 8716, 8717, 8718, 8719, 8720, 8721, 8722, 8723, 8724, 8725, 8726, 8727, 8728, 8729, 8730, 8731, 8732, 8733, 8734, 8735, 8736, 8737, 8738, 8739, 8740, 8741, 8742, 8743, 8744, 8745, 8746, 8747, 8748, 8749, 8750, 8751, 8752, 8753, 8754, 8755, 8756, 8757, 8758, 8759, 8760, 8761, 8762, 8763, 8764, 8765, 8766, 8767, 8768, 8769, 8770, 8771, 8772, 8773, 8774, 8775, 8776, 8777, 8778, 8779, 8780, 8781, 8782, 8783, 8784, 8785, 8786, 8787, 8788, 8789, 8790, 8791, 8792, 8793, 8794, 8795, 8796, 8797, 8798, 8799, 8800, 8801, 8802, 8803, 8804, 8805, 8806, 8807, 8808, 8809, 8810, 8811, 8812, 8813, 8814, 8815, 8816, 8817, 8818, 8819, 8820, 8821, 8822, 8823, 8824, 8825, 8826, 8827, 8828, 8829, 8830, 8831, 8832, 8833, 8834, 8835, 8836, 8837, 8838, 8839, 8840, 8841, 8842, 8843, 8844, 8845, 8846, 8847, 8848, 8849, 8850, 8851, 8852, 8853, 8854, 8855, 8856, 8857, 8858, 8859, 8860, 8861, 8862, 8863, 8864, 8865, 8866, 8867, 8868, 8869, 8870, 8871, 8872, 8873, 8874, 8875, 8876, 8877, 8878, 8879, 8880, 8881, 8882, 8883, 8884, 8885, 8886, 8887, 8888, 8889, 8890, 8891, 8892, 8893, 8894, 8895, 8896, 8897, 8898, 8899, 8900, 8901, 8902, 8903, 8904, 8905, 8906, 8907, 8908, 8909, 8910, 8911, 8912, 8913, 8914, 8915, 8916, 8917, 8918, 8919, 8920, 8921, 8922, 8923, 8924, 8925, 8926, 8927, 8928, 8929, 8930, 8931, 8932, 8933, 8934, 8935, 8936, 8937, 8938, 8939, 8940, 8941, 8942, 8943, 8944, 8945, 8946, 8947, 8948, 8949, 8950, 8951, 8952, 8953, 8954, 8955, 8956, 8957, 8958, 8959, 8960, 8961, 8962, 8963, 8964, 8965, 8966, 8967, 8968, 8969, 8970, 8971, 8972, 8973, 8974, 8975, 8976, 8977, 8978, 8979, 8980, 8981, 8982, 8983, 8984, 8985, 8986, 8987, 8988, 8989, 8990, 8991, 8992, 8993, 8994, 8995, 8996, 8997, 8998, 8999, 9000, 9001, 9002, 9003, 9004, 9005, 9006, 9007, 9008, 9009, 9010, 9011, 9012, 9013, 9014, 9015, 9016, 9017, 9018, 9019, 9020, 9021, 9022, 9023, 9024, 9025, 9026, 9027, 9028, 9029, 9030, 9031, 9032, 9033, 9034, 9035, 9036, 9037, 9038, 9039, 9040, 9041, 9042, 9043, 9044, 9045, 9046, 9047, 9048, 9049, 9050, 9051, 9052, 9053, 9054, 9055, 9056, 9057, 9058, 9059, 9060, 9061, 9062, 9063, 9064, 9065, 9066, 9067, 9068, 9069, 9070, 9071, 9072, 9073, 9074, 9075, 9076, 9077, 9078, 9079, 9080, 9081, 9082, 9083, 9084, 9085, 9086, 9087, 9088, 9089, 9090, 9091, 9092, 9093, 9094, 9095, 9096, 9097, 9098, 9099, 9100, 9101, 9102, 9103, 9104, 9105, 9106, 9107, 9108, 9109, 9110, 9111, 9112, 9113, 9114, 9115, 9116, 9117, 9118, 9119, 9120, 9121, 9122, 9123, 9124, 9125, 9126, 9127, 9128, 9129, 9130, 9131, 9132, 9133, 9134, 9135, 9136, 9137, 9138, 9139, 9140, 9141, 9142, 9143, 9144, 9145, 9146, 9147, 9148, 9149, 9150, 9151, 9152, 9153, 9154, 9155, 9156, 9157, 9158, 9159, 9160, 9161, 9162, 9163, 9164, 9165, 9166, 9167, 9168, 9169, 9170, 9171, 9172, 9173, 9174, 9175, 9176, 9177, 9178, 9179, 9180, 9181, 9182, 9183, 9184, 9185, 9186, 9187, 9188, 9189, 9190, 9191, 9192, 9193, 9194, 9195, 9196, 9197, 9198, 9199, 9200, 9201, 9202, 9203, 9204, 9205, 9206, 9207, 9208, 9209, 9210, 9211, 9212, 9213, 9214, 9215, 9216, 9217, 9218, 9219, 9220, 9221, 9222, 9223, 9224, 9225, 9226, 9227, 9228, 9229, 9230, 9231, 9232, 9233, 9234, 9235, 9236, 9237, 9238, 9239, 9240, 9241, 9242, 9243, 9244, 9245, 9246, 9247, 9248, 9249, 9250, 9251, 9252, 9253, 9254, 9255, 9256, 9257, 9258, 9259, 9260, 9261, 9262, 9263, 9264, 9265, 9266, 9267, 9268, 9269, 9270, 9271, 9272, 9273, 9274, 9275, 9276, 9277, 9278, 9279, 9280, 9281, 9282, 9283, 9284, 9285, 9286, 9287, 9288, 9289, 9290, 9291, 9292, 9293, 9294, 9295, 9296, 9297, 9298, 9299, 9300, 9301, 9302, 9303, 9304, 9305, 9306, 9307, 9308, 9309, 9310, 9311, 9312, 9313, 9314, 9315, 9316, 9317, 9318, 9319, 9320, 9321, 9322, 9323, 9324, 9325, 9326, 9327, 9328, 9329, 9330, 9331, 9332, 9333, 9334, 9335, 9336, 9337, 9338, 9339, 9340, 9341, 9342, 9343, 9344, 9345, 9346, 9347, 9348, 9349, 9350, 9351, 9352, 9353, 9354, 9355, 9356, 9357, 9358, 9359, 9360, 9361, 9362, 9363, 9364, 9365, 9366, 9367, 9368, 9369, 9370, 9371, 9372, 9373, 9374, 9375, 9376, 9377, 9378, 9379, 9380, 9381, 9382, 9383, 9384, 9385, 9386, 9387, 9388, 9389, 9390, 9391, 9392, 9393, 9394, 9395, 9396, 9397, 9424, 9425, 9426, 9427, 9428, 9429, 9430, 9431, 9432, 9433, 9434, 9435, 9436, 9437, 9438, 9439, 9440, 9441, 9442, 9443, 9444, 9445, 9446, 9447, 9448, 9449 }; const Il2CppChar ToLowerDataHigh[] = { 65345, 65346, 65347, 65348, 65349, 65350, 65351, 65352, 65353, 65354, 65355, 65356, 65357, 65358, 65359, 65360, 65361, 65362, 65363, 65364, 65365, 65366, 65367, 65368, 65369, 65370, 65339, 65340, 65341, 65342, 65343, 65344, 65345, 65346, 65347, 65348, 65349, 65350, 65351, 65352, 65353, 65354, 65355, 65356, 65357, 65358, 65359, 65360, 65361, 65362, 65363, 65364, 65365, 65366, 65367, 65368, 65369, 65370, 65371, 65372, 65373, 65374, 65375, 65376, 65377, 65378, 65379, 65380, 65381, 65382, 65383, 65384, 65385, 65386, 65387, 65388, 65389, 65390, 65391, 65392, 65393, 65394, 65395, 65396, 65397, 65398, 65399, 65400, 65401, 65402, 65403, 65404, 65405, 65406, 65407, 65408, 65409, 65410, 65411, 65412, 65413, 65414, 65415, 65416, 65417, 65418, 65419, 65420, 65421, 65422, 65423, 65424, 65425, 65426, 65427, 65428, 65429, 65430, 65431, 65432, 65433, 65434, 65435, 65436, 65437, 65438, 65439, 65440, 65441, 65442, 65443, 65444, 65445, 65446, 65447, 65448, 65449, 65450, 65451, 65452, 65453, 65454, 65455, 65456, 65457, 65458, 65459, 65460, 65461, 65462, 65463, 65464, 65465, 65466, 65467, 65468, 65469, 65470, 65471, 65472, 65473, 65474, 65475, 65476, 65477, 65478, 65479, 65480, 65481, 65482, 65483, 65484, 65485, 65486, 65487, 65488, 65489, 65490, 65491, 65492, 65493, 65494, 65495, 65496, 65497, 65498, 65499, 65500, 65501, 65502, 65503, 65504, 65505, 65506, 65507, 65508, 65509, 65510, 65511, 65512, 65513, 65514, 65515, 65516, 65517, 65518, 65519, 65520, 65521, 65522, 65523, 65524, 65525, 65526, 65527, 65528, 65529, 65530, 65531, 65532, 65533, 65534, 65535 }; const Il2CppChar ToUpperDataLow[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 247, 216, 217, 218, 219, 220, 221, 222, 376, 256, 256, 258, 258, 260, 260, 262, 262, 264, 264, 266, 266, 268, 268, 270, 270, 272, 272, 274, 274, 276, 276, 278, 278, 280, 280, 282, 282, 284, 284, 286, 286, 288, 288, 290, 290, 292, 292, 294, 294, 296, 296, 298, 298, 300, 300, 302, 302, 304, 305, 306, 306, 308, 308, 310, 310, 312, 313, 313, 315, 315, 317, 317, 319, 319, 321, 321, 323, 323, 325, 325, 327, 327, 329, 330, 330, 332, 332, 334, 334, 336, 336, 338, 338, 340, 340, 342, 342, 344, 344, 346, 346, 348, 348, 350, 350, 352, 352, 354, 354, 356, 356, 358, 358, 360, 360, 362, 362, 364, 364, 366, 366, 368, 368, 370, 370, 372, 372, 374, 374, 376, 377, 377, 379, 379, 381, 381, 383, 384, 385, 386, 386, 388, 388, 390, 391, 391, 393, 394, 395, 395, 397, 398, 399, 400, 401, 401, 403, 404, 405, 406, 407, 408, 408, 410, 411, 412, 413, 414, 415, 416, 416, 418, 418, 420, 420, 422, 423, 423, 425, 426, 427, 428, 428, 430, 431, 431, 433, 434, 435, 435, 437, 437, 439, 440, 440, 442, 443, 444, 444, 446, 447, 448, 449, 450, 451, 452, 453, 452, 455, 456, 455, 458, 459, 458, 461, 461, 463, 463, 465, 465, 467, 467, 469, 469, 471, 471, 473, 473, 475, 475, 398, 478, 478, 480, 480, 482, 482, 484, 484, 486, 486, 488, 488, 490, 490, 492, 492, 494, 494, 496, 497, 498, 497, 500, 500, 502, 503, 504, 505, 506, 506, 508, 508, 510, 510, 512, 512, 514, 514, 516, 516, 518, 518, 520, 520, 522, 522, 524, 524, 526, 526, 528, 528, 530, 530, 532, 532, 534, 534, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 385, 390, 597, 393, 394, 600, 399, 602, 400, 604, 605, 606, 607, 403, 609, 610, 404, 612, 613, 614, 615, 407, 406, 618, 619, 620, 621, 622, 412, 624, 625, 413, 627, 628, 415, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 425, 644, 645, 646, 647, 430, 649, 433, 434, 652, 653, 654, 655, 656, 657, 439, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 902, 904, 905, 906, 944, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 931, 932, 933, 934, 935, 936, 937, 938, 939, 908, 910, 911, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 994, 996, 996, 998, 998, 1000, 1000, 1002, 1002, 1004, 1004, 1006, 1006, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1104, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1117, 1038, 1039, 1120, 1120, 1122, 1122, 1124, 1124, 1126, 1126, 1128, 1128, 1130, 1130, 1132, 1132, 1134, 1134, 1136, 1136, 1138, 1138, 1140, 1140, 1142, 1142, 1144, 1144, 1146, 1146, 1148, 1148, 1150, 1150, 1152, 1152, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161, 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1168, 1170, 1170, 1172, 1172, 1174, 1174, 1176, 1176, 1178, 1178, 1180, 1180, 1182, 1182, 1184, 1184, 1186, 1186, 1188, 1188, 1190, 1190, 1192, 1192, 1194, 1194, 1196, 1196, 1198, 1198, 1200, 1200, 1202, 1202, 1204, 1204, 1206, 1206, 1208, 1208, 1210, 1210, 1212, 1212, 1214, 1214, 1216, 1217, 1217, 1219, 1219, 1221, 1222, 1223, 1223, 1225, 1226, 1227, 1227, 1229, 1230, 1231, 1232, 1232, 1234, 1234, 1236, 1236, 1238, 1238, 1240, 1240, 1242, 1242, 1244, 1244, 1246, 1246, 1248, 1248, 1250, 1250, 1252, 1252, 1254, 1254, 1256, 1256, 1258, 1258, 1260, 1261, 1262, 1262, 1264, 1264, 1266, 1266, 1268, 1268, 1270, 1271, 1272, 1272, 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1322, 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1354, 1355, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1370, 1371, 1372, 1373, 1374, 1375, 1376, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1354, 1355, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1415, 1416, 1417, 1418, 1419, 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437, 1438, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, 1447, 1448, 1449, 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481, 1482, 1483, 1484, 1485, 1486, 1487, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529, 1530, 1531, 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562, 1563, 1564, 1565, 1566, 1567, 1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1596, 1597, 1598, 1599, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, 1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686, 1687, 1688, 1689, 1690, 1691, 1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1700, 1701, 1702, 1703, 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721, 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, 1732, 1733, 1734, 1735, 1736, 1737, 1738, 1739, 1740, 1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765, 1766, 1767, 1768, 1769, 1770, 1771, 1772, 1773, 1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, 1782, 1783, 1784, 1785, 1786, 1787, 1788, 1789, 1790, 1791, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800, 1801, 1802, 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819, 1820, 1821, 1822, 1823, 1824, 1825, 1826, 1827, 1828, 1829, 1830, 1831, 1832, 1833, 1834, 1835, 1836, 1837, 1838, 1839, 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, 1851, 1852, 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866, 1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, 1897, 1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, 1938, 1939, 1940, 1941, 1942, 1943, 1944, 1945, 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, 2030, 2031, 2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, 2137, 2138, 2139, 2140, 2141, 2142, 2143, 2144, 2145, 2146, 2147, 2148, 2149, 2150, 2151, 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165, 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176, 2177, 2178, 2179, 2180, 2181, 2182, 2183, 2184, 2185, 2186, 2187, 2188, 2189, 2190, 2191, 2192, 2193, 2194, 2195, 2196, 2197, 2198, 2199, 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211, 2212, 2213, 2214, 2215, 2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224, 2225, 2226, 2227, 2228, 2229, 2230, 2231, 2232, 2233, 2234, 2235, 2236, 2237, 2238, 2239, 2240, 2241, 2242, 2243, 2244, 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, 2256, 2257, 2258, 2259, 2260, 2261, 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270, 2271, 2272, 2273, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2282, 2283, 2284, 2285, 2286, 2287, 2288, 2289, 2290, 2291, 2292, 2293, 2294, 2295, 2296, 2297, 2298, 2299, 2300, 2301, 2302, 2303, 2304, 2305, 2306, 2307, 2308, 2309, 2310, 2311, 2312, 2313, 2314, 2315, 2316, 2317, 2318, 2319, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2328, 2329, 2330, 2331, 2332, 2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340, 2341, 2342, 2343, 2344, 2345, 2346, 2347, 2348, 2349, 2350, 2351, 2352, 2353, 2354, 2355, 2356, 2357, 2358, 2359, 2360, 2361, 2362, 2363, 2364, 2365, 2366, 2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376, 2377, 2378, 2379, 2380, 2381, 2382, 2383, 2384, 2385, 2386, 2387, 2388, 2389, 2390, 2391, 2392, 2393, 2394, 2395, 2396, 2397, 2398, 2399, 2400, 2401, 2402, 2403, 2404, 2405, 2406, 2407, 2408, 2409, 2410, 2411, 2412, 2413, 2414, 2415, 2416, 2417, 2418, 2419, 2420, 2421, 2422, 2423, 2424, 2425, 2426, 2427, 2428, 2429, 2430, 2431, 2432, 2433, 2434, 2435, 2436, 2437, 2438, 2439, 2440, 2441, 2442, 2443, 2444, 2445, 2446, 2447, 2448, 2449, 2450, 2451, 2452, 2453, 2454, 2455, 2456, 2457, 2458, 2459, 2460, 2461, 2462, 2463, 2464, 2465, 2466, 2467, 2468, 2469, 2470, 2471, 2472, 2473, 2474, 2475, 2476, 2477, 2478, 2479, 2480, 2481, 2482, 2483, 2484, 2485, 2486, 2487, 2488, 2489, 2490, 2491, 2492, 2493, 2494, 2495, 2496, 2497, 2498, 2499, 2500, 2501, 2502, 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511, 2512, 2513, 2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, 2524, 2525, 2526, 2527, 2528, 2529, 2530, 2531, 2532, 2533, 2534, 2535, 2536, 2537, 2538, 2539, 2540, 2541, 2542, 2543, 2544, 2545, 2546, 2547, 2548, 2549, 2550, 2551, 2552, 2553, 2554, 2555, 2556, 2557, 2558, 2559, 2560, 2561, 2562, 2563, 2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, 2572, 2573, 2574, 2575, 2576, 2577, 2578, 2579, 2580, 2581, 2582, 2583, 2584, 2585, 2586, 2587, 2588, 2589, 2590, 2591, 2592, 2593, 2594, 2595, 2596, 2597, 2598, 2599, 2600, 2601, 2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611, 2612, 2613, 2614, 2615, 2616, 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626, 2627, 2628, 2629, 2630, 2631, 2632, 2633, 2634, 2635, 2636, 2637, 2638, 2639, 2640, 2641, 2642, 2643, 2644, 2645, 2646, 2647, 2648, 2649, 2650, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661, 2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676, 2677, 2678, 2679, 2680, 2681, 2682, 2683, 2684, 2685, 2686, 2687, 2688, 2689, 2690, 2691, 2692, 2693, 2694, 2695, 2696, 2697, 2698, 2699, 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, 2710, 2711, 2712, 2713, 2714, 2715, 2716, 2717, 2718, 2719, 2720, 2721, 2722, 2723, 2724, 2725, 2726, 2727, 2728, 2729, 2730, 2731, 2732, 2733, 2734, 2735, 2736, 2737, 2738, 2739, 2740, 2741, 2742, 2743, 2744, 2745, 2746, 2747, 2748, 2749, 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2760, 2761, 2762, 2763, 2764, 2765, 2766, 2767, 2768, 2769, 2770, 2771, 2772, 2773, 2774, 2775, 2776, 2777, 2778, 2779, 2780, 2781, 2782, 2783, 2784, 2785, 2786, 2787, 2788, 2789, 2790, 2791, 2792, 2793, 2794, 2795, 2796, 2797, 2798, 2799, 2800, 2801, 2802, 2803, 2804, 2805, 2806, 2807, 2808, 2809, 2810, 2811, 2812, 2813, 2814, 2815, 2816, 2817, 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825, 2826, 2827, 2828, 2829, 2830, 2831, 2832, 2833, 2834, 2835, 2836, 2837, 2838, 2839, 2840, 2841, 2842, 2843, 2844, 2845, 2846, 2847, 2848, 2849, 2850, 2851, 2852, 2853, 2854, 2855, 2856, 2857, 2858, 2859, 2860, 2861, 2862, 2863, 2864, 2865, 2866, 2867, 2868, 2869, 2870, 2871, 2872, 2873, 2874, 2875, 2876, 2877, 2878, 2879, 2880, 2881, 2882, 2883, 2884, 2885, 2886, 2887, 2888, 2889, 2890, 2891, 2892, 2893, 2894, 2895, 2896, 2897, 2898, 2899, 2900, 2901, 2902, 2903, 2904, 2905, 2906, 2907, 2908, 2909, 2910, 2911, 2912, 2913, 2914, 2915, 2916, 2917, 2918, 2919, 2920, 2921, 2922, 2923, 2924, 2925, 2926, 2927, 2928, 2929, 2930, 2931, 2932, 2933, 2934, 2935, 2936, 2937, 2938, 2939, 2940, 2941, 2942, 2943, 2944, 2945, 2946, 2947, 2948, 2949, 2950, 2951, 2952, 2953, 2954, 2955, 2956, 2957, 2958, 2959, 2960, 2961, 2962, 2963, 2964, 2965, 2966, 2967, 2968, 2969, 2970, 2971, 2972, 2973, 2974, 2975, 2976, 2977, 2978, 2979, 2980, 2981, 2982, 2983, 2984, 2985, 2986, 2987, 2988, 2989, 2990, 2991, 2992, 2993, 2994, 2995, 2996, 2997, 2998, 2999, 3000, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019, 3020, 3021, 3022, 3023, 3024, 3025, 3026, 3027, 3028, 3029, 3030, 3031, 3032, 3033, 3034, 3035, 3036, 3037, 3038, 3039, 3040, 3041, 3042, 3043, 3044, 3045, 3046, 3047, 3048, 3049, 3050, 3051, 3052, 3053, 3054, 3055, 3056, 3057, 3058, 3059, 3060, 3061, 3062, 3063, 3064, 3065, 3066, 3067, 3068, 3069, 3070, 3071, 3072, 3073, 3074, 3075, 3076, 3077, 3078, 3079, 3080, 3081, 3082, 3083, 3084, 3085, 3086, 3087, 3088, 3089, 3090, 3091, 3092, 3093, 3094, 3095, 3096, 3097, 3098, 3099, 3100, 3101, 3102, 3103, 3104, 3105, 3106, 3107, 3108, 3109, 3110, 3111, 3112, 3113, 3114, 3115, 3116, 3117, 3118, 3119, 3120, 3121, 3122, 3123, 3124, 3125, 3126, 3127, 3128, 3129, 3130, 3131, 3132, 3133, 3134, 3135, 3136, 3137, 3138, 3139, 3140, 3141, 3142, 3143, 3144, 3145, 3146, 3147, 3148, 3149, 3150, 3151, 3152, 3153, 3154, 3155, 3156, 3157, 3158, 3159, 3160, 3161, 3162, 3163, 3164, 3165, 3166, 3167, 3168, 3169, 3170, 3171, 3172, 3173, 3174, 3175, 3176, 3177, 3178, 3179, 3180, 3181, 3182, 3183, 3184, 3185, 3186, 3187, 3188, 3189, 3190, 3191, 3192, 3193, 3194, 3195, 3196, 3197, 3198, 3199, 3200, 3201, 3202, 3203, 3204, 3205, 3206, 3207, 3208, 3209, 3210, 3211, 3212, 3213, 3214, 3215, 3216, 3217, 3218, 3219, 3220, 3221, 3222, 3223, 3224, 3225, 3226, 3227, 3228, 3229, 3230, 3231, 3232, 3233, 3234, 3235, 3236, 3237, 3238, 3239, 3240, 3241, 3242, 3243, 3244, 3245, 3246, 3247, 3248, 3249, 3250, 3251, 3252, 3253, 3254, 3255, 3256, 3257, 3258, 3259, 3260, 3261, 3262, 3263, 3264, 3265, 3266, 3267, 3268, 3269, 3270, 3271, 3272, 3273, 3274, 3275, 3276, 3277, 3278, 3279, 3280, 3281, 3282, 3283, 3284, 3285, 3286, 3287, 3288, 3289, 3290, 3291, 3292, 3293, 3294, 3295, 3296, 3297, 3298, 3299, 3300, 3301, 3302, 3303, 3304, 3305, 3306, 3307, 3308, 3309, 3310, 3311, 3312, 3313, 3314, 3315, 3316, 3317, 3318, 3319, 3320, 3321, 3322, 3323, 3324, 3325, 3326, 3327, 3328, 3329, 3330, 3331, 3332, 3333, 3334, 3335, 3336, 3337, 3338, 3339, 3340, 3341, 3342, 3343, 3344, 3345, 3346, 3347, 3348, 3349, 3350, 3351, 3352, 3353, 3354, 3355, 3356, 3357, 3358, 3359, 3360, 3361, 3362, 3363, 3364, 3365, 3366, 3367, 3368, 3369, 3370, 3371, 3372, 3373, 3374, 3375, 3376, 3377, 3378, 3379, 3380, 3381, 3382, 3383, 3384, 3385, 3386, 3387, 3388, 3389, 3390, 3391, 3392, 3393, 3394, 3395, 3396, 3397, 3398, 3399, 3400, 3401, 3402, 3403, 3404, 3405, 3406, 3407, 3408, 3409, 3410, 3411, 3412, 3413, 3414, 3415, 3416, 3417, 3418, 3419, 3420, 3421, 3422, 3423, 3424, 3425, 3426, 3427, 3428, 3429, 3430, 3431, 3432, 3433, 3434, 3435, 3436, 3437, 3438, 3439, 3440, 3441, 3442, 3443, 3444, 3445, 3446, 3447, 3448, 3449, 3450, 3451, 3452, 3453, 3454, 3455, 3456, 3457, 3458, 3459, 3460, 3461, 3462, 3463, 3464, 3465, 3466, 3467, 3468, 3469, 3470, 3471, 3472, 3473, 3474, 3475, 3476, 3477, 3478, 3479, 3480, 3481, 3482, 3483, 3484, 3485, 3486, 3487, 3488, 3489, 3490, 3491, 3492, 3493, 3494, 3495, 3496, 3497, 3498, 3499, 3500, 3501, 3502, 3503, 3504, 3505, 3506, 3507, 3508, 3509, 3510, 3511, 3512, 3513, 3514, 3515, 3516, 3517, 3518, 3519, 3520, 3521, 3522, 3523, 3524, 3525, 3526, 3527, 3528, 3529, 3530, 3531, 3532, 3533, 3534, 3535, 3536, 3537, 3538, 3539, 3540, 3541, 3542, 3543, 3544, 3545, 3546, 3547, 3548, 3549, 3550, 3551, 3552, 3553, 3554, 3555, 3556, 3557, 3558, 3559, 3560, 3561, 3562, 3563, 3564, 3565, 3566, 3567, 3568, 3569, 3570, 3571, 3572, 3573, 3574, 3575, 3576, 3577, 3578, 3579, 3580, 3581, 3582, 3583, 3584, 3585, 3586, 3587, 3588, 3589, 3590, 3591, 3592, 3593, 3594, 3595, 3596, 3597, 3598, 3599, 3600, 3601, 3602, 3603, 3604, 3605, 3606, 3607, 3608, 3609, 3610, 3611, 3612, 3613, 3614, 3615, 3616, 3617, 3618, 3619, 3620, 3621, 3622, 3623, 3624, 3625, 3626, 3627, 3628, 3629, 3630, 3631, 3632, 3633, 3634, 3635, 3636, 3637, 3638, 3639, 3640, 3641, 3642, 3643, 3644, 3645, 3646, 3647, 3648, 3649, 3650, 3651, 3652, 3653, 3654, 3655, 3656, 3657, 3658, 3659, 3660, 3661, 3662, 3663, 3664, 3665, 3666, 3667, 3668, 3669, 3670, 3671, 3672, 3673, 3674, 3675, 3676, 3677, 3678, 3679, 3680, 3681, 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 3696, 3697, 3698, 3699, 3700, 3701, 3702, 3703, 3704, 3705, 3706, 3707, 3708, 3709, 3710, 3711, 3712, 3713, 3714, 3715, 3716, 3717, 3718, 3719, 3720, 3721, 3722, 3723, 3724, 3725, 3726, 3727, 3728, 3729, 3730, 3731, 3732, 3733, 3734, 3735, 3736, 3737, 3738, 3739, 3740, 3741, 3742, 3743, 3744, 3745, 3746, 3747, 3748, 3749, 3750, 3751, 3752, 3753, 3754, 3755, 3756, 3757, 3758, 3759, 3760, 3761, 3762, 3763, 3764, 3765, 3766, 3767, 3768, 3769, 3770, 3771, 3772, 3773, 3774, 3775, 3776, 3777, 3778, 3779, 3780, 3781, 3782, 3783, 3784, 3785, 3786, 3787, 3788, 3789, 3790, 3791, 3792, 3793, 3794, 3795, 3796, 3797, 3798, 3799, 3800, 3801, 3802, 3803, 3804, 3805, 3806, 3807, 3808, 3809, 3810, 3811, 3812, 3813, 3814, 3815, 3816, 3817, 3818, 3819, 3820, 3821, 3822, 3823, 3824, 3825, 3826, 3827, 3828, 3829, 3830, 3831, 3832, 3833, 3834, 3835, 3836, 3837, 3838, 3839, 3840, 3841, 3842, 3843, 3844, 3845, 3846, 3847, 3848, 3849, 3850, 3851, 3852, 3853, 3854, 3855, 3856, 3857, 3858, 3859, 3860, 3861, 3862, 3863, 3864, 3865, 3866, 3867, 3868, 3869, 3870, 3871, 3872, 3873, 3874, 3875, 3876, 3877, 3878, 3879, 3880, 3881, 3882, 3883, 3884, 3885, 3886, 3887, 3888, 3889, 3890, 3891, 3892, 3893, 3894, 3895, 3896, 3897, 3898, 3899, 3900, 3901, 3902, 3903, 3904, 3905, 3906, 3907, 3908, 3909, 3910, 3911, 3912, 3913, 3914, 3915, 3916, 3917, 3918, 3919, 3920, 3921, 3922, 3923, 3924, 3925, 3926, 3927, 3928, 3929, 3930, 3931, 3932, 3933, 3934, 3935, 3936, 3937, 3938, 3939, 3940, 3941, 3942, 3943, 3944, 3945, 3946, 3947, 3948, 3949, 3950, 3951, 3952, 3953, 3954, 3955, 3956, 3957, 3958, 3959, 3960, 3961, 3962, 3963, 3964, 3965, 3966, 3967, 3968, 3969, 3970, 3971, 3972, 3973, 3974, 3975, 3976, 3977, 3978, 3979, 3980, 3981, 3982, 3983, 3984, 3985, 3986, 3987, 3988, 3989, 3990, 3991, 3992, 3993, 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4035, 4036, 4037, 4038, 4039, 4040, 4041, 4042, 4043, 4044, 4045, 4046, 4047, 4048, 4049, 4050, 4051, 4052, 4053, 4054, 4055, 4056, 4057, 4058, 4059, 4060, 4061, 4062, 4063, 4064, 4065, 4066, 4067, 4068, 4069, 4070, 4071, 4072, 4073, 4074, 4075, 4076, 4077, 4078, 4079, 4080, 4081, 4082, 4083, 4084, 4085, 4086, 4087, 4088, 4089, 4090, 4091, 4092, 4093, 4094, 4095, 4096, 4097, 4098, 4099, 4100, 4101, 4102, 4103, 4104, 4105, 4106, 4107, 4108, 4109, 4110, 4111, 4112, 4113, 4114, 4115, 4116, 4117, 4118, 4119, 4120, 4121, 4122, 4123, 4124, 4125, 4126, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4140, 4141, 4142, 4143, 4144, 4145, 4146, 4147, 4148, 4149, 4150, 4151, 4152, 4153, 4154, 4155, 4156, 4157, 4158, 4159, 4160, 4161, 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4172, 4173, 4174, 4175, 4176, 4177, 4178, 4179, 4180, 4181, 4182, 4183, 4184, 4185, 4186, 4187, 4188, 4189, 4190, 4191, 4192, 4193, 4194, 4195, 4196, 4197, 4198, 4199, 4200, 4201, 4202, 4203, 4204, 4205, 4206, 4207, 4208, 4209, 4210, 4211, 4212, 4213, 4214, 4215, 4216, 4217, 4218, 4219, 4220, 4221, 4222, 4223, 4224, 4225, 4226, 4227, 4228, 4229, 4230, 4231, 4232, 4233, 4234, 4235, 4236, 4237, 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4245, 4246, 4247, 4248, 4249, 4250, 4251, 4252, 4253, 4254, 4255, 4256, 4257, 4258, 4259, 4260, 4261, 4262, 4263, 4264, 4265, 4266, 4267, 4268, 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4287, 4288, 4289, 4290, 4291, 4292, 4293, 4294, 4295, 4296, 4297, 4298, 4299, 4300, 4301, 4302, 4303, 4304, 4305, 4306, 4307, 4308, 4309, 4310, 4311, 4312, 4313, 4314, 4315, 4316, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325, 4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339, 4340, 4341, 4342, 4343, 4344, 4345, 4346, 4347, 4348, 4349, 4350, 4351, 4352, 4353, 4354, 4355, 4356, 4357, 4358, 4359, 4360, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, 4371, 4372, 4373, 4374, 4375, 4376, 4377, 4378, 4379, 4380, 4381, 4382, 4383, 4384, 4385, 4386, 4387, 4388, 4389, 4390, 4391, 4392, 4393, 4394, 4395, 4396, 4397, 4398, 4399, 4400, 4401, 4402, 4403, 4404, 4405, 4406, 4407, 4408, 4409, 4410, 4411, 4412, 4413, 4414, 4415, 4416, 4417, 4418, 4419, 4420, 4421, 4422, 4423, 4424, 4425, 4426, 4427, 4428, 4429, 4430, 4431, 4432, 4433, 4434, 4435, 4436, 4437, 4438, 4439, 4440, 4441, 4442, 4443, 4444, 4445, 4446, 4447, 4448, 4449, 4450, 4451, 4452, 4453, 4454, 4455, 4456, 4457, 4458, 4459, 4460, 4461, 4462, 4463, 4464, 4465, 4466, 4467, 4468, 4469, 4470, 4471, 4472, 4473, 4474, 4475, 4476, 4477, 4478, 4479, 4480, 4481, 4482, 4483, 4484, 4485, 4486, 4487, 4488, 4489, 4490, 4491, 4492, 4493, 4494, 4495, 4496, 4497, 4498, 4499, 4500, 4501, 4502, 4503, 4504, 4505, 4506, 4507, 4508, 4509, 4510, 4511, 4512, 4513, 4514, 4515, 4516, 4517, 4518, 4519, 4520, 4521, 4522, 4523, 4524, 4525, 4526, 4527, 4528, 4529, 4530, 4531, 4532, 4533, 4534, 4535, 4536, 4537, 4538, 4539, 4540, 4541, 4542, 4543, 4544, 4545, 4546, 4547, 4548, 4549, 4550, 4551, 4552, 4553, 4554, 4555, 4556, 4557, 4558, 4559, 4560, 4561, 4562, 4563, 4564, 4565, 4566, 4567, 4568, 4569, 4570, 4571, 4572, 4573, 4574, 4575, 4576, 4577, 4578, 4579, 4580, 4581, 4582, 4583, 4584, 4585, 4586, 4587, 4588, 4589, 4590, 4591, 4592, 4593, 4594, 4595, 4596, 4597, 4598, 4599, 4600, 4601, 4602, 4603, 4604, 4605, 4606, 4607, 4608, 4609, 4610, 4611, 4612, 4613, 4614, 4615, 4616, 4617, 4618, 4619, 4620, 4621, 4622, 4623, 4624, 4625, 4626, 4627, 4628, 4629, 4630, 4631, 4632, 4633, 4634, 4635, 4636, 4637, 4638, 4639, 4640, 4641, 4642, 4643, 4644, 4645, 4646, 4647, 4648, 4649, 4650, 4651, 4652, 4653, 4654, 4655, 4656, 4657, 4658, 4659, 4660, 4661, 4662, 4663, 4664, 4665, 4666, 4667, 4668, 4669, 4670, 4671, 4672, 4673, 4674, 4675, 4676, 4677, 4678, 4679, 4680, 4681, 4682, 4683, 4684, 4685, 4686, 4687, 4688, 4689, 4690, 4691, 4692, 4693, 4694, 4695, 4696, 4697, 4698, 4699, 4700, 4701, 4702, 4703, 4704, 4705, 4706, 4707, 4708, 4709, 4710, 4711, 4712, 4713, 4714, 4715, 4716, 4717, 4718, 4719, 4720, 4721, 4722, 4723, 4724, 4725, 4726, 4727, 4728, 4729, 4730, 4731, 4732, 4733, 4734, 4735, 4736, 4737, 4738, 4739, 4740, 4741, 4742, 4743, 4744, 4745, 4746, 4747, 4748, 4749, 4750, 4751, 4752, 4753, 4754, 4755, 4756, 4757, 4758, 4759, 4760, 4761, 4762, 4763, 4764, 4765, 4766, 4767, 4768, 4769, 4770, 4771, 4772, 4773, 4774, 4775, 4776, 4777, 4778, 4779, 4780, 4781, 4782, 4783, 4784, 4785, 4786, 4787, 4788, 4789, 4790, 4791, 4792, 4793, 4794, 4795, 4796, 4797, 4798, 4799, 4800, 4801, 4802, 4803, 4804, 4805, 4806, 4807, 4808, 4809, 4810, 4811, 4812, 4813, 4814, 4815, 4816, 4817, 4818, 4819, 4820, 4821, 4822, 4823, 4824, 4825, 4826, 4827, 4828, 4829, 4830, 4831, 4832, 4833, 4834, 4835, 4836, 4837, 4838, 4839, 4840, 4841, 4842, 4843, 4844, 4845, 4846, 4847, 4848, 4849, 4850, 4851, 4852, 4853, 4854, 4855, 4856, 4857, 4858, 4859, 4860, 4861, 4862, 4863, 4864, 4865, 4866, 4867, 4868, 4869, 4870, 4871, 4872, 4873, 4874, 4875, 4876, 4877, 4878, 4879, 4880, 4881, 4882, 4883, 4884, 4885, 4886, 4887, 4888, 4889, 4890, 4891, 4892, 4893, 4894, 4895, 4896, 4897, 4898, 4899, 4900, 4901, 4902, 4903, 4904, 4905, 4906, 4907, 4908, 4909, 4910, 4911, 4912, 4913, 4914, 4915, 4916, 4917, 4918, 4919, 4920, 4921, 4922, 4923, 4924, 4925, 4926, 4927, 4928, 4929, 4930, 4931, 4932, 4933, 4934, 4935, 4936, 4937, 4938, 4939, 4940, 4941, 4942, 4943, 4944, 4945, 4946, 4947, 4948, 4949, 4950, 4951, 4952, 4953, 4954, 4955, 4956, 4957, 4958, 4959, 4960, 4961, 4962, 4963, 4964, 4965, 4966, 4967, 4968, 4969, 4970, 4971, 4972, 4973, 4974, 4975, 4976, 4977, 4978, 4979, 4980, 4981, 4982, 4983, 4984, 4985, 4986, 4987, 4988, 4989, 4990, 4991, 4992, 4993, 4994, 4995, 4996, 4997, 4998, 4999, 5000, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012, 5013, 5014, 5015, 5016, 5017, 5018, 5019, 5020, 5021, 5022, 5023, 5024, 5025, 5026, 5027, 5028, 5029, 5030, 5031, 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042, 5043, 5044, 5045, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055, 5056, 5057, 5058, 5059, 5060, 5061, 5062, 5063, 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 5072, 5073, 5074, 5075, 5076, 5077, 5078, 5079, 5080, 5081, 5082, 5083, 5084, 5085, 5086, 5087, 5088, 5089, 5090, 5091, 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, 5100, 5101, 5102, 5103, 5104, 5105, 5106, 5107, 5108, 5109, 5110, 5111, 5112, 5113, 5114, 5115, 5116, 5117, 5118, 5119, 5120, 5121, 5122, 5123, 5124, 5125, 5126, 5127, 5128, 5129, 5130, 5131, 5132, 5133, 5134, 5135, 5136, 5137, 5138, 5139, 5140, 5141, 5142, 5143, 5144, 5145, 5146, 5147, 5148, 5149, 5150, 5151, 5152, 5153, 5154, 5155, 5156, 5157, 5158, 5159, 5160, 5161, 5162, 5163, 5164, 5165, 5166, 5167, 5168, 5169, 5170, 5171, 5172, 5173, 5174, 5175, 5176, 5177, 5178, 5179, 5180, 5181, 5182, 5183, 5184, 5185, 5186, 5187, 5188, 5189, 5190, 5191, 5192, 5193, 5194, 5195, 5196, 5197, 5198, 5199, 5200, 5201, 5202, 5203, 5204, 5205, 5206, 5207, 5208, 5209, 5210, 5211, 5212, 5213, 5214, 5215, 5216, 5217, 5218, 5219, 5220, 5221, 5222, 5223, 5224, 5225, 5226, 5227, 5228, 5229, 5230, 5231, 5232, 5233, 5234, 5235, 5236, 5237, 5238, 5239, 5240, 5241, 5242, 5243, 5244, 5245, 5246, 5247, 5248, 5249, 5250, 5251, 5252, 5253, 5254, 5255, 5256, 5257, 5258, 5259, 5260, 5261, 5262, 5263, 5264, 5265, 5266, 5267, 5268, 5269, 5270, 5271, 5272, 5273, 5274, 5275, 5276, 5277, 5278, 5279, 5280, 5281, 5282, 5283, 5284, 5285, 5286, 5287, 5288, 5289, 5290, 5291, 5292, 5293, 5294, 5295, 5296, 5297, 5298, 5299, 5300, 5301, 5302, 5303, 5304, 5305, 5306, 5307, 5308, 5309, 5310, 5311, 5312, 5313, 5314, 5315, 5316, 5317, 5318, 5319, 5320, 5321, 5322, 5323, 5324, 5325, 5326, 5327, 5328, 5329, 5330, 5331, 5332, 5333, 5334, 5335, 5336, 5337, 5338, 5339, 5340, 5341, 5342, 5343, 5344, 5345, 5346, 5347, 5348, 5349, 5350, 5351, 5352, 5353, 5354, 5355, 5356, 5357, 5358, 5359, 5360, 5361, 5362, 5363, 5364, 5365, 5366, 5367, 5368, 5369, 5370, 5371, 5372, 5373, 5374, 5375, 5376, 5377, 5378, 5379, 5380, 5381, 5382, 5383, 5384, 5385, 5386, 5387, 5388, 5389, 5390, 5391, 5392, 5393, 5394, 5395, 5396, 5397, 5398, 5399, 5400, 5401, 5402, 5403, 5404, 5405, 5406, 5407, 5408, 5409, 5410, 5411, 5412, 5413, 5414, 5415, 5416, 5417, 5418, 5419, 5420, 5421, 5422, 5423, 5424, 5425, 5426, 5427, 5428, 5429, 5430, 5431, 5432, 5433, 5434, 5435, 5436, 5437, 5438, 5439, 5440, 5441, 5442, 5443, 5444, 5445, 5446, 5447, 5448, 5449, 5450, 5451, 5452, 5453, 5454, 5455, 5456, 5457, 5458, 5459, 5460, 5461, 5462, 5463, 5464, 5465, 5466, 5467, 5468, 5469, 5470, 5471, 5472, 5473, 5474, 5475, 5476, 5477, 5478, 5479, 5480, 5481, 5482, 5483, 5484, 5485, 5486, 5487, 5488, 5489, 5490, 5491, 5492, 5493, 5494, 5495, 5496, 5497, 5498, 5499, 5500, 5501, 5502, 5503, 5504, 5505, 5506, 5507, 5508, 5509, 5510, 5511, 5512, 5513, 5514, 5515, 5516, 5517, 5518, 5519, 5520, 5521, 5522, 5523, 5524, 5525, 5526, 5527, 5528, 5529, 5530, 5531, 5532, 5533, 5534, 5535, 5536, 5537, 5538, 5539, 5540, 5541, 5542, 5543, 5544, 5545, 5546, 5547, 5548, 5549, 5550, 5551, 5552, 5553, 5554, 5555, 5556, 5557, 5558, 5559, 5560, 5561, 5562, 5563, 5564, 5565, 5566, 5567, 5568, 5569, 5570, 5571, 5572, 5573, 5574, 5575, 5576, 5577, 5578, 5579, 5580, 5581, 5582, 5583, 5584, 5585, 5586, 5587, 5588, 5589, 5590, 5591, 5592, 5593, 5594, 5595, 5596, 5597, 5598, 5599, 5600, 5601, 5602, 5603, 5604, 5605, 5606, 5607, 5608, 5609, 5610, 5611, 5612, 5613, 5614, 5615, 5616, 5617, 5618, 5619, 5620, 5621, 5622, 5623, 5624, 5625, 5626, 5627, 5628, 5629, 5630, 5631, 5632, 5633, 5634, 5635, 5636, 5637, 5638, 5639, 5640, 5641, 5642, 5643, 5644, 5645, 5646, 5647, 5648, 5649, 5650, 5651, 5652, 5653, 5654, 5655, 5656, 5657, 5658, 5659, 5660, 5661, 5662, 5663, 5664, 5665, 5666, 5667, 5668, 5669, 5670, 5671, 5672, 5673, 5674, 5675, 5676, 5677, 5678, 5679, 5680, 5681, 5682, 5683, 5684, 5685, 5686, 5687, 5688, 5689, 5690, 5691, 5692, 5693, 5694, 5695, 5696, 5697, 5698, 5699, 5700, 5701, 5702, 5703, 5704, 5705, 5706, 5707, 5708, 5709, 5710, 5711, 5712, 5713, 5714, 5715, 5716, 5717, 5718, 5719, 5720, 5721, 5722, 5723, 5724, 5725, 5726, 5727, 5728, 5729, 5730, 5731, 5732, 5733, 5734, 5735, 5736, 5737, 5738, 5739, 5740, 5741, 5742, 5743, 5744, 5745, 5746, 5747, 5748, 5749, 5750, 5751, 5752, 5753, 5754, 5755, 5756, 5757, 5758, 5759, 5760, 5761, 5762, 5763, 5764, 5765, 5766, 5767, 5768, 5769, 5770, 5771, 5772, 5773, 5774, 5775, 5776, 5777, 5778, 5779, 5780, 5781, 5782, 5783, 5784, 5785, 5786, 5787, 5788, 5789, 5790, 5791, 5792, 5793, 5794, 5795, 5796, 5797, 5798, 5799, 5800, 5801, 5802, 5803, 5804, 5805, 5806, 5807, 5808, 5809, 5810, 5811, 5812, 5813, 5814, 5815, 5816, 5817, 5818, 5819, 5820, 5821, 5822, 5823, 5824, 5825, 5826, 5827, 5828, 5829, 5830, 5831, 5832, 5833, 5834, 5835, 5836, 5837, 5838, 5839, 5840, 5841, 5842, 5843, 5844, 5845, 5846, 5847, 5848, 5849, 5850, 5851, 5852, 5853, 5854, 5855, 5856, 5857, 5858, 5859, 5860, 5861, 5862, 5863, 5864, 5865, 5866, 5867, 5868, 5869, 5870, 5871, 5872, 5873, 5874, 5875, 5876, 5877, 5878, 5879, 5880, 5881, 5882, 5883, 5884, 5885, 5886, 5887, 5888, 5889, 5890, 5891, 5892, 5893, 5894, 5895, 5896, 5897, 5898, 5899, 5900, 5901, 5902, 5903, 5904, 5905, 5906, 5907, 5908, 5909, 5910, 5911, 5912, 5913, 5914, 5915, 5916, 5917, 5918, 5919, 5920, 5921, 5922, 5923, 5924, 5925, 5926, 5927, 5928, 5929, 5930, 5931, 5932, 5933, 5934, 5935, 5936, 5937, 5938, 5939, 5940, 5941, 5942, 5943, 5944, 5945, 5946, 5947, 5948, 5949, 5950, 5951, 5952, 5953, 5954, 5955, 5956, 5957, 5958, 5959, 5960, 5961, 5962, 5963, 5964, 5965, 5966, 5967, 5968, 5969, 5970, 5971, 5972, 5973, 5974, 5975, 5976, 5977, 5978, 5979, 5980, 5981, 5982, 5983, 5984, 5985, 5986, 5987, 5988, 5989, 5990, 5991, 5992, 5993, 5994, 5995, 5996, 5997, 5998, 5999, 6000, 6001, 6002, 6003, 6004, 6005, 6006, 6007, 6008, 6009, 6010, 6011, 6012, 6013, 6014, 6015, 6016, 6017, 6018, 6019, 6020, 6021, 6022, 6023, 6024, 6025, 6026, 6027, 6028, 6029, 6030, 6031, 6032, 6033, 6034, 6035, 6036, 6037, 6038, 6039, 6040, 6041, 6042, 6043, 6044, 6045, 6046, 6047, 6048, 6049, 6050, 6051, 6052, 6053, 6054, 6055, 6056, 6057, 6058, 6059, 6060, 6061, 6062, 6063, 6064, 6065, 6066, 6067, 6068, 6069, 6070, 6071, 6072, 6073, 6074, 6075, 6076, 6077, 6078, 6079, 6080, 6081, 6082, 6083, 6084, 6085, 6086, 6087, 6088, 6089, 6090, 6091, 6092, 6093, 6094, 6095, 6096, 6097, 6098, 6099, 6100, 6101, 6102, 6103, 6104, 6105, 6106, 6107, 6108, 6109, 6110, 6111, 6112, 6113, 6114, 6115, 6116, 6117, 6118, 6119, 6120, 6121, 6122, 6123, 6124, 6125, 6126, 6127, 6128, 6129, 6130, 6131, 6132, 6133, 6134, 6135, 6136, 6137, 6138, 6139, 6140, 6141, 6142, 6143, 6144, 6145, 6146, 6147, 6148, 6149, 6150, 6151, 6152, 6153, 6154, 6155, 6156, 6157, 6158, 6159, 6160, 6161, 6162, 6163, 6164, 6165, 6166, 6167, 6168, 6169, 6170, 6171, 6172, 6173, 6174, 6175, 6176, 6177, 6178, 6179, 6180, 6181, 6182, 6183, 6184, 6185, 6186, 6187, 6188, 6189, 6190, 6191, 6192, 6193, 6194, 6195, 6196, 6197, 6198, 6199, 6200, 6201, 6202, 6203, 6204, 6205, 6206, 6207, 6208, 6209, 6210, 6211, 6212, 6213, 6214, 6215, 6216, 6217, 6218, 6219, 6220, 6221, 6222, 6223, 6224, 6225, 6226, 6227, 6228, 6229, 6230, 6231, 6232, 6233, 6234, 6235, 6236, 6237, 6238, 6239, 6240, 6241, 6242, 6243, 6244, 6245, 6246, 6247, 6248, 6249, 6250, 6251, 6252, 6253, 6254, 6255, 6256, 6257, 6258, 6259, 6260, 6261, 6262, 6263, 6264, 6265, 6266, 6267, 6268, 6269, 6270, 6271, 6272, 6273, 6274, 6275, 6276, 6277, 6278, 6279, 6280, 6281, 6282, 6283, 6284, 6285, 6286, 6287, 6288, 6289, 6290, 6291, 6292, 6293, 6294, 6295, 6296, 6297, 6298, 6299, 6300, 6301, 6302, 6303, 6304, 6305, 6306, 6307, 6308, 6309, 6310, 6311, 6312, 6313, 6314, 6315, 6316, 6317, 6318, 6319, 6320, 6321, 6322, 6323, 6324, 6325, 6326, 6327, 6328, 6329, 6330, 6331, 6332, 6333, 6334, 6335, 6336, 6337, 6338, 6339, 6340, 6341, 6342, 6343, 6344, 6345, 6346, 6347, 6348, 6349, 6350, 6351, 6352, 6353, 6354, 6355, 6356, 6357, 6358, 6359, 6360, 6361, 6362, 6363, 6364, 6365, 6366, 6367, 6368, 6369, 6370, 6371, 6372, 6373, 6374, 6375, 6376, 6377, 6378, 6379, 6380, 6381, 6382, 6383, 6384, 6385, 6386, 6387, 6388, 6389, 6390, 6391, 6392, 6393, 6394, 6395, 6396, 6397, 6398, 6399, 6400, 6401, 6402, 6403, 6404, 6405, 6406, 6407, 6408, 6409, 6410, 6411, 6412, 6413, 6414, 6415, 6416, 6417, 6418, 6419, 6420, 6421, 6422, 6423, 6424, 6425, 6426, 6427, 6428, 6429, 6430, 6431, 6432, 6433, 6434, 6435, 6436, 6437, 6438, 6439, 6440, 6441, 6442, 6443, 6444, 6445, 6446, 6447, 6448, 6449, 6450, 6451, 6452, 6453, 6454, 6455, 6456, 6457, 6458, 6459, 6460, 6461, 6462, 6463, 6464, 6465, 6466, 6467, 6468, 6469, 6470, 6471, 6472, 6473, 6474, 6475, 6476, 6477, 6478, 6479, 6480, 6481, 6482, 6483, 6484, 6485, 6486, 6487, 6488, 6489, 6490, 6491, 6492, 6493, 6494, 6495, 6496, 6497, 6498, 6499, 6500, 6501, 6502, 6503, 6504, 6505, 6506, 6507, 6508, 6509, 6510, 6511, 6512, 6513, 6514, 6515, 6516, 6517, 6518, 6519, 6520, 6521, 6522, 6523, 6524, 6525, 6526, 6527, 6528, 6529, 6530, 6531, 6532, 6533, 6534, 6535, 6536, 6537, 6538, 6539, 6540, 6541, 6542, 6543, 6544, 6545, 6546, 6547, 6548, 6549, 6550, 6551, 6552, 6553, 6554, 6555, 6556, 6557, 6558, 6559, 6560, 6561, 6562, 6563, 6564, 6565, 6566, 6567, 6568, 6569, 6570, 6571, 6572, 6573, 6574, 6575, 6576, 6577, 6578, 6579, 6580, 6581, 6582, 6583, 6584, 6585, 6586, 6587, 6588, 6589, 6590, 6591, 6592, 6593, 6594, 6595, 6596, 6597, 6598, 6599, 6600, 6601, 6602, 6603, 6604, 6605, 6606, 6607, 6608, 6609, 6610, 6611, 6612, 6613, 6614, 6615, 6616, 6617, 6618, 6619, 6620, 6621, 6622, 6623, 6624, 6625, 6626, 6627, 6628, 6629, 6630, 6631, 6632, 6633, 6634, 6635, 6636, 6637, 6638, 6639, 6640, 6641, 6642, 6643, 6644, 6645, 6646, 6647, 6648, 6649, 6650, 6651, 6652, 6653, 6654, 6655, 6656, 6657, 6658, 6659, 6660, 6661, 6662, 6663, 6664, 6665, 6666, 6667, 6668, 6669, 6670, 6671, 6672, 6673, 6674, 6675, 6676, 6677, 6678, 6679, 6680, 6681, 6682, 6683, 6684, 6685, 6686, 6687, 6688, 6689, 6690, 6691, 6692, 6693, 6694, 6695, 6696, 6697, 6698, 6699, 6700, 6701, 6702, 6703, 6704, 6705, 6706, 6707, 6708, 6709, 6710, 6711, 6712, 6713, 6714, 6715, 6716, 6717, 6718, 6719, 6720, 6721, 6722, 6723, 6724, 6725, 6726, 6727, 6728, 6729, 6730, 6731, 6732, 6733, 6734, 6735, 6736, 6737, 6738, 6739, 6740, 6741, 6742, 6743, 6744, 6745, 6746, 6747, 6748, 6749, 6750, 6751, 6752, 6753, 6754, 6755, 6756, 6757, 6758, 6759, 6760, 6761, 6762, 6763, 6764, 6765, 6766, 6767, 6768, 6769, 6770, 6771, 6772, 6773, 6774, 6775, 6776, 6777, 6778, 6779, 6780, 6781, 6782, 6783, 6784, 6785, 6786, 6787, 6788, 6789, 6790, 6791, 6792, 6793, 6794, 6795, 6796, 6797, 6798, 6799, 6800, 6801, 6802, 6803, 6804, 6805, 6806, 6807, 6808, 6809, 6810, 6811, 6812, 6813, 6814, 6815, 6816, 6817, 6818, 6819, 6820, 6821, 6822, 6823, 6824, 6825, 6826, 6827, 6828, 6829, 6830, 6831, 6832, 6833, 6834, 6835, 6836, 6837, 6838, 6839, 6840, 6841, 6842, 6843, 6844, 6845, 6846, 6847, 6848, 6849, 6850, 6851, 6852, 6853, 6854, 6855, 6856, 6857, 6858, 6859, 6860, 6861, 6862, 6863, 6864, 6865, 6866, 6867, 6868, 6869, 6870, 6871, 6872, 6873, 6874, 6875, 6876, 6877, 6878, 6879, 6880, 6881, 6882, 6883, 6884, 6885, 6886, 6887, 6888, 6889, 6890, 6891, 6892, 6893, 6894, 6895, 6896, 6897, 6898, 6899, 6900, 6901, 6902, 6903, 6904, 6905, 6906, 6907, 6908, 6909, 6910, 6911, 6912, 6913, 6914, 6915, 6916, 6917, 6918, 6919, 6920, 6921, 6922, 6923, 6924, 6925, 6926, 6927, 6928, 6929, 6930, 6931, 6932, 6933, 6934, 6935, 6936, 6937, 6938, 6939, 6940, 6941, 6942, 6943, 6944, 6945, 6946, 6947, 6948, 6949, 6950, 6951, 6952, 6953, 6954, 6955, 6956, 6957, 6958, 6959, 6960, 6961, 6962, 6963, 6964, 6965, 6966, 6967, 6968, 6969, 6970, 6971, 6972, 6973, 6974, 6975, 6976, 6977, 6978, 6979, 6980, 6981, 6982, 6983, 6984, 6985, 6986, 6987, 6988, 6989, 6990, 6991, 6992, 6993, 6994, 6995, 6996, 6997, 6998, 6999, 7000, 7001, 7002, 7003, 7004, 7005, 7006, 7007, 7008, 7009, 7010, 7011, 7012, 7013, 7014, 7015, 7016, 7017, 7018, 7019, 7020, 7021, 7022, 7023, 7024, 7025, 7026, 7027, 7028, 7029, 7030, 7031, 7032, 7033, 7034, 7035, 7036, 7037, 7038, 7039, 7040, 7041, 7042, 7043, 7044, 7045, 7046, 7047, 7048, 7049, 7050, 7051, 7052, 7053, 7054, 7055, 7056, 7057, 7058, 7059, 7060, 7061, 7062, 7063, 7064, 7065, 7066, 7067, 7068, 7069, 7070, 7071, 7072, 7073, 7074, 7075, 7076, 7077, 7078, 7079, 7080, 7081, 7082, 7083, 7084, 7085, 7086, 7087, 7088, 7089, 7090, 7091, 7092, 7093, 7094, 7095, 7096, 7097, 7098, 7099, 7100, 7101, 7102, 7103, 7104, 7105, 7106, 7107, 7108, 7109, 7110, 7111, 7112, 7113, 7114, 7115, 7116, 7117, 7118, 7119, 7120, 7121, 7122, 7123, 7124, 7125, 7126, 7127, 7128, 7129, 7130, 7131, 7132, 7133, 7134, 7135, 7136, 7137, 7138, 7139, 7140, 7141, 7142, 7143, 7144, 7145, 7146, 7147, 7148, 7149, 7150, 7151, 7152, 7153, 7154, 7155, 7156, 7157, 7158, 7159, 7160, 7161, 7162, 7163, 7164, 7165, 7166, 7167, 7168, 7169, 7170, 7171, 7172, 7173, 7174, 7175, 7176, 7177, 7178, 7179, 7180, 7181, 7182, 7183, 7184, 7185, 7186, 7187, 7188, 7189, 7190, 7191, 7192, 7193, 7194, 7195, 7196, 7197, 7198, 7199, 7200, 7201, 7202, 7203, 7204, 7205, 7206, 7207, 7208, 7209, 7210, 7211, 7212, 7213, 7214, 7215, 7216, 7217, 7218, 7219, 7220, 7221, 7222, 7223, 7224, 7225, 7226, 7227, 7228, 7229, 7230, 7231, 7232, 7233, 7234, 7235, 7236, 7237, 7238, 7239, 7240, 7241, 7242, 7243, 7244, 7245, 7246, 7247, 7248, 7249, 7250, 7251, 7252, 7253, 7254, 7255, 7256, 7257, 7258, 7259, 7260, 7261, 7262, 7263, 7264, 7265, 7266, 7267, 7268, 7269, 7270, 7271, 7272, 7273, 7274, 7275, 7276, 7277, 7278, 7279, 7280, 7281, 7282, 7283, 7284, 7285, 7286, 7287, 7288, 7289, 7290, 7291, 7292, 7293, 7294, 7295, 7296, 7297, 7298, 7299, 7300, 7301, 7302, 7303, 7304, 7305, 7306, 7307, 7308, 7309, 7310, 7311, 7312, 7313, 7314, 7315, 7316, 7317, 7318, 7319, 7320, 7321, 7322, 7323, 7324, 7325, 7326, 7327, 7328, 7329, 7330, 7331, 7332, 7333, 7334, 7335, 7336, 7337, 7338, 7339, 7340, 7341, 7342, 7343, 7344, 7345, 7346, 7347, 7348, 7349, 7350, 7351, 7352, 7353, 7354, 7355, 7356, 7357, 7358, 7359, 7360, 7361, 7362, 7363, 7364, 7365, 7366, 7367, 7368, 7369, 7370, 7371, 7372, 7373, 7374, 7375, 7376, 7377, 7378, 7379, 7380, 7381, 7382, 7383, 7384, 7385, 7386, 7387, 7388, 7389, 7390, 7391, 7392, 7393, 7394, 7395, 7396, 7397, 7398, 7399, 7400, 7401, 7402, 7403, 7404, 7405, 7406, 7407, 7408, 7409, 7410, 7411, 7412, 7413, 7414, 7415, 7416, 7417, 7418, 7419, 7420, 7421, 7422, 7423, 7424, 7425, 7426, 7427, 7428, 7429, 7430, 7431, 7432, 7433, 7434, 7435, 7436, 7437, 7438, 7439, 7440, 7441, 7442, 7443, 7444, 7445, 7446, 7447, 7448, 7449, 7450, 7451, 7452, 7453, 7454, 7455, 7456, 7457, 7458, 7459, 7460, 7461, 7462, 7463, 7464, 7465, 7466, 7467, 7468, 7469, 7470, 7471, 7472, 7473, 7474, 7475, 7476, 7477, 7478, 7479, 7480, 7481, 7482, 7483, 7484, 7485, 7486, 7487, 7488, 7489, 7490, 7491, 7492, 7493, 7494, 7495, 7496, 7497, 7498, 7499, 7500, 7501, 7502, 7503, 7504, 7505, 7506, 7507, 7508, 7509, 7510, 7511, 7512, 7513, 7514, 7515, 7516, 7517, 7518, 7519, 7520, 7521, 7522, 7523, 7524, 7525, 7526, 7527, 7528, 7529, 7530, 7531, 7532, 7533, 7534, 7535, 7536, 7537, 7538, 7539, 7540, 7541, 7542, 7543, 7544, 7545, 7546, 7547, 7548, 7549, 7550, 7551, 7552, 7553, 7554, 7555, 7556, 7557, 7558, 7559, 7560, 7561, 7562, 7563, 7564, 7565, 7566, 7567, 7568, 7569, 7570, 7571, 7572, 7573, 7574, 7575, 7576, 7577, 7578, 7579, 7580, 7581, 7582, 7583, 7584, 7585, 7586, 7587, 7588, 7589, 7590, 7591, 7592, 7593, 7594, 7595, 7596, 7597, 7598, 7599, 7600, 7601, 7602, 7603, 7604, 7605, 7606, 7607, 7608, 7609, 7610, 7611, 7612, 7613, 7614, 7615, 7616, 7617, 7618, 7619, 7620, 7621, 7622, 7623, 7624, 7625, 7626, 7627, 7628, 7629, 7630, 7631, 7632, 7633, 7634, 7635, 7636, 7637, 7638, 7639, 7640, 7641, 7642, 7643, 7644, 7645, 7646, 7647, 7648, 7649, 7650, 7651, 7652, 7653, 7654, 7655, 7656, 7657, 7658, 7659, 7660, 7661, 7662, 7663, 7664, 7665, 7666, 7667, 7668, 7669, 7670, 7671, 7672, 7673, 7674, 7675, 7676, 7677, 7678, 7679, 7680, 7680, 7682, 7682, 7684, 7684, 7686, 7686, 7688, 7688, 7690, 7690, 7692, 7692, 7694, 7694, 7696, 7696, 7698, 7698, 7700, 7700, 7702, 7702, 7704, 7704, 7706, 7706, 7708, 7708, 7710, 7710, 7712, 7712, 7714, 7714, 7716, 7716, 7718, 7718, 7720, 7720, 7722, 7722, 7724, 7724, 7726, 7726, 7728, 7728, 7730, 7730, 7732, 7732, 7734, 7734, 7736, 7736, 7738, 7738, 7740, 7740, 7742, 7742, 7744, 7744, 7746, 7746, 7748, 7748, 7750, 7750, 7752, 7752, 7754, 7754, 7756, 7756, 7758, 7758, 7760, 7760, 7762, 7762, 7764, 7764, 7766, 7766, 7768, 7768, 7770, 7770, 7772, 7772, 7774, 7774, 7776, 7776, 7778, 7778, 7780, 7780, 7782, 7782, 7784, 7784, 7786, 7786, 7788, 7788, 7790, 7790, 7792, 7792, 7794, 7794, 7796, 7796, 7798, 7798, 7800, 7800, 7802, 7802, 7804, 7804, 7806, 7806, 7808, 7808, 7810, 7810, 7812, 7812, 7814, 7814, 7816, 7816, 7818, 7818, 7820, 7820, 7822, 7822, 7824, 7824, 7826, 7826, 7828, 7828, 7830, 7831, 7832, 7833, 7834, 7835, 7836, 7837, 7838, 7839, 7840, 7840, 7842, 7842, 7844, 7844, 7846, 7846, 7848, 7848, 7850, 7850, 7852, 7852, 7854, 7854, 7856, 7856, 7858, 7858, 7860, 7860, 7862, 7862, 7864, 7864, 7866, 7866, 7868, 7868, 7870, 7870, 7872, 7872, 7874, 7874, 7876, 7876, 7878, 7878, 7880, 7880, 7882, 7882, 7884, 7884, 7886, 7886, 7888, 7888, 7890, 7890, 7892, 7892, 7894, 7894, 7896, 7896, 7898, 7898, 7900, 7900, 7902, 7902, 7904, 7904, 7906, 7906, 7908, 7908, 7910, 7910, 7912, 7912, 7914, 7914, 7916, 7916, 7918, 7918, 7920, 7920, 7922, 7922, 7924, 7924, 7926, 7926, 7928, 7928, 7930, 7931, 7932, 7933, 7934, 7935, 7944, 7945, 7946, 7947, 7948, 7949, 7950, 7951, 7944, 7945, 7946, 7947, 7948, 7949, 7950, 7951, 7960, 7961, 7962, 7963, 7964, 7965, 7958, 7959, 7960, 7961, 7962, 7963, 7964, 7965, 7966, 7967, 7976, 7977, 7978, 7979, 7980, 7981, 7982, 7983, 7976, 7977, 7978, 7979, 7980, 7981, 7982, 7983, 7992, 7993, 7994, 7995, 7996, 7997, 7998, 7999, 7992, 7993, 7994, 7995, 7996, 7997, 7998, 7999, 8008, 8009, 8010, 8011, 8012, 8013, 8006, 8007, 8008, 8009, 8010, 8011, 8012, 8013, 8014, 8015, 8016, 8025, 8018, 8027, 8020, 8029, 8022, 8031, 8024, 8025, 8026, 8027, 8028, 8029, 8030, 8031, 8040, 8041, 8042, 8043, 8044, 8045, 8046, 8047, 8040, 8041, 8042, 8043, 8044, 8045, 8046, 8047, 8122, 8123, 8136, 8137, 8138, 8139, 8154, 8155, 8184, 8185, 8170, 8171, 8186, 8187, 8062, 8063, 8064, 8065, 8066, 8067, 8068, 8069, 8070, 8071, 8072, 8073, 8074, 8075, 8076, 8077, 8078, 8079, 8080, 8081, 8082, 8083, 8084, 8085, 8086, 8087, 8088, 8089, 8090, 8091, 8092, 8093, 8094, 8095, 8096, 8097, 8098, 8099, 8100, 8101, 8102, 8103, 8104, 8105, 8106, 8107, 8108, 8109, 8110, 8111, 8120, 8121, 8114, 8115, 8116, 8117, 8118, 8119, 8120, 8121, 8122, 8123, 8124, 8125, 8126, 8127, 8128, 8129, 8130, 8131, 8132, 8133, 8134, 8135, 8136, 8137, 8138, 8139, 8140, 8141, 8142, 8143, 8152, 8153, 8146, 8147, 8148, 8149, 8150, 8151, 8152, 8153, 8154, 8155, 8156, 8157, 8158, 8159, 8168, 8169, 8162, 8163, 8164, 8172, 8166, 8167, 8168, 8169, 8170, 8171, 8172, 8173, 8174, 8175, 8176, 8177, 8178, 8179, 8180, 8181, 8182, 8183, 8184, 8185, 8186, 8187, 8188, 8189, 8190, 8191, 8192, 8193, 8194, 8195, 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8203, 8204, 8205, 8206, 8207, 8208, 8209, 8210, 8211, 8212, 8213, 8214, 8215, 8216, 8217, 8218, 8219, 8220, 8221, 8222, 8223, 8224, 8225, 8226, 8227, 8228, 8229, 8230, 8231, 8232, 8233, 8234, 8235, 8236, 8237, 8238, 8239, 8240, 8241, 8242, 8243, 8244, 8245, 8246, 8247, 8248, 8249, 8250, 8251, 8252, 8253, 8254, 8255, 8256, 8257, 8258, 8259, 8260, 8261, 8262, 8263, 8264, 8265, 8266, 8267, 8268, 8269, 8270, 8271, 8272, 8273, 8274, 8275, 8276, 8277, 8278, 8279, 8280, 8281, 8282, 8283, 8284, 8285, 8286, 8287, 8288, 8289, 8290, 8291, 8292, 8293, 8294, 8295, 8296, 8297, 8298, 8299, 8300, 8301, 8302, 8303, 8304, 8305, 8306, 8307, 8308, 8309, 8310, 8311, 8312, 8313, 8314, 8315, 8316, 8317, 8318, 8319, 8320, 8321, 8322, 8323, 8324, 8325, 8326, 8327, 8328, 8329, 8330, 8331, 8332, 8333, 8334, 8335, 8336, 8337, 8338, 8339, 8340, 8341, 8342, 8343, 8344, 8345, 8346, 8347, 8348, 8349, 8350, 8351, 8352, 8353, 8354, 8355, 8356, 8357, 8358, 8359, 8360, 8361, 8362, 8363, 8364, 8365, 8366, 8367, 8368, 8369, 8370, 8371, 8372, 8373, 8374, 8375, 8376, 8377, 8378, 8379, 8380, 8381, 8382, 8383, 8384, 8385, 8386, 8387, 8388, 8389, 8390, 8391, 8392, 8393, 8394, 8395, 8396, 8397, 8398, 8399, 8400, 8401, 8402, 8403, 8404, 8405, 8406, 8407, 8408, 8409, 8410, 8411, 8412, 8413, 8414, 8415, 8416, 8417, 8418, 8419, 8420, 8421, 8422, 8423, 8424, 8425, 8426, 8427, 8428, 8429, 8430, 8431, 8432, 8433, 8434, 8435, 8436, 8437, 8438, 8439, 8440, 8441, 8442, 8443, 8444, 8445, 8446, 8447, 8448, 8449, 8450, 8451, 8452, 8453, 8454, 8455, 8456, 8457, 8458, 8459, 8460, 8461, 8462, 8463, 8464, 8465, 8466, 8467, 8468, 8469, 8470, 8471, 8472, 8473, 8474, 8475, 8476, 8477, 8478, 8479, 8480, 8481, 8482, 8483, 8484, 8485, 8486, 8487, 8488, 8489, 8490, 8491, 8492, 8493, 8494, 8495, 8496, 8497, 8498, 8499, 8500, 8501, 8502, 8503, 8504, 8505, 8506, 8507, 8508, 8509, 8510, 8511, 8512, 8513, 8514, 8515, 8516, 8517, 8518, 8519, 8520, 8521, 8522, 8523, 8524, 8525, 8526, 8527, 8528, 8529, 8530, 8531, 8532, 8533, 8534, 8535, 8536, 8537, 8538, 8539, 8540, 8541, 8542, 8543, 8544, 8545, 8546, 8547, 8548, 8549, 8550, 8551, 8552, 8553, 8554, 8555, 8556, 8557, 8558, 8559, 8544, 8545, 8546, 8547, 8548, 8549, 8550, 8551, 8552, 8553, 8554, 8555, 8556, 8557, 8558, 8559, 8576, 8577, 8578, 8579, 8580, 8581, 8582, 8583, 8584, 8585, 8586, 8587, 8588, 8589, 8590, 8591, 8592, 8593, 8594, 8595, 8596, 8597, 8598, 8599, 8600, 8601, 8602, 8603, 8604, 8605, 8606, 8607, 8608, 8609, 8610, 8611, 8612, 8613, 8614, 8615, 8616, 8617, 8618, 8619, 8620, 8621, 8622, 8623, 8624, 8625, 8626, 8627, 8628, 8629, 8630, 8631, 8632, 8633, 8634, 8635, 8636, 8637, 8638, 8639, 8640, 8641, 8642, 8643, 8644, 8645, 8646, 8647, 8648, 8649, 8650, 8651, 8652, 8653, 8654, 8655, 8656, 8657, 8658, 8659, 8660, 8661, 8662, 8663, 8664, 8665, 8666, 8667, 8668, 8669, 8670, 8671, 8672, 8673, 8674, 8675, 8676, 8677, 8678, 8679, 8680, 8681, 8682, 8683, 8684, 8685, 8686, 8687, 8688, 8689, 8690, 8691, 8692, 8693, 8694, 8695, 8696, 8697, 8698, 8699, 8700, 8701, 8702, 8703, 8704, 8705, 8706, 8707, 8708, 8709, 8710, 8711, 8712, 8713, 8714, 8715, 8716, 8717, 8718, 8719, 8720, 8721, 8722, 8723, 8724, 8725, 8726, 8727, 8728, 8729, 8730, 8731, 8732, 8733, 8734, 8735, 8736, 8737, 8738, 8739, 8740, 8741, 8742, 8743, 8744, 8745, 8746, 8747, 8748, 8749, 8750, 8751, 8752, 8753, 8754, 8755, 8756, 8757, 8758, 8759, 8760, 8761, 8762, 8763, 8764, 8765, 8766, 8767, 8768, 8769, 8770, 8771, 8772, 8773, 8774, 8775, 8776, 8777, 8778, 8779, 8780, 8781, 8782, 8783, 8784, 8785, 8786, 8787, 8788, 8789, 8790, 8791, 8792, 8793, 8794, 8795, 8796, 8797, 8798, 8799, 8800, 8801, 8802, 8803, 8804, 8805, 8806, 8807, 8808, 8809, 8810, 8811, 8812, 8813, 8814, 8815, 8816, 8817, 8818, 8819, 8820, 8821, 8822, 8823, 8824, 8825, 8826, 8827, 8828, 8829, 8830, 8831, 8832, 8833, 8834, 8835, 8836, 8837, 8838, 8839, 8840, 8841, 8842, 8843, 8844, 8845, 8846, 8847, 8848, 8849, 8850, 8851, 8852, 8853, 8854, 8855, 8856, 8857, 8858, 8859, 8860, 8861, 8862, 8863, 8864, 8865, 8866, 8867, 8868, 8869, 8870, 8871, 8872, 8873, 8874, 8875, 8876, 8877, 8878, 8879, 8880, 8881, 8882, 8883, 8884, 8885, 8886, 8887, 8888, 8889, 8890, 8891, 8892, 8893, 8894, 8895, 8896, 8897, 8898, 8899, 8900, 8901, 8902, 8903, 8904, 8905, 8906, 8907, 8908, 8909, 8910, 8911, 8912, 8913, 8914, 8915, 8916, 8917, 8918, 8919, 8920, 8921, 8922, 8923, 8924, 8925, 8926, 8927, 8928, 8929, 8930, 8931, 8932, 8933, 8934, 8935, 8936, 8937, 8938, 8939, 8940, 8941, 8942, 8943, 8944, 8945, 8946, 8947, 8948, 8949, 8950, 8951, 8952, 8953, 8954, 8955, 8956, 8957, 8958, 8959, 8960, 8961, 8962, 8963, 8964, 8965, 8966, 8967, 8968, 8969, 8970, 8971, 8972, 8973, 8974, 8975, 8976, 8977, 8978, 8979, 8980, 8981, 8982, 8983, 8984, 8985, 8986, 8987, 8988, 8989, 8990, 8991, 8992, 8993, 8994, 8995, 8996, 8997, 8998, 8999, 9000, 9001, 9002, 9003, 9004, 9005, 9006, 9007, 9008, 9009, 9010, 9011, 9012, 9013, 9014, 9015, 9016, 9017, 9018, 9019, 9020, 9021, 9022, 9023, 9024, 9025, 9026, 9027, 9028, 9029, 9030, 9031, 9032, 9033, 9034, 9035, 9036, 9037, 9038, 9039, 9040, 9041, 9042, 9043, 9044, 9045, 9046, 9047, 9048, 9049, 9050, 9051, 9052, 9053, 9054, 9055, 9056, 9057, 9058, 9059, 9060, 9061, 9062, 9063, 9064, 9065, 9066, 9067, 9068, 9069, 9070, 9071, 9072, 9073, 9074, 9075, 9076, 9077, 9078, 9079, 9080, 9081, 9082, 9083, 9084, 9085, 9086, 9087, 9088, 9089, 9090, 9091, 9092, 9093, 9094, 9095, 9096, 9097, 9098, 9099, 9100, 9101, 9102, 9103, 9104, 9105, 9106, 9107, 9108, 9109, 9110, 9111, 9112, 9113, 9114, 9115, 9116, 9117, 9118, 9119, 9120, 9121, 9122, 9123, 9124, 9125, 9126, 9127, 9128, 9129, 9130, 9131, 9132, 9133, 9134, 9135, 9136, 9137, 9138, 9139, 9140, 9141, 9142, 9143, 9144, 9145, 9146, 9147, 9148, 9149, 9150, 9151, 9152, 9153, 9154, 9155, 9156, 9157, 9158, 9159, 9160, 9161, 9162, 9163, 9164, 9165, 9166, 9167, 9168, 9169, 9170, 9171, 9172, 9173, 9174, 9175, 9176, 9177, 9178, 9179, 9180, 9181, 9182, 9183, 9184, 9185, 9186, 9187, 9188, 9189, 9190, 9191, 9192, 9193, 9194, 9195, 9196, 9197, 9198, 9199, 9200, 9201, 9202, 9203, 9204, 9205, 9206, 9207, 9208, 9209, 9210, 9211, 9212, 9213, 9214, 9215, 9216, 9217, 9218, 9219, 9220, 9221, 9222, 9223, 9224, 9225, 9226, 9227, 9228, 9229, 9230, 9231, 9232, 9233, 9234, 9235, 9236, 9237, 9238, 9239, 9240, 9241, 9242, 9243, 9244, 9245, 9246, 9247, 9248, 9249, 9250, 9251, 9252, 9253, 9254, 9255, 9256, 9257, 9258, 9259, 9260, 9261, 9262, 9263, 9264, 9265, 9266, 9267, 9268, 9269, 9270, 9271, 9272, 9273, 9274, 9275, 9276, 9277, 9278, 9279, 9280, 9281, 9282, 9283, 9284, 9285, 9286, 9287, 9288, 9289, 9290, 9291, 9292, 9293, 9294, 9295, 9296, 9297, 9298, 9299, 9300, 9301, 9302, 9303, 9304, 9305, 9306, 9307, 9308, 9309, 9310, 9311, 9312, 9313, 9314, 9315, 9316, 9317, 9318, 9319, 9320, 9321, 9322, 9323, 9324, 9325, 9326, 9327, 9328, 9329, 9330, 9331, 9332, 9333, 9334, 9335, 9336, 9337, 9338, 9339, 9340, 9341, 9342, 9343, 9344, 9345, 9346, 9347, 9348, 9349, 9350, 9351, 9352, 9353, 9354, 9355, 9356, 9357, 9358, 9359, 9360, 9361, 9362, 9363, 9364, 9365, 9366, 9367, 9368, 9369, 9370, 9371, 9372, 9373, 9374, 9375, 9376, 9377, 9378, 9379, 9380, 9381, 9382, 9383, 9384, 9385, 9386, 9387, 9388, 9389, 9390, 9391, 9392, 9393, 9394, 9395, 9396, 9397, 9398, 9399, 9400, 9401, 9402, 9403, 9404, 9405, 9406, 9407, 9408, 9409, 9410, 9411, 9412, 9413, 9414, 9415, 9416, 9417, 9418, 9419, 9420, 9421, 9422, 9423, 9398, 9399, 9400, 9401, 9402, 9403, 9404, 9405, 9406, 9407, 9408, 9409, 9410, 9411, 9412, 9413, 9414, 9415, 9416, 9417, 9418, 9419, 9420, 9421, 9422, 9423 }; const Il2CppChar ToUpperDataHigh[] = { 65313, 65314, 65315, 65316, 65317, 65318, 65319, 65320, 65321, 65322, 65323, 65324, 65325, 65326, 65327, 65328, 65329, 65330, 65331, 65332, 65333, 65334, 65335, 65336, 65337, 65338, 65339, 65340, 65341, 65342, 65343, 65344, 65313, 65314, 65315, 65316, 65317, 65318, 65319, 65320, 65321, 65322, 65323, 65324, 65325, 65326, 65327, 65328, 65329, 65330, 65331, 65332, 65333, 65334, 65335, 65336, 65337, 65338, 65371, 65372, 65373, 65374, 65375, 65376, 65377, 65378, 65379, 65380, 65381, 65382, 65383, 65384, 65385, 65386, 65387, 65388, 65389, 65390, 65391, 65392, 65393, 65394, 65395, 65396, 65397, 65398, 65399, 65400, 65401, 65402, 65403, 65404, 65405, 65406, 65407, 65408, 65409, 65410, 65411, 65412, 65413, 65414, 65415, 65416, 65417, 65418, 65419, 65420, 65421, 65422, 65423, 65424, 65425, 65426, 65427, 65428, 65429, 65430, 65431, 65432, 65433, 65434, 65435, 65436, 65437, 65438, 65439, 65440, 65441, 65442, 65443, 65444, 65445, 65446, 65447, 65448, 65449, 65450, 65451, 65452, 65453, 65454, 65455, 65456, 65457, 65458, 65459, 65460, 65461, 65462, 65463, 65464, 65465, 65466, 65467, 65468, 65469, 65470, 65471, 65472, 65473, 65474, 65475, 65476, 65477, 65478, 65479, 65480, 65481, 65482, 65483, 65484, 65485, 65486, 65487, 65488, 65489, 65490, 65491, 65492, 65493, 65494, 65495, 65496, 65497, 65498, 65499, 65500, 65501, 65502, 65503, 65504, 65505, 65506, 65507, 65508, 65509, 65510, 65511, 65512, 65513, 65514, 65515, 65516, 65517, 65518, 65519, 65520, 65521, 65522, 65523, 65524, 65525, 65526, 65527, 65528, 65529, 65530, 65531, 65532, 65533, 65534, 65535 }; ================================================ FILE: unity_decoder/libil2cpp/char-conversions.h ================================================ #pragma once extern const uint8_t CategoryData_v4[71680]; extern const uint8_t NumericData[12938]; extern const double NumericDataValues[58]; extern const Il2CppChar ToLowerDataLow[9424]; extern const Il2CppChar ToLowerDataHigh[223]; extern const Il2CppChar ToUpperDataLow[9450]; extern const Il2CppChar ToUpperDataHigh[223]; ================================================ FILE: unity_decoder/libil2cpp/class-internals.cpp ================================================ #include "class-internals.h" Il2CppRuntimeStats il2cpp_runtime_stats = { 0 }; ================================================ FILE: unity_decoder/libil2cpp/class-internals.h ================================================ #pragma once #include "il2cpp-config.h" #include #include "metadata.h" #include "il2cpp-metadata.h" #define IL2CPP_CLASS_IS_ARRAY(c) ((c)->rank) struct Il2CppClass; struct Il2CppGuid; struct Il2CppImage; struct Il2CppAssembly; struct Il2CppAppDomain; struct Il2CppAppDomainSetup; struct Il2CppDelegate; struct Il2CppAppContext; struct Il2CppNameToTypeDefinitionIndexHashTable; struct VirtualInvokeData { Il2CppMethodPointer methodPtr; #if RUNTIME_MONO const MonoMethod* method; #else const MethodInfo* method; #endif }; enum Il2CppTypeNameFormat { IL2CPP_TYPE_NAME_FORMAT_IL, IL2CPP_TYPE_NAME_FORMAT_REFLECTION, IL2CPP_TYPE_NAME_FORMAT_FULL_NAME, IL2CPP_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED }; extern bool g_il2cpp_is_fully_initialized; typedef struct { Il2CppImage *corlib; Il2CppClass *object_class; Il2CppClass *byte_class; Il2CppClass *void_class; Il2CppClass *boolean_class; Il2CppClass *sbyte_class; Il2CppClass *int16_class; Il2CppClass *uint16_class; Il2CppClass *int32_class; Il2CppClass *uint32_class; Il2CppClass *int_class; Il2CppClass *uint_class; Il2CppClass *int64_class; Il2CppClass *uint64_class; Il2CppClass *single_class; Il2CppClass *double_class; Il2CppClass *char_class; Il2CppClass *string_class; Il2CppClass *enum_class; Il2CppClass *array_class; Il2CppClass *delegate_class; Il2CppClass *multicastdelegate_class; Il2CppClass *asyncresult_class; Il2CppClass *manualresetevent_class; Il2CppClass *typehandle_class; Il2CppClass *fieldhandle_class; Il2CppClass *methodhandle_class; Il2CppClass *systemtype_class; Il2CppClass *monotype_class; Il2CppClass *exception_class; Il2CppClass *threadabortexception_class; Il2CppClass *thread_class; #if NET_4_0 Il2CppClass *internal_thread_class; #endif /*Il2CppClass *transparent_proxy_class; Il2CppClass *real_proxy_class; Il2CppClass *mono_method_message_class;*/ Il2CppClass *appdomain_class; Il2CppClass *appdomain_setup_class; Il2CppClass *field_info_class; Il2CppClass *method_info_class; Il2CppClass *property_info_class; Il2CppClass *event_info_class; Il2CppClass *mono_event_info_class; Il2CppClass *stringbuilder_class; /*Il2CppClass *math_class;*/ Il2CppClass *stack_frame_class; Il2CppClass *stack_trace_class; Il2CppClass *marshal_class; /*Il2CppClass *iserializeable_class; Il2CppClass *serializationinfo_class; Il2CppClass *streamingcontext_class;*/ Il2CppClass *typed_reference_class; /*Il2CppClass *argumenthandle_class;*/ Il2CppClass *marshalbyrefobject_class; /*Il2CppClass *monitor_class; Il2CppClass *iremotingtypeinfo_class; Il2CppClass *runtimesecurityframe_class; Il2CppClass *executioncontext_class; Il2CppClass *internals_visible_class;*/ Il2CppClass *generic_ilist_class; Il2CppClass *generic_icollection_class; Il2CppClass *generic_ienumerable_class; #if NET_4_0 Il2CppClass *generic_ireadonlylist_class; Il2CppClass *generic_ireadonlycollection_class; Il2CppClass *runtimetype_class; #endif Il2CppClass *generic_nullable_class; /*Il2CppClass *variant_class; Il2CppClass *com_object_class;*/ Il2CppClass *il2cpp_com_object_class; /*Il2CppClass *com_interop_proxy_class; Il2CppClass *iunknown_class; Il2CppClass *idispatch_class; Il2CppClass *safehandle_class; Il2CppClass *handleref_class; Il2CppClass *attribute_class;*/ Il2CppClass *customattribute_data_class; //Il2CppClass *critical_finalizer_object; Il2CppClass *version; Il2CppClass *culture_info; Il2CppClass *async_call_class; Il2CppClass *assembly_class; #if NET_4_0 Il2CppClass *mono_assembly_class; #endif Il2CppClass *assembly_name_class; #if !NET_4_0 Il2CppClass *enum_info_class; #endif Il2CppClass *mono_field_class; Il2CppClass *mono_method_class; Il2CppClass *mono_method_info_class; Il2CppClass *mono_property_info_class; Il2CppClass *parameter_info_class; #if NET_4_0 Il2CppClass *mono_parameter_info_class; #endif Il2CppClass *module_class; Il2CppClass *pointer_class; Il2CppClass *system_exception_class; Il2CppClass *argument_exception_class; Il2CppClass *wait_handle_class; Il2CppClass *safe_handle_class; Il2CppClass *sort_key_class; Il2CppClass *dbnull_class; Il2CppClass *error_wrapper_class; Il2CppClass *missing_class; Il2CppClass *value_type_class; #if NET_4_0 // Stuff used by the mono code Il2CppClass *threadpool_wait_callback_class; MethodInfo *threadpool_perform_wait_callback_method; Il2CppClass *mono_method_message_class; #endif // Windows.Foundation.IReference`1 Il2CppClass* ireference_class; // Windows.Foundation.Collections.IKeyValuePair`2 Il2CppClass* ikey_value_pair_class; // System.Collections.Generic.KeyValuePair`2 Il2CppClass* key_value_pair_class; // Windows.Foundation.Uri Il2CppClass* windows_foundation_uri_class; // Windows.Foundation.IUriRuntimeClass Il2CppClass* windows_foundation_iuri_runtime_class_class; // System.Uri Il2CppClass* system_uri_class; } Il2CppDefaults; extern LIBIL2CPP_CODEGEN_API Il2CppDefaults il2cpp_defaults; struct Il2CppClass; struct MethodInfo; struct FieldInfo; struct Il2CppObject; struct MemberInfo; struct CustomAttributesCache { int count; Il2CppObject** attributes; }; struct CustomAttributeTypeCache { int count; Il2CppClass** attributeTypes; }; typedef void (*CustomAttributesCacheGenerator)(CustomAttributesCache*); const int THREAD_STATIC_FIELD_OFFSET = -1; struct FieldInfo { const char* name; const Il2CppType* type; Il2CppClass *parent; int32_t offset; // If offset is -1, then it's thread static CustomAttributeIndex customAttributeIndex; uint32_t token; }; struct PropertyInfo { Il2CppClass *parent; const char *name; const MethodInfo *get; const MethodInfo *set; uint32_t attrs; CustomAttributeIndex customAttributeIndex; uint32_t token; }; struct EventInfo { const char* name; const Il2CppType* eventType; Il2CppClass* parent; const MethodInfo* add; const MethodInfo* remove; const MethodInfo* raise; CustomAttributeIndex customAttributeIndex; uint32_t token; }; struct ParameterInfo { const char* name; int32_t position; uint32_t token; CustomAttributeIndex customAttributeIndex; const Il2CppType* parameter_type; }; #if RUNTIME_MONO typedef void* (*InvokerMethod)(Il2CppMethodPointer, const MonoMethod*, void*, void**); #else typedef void* (*InvokerMethod)(Il2CppMethodPointer, const MethodInfo*, void*, void**); #endif #if IL2CPP_DEBUGGER_ENABLED struct Il2CppDebugDocument { const char *directory; const char *filename; }; struct Il2CppDebugTypeInfo { const Il2CppDebugDocument *document; }; struct Il2CppDebugLocalsInfo { Il2CppClass *type; const char *name; uint32_t start_offset; uint32_t end_offset; }; struct SequencePointRecord { int32_t start_offset; int32_t end_offset; void *user_data; }; struct Il2CppDebugMethodInfo { const Il2CppDebugDocument *document; // Table of [offset -> lineno] mapping. // Ends with {-1,-1} const int32_t *offsets_table; const size_t code_size; const Il2CppDebugLocalsInfo **locals; int32_t sequence_points_count; int32_t breakpoints_count;// incremented atomically SequencePointRecord *sequence_points; }; #endif union Il2CppRGCTXData { void* rgctxDataDummy; const MethodInfo* method; const Il2CppType* type; Il2CppClass* klass; }; struct MethodInfo { Il2CppMethodPointer methodPointer; InvokerMethod invoker_method; const char* name; Il2CppClass *declaring_type; const Il2CppType *return_type; const ParameterInfo* parameters; union { const Il2CppRGCTXData* rgctx_data; /* is_inflated is true and is_generic is false, i.e. a generic instance method */ const Il2CppMethodDefinition* methodDefinition; }; /* note, when is_generic == true and is_inflated == true the method represents an uninflated generic method on an inflated type. */ union { const Il2CppGenericMethod* genericMethod; /* is_inflated is true */ const Il2CppGenericContainer* genericContainer; /* is_inflated is false and is_generic is true */ }; CustomAttributeIndex customAttributeIndex; uint32_t token; uint16_t flags; uint16_t iflags; uint16_t slot; uint8_t parameters_count; uint8_t is_generic : 1; /* true if method is a generic method definition */ uint8_t is_inflated : 1; /* true if declaring_type is a generic instance or if method is a generic instance*/ #if IL2CPP_DEBUGGER_ENABLED const Il2CppDebugMethodInfo *debug_info; #endif }; struct Il2CppRuntimeInterfaceOffsetPair { Il2CppClass* interfaceType; int32_t offset; }; typedef void (*PInvokeMarshalToNativeFunc)(void* managedStructure, void* marshaledStructure); typedef void (*PInvokeMarshalFromNativeFunc)(void* marshaledStructure, void* managedStructure); typedef void (*PInvokeMarshalCleanupFunc)(void* marshaledStructure); typedef struct Il2CppIUnknown* (*CreateCCWFunc)(Il2CppObject* obj); #if RUNTIME_MONO #include "il2cpp-mapping.h" #endif struct Il2CppInteropData { Il2CppMethodPointer delegatePInvokeWrapperFunction; PInvokeMarshalToNativeFunc pinvokeMarshalToNativeFunction; PInvokeMarshalFromNativeFunc pinvokeMarshalFromNativeFunction; PInvokeMarshalCleanupFunc pinvokeMarshalCleanupFunction; CreateCCWFunc createCCWFunction; const Il2CppGuid* guid; #if RUNTIME_MONO MonoMetadataToken typeToken; uint64_t hash; #else const Il2CppType* type; #endif }; #if IL2CPP_COMPILER_MSVC #pragma warning( push ) #pragma warning( disable : 4200 ) #elif defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Winvalid-offsetof" #endif struct Il2CppClass { // The following fields are always valid for a Il2CppClass structure const Il2CppImage* image; void* gc_desc; const char* name; const char* namespaze; const Il2CppType* byval_arg; const Il2CppType* this_arg; Il2CppClass* element_class; Il2CppClass* castClass; Il2CppClass* declaringType; Il2CppClass* parent; Il2CppGenericClass *generic_class; const Il2CppTypeDefinition* typeDefinition; // non-NULL for Il2CppClass's constructed from type defintions const Il2CppInteropData* interopData; // End always valid fields // The following fields need initialized before access. This can be done per field or as an aggregate via a call to Class::Init FieldInfo* fields; // Initialized in SetupFields const EventInfo* events; // Initialized in SetupEvents const PropertyInfo* properties; // Initialized in SetupProperties const MethodInfo** methods; // Initialized in SetupMethods Il2CppClass** nestedTypes; // Initialized in SetupNestedTypes Il2CppClass** implementedInterfaces; // Initialized in SetupInterfaces Il2CppRuntimeInterfaceOffsetPair* interfaceOffsets; // Initialized in Init void* static_fields; // Initialized in Init const Il2CppRGCTXData* rgctx_data; // Initialized in Init // used for fast parent checks Il2CppClass** typeHierarchy; // Initialized in SetupTypeHierachy // End initialization required fields #if IL2CPP_DEBUGGER_ENABLED const Il2CppDebugTypeInfo *debug_info; #endif uint32_t cctor_started; uint32_t cctor_finished; ALIGN_TYPE(8) uint64_t cctor_thread; // Remaining fields are always valid except where noted GenericContainerIndex genericContainerIndex; CustomAttributeIndex customAttributeIndex; uint32_t instance_size; uint32_t actualSize; uint32_t element_size; int32_t native_size; uint32_t static_fields_size; uint32_t thread_static_fields_size; int32_t thread_static_fields_offset; uint32_t flags; uint32_t token; uint16_t method_count; // lazily calculated for arrays, i.e. when rank > 0 uint16_t property_count; uint16_t field_count; uint16_t event_count; uint16_t nested_type_count; uint16_t vtable_count; // lazily calculated for arrays, i.e. when rank > 0 uint16_t interfaces_count; uint16_t interface_offsets_count; // lazily calculated for arrays, i.e. when rank > 0 uint8_t typeHierarchyDepth; // Initialized in SetupTypeHierachy uint8_t genericRecursionDepth; uint8_t rank; uint8_t minimumAlignment; uint8_t packingSize; uint8_t valuetype : 1; uint8_t initialized : 1; uint8_t enumtype : 1; uint8_t is_generic : 1; uint8_t has_references : 1; uint8_t init_pending : 1; uint8_t size_inited : 1; uint8_t has_finalize : 1; uint8_t has_cctor : 1; uint8_t is_blittable : 1; uint8_t is_import_or_windows_runtime : 1; uint8_t is_vtable_initialized : 1; VirtualInvokeData vtable[IL2CPP_ZERO_LEN_ARRAY]; }; #if IL2CPP_COMPILER_MSVC #pragma warning( pop ) #elif defined(__clang__) #pragma clang diagnostic pop #endif // compiler calcualted values struct Il2CppTypeDefinitionSizes { uint32_t instance_size; int32_t native_size; uint32_t static_fields_size; uint32_t thread_static_fields_size; }; struct Il2CppDomain { Il2CppAppDomain* domain; Il2CppAppDomainSetup* setup; Il2CppAppContext* default_context; const char* friendly_name; uint32_t domain_id; #if NET_4_0 volatile int threadpool_jobs; #endif }; struct Il2CppImage { const char* name; const char* nameNoExt; AssemblyIndex assemblyIndex; TypeDefinitionIndex typeStart; uint32_t typeCount; TypeDefinitionIndex exportedTypeStart; uint32_t exportedTypeCount; MethodIndex entryPointIndex; mutable Il2CppNameToTypeDefinitionIndexHashTable* nameToClassHashTable; uint32_t token; }; struct Il2CppCodeGenOptions { bool enablePrimitiveValueTypeGenericSharing; }; struct Il2CppCodeRegistration { uint32_t methodPointersCount; const Il2CppMethodPointer* methodPointers; uint32_t reversePInvokeWrapperCount; const Il2CppMethodPointer* reversePInvokeWrappers; uint32_t genericMethodPointersCount; const Il2CppMethodPointer* genericMethodPointers; uint32_t invokerPointersCount; const InvokerMethod* invokerPointers; CustomAttributeIndex customAttributeCount; const CustomAttributesCacheGenerator* customAttributeGenerators; uint32_t unresolvedVirtualCallCount; const Il2CppMethodPointer* unresolvedVirtualCallPointers; uint32_t interopDataCount; Il2CppInteropData* interopData; }; struct Il2CppMetadataRegistration { int32_t genericClassesCount; Il2CppGenericClass* const * genericClasses; int32_t genericInstsCount; const Il2CppGenericInst* const * genericInsts; int32_t genericMethodTableCount; const Il2CppGenericMethodFunctionsDefinitions* genericMethodTable; int32_t typesCount; const Il2CppType* const * types; int32_t methodSpecsCount; const Il2CppMethodSpec* methodSpecs; FieldIndex fieldOffsetsCount; const int32_t** fieldOffsets; TypeDefinitionIndex typeDefinitionsSizesCount; const Il2CppTypeDefinitionSizes** typeDefinitionsSizes; const size_t metadataUsagesCount; void** const* metadataUsages; }; struct Il2CppRuntimeStats { uint64_t new_object_count; uint64_t initialized_class_count; // uint64_t generic_vtable_count; // uint64_t used_class_count; uint64_t method_count; // uint64_t class_vtable_size; uint64_t class_static_data_size; uint64_t generic_instance_count; uint64_t generic_class_count; uint64_t inflated_method_count; uint64_t inflated_type_count; // uint64_t delegate_creations; // uint64_t minor_gc_count; // uint64_t major_gc_count; // uint64_t minor_gc_time_usecs; // uint64_t major_gc_time_usecs; bool enabled; }; extern Il2CppRuntimeStats il2cpp_runtime_stats; /* * new structure to hold performance counters values that are exported * to managed code. * Note: never remove fields from this structure and only add them to the end. * Size of fields and type should not be changed as well. */ struct Il2CppPerfCounters { /* JIT category */ uint32_t jit_methods; uint32_t jit_bytes; uint32_t jit_time; uint32_t jit_failures; /* Exceptions category */ uint32_t exceptions_thrown; uint32_t exceptions_filters; uint32_t exceptions_finallys; uint32_t exceptions_depth; uint32_t aspnet_requests_queued; uint32_t aspnet_requests; /* Memory category */ uint32_t gc_collections0; uint32_t gc_collections1; uint32_t gc_collections2; uint32_t gc_promotions0; uint32_t gc_promotions1; uint32_t gc_promotion_finalizers; uint32_t gc_gen0size; uint32_t gc_gen1size; uint32_t gc_gen2size; uint32_t gc_lossize; uint32_t gc_fin_survivors; uint32_t gc_num_handles; uint32_t gc_allocated; uint32_t gc_induced; uint32_t gc_time; uint32_t gc_total_bytes; uint32_t gc_committed_bytes; uint32_t gc_reserved_bytes; uint32_t gc_num_pinned; uint32_t gc_sync_blocks; /* Remoting category */ uint32_t remoting_calls; uint32_t remoting_channels; uint32_t remoting_proxies; uint32_t remoting_classes; uint32_t remoting_objects; uint32_t remoting_contexts; /* Loader category */ uint32_t loader_classes; uint32_t loader_total_classes; uint32_t loader_appdomains; uint32_t loader_total_appdomains; uint32_t loader_assemblies; uint32_t loader_total_assemblies; uint32_t loader_failures; uint32_t loader_bytes; uint32_t loader_appdomains_uloaded; /* Threads and Locks category */ uint32_t thread_contentions; uint32_t thread_queue_len; uint32_t thread_queue_max; uint32_t thread_num_logical; uint32_t thread_num_physical; uint32_t thread_cur_recognized; uint32_t thread_num_recognized; /* Interop category */ uint32_t interop_num_ccw; uint32_t interop_num_stubs; uint32_t interop_num_marshals; /* Security category */ uint32_t security_num_checks; uint32_t security_num_link_checks; uint32_t security_time; uint32_t security_depth; uint32_t unused; /* Threadpool */ uint64_t threadpool_workitems; uint64_t threadpool_ioworkitems; unsigned int threadpool_threads; unsigned int threadpool_iothreads; }; ================================================ FILE: unity_decoder/libil2cpp/codegen/il2cpp-codegen-common.h ================================================ #pragma once #include "il2cpp-config.h" #include #include #include #include #include #include #include "object-internals.h" #include "class-internals.h" #include "tabledefs.h" #include "icallincludes.h" #include "vm/PlatformInvoke.h" #include "vm/StackTrace.h" #include "vm/PlatformInvoke.h" #include "vm/StackTrace.h" #include "utils/StringUtils.h" #include "utils/StringView.h" #include "utils/Exception.h" #include "utils/Output.h" #include "utils/Runtime.h" #ifdef _MSC_VER #define IL2CPP_DEBUG_BREAK() __debugbreak() #else #define IL2CPP_DEBUG_BREAK() #endif // This function exists to help with generation of callstacks for exceptions // on iOS and MacOS x64 with clang 6.0 (newer versions of clang don't have this // problem on x64). There we call the backtrace function, which does not play nicely // with NORETURN, since the compiler eliminates the method prologue code setting up // the address of the return frame (which makes sense). So on iOS we need to make // the NORETURN define do nothing, then we use this dummy method which has the // attribute for clang on iOS defined to prevent clang compiler errors for // method that end by throwing a managed exception. REAL_NORETURN IL2CPP_NO_INLINE static void il2cpp_codegen_no_return() { IL2CPP_UNREACHABLE; } #if IL2CPP_COMPILER_MSVC #define STDCALL __stdcall #define CDECL __cdecl #define DEFAULT_CALL STDCALL #else #define STDCALL #define CDECL #define DEFAULT_CALL #endif #if defined(__ARMCC_VERSION) inline double bankers_round(double x) { return __builtin_round(x); } inline float bankers_roundf(float x) { return __builtin_roundf(x); } #else inline double bankers_round(double x) { double integerPart; if (x >= 0.0) { if (modf(x, &integerPart) == 0.5) return (int64_t)integerPart % 2 == 0 ? integerPart : integerPart + 1.0; return floor(x + 0.5); } else { if (modf(x, &integerPart) == -0.5) return (int64_t)integerPart % 2 == 0 ? integerPart : integerPart - 1.0; return ceil(x - 0.5); } } inline float bankers_roundf(float x) { double integerPart; if (x >= 0.0f) { if (modf(x, &integerPart) == 0.5) return (int64_t)integerPart % 2 == 0 ? (float)integerPart : (float)integerPart + 1.0f; return floorf(x + 0.5f); } else { if (modf(x, &integerPart) == -0.5) return (int64_t)integerPart % 2 == 0 ? (float)integerPart : (float)integerPart - 1.0f; return ceilf(x - 0.5f); } } #endif // returns true if overflow occurs inline bool il2cpp_codegen_check_mul_overflow_i64(int64_t a, int64_t b, int64_t imin, int64_t imax) { // TODO: use a better algorithm without division uint64_t ua = (uint64_t)llabs(a); uint64_t ub = (uint64_t)llabs(b); uint64_t c; if ((a > 0 && b > 0) || (a <= 0 && b <= 0)) c = (uint64_t)llabs(imax); else c = (uint64_t)llabs(imin); return ua != 0 && ub > c / ua; } inline int32_t il2cpp_codegen_abs(uint32_t value) { return abs(static_cast(value)); } inline int32_t il2cpp_codegen_abs(int32_t value) { return abs(value); } inline int64_t il2cpp_codegen_abs(uint64_t value) { return llabs(static_cast(value)); } inline int64_t il2cpp_codegen_abs(int64_t value) { return llabs(value); } // Exception support macros #define IL2CPP_LEAVE(Offset, Target) \ __leave_target = Offset; \ goto Target; #define IL2CPP_END_FINALLY(Id) \ goto __CLEANUP_ ## Id; #define IL2CPP_CLEANUP(Id) \ __CLEANUP_ ## Id: #define IL2CPP_RETHROW_IF_UNHANDLED(ExcType) \ if(__last_unhandled_exception) { \ ExcType _tmp_exception_local = __last_unhandled_exception; \ __last_unhandled_exception = 0; \ il2cpp_codegen_raise_exception(_tmp_exception_local); \ } #define IL2CPP_JUMP_TBL(Offset, Target) \ if(__leave_target == Offset) { \ __leave_target = 0; \ goto Target; \ } #define IL2CPP_END_CLEANUP(Offset, Target) \ if(__leave_target == Offset) \ goto Target; #define IL2CPP_RAISE_MANAGED_EXCEPTION(message) \ do {\ il2cpp_codegen_raise_exception((Il2CppCodeGenException*)message);\ il2cpp_codegen_no_return();\ } while (0) template inline void Il2CppCodeGenWriteBarrier(T** targetAddress, T* object) { // TODO } void il2cpp_codegen_memory_barrier(); template inline T VolatileRead(T* location) { T result = *location; il2cpp_codegen_memory_barrier(); return result; } template inline void VolatileWrite(T* location, T value) { il2cpp_codegen_memory_barrier(); *location = value; } inline void il2cpp_codegen_write_to_stdout(const char* str) { il2cpp::utils::Output::WriteToStdout(str); } inline void il2cpp_codegen_write_to_stderr(const char* str) { il2cpp::utils::Output::WriteToStderr(str); } inline REAL_NORETURN void il2cpp_codegen_abort() { il2cpp::utils::Runtime::Abort(); il2cpp_codegen_no_return(); } ================================================ FILE: unity_decoder/libil2cpp/codegen/il2cpp-codegen-il2cpp.h ================================================ #pragma once #include "il2cpp-codegen-common.h" #include "utils/Il2CppHStringReference.h" #include "utils/RegisterRuntimeInitializeAndCleanup.h" #include "metadata/GenericMethod.h" #include "vm/Array.h" #include "vm/Assembly.h" #include "vm/Atomic.h" #include "vm/CCW.h" #include "vm/Class.h" #include "vm/COM.h" #include "vm/Domain.h" #include "vm/Exception.h" #include "vm/InternalCalls.h" #include "vm/LastError.h" #include "vm/MarshalAlloc.h" #include "vm/MetadataCache.h" #include "vm/Method.h" #include "vm/Object.h" #include "vm/Profiler.h" #include "vm/RCW.h" #include "vm/Reflection.h" #include "vm/Runtime.h" #include "vm/String.h" #include "vm/Thread.h" #include "vm/ThreadPool.h" #include "vm/Type.h" #include "vm/WindowsRuntime.h" #include "vm/ThreadPoolMs.h" #ifdef _MSC_VER #define IL2CPP_DISABLE_OPTIMIZATIONS __pragma(optimize("", off)) #define IL2CPP_ENABLE_OPTIMIZATIONS __pragma(optimize("", on)) #else #define IL2CPP_DISABLE_OPTIMIZATIONS #define IL2CPP_ENABLE_OPTIMIZATIONS #endif struct ProfilerMethodSentry { ProfilerMethodSentry(const RuntimeMethod* method) #if IL2CPP_ENABLE_PROFILER : m_method(method) #endif { #if IL2CPP_ENABLE_PROFILER il2cpp::vm::Profiler::MethodEnter(m_method); #endif } ~ProfilerMethodSentry() { #if IL2CPP_ENABLE_PROFILER il2cpp::vm::Profiler::MethodExit(m_method); #endif } private: const RuntimeMethod* m_method; }; struct StackTraceSentry { StackTraceSentry(const RuntimeMethod* method) : m_method(method) { Il2CppStackFrameInfo frame_info; frame_info.method = method; #if IL2CPP_DEBUGGER_ENABLED frame_info.id = -1; frame_info.il_offset = 0; frame_info.type = FRAME_TYPE_MANAGED; #endif il2cpp::vm::StackTrace::PushFrame(frame_info); } #if IL2CPP_DEBUGGER_ENABLED StackTraceSentry(const RuntimeMethod* method, void* this_ptr, void **params, int32_t params_count, void **locals, int32_t locals_count) : m_method(method) { Il2CppStackFrameInfo frame_info; frame_info.id = -1; frame_info.this_ptr = this_ptr; frame_info.method = method; frame_info.il_offset = 0; frame_info.type = FRAME_TYPE_MANAGED; frame_info.params = params; frame_info.params_count = params_count; frame_info.locals = locals; frame_info.locals_count = locals_count; il2cpp::vm::StackTrace::PushFrame(frame_info); } #endif ~StackTraceSentry() { il2cpp::vm::StackTrace::PopFrame(); } private: const RuntimeMethod* m_method; }; template struct Il2CppFakeBox : RuntimeObject { T m_Value; Il2CppFakeBox(RuntimeClass* boxedType, T* value) { klass = boxedType; monitor = NULL; m_Value = *value; } }; // TODO: This file should contain all the functions and type declarations needed for the generated code. // Hopefully, we stop including everything in the generated code and know exactly what dependencies we have. // Note that all parameter and return types should match the generated types not the runtime types. inline void il2cpp_codegen_register(const Il2CppCodeRegistration* const codeRegistration, const Il2CppMetadataRegistration* const metadataRegistration, const Il2CppCodeGenOptions* const codeGenOptions) { il2cpp::vm::MetadataCache::Register(codeRegistration, metadataRegistration, codeGenOptions); } #include "GeneratedCodeGen.h" // type registration inline void* il2cpp_codegen_get_thread_static_data(RuntimeClass* klass) { return il2cpp::vm::Thread::GetThreadStaticData(klass->thread_static_fields_offset); } inline Il2CppCodeGenString* il2cpp_codegen_string_new_wrapper(const char* str) { return (Il2CppCodeGenString*)il2cpp::vm::String::NewWrapper(str); } inline Il2CppCodeGenString* il2cpp_codegen_string_new_utf16(const il2cpp::utils::StringView& str) { return (Il2CppCodeGenString*)il2cpp::vm::String::NewUtf16(str.Str(), static_cast(str.Length())); } inline Il2CppCodeGenType* il2cpp_codegen_type_get_object(const RuntimeType* type) { return (Il2CppCodeGenType*)il2cpp::vm::Reflection::GetTypeObject(type); } inline NORETURN void il2cpp_codegen_raise_exception(Il2CppCodeGenException *ex) { il2cpp::vm::Exception::Raise((RuntimeException*)ex); } inline void il2cpp_codegen_raise_execution_engine_exception_if_method_is_not_found(const RuntimeMethod* method) { il2cpp::vm::Runtime::RaiseExecutionEngineExceptionIfMethodIsNotFound(method); } inline void il2cpp_codegen_raise_execution_engine_exception(const RuntimeMethod* method) { il2cpp::vm::Runtime::AlwaysRaiseExecutionEngineException(method); } inline void il2cpp_codegen_raise_out_of_memory_exception() { il2cpp::vm::Exception::RaiseOutOfMemoryException(); } inline Il2CppCodeGenException* il2cpp_codegen_get_argument_exception(const char* param, const char* msg) { return (Il2CppCodeGenException*)il2cpp::vm::Exception::GetArgumentException(param, msg); } inline Il2CppCodeGenException* il2cpp_codegen_get_argument_null_exception(const char* param) { return (Il2CppCodeGenException*)il2cpp::vm::Exception::GetArgumentNullException(param); } inline Il2CppCodeGenException* il2cpp_codegen_get_overflow_exception() { return (Il2CppCodeGenException*)il2cpp::vm::Exception::GetOverflowException("Arithmetic operation resulted in an overflow."); } inline Il2CppCodeGenException* il2cpp_codegen_get_not_supported_exception(const char* msg) { return (Il2CppCodeGenException*)il2cpp::vm::Exception::GetNotSupportedException(msg); } inline Il2CppCodeGenException* il2cpp_codegen_get_array_type_mismatch_exception() { return (Il2CppCodeGenException*)il2cpp::vm::Exception::GetArrayTypeMismatchException(); } inline Il2CppCodeGenException* il2cpp_codegen_get_invalid_cast_exception(const char* msg) { return (Il2CppCodeGenException*)il2cpp::vm::Exception::GetInvalidCastException(msg); } inline Il2CppCodeGenException* il2cpp_codegen_get_invalid_operation_exception(const char* msg) { return (Il2CppCodeGenException*)il2cpp::vm::Exception::GetInvalidOperationException(msg); } inline Il2CppCodeGenException* il2cpp_codegen_get_marshal_directive_exception(const char* msg) { return (Il2CppCodeGenException*)il2cpp::vm::Exception::GetMarshalDirectiveException(msg); } inline Il2CppCodeGenException* il2cpp_codegen_get_missing_method_exception(const char* msg) { return (Il2CppCodeGenException*)il2cpp::vm::Exception::GetMissingMethodException(msg); } inline Il2CppCodeGenException* il2cpp_codegen_get_maximum_nested_generics_exception() { return (Il2CppCodeGenException*)il2cpp::vm::Exception::GetMaxmimumNestedGenericsException(); } inline RuntimeClass* il2cpp_codegen_object_class(RuntimeObject* obj) { return obj->klass; } // OpCode.IsInst inline RuntimeObject* IsInst(RuntimeObject *obj, RuntimeClass* targetType) { return il2cpp::vm::Object::IsInst(obj, targetType); } inline RuntimeObject* IsInstSealed(RuntimeObject *obj, RuntimeClass* targetType) { #if IL2CPP_DEBUG IL2CPP_ASSERT((targetType->flags & TYPE_ATTRIBUTE_SEALED) != 0); IL2CPP_ASSERT((targetType->flags & TYPE_ATTRIBUTE_INTERFACE) == 0); #endif if (!obj) return NULL; // optimized version to compare sealed classes return (obj->klass == targetType ? obj : NULL); } inline RuntimeObject* IsInstClass(RuntimeObject *obj, RuntimeClass* targetType) { #if IL2CPP_DEBUG IL2CPP_ASSERT((targetType->flags & TYPE_ATTRIBUTE_INTERFACE) == 0); #endif if (!obj) return NULL; // optimized version to compare classes return il2cpp::vm::Class::HasParentUnsafe(obj->klass, targetType) ? obj : NULL; } // OpCode.Castclass NORETURN inline void RaiseInvalidCastException(RuntimeObject* obj, RuntimeClass* targetType) { std::string exceptionMessage = il2cpp::utils::Exception::FormatInvalidCastException(obj->klass->element_class, targetType); RuntimeException* exception = il2cpp::vm::Exception::GetInvalidCastException(exceptionMessage.c_str()); il2cpp::vm::Exception::Raise(exception); } inline RuntimeObject* Castclass(RuntimeObject *obj, RuntimeClass* targetType) { if (!obj) return NULL; RuntimeObject* result = il2cpp::vm::Object::IsInst(obj, targetType); if (result) return result; RaiseInvalidCastException(obj, targetType); return NULL; } inline RuntimeObject* CastclassSealed(RuntimeObject *obj, RuntimeClass* targetType) { if (!obj) return NULL; RuntimeObject* result = IsInstSealed(obj, targetType); if (result) return result; RaiseInvalidCastException(obj, targetType); return NULL; } inline RuntimeObject* CastclassClass(RuntimeObject *obj, RuntimeClass* targetType) { if (!obj) return NULL; RuntimeObject* result = IsInstClass(obj, targetType); if (result) return result; RaiseInvalidCastException(obj, targetType); return NULL; } inline void NullCheck(void* this_ptr) { if (this_ptr != NULL) return; il2cpp::vm::Exception::RaiseNullReferenceException(); #if !IL2CPP_TARGET_IOS il2cpp_codegen_no_return(); #endif } // OpCode.Box inline RuntimeObject* Box(RuntimeClass* type, void* data) { return il2cpp::vm::Object::Box(type, data); } // OpCode.UnBox inline void* UnBox(RuntimeObject* obj) { NullCheck(obj); return il2cpp::vm::Object::Unbox(obj); } inline void* UnBox(RuntimeObject* obj, RuntimeClass* expectedBoxedClass) { NullCheck(obj); if (obj->klass->element_class == expectedBoxedClass->element_class) return il2cpp::vm::Object::Unbox(obj); RaiseInvalidCastException(obj, expectedBoxedClass); return NULL; } inline void UnBoxNullable(RuntimeObject* obj, RuntimeClass* expectedBoxedClass, void* storage) { // We only need to do type checks if obj is not null // Unboxing null nullable is perfectly valid and returns an instance that has no value if (obj != NULL) { if (obj->klass->element_class != expectedBoxedClass->element_class) RaiseInvalidCastException(obj, expectedBoxedClass); } il2cpp::vm::Object::UnboxNullable(obj, expectedBoxedClass, storage); } inline uint32_t il2cpp_codegen_sizeof(RuntimeClass* klass) { if (!klass->valuetype) { return sizeof(void*); } return il2cpp::vm::Class::GetInstanceSize(klass) - sizeof(RuntimeObject); } FORCE_INLINE const VirtualInvokeData& il2cpp_codegen_get_virtual_invoke_data(Il2CppMethodSlot slot, const RuntimeObject* obj) { Assert(slot != 65535 && "il2cpp_codegen_get_virtual_invoke_data got called on a non-virtual method"); return obj->klass->vtable[slot]; } FORCE_INLINE const VirtualInvokeData& il2cpp_codegen_get_interface_invoke_data(Il2CppMethodSlot slot, const RuntimeObject* obj, const RuntimeClass* declaringInterface) { Assert(slot != 65535 && "il2cpp_codegen_get_interface_invoke_data got called on a non-virtual method"); return il2cpp::vm::Class::GetInterfaceInvokeDataFromVTable(obj, declaringInterface, slot); } FORCE_INLINE const RuntimeMethod* il2cpp_codegen_get_generic_virtual_method(const RuntimeMethod* method, const RuntimeObject* obj) { uint16_t slot = method->slot; const RuntimeMethod* methodDefinition = obj->klass->vtable[slot].method; return il2cpp::vm::Runtime::GetGenericVirtualMethod(methodDefinition, method); } FORCE_INLINE void il2cpp_codegen_get_generic_virtual_invoke_data(const RuntimeMethod* method, const RuntimeObject* obj, VirtualInvokeData* invokeData) { const RuntimeMethod* targetRuntimeMethod = il2cpp_codegen_get_generic_virtual_method(method, obj); #if IL2CPP_DEBUG IL2CPP_ASSERT(targetRuntimeMethod); #endif invokeData->methodPtr = targetRuntimeMethod->methodPointer; invokeData->method = targetRuntimeMethod; } FORCE_INLINE const RuntimeMethod* il2cpp_codegen_get_generic_interface_method(const RuntimeMethod* method, const RuntimeObject* obj) { const RuntimeMethod* methodDefinition = il2cpp::vm::Class::GetInterfaceInvokeDataFromVTable(obj, method->declaring_type, method->slot).method; return il2cpp::vm::Runtime::GetGenericVirtualMethod(methodDefinition, method); } FORCE_INLINE void il2cpp_codegen_get_generic_interface_invoke_data(const RuntimeMethod* method, const RuntimeObject* obj, VirtualInvokeData* invokeData) { const RuntimeMethod* targetRuntimeMethod = il2cpp_codegen_get_generic_interface_method(method, obj); #if IL2CPP_DEBUG IL2CPP_ASSERT(targetRuntimeMethod); #endif invokeData->methodPtr = targetRuntimeMethod->methodPointer; invokeData->method = targetRuntimeMethod; } #include "GeneratedVirtualInvokers.h" #include "GeneratedInterfaceInvokers.h" #include "GeneratedGenericVirtualInvokers.h" #include "GeneratedGenericInterfaceInvokers.h" // OpCode.Ldtoken inline Il2CppCodeGenRuntimeTypeHandle LoadTypeToken(const RuntimeType* ptr) { Il2CppCodeGenIntPtr intptr; intptr.set_m_value_0(const_cast(ptr)); Il2CppCodeGenRuntimeTypeHandle handle; handle.set_value_0(intptr); return handle; } inline Il2CppCodeGenRuntimeFieldHandle LoadFieldToken(void* ptr) { Il2CppCodeGenIntPtr intptr; intptr.set_m_value_0(ptr); Il2CppCodeGenRuntimeFieldHandle handle; handle.set_value_0(intptr); return handle; } inline Il2CppCodeGenRuntimeArgumentHandle LoadArgList() { Il2CppCodeGenIntPtr intptr; intptr.set_m_value_0(NULL); Il2CppCodeGenRuntimeArgumentHandle handle; handle.set_args_0(intptr); IL2CPP_ASSERT(false && "__arglist usage not supported."); return handle; } inline Il2CppCodeGenRuntimeMethodHandle LoadMethodToken(const RuntimeMethod* ptr) { Il2CppCodeGenIntPtr intptr; intptr.set_m_value_0(const_cast(ptr)); Il2CppCodeGenRuntimeMethodHandle handle; handle.set_value_0(intptr); return handle; } inline RuntimeClass* InitializedTypeInfo(RuntimeClass* klass) { il2cpp::vm::Class::Init(klass); return klass; } inline RuntimeClass* il2cpp_codegen_class_from_type(const RuntimeType *type) { return InitializedTypeInfo(il2cpp::vm::Class::FromIl2CppType(type)); } inline void* InterlockedExchangeImplRef(void** location, void* value) { return il2cpp::icalls::mscorlib::System::Threading::Interlocked::ExchangePointer(location, value); } template inline T InterlockedCompareExchangeImpl(T* location, T value, T comparand) { return (T)il2cpp::icalls::mscorlib::System::Threading::Interlocked::CompareExchange_T((void**)location, value, comparand); } template inline T InterlockedExchangeImpl(T* location, T value) { return (T)InterlockedExchangeImplRef((void**)location, value); } inline void il2cpp_codegen_memory_barrier() { il2cpp::vm::Thread::MemoryBarrier(); } inline void ArrayGetGenericValueImpl(RuntimeArray* thisPtr, int32_t pos, void* value) { memcpy(value, ((uint8_t*)thisPtr) + sizeof(RuntimeArray) + pos * thisPtr->klass->element_size, thisPtr->klass->element_size); } inline void ArraySetGenericValueImpl(RuntimeArray * thisPtr, int32_t pos, void* value) { memcpy(((uint8_t*)thisPtr) + sizeof(RuntimeArray) + pos * thisPtr->klass->element_size, value, thisPtr->klass->element_size); } inline RuntimeArray* SZArrayNew(RuntimeClass* arrayType, uint32_t length) { il2cpp::vm::Class::Init(arrayType); return il2cpp::vm::Array::NewSpecific(arrayType, length); } inline RuntimeArray* GenArrayNew(RuntimeClass* arrayType, il2cpp_array_size_t* dimensions) { return il2cpp::vm::Array::NewFull(arrayType, dimensions, NULL); } // Performance optimization as detailed here: http://blogs.msdn.com/b/clrcodegeneration/archive/2009/08/13/array-bounds-check-elimination-in-the-clr.aspx // Since array size is a signed int32_t, a single unsigned check can be performed to determine if index is less than array size. // Negative indices will map to a unsigned number greater than or equal to 2^31 which is larger than allowed for a valid array. #define IL2CPP_ARRAY_BOUNDS_CHECK(index, length) \ do { \ if (((uint32_t)(index)) >= ((uint32_t)length)) il2cpp::vm::Exception::Raise (il2cpp::vm::Exception::GetIndexOutOfRangeException()); \ } while (0) inline bool il2cpp_codegen_class_is_assignable_from(RuntimeClass *klass, RuntimeClass *oklass) { return il2cpp::vm::Class::IsAssignableFrom(klass, oklass); } inline RuntimeObject* il2cpp_codegen_object_new(RuntimeClass *klass) { return il2cpp::vm::Object::New(klass); } inline Il2CppMethodPointer il2cpp_codegen_resolve_icall(const char* name) { Il2CppMethodPointer method = il2cpp::vm::InternalCalls::Resolve(name); if (!method) { il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetMissingMethodException(name)); } return method; } template inline FunctionPointerType il2cpp_codegen_resolve_pinvoke(const Il2CppNativeChar(&nativeDynamicLibrary)[dynamicLibraryLength], const char(&entryPoint)[entryPointLength], Il2CppCallConvention callingConvention, Il2CppCharSet charSet, int parameterSize, bool isNoMangle) { const PInvokeArguments pinvokeArgs = { il2cpp::utils::StringView(nativeDynamicLibrary), il2cpp::utils::StringView(entryPoint), callingConvention, charSet, parameterSize, isNoMangle }; return reinterpret_cast(il2cpp::vm::PlatformInvoke::Resolve(pinvokeArgs)); } template inline T* il2cpp_codegen_marshal_allocate_array(size_t length) { return static_cast(il2cpp::vm::MarshalAlloc::Allocate((il2cpp_array_size_t)(sizeof(T) * length))); } inline char* il2cpp_codegen_marshal_string(Il2CppCodeGenString* il2CppString) { return il2cpp::vm::PlatformInvoke::MarshalCSharpStringToCppString((Il2CppString*)il2CppString); } inline void il2cpp_codegen_marshal_string_fixed(Il2CppCodeGenString* il2CppString, char* buffer, int numberOfCharacters) { return il2cpp::vm::PlatformInvoke::MarshalCSharpStringToCppStringFixed((Il2CppString*)il2CppString, buffer, numberOfCharacters); } inline Il2CppChar* il2cpp_codegen_marshal_wstring(Il2CppCodeGenString* il2CppString) { return il2cpp::vm::PlatformInvoke::MarshalCSharpStringToCppWString((Il2CppString*)il2CppString); } inline void il2cpp_codegen_marshal_wstring_fixed(Il2CppCodeGenString* il2CppString, Il2CppChar* buffer, int numberOfCharacters) { return il2cpp::vm::PlatformInvoke::MarshalCSharpStringToCppWStringFixed((Il2CppString*)il2CppString, buffer, numberOfCharacters); } inline Il2CppChar* il2cpp_codegen_marshal_bstring(Il2CppCodeGenString* il2CppString) { return il2cpp::vm::PlatformInvoke::MarshalCSharpStringToCppBString((Il2CppString*)il2CppString); } inline Il2CppCodeGenString* il2cpp_codegen_marshal_string_result(const char* value) { return (Il2CppCodeGenString*)il2cpp::vm::PlatformInvoke::MarshalCppStringToCSharpStringResult(value); } inline Il2CppCodeGenString* il2cpp_codegen_marshal_wstring_result(const Il2CppChar* value) { return (Il2CppCodeGenString*)il2cpp::vm::PlatformInvoke::MarshalCppWStringToCSharpStringResult(value); } inline Il2CppCodeGenString* il2cpp_codegen_marshal_bstring_result(const Il2CppChar* value) { return (Il2CppCodeGenString*)il2cpp::vm::PlatformInvoke::MarshalCppBStringToCSharpStringResult(value); } inline void il2cpp_codegen_marshal_free_bstring(Il2CppChar* value) { il2cpp::vm::PlatformInvoke::MarshalFreeBString(value); } inline char* il2cpp_codegen_marshal_string_builder(Il2CppCodeGenStringBuilder* stringBuilder) { return il2cpp::vm::PlatformInvoke::MarshalStringBuilder((Il2CppStringBuilder*)stringBuilder); } inline Il2CppChar* il2cpp_codegen_marshal_wstring_builder(Il2CppCodeGenStringBuilder* stringBuilder) { return il2cpp::vm::PlatformInvoke::MarshalWStringBuilder((Il2CppStringBuilder*)stringBuilder); } inline void il2cpp_codegen_marshal_string_builder_result(Il2CppCodeGenStringBuilder* stringBuilder, char* buffer) { il2cpp::vm::PlatformInvoke::MarshalStringBuilderResult((Il2CppStringBuilder*)stringBuilder, buffer); } inline void il2cpp_codegen_marshal_wstring_builder_result(Il2CppCodeGenStringBuilder* stringBuilder, Il2CppChar* buffer) { il2cpp::vm::PlatformInvoke::MarshalWStringBuilderResult((Il2CppStringBuilder*)stringBuilder, buffer); } inline Il2CppHString il2cpp_codegen_create_hstring(Il2CppCodeGenString* str) { return il2cpp::vm::WindowsRuntime::CreateHString(reinterpret_cast(str)); } inline Il2CppCodeGenString* il2cpp_codegen_marshal_hstring_result(Il2CppHString hstring) { return reinterpret_cast(il2cpp::vm::WindowsRuntime::HStringToManagedString(hstring)); } inline void il2cpp_codegen_marshal_free_hstring(Il2CppHString hstring) { il2cpp::vm::WindowsRuntime::DeleteHString(hstring); } inline void il2cpp_codegen_marshal_free(void* ptr) { il2cpp::vm::PlatformInvoke::MarshalFree(ptr); } inline Il2CppMethodPointer il2cpp_codegen_marshal_delegate(Il2CppCodeGenMulticastDelegate* d) { return (Il2CppMethodPointer)il2cpp::vm::PlatformInvoke::MarshalDelegate((Il2CppDelegate*)d).m_value; } template inline T* il2cpp_codegen_marshal_function_ptr_to_delegate(Il2CppMethodPointer functionPtr, RuntimeClass* delegateType) { return (T*)il2cpp::vm::PlatformInvoke::MarshalFunctionPointerToDelegate(reinterpret_cast(functionPtr), delegateType); } inline void il2cpp_codegen_marshal_store_last_error() { il2cpp::vm::LastError::StoreLastError(); } class il2cpp_native_wrapper_vm_thread_attacher { public: il2cpp_native_wrapper_vm_thread_attacher() : _threadWasAttached(false) { if (il2cpp::vm::Thread::Current() == NULL) { il2cpp::vm::Thread::Attach(il2cpp::vm::Domain::GetRoot()); _threadWasAttached = true; } } ~il2cpp_native_wrapper_vm_thread_attacher() { if (_threadWasAttached) il2cpp::vm::Thread::Detach(il2cpp::vm::Thread::Current()); } private: bool _threadWasAttached; }; #if _DEBUG struct ScopedMarshallingAllocationFrame { ScopedMarshallingAllocationFrame() { il2cpp::vm::MarshalAlloc::PushAllocationFrame(); } ~ScopedMarshallingAllocationFrame() { il2cpp::vm::MarshalAlloc::PopAllocationFrame(); } }; struct ScopedMarshallingAllocationCheck { ~ScopedMarshallingAllocationCheck() { if (il2cpp::vm::MarshalAlloc::HasUnfreedAllocations()) il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetInvalidOperationException("Error in marshaling allocation. Some memory has been leaked.")); } private: ScopedMarshallingAllocationFrame m_AllocationFrame; }; struct ScopedMarshalingAllocationClearer { ~ScopedMarshalingAllocationClearer() { il2cpp::vm::MarshalAlloc::ClearAllTrackedAllocations(); } private: ScopedMarshallingAllocationFrame m_AllocationFrame; }; #endif inline void DivideByZeroCheck(int64_t denominator) { if (denominator != 0) return; il2cpp::vm::Exception::RaiseDivideByZeroException(); #if !IL2CPP_TARGET_IOS il2cpp_codegen_no_return(); #endif } inline void Initobj(RuntimeClass* type, void* data) { if (type->valuetype) memset(data, 0, type->instance_size - sizeof(RuntimeObject)); else *static_cast(data) = NULL; } inline bool MethodIsStatic(const RuntimeMethod* method) { return !il2cpp::vm::Method::IsInstance(method); } inline bool MethodHasParameters(const RuntimeMethod* method) { return il2cpp::vm::Method::GetParamCount(method) != 0; } #define IL2CPP_RUNTIME_CLASS_INIT(klass) do { if((klass)->has_cctor && !(klass)->cctor_finished) il2cpp::vm::Runtime::ClassInit ((klass)); } while (0) // generic sharing #define IL2CPP_RGCTX_DATA(rgctxVar, index) (InitializedTypeInfo(rgctxVar[index].klass)) #define IL2CPP_RGCTX_SIZEOF(rgctxVar, index) (il2cpp_codegen_sizeof(IL2CPP_RGCTX_DATA(rgctxVar, index))) #define IL2CPP_RGCTX_TYPE(rgctxVar, index) (rgctxVar[index].type) #define IL2CPP_RGCTX_METHOD_INFO(rgctxVar, index) (rgctxVar[index].method) #define IL2CPP_RGCTX_FIELD_INFO(klass, index) ((klass)->fields+index) inline void ArrayElementTypeCheck(RuntimeArray* array, void* value) { if (value != NULL && il2cpp::vm::Object::IsInst((RuntimeObject*)value, array->klass->element_class) == NULL) il2cpp_codegen_raise_exception(il2cpp_codegen_get_array_type_mismatch_exception()); } inline const RuntimeMethod* GetVirtualMethodInfo(RuntimeObject* pThis, Il2CppMethodSlot slot) { if (!pThis) il2cpp::vm::Exception::RaiseNullReferenceException(); return pThis->klass->vtable[slot].method; } inline const RuntimeMethod* GetInterfaceMethodInfo(RuntimeObject* pThis, Il2CppMethodSlot slot, RuntimeClass* declaringInterface) { if (!pThis) il2cpp::vm::Exception::RaiseNullReferenceException(); return il2cpp::vm::Class::GetInterfaceInvokeDataFromVTable(pThis, declaringInterface, slot).method; } inline void il2cpp_codegen_initialize_method(uint32_t index) { il2cpp::vm::MetadataCache::InitializeMethodMetadata(index); } inline bool il2cpp_codegen_type_implements_virtual_method(RuntimeClass* type, const RuntimeMethod* method) { IL2CPP_ASSERT(il2cpp::vm::Class::IsValuetype(type)); return method->declaring_type == type; } inline Il2CppCodeGenMethodBase* il2cpp_codegen_get_method_object(const RuntimeMethod* method) { if (method->is_inflated) method = il2cpp::vm::MetadataCache::GetGenericMethodDefinition(method); return (Il2CppCodeGenMethodBase*)il2cpp::vm::Reflection::GetMethodObject(method, method->declaring_type); } inline Il2CppCodeGenType* il2cpp_codegen_get_type(Il2CppMethodPointer getTypeFunction, Il2CppCodeGenString* typeName, const char* assemblyName) { typedef Il2CppCodeGenType* (*getTypeFuncType)(RuntimeObject*, Il2CppCodeGenString*, const RuntimeMethod*); Il2CppString* assemblyQualifiedTypeName = il2cpp::vm::Type::AppendAssemblyNameIfNecessary((Il2CppString*)typeName, assemblyName); // Try to find the type using a hint about about calling assembly. If it is not found, fall back to calling GetType without the hint. Il2CppCodeGenType* type = ((getTypeFuncType)getTypeFunction)(NULL, (Il2CppCodeGenString*)assemblyQualifiedTypeName, NULL); if (type == NULL) return ((getTypeFuncType)getTypeFunction)(NULL, typeName, NULL); return type; } inline Il2CppCodeGenType* il2cpp_codegen_get_type(Il2CppMethodPointer getTypeFunction, Il2CppCodeGenString* typeName, bool throwOnError, const char* assemblyName) { typedef Il2CppCodeGenType* (*getTypeFuncType)(RuntimeObject*, Il2CppCodeGenString*, bool, const RuntimeMethod*); Il2CppString* assemblyQualifiedTypeName = il2cpp::vm::Type::AppendAssemblyNameIfNecessary((Il2CppString*)typeName, assemblyName); // Try to find the type using a hint about about calling assembly. If it is not found, fall back to calling GetType without the hint. Il2CppCodeGenType* type = ((getTypeFuncType)getTypeFunction)(NULL, (Il2CppCodeGenString*)assemblyQualifiedTypeName, throwOnError, NULL); if (type == NULL) return ((getTypeFuncType)getTypeFunction)(NULL, typeName, throwOnError, NULL); return type; } inline Il2CppCodeGenType* il2cpp_codegen_get_type(Il2CppMethodPointer getTypeFunction, Il2CppCodeGenString* typeName, bool throwOnError, bool ignoreCase, const char* assemblyName) { typedef Il2CppCodeGenType* (*getTypeFuncType)(RuntimeObject*, Il2CppCodeGenString*, bool, bool, const RuntimeMethod*); Il2CppString* assemblyQualifiedTypeName = il2cpp::vm::Type::AppendAssemblyNameIfNecessary((Il2CppString*)typeName, assemblyName); // Try to find the type using a hint about about calling assembly. If it is not found, fall back to calling GetType without the hint. Il2CppCodeGenType* type = ((getTypeFuncType)getTypeFunction)(NULL, (Il2CppCodeGenString*)assemblyQualifiedTypeName, throwOnError, ignoreCase, NULL); if (type == NULL) return ((getTypeFuncType)getTypeFunction)(NULL, typeName, throwOnError, ignoreCase, NULL); return type; } inline Il2CppCodeGenAssembly* il2cpp_codegen_get_executing_assembly(const RuntimeMethod* method) { return (Il2CppCodeGenAssembly*)il2cpp::vm::Reflection::GetAssemblyObject(il2cpp::vm::MetadataCache::GetAssemblyFromIndex(method->declaring_type->image->assemblyIndex)); } // Atomic inline void* il2cpp_codegen_atomic_compare_exchange_pointer(void* volatile* dest, void* exchange, void* comparand) { return il2cpp::vm::Atomic::CompareExchangePointer(dest, exchange, comparand); } template inline T* il2cpp_codegen_atomic_compare_exchange_pointer(T* volatile* dest, T* newValue, T* oldValue) { return il2cpp::vm::Atomic::CompareExchangePointer(dest, newValue, oldValue); } // COM inline void il2cpp_codegen_com_marshal_variant(RuntimeObject* obj, Il2CppVariant* variant) { il2cpp::vm::COM::MarshalVariant(obj, variant); } inline RuntimeObject* il2cpp_codegen_com_marshal_variant_result(const Il2CppVariant* variant) { return il2cpp::vm::COM::MarshalVariantResult(variant); } inline void il2cpp_codegen_com_destroy_variant(Il2CppVariant* variant) { il2cpp::vm::COM::DestroyVariant(variant); } inline Il2CppSafeArray* il2cpp_codegen_com_marshal_safe_array(Il2CppChar type, RuntimeArray* managedArray) { return il2cpp::vm::COM::MarshalSafeArray(type, managedArray); } inline RuntimeArray* il2cpp_codegen_com_marshal_safe_array_result(Il2CppChar variantType, RuntimeClass* type, Il2CppSafeArray* safeArray) { return il2cpp::vm::COM::MarshalSafeArrayResult(variantType, type, safeArray); } inline Il2CppSafeArray* il2cpp_codegen_com_marshal_safe_array_bstring(RuntimeArray* managedArray) { return il2cpp::vm::COM::MarshalSafeArrayBString(managedArray); } inline RuntimeArray* il2cpp_codegen_com_marshal_safe_array_bstring_result(RuntimeClass* type, Il2CppSafeArray* safeArray) { return il2cpp::vm::COM::MarshalSafeArrayBStringResult(type, safeArray); } inline void il2cpp_codegen_com_destroy_safe_array(Il2CppSafeArray* safeArray) { il2cpp::vm::COM::DestroySafeArray(safeArray); } inline void il2cpp_codegen_com_create_instance(const Il2CppGuid& clsid, Il2CppIUnknown** identity) { il2cpp::vm::COM::CreateInstance(clsid, identity); } inline void il2cpp_codegen_com_register_rcw(Il2CppComObject* rcw) { il2cpp::vm::RCW::Register(rcw); } template inline T* il2cpp_codegen_com_get_or_create_rcw_from_iunknown(Il2CppIUnknown* unknown, RuntimeClass* fallbackClass) { return static_cast(il2cpp::vm::RCW::GetOrCreateFromIUnknown(unknown, fallbackClass)); } template inline T* il2cpp_codegen_com_get_or_create_rcw_from_iinspectable(Il2CppIInspectable* unknown, RuntimeClass* fallbackClass) { return static_cast(il2cpp::vm::RCW::GetOrCreateFromIInspectable(unknown, fallbackClass)); } template inline T* il2cpp_codegen_com_get_or_create_rcw_for_sealed_class(Il2CppIUnknown* unknown, RuntimeClass* objectClass) { return static_cast(il2cpp::vm::RCW::GetOrCreateForSealedClass(unknown, objectClass)); } inline void il2cpp_codegen_il2cpp_com_object_cleanup(Il2CppComObject* rcw) { il2cpp::vm::RCW::Cleanup(rcw); } template inline InterfaceType* il2cpp_codegen_com_get_or_create_ccw(RuntimeObject* obj) { return static_cast(il2cpp::vm::CCW::GetOrCreate(obj, InterfaceType::IID)); } inline Il2CppCodeGenIntPtr il2cpp_codegen_com_get_iunknown_for_object(RuntimeObject* obj) { Il2CppCodeGenIntPtr result; result.set_m_value_0(il2cpp::vm::CCW::GetOrCreate(obj, Il2CppIUnknown::IID)); return result; } inline void il2cpp_codegen_com_raise_exception_if_failed(il2cpp_hresult_t hr, bool defaultToCOMException) { il2cpp::vm::Exception::RaiseIfFailed(hr, defaultToCOMException); } inline RuntimeException* il2cpp_codegen_com_get_exception(il2cpp_hresult_t hr, bool defaultToCOMException) { return il2cpp::vm::Exception::Get(hr, defaultToCOMException); } inline RuntimeException* il2cpp_codegen_com_get_exception_for_invalid_iproperty_cast(RuntimeObject* value, const char* a, const char* b) { return il2cpp::vm::CCW::GetIPropertyValueInvalidCast(value, a, b); } inline void il2cpp_codegen_store_exception_info(RuntimeException* ex, Il2CppCodeGenString* exceptionString) { il2cpp::vm::Exception::StoreExceptionInfo(ex, reinterpret_cast(exceptionString)); } inline Il2CppIActivationFactory* il2cpp_codegen_windows_runtime_get_activation_factory(const il2cpp::utils::StringView& runtimeClassName) { return il2cpp::vm::WindowsRuntime::GetActivationFactory(runtimeClassName); } // delegate inline Il2CppAsyncResult* il2cpp_codegen_delegate_begin_invoke(Il2CppDelegate* delegate, void** params, Il2CppDelegate* asyncCallback, RuntimeObject* state) { #if NET_4_0 return il2cpp::vm::ThreadPoolMs::DelegateBeginInvoke(delegate, params, asyncCallback, state); #else return il2cpp::vm::ThreadPool::Queue(delegate, params, asyncCallback, state); #endif } inline RuntimeObject* il2cpp_codegen_delegate_end_invoke(Il2CppAsyncResult* asyncResult, void **out_args) { #if NET_4_0 return il2cpp::vm::ThreadPoolMs::DelegateEndInvoke(asyncResult, out_args); #else return il2cpp::vm::ThreadPool::Wait(asyncResult, out_args); #endif } inline const Il2CppGenericInst* il2cpp_codegen_get_generic_class_inst(RuntimeClass* genericClass) { IL2CPP_ASSERT(genericClass->generic_class); return genericClass->generic_class->context.class_inst; } inline RuntimeClass* il2cpp_codegen_inflate_generic_class(RuntimeClass* genericClassDefinition, const Il2CppGenericInst* genericInst) { return il2cpp::vm::Class::GetInflatedGenericInstanceClass(genericClassDefinition, genericInst); } inline void* il2cpp_codegen_static_fields_for(RuntimeClass* klass) { return klass->static_fields; } inline Il2CppMethodPointer il2cpp_codegen_get_method_pointer(const RuntimeMethod* method) { return method->methodPointer; } inline const RuntimeType* il2cpp_codegen_method_return_type(const RuntimeMethod* method) { return method->return_type; } inline bool il2cpp_codegen_is_import_or_windows_runtime(const RuntimeObject *object) { return object->klass->is_import_or_windows_runtime; } inline std::string il2cpp_codegen_format_exception(const RuntimeException* ex) { return il2cpp::utils::Exception::FormatException(ex); } ================================================ FILE: unity_decoder/libil2cpp/codegen/il2cpp-codegen-mono.h ================================================ #pragma once #include "il2cpp-codegen-common.h" #include "il2cpp-mono-support.h" #include "mono-api.h" struct ProfilerMethodSentry { ProfilerMethodSentry(const RuntimeMethod* method) #if IL2CPP_ENABLE_PROFILER : m_method(method) #endif { NOT_IMPLEMENTED("Unity profiler hooks are not implemented yet for the libmonoruntime backend."); } ~ProfilerMethodSentry() { NOT_IMPLEMENTED("Unity profiler hooks are not implemented yet for the libmonoruntime backend."); } private: const RuntimeMethod* m_method; }; struct StackTraceSentry { StackTraceSentry(RuntimeMethod* method) : m_method(method) { MonoStackFrameInfo frame_info; frame_info.method = method; frame_info.actual_method = method; frame_info.type = MONO_FRAME_TYPE_MANAGED; frame_info.managed = 1; frame_info.il_offset = 0; frame_info.native_offset = 0; frame_info.ji = (void*)-1; mono::vm::StackTrace::PushFrame(frame_info); } #if IL2CPP_DEBUGGER_ENABLED StackTraceSentry(const RuntimeMethod* method, void* this_ptr, void **params, int32_t params_count, void **locals, int32_t locals_count) : m_method(method) { } #endif ~StackTraceSentry() { mono::vm::StackTrace::PopFrame(); } private: const RuntimeMethod* m_method; }; template struct Il2CppFakeBox : RuntimeObject { T m_Value; Il2CppFakeBox(RuntimeClass* boxedType, T* value) { vtable = mono_class_vtable(mono_domain_get(), boxedType); synchronisation = NULL; m_Value = *value; } }; // TODO: This file should contain all the functions and type declarations needed for the generated code. // Hopefully, we stop including everything in the generated code and know exactly what dependencies we have. // Note that all parameter and return types should match the generated types not the runtime types. #include "GeneratedCodeGen.h" // type registration inline Il2CppCodeGenString* il2cpp_codegen_string_new_utf16(const il2cpp::utils::StringView& str) { return (Il2CppCodeGenString*)mono_string_new_utf16(mono_domain_get(), (uint16_t*)str.Str(), (int32_t)str.Length()); } inline NORETURN void il2cpp_codegen_raise_exception(Il2CppCodeGenException *ex) { mono_raise_exception((RuntimeException*)ex); il2cpp_codegen_no_return(); } inline void il2cpp_codegen_raise_execution_engine_exception_if_method_is_not_found(const RuntimeMethod* method) { il2cpp_mono_raise_execution_engine_exception_if_method_is_not_found(const_cast(method)); } inline void il2cpp_codegen_raise_execution_engine_exception(const RuntimeMethod* method) { mono_raise_exception(mono_get_exception_execution_engine(mono_unity_method_get_name(method))); } inline Il2CppCodeGenException* il2cpp_codegen_get_argument_exception(const char* param, const char* msg) { return (Il2CppCodeGenException*)mono_get_exception_argument(param, msg); } inline Il2CppCodeGenException* il2cpp_codegen_get_argument_null_exception(const char* param) { return (Il2CppCodeGenException*)mono_get_exception_argument_null(param); } inline Il2CppCodeGenException* il2cpp_codegen_get_overflow_exception() { return (Il2CppCodeGenException*)mono_get_exception_overflow(); } inline Il2CppCodeGenException* il2cpp_codegen_get_not_supported_exception(const char* msg) { return (Il2CppCodeGenException*)mono_get_exception_not_supported(msg); } inline Il2CppCodeGenException* il2cpp_codegen_get_array_type_mismatch_exception() { return (Il2CppCodeGenException*)mono_get_exception_array_type_mismatch(); } inline Il2CppCodeGenException* il2cpp_codegen_get_invalid_operation_exception(const char* msg) { return (Il2CppCodeGenException*)mono_get_exception_invalid_operation(msg); } inline Il2CppCodeGenException* il2cpp_codegen_get_marshal_directive_exception(const char* msg) { return (Il2CppCodeGenException*)mono_unity_exception_get_marshal_directive(msg); } inline Il2CppCodeGenException* il2cpp_codegen_get_missing_method_exception(const char* msg) { return (Il2CppCodeGenException*)mono_get_exception_missing_method(msg, "ctor"); } inline Il2CppCodeGenException* il2cpp_codegen_get_maximum_nested_generics_exception() { return (Il2CppCodeGenException*)mono_get_exception_not_supported(MAXIMUM_NESTED_GENERICS_EXCEPTION_MESSAGE); } inline RuntimeClass* il2cpp_codegen_object_class(RuntimeObject* obj) { return mono_object_get_class(obj); } // OpCode.IsInst inline RuntimeObject* IsInst(RuntimeObject *obj, RuntimeClass* targetType) { return mono_object_isinst(obj, targetType); } inline RuntimeObject* IsInstSealed(RuntimeObject *obj, RuntimeClass* targetType) { if (!obj) return NULL; // optimized version to compare sealed classes return mono_unity_object_isinst_sealed(obj, targetType); } inline RuntimeObject* IsInstClass(RuntimeObject *obj, RuntimeClass* targetType) { if (!obj) return NULL; return mono_unity_class_has_parent_unsafe(mono_object_get_class(obj), targetType) ? obj : NULL; } // OpCode.Castclass inline RuntimeObject* Castclass(RuntimeObject *obj, RuntimeClass* targetType) { if (!obj) return NULL; RuntimeObject* result = mono_object_isinst(obj, targetType); if (result) return result; mono_raise_exception(mono_get_exception_invalid_cast()); return NULL; } inline RuntimeObject* CastclassSealed(RuntimeObject *obj, RuntimeClass* targetType) { if (!obj) return NULL; RuntimeObject* result = IsInstSealed(obj, targetType); if (result) return result; mono_raise_exception(mono_get_exception_invalid_cast()); return NULL; } inline RuntimeObject* CastclassClass(RuntimeObject *obj, RuntimeClass* targetType) { if (!obj) return NULL; RuntimeObject* result = IsInstClass(obj, targetType); if (result) return result; mono_raise_exception(mono_get_exception_invalid_cast()); return NULL; } // OpCode.Box inline RuntimeObject* Box(RuntimeClass* type, void* data) { return mono_value_box(mono_domain_get(), type, data); } // OpCode.UnBox inline void* UnBox(RuntimeObject* obj) { if (!obj) { mono_raise_exception(mono_get_exception_null_reference()); il2cpp_codegen_no_return(); } return mono_object_unbox(obj); } inline void* UnBox(RuntimeObject* obj, RuntimeClass* klass) { if (!obj) { mono_raise_exception(mono_get_exception_null_reference()); il2cpp_codegen_no_return(); } if (!mono_unity_object_check_box_cast(obj, klass)) { mono_raise_exception(mono_get_exception_invalid_cast()); il2cpp_codegen_no_return(); } return mono_object_unbox(obj); } inline void UnBoxNullable(RuntimeObject* obj, RuntimeClass* klass, void* storage) { mono_unity_object_unbox_nullable(obj, klass, storage); } inline uint32_t il2cpp_codegen_sizeof(RuntimeClass* klass) { if (!mono_class_is_valuetype(klass)) return sizeof(void*); return mono_class_instance_size(klass) - sizeof(RuntimeObject); } FORCE_INLINE const VirtualInvokeData il2cpp_codegen_get_virtual_invoke_data(RuntimeMethod* method, void* obj) { VirtualInvokeData invokeData; il2cpp_mono_get_virtual_invoke_data(method, obj, &invokeData); return invokeData; } FORCE_INLINE const VirtualInvokeData il2cpp_codegen_get_interface_invoke_data(RuntimeMethod* method, void* obj, RuntimeClass* declaringInterface) { VirtualInvokeData invokeData; il2cpp_mono_get_interface_invoke_data(method, obj, &invokeData); return invokeData; } FORCE_INLINE const RuntimeMethod* il2cpp_codegen_get_generic_virtual_method(const RuntimeMethod* method, const RuntimeObject* obj) { return il2cpp_mono_get_virtual_target_method(const_cast(method), const_cast(obj)); } FORCE_INLINE void il2cpp_codegen_get_generic_virtual_invoke_data(const RuntimeMethod* method, void* obj, VirtualInvokeData* invokeData) { il2cpp_mono_get_invoke_data(const_cast(method), obj, invokeData); } FORCE_INLINE const RuntimeMethod* il2cpp_codegen_get_generic_interface_method(const RuntimeMethod* method, const RuntimeObject* obj) { return il2cpp_mono_get_virtual_target_method(const_cast(method), const_cast(obj)); } FORCE_INLINE void il2cpp_codegen_get_generic_interface_invoke_data(RuntimeMethod* method, void* obj, VirtualInvokeData* invokeData) { il2cpp_mono_get_invoke_data(method, obj, invokeData); } FORCE_INLINE void il2cpp_codegen_get_generic_interface_invoke_data(const RuntimeMethod* method, void* obj, VirtualInvokeData* invokeData) { il2cpp_codegen_get_generic_interface_invoke_data(const_cast(method), obj, invokeData); } #include "GeneratedVirtualInvokers.h" #include "GeneratedInterfaceInvokers.h" #include "GeneratedGenericVirtualInvokers.h" #include "GeneratedGenericInterfaceInvokers.h" // OpCode.Ldtoken inline Il2CppCodeGenRuntimeTypeHandle LoadTypeToken(const RuntimeType* ptr) { Il2CppCodeGenIntPtr intptr; intptr.set_m_value_0(const_cast(ptr)); Il2CppCodeGenRuntimeTypeHandle handle; handle.set_value_0(intptr); return handle; } inline Il2CppCodeGenRuntimeFieldHandle LoadFieldToken(void* ptr) { Il2CppCodeGenIntPtr intptr; intptr.set_m_value_0(ptr); Il2CppCodeGenRuntimeFieldHandle handle; handle.set_value_0(intptr); return handle; } inline Il2CppCodeGenRuntimeArgumentHandle LoadArgList() { Il2CppCodeGenIntPtr intptr; intptr.set_m_value_0(NULL); Il2CppCodeGenRuntimeArgumentHandle handle; handle.set_args_0(intptr); assert(0 && false && "__arglist usage not supported."); return handle; } inline Il2CppCodeGenRuntimeMethodHandle LoadMethodToken(const RuntimeMethod* ptr) { Il2CppCodeGenIntPtr intptr; intptr.set_m_value_0((void*)ptr); Il2CppCodeGenRuntimeMethodHandle handle; handle.set_value_0(intptr); return handle; } inline RuntimeClass* il2cpp_codegen_class_from_type(RuntimeType* type) { return mono_class_from_mono_type(type); } inline RuntimeClass* il2cpp_codegen_class_from_type(const RuntimeType *type) { return il2cpp_codegen_class_from_type(const_cast(type)); } template inline T InterlockedCompareExchangeImpl(T* location, T value, T comparand) { return (T)mono_unity_object_compare_exchange((RuntimeObject**)location, (RuntimeObject*)value, (RuntimeObject*)comparand); } template inline T InterlockedExchangeImpl(T* location, T value) { return (T)mono_unity_object_exchange((RuntimeObject**)location, (RuntimeObject*)value); } inline void ArrayGetGenericValueImpl(RuntimeArray* __this, int32_t pos, void* value) { int elementSize = mono_unity_array_get_element_size(__this); memcpy(value, mono_array_addr_with_size(__this, elementSize, pos), elementSize); } inline void ArraySetGenericValueImpl(RuntimeArray * __this, int32_t pos, void* value) { int elementSize = mono_unity_array_get_element_size(__this); memcpy(mono_array_addr_with_size(__this, elementSize, pos), value, elementSize); } inline RuntimeArray* SZArrayNew(RuntimeClass* arrayType, uint32_t length) { mono_class_init(arrayType); MonoError error; RuntimeArray *retVal = mono_array_new_specific_checked(mono_class_vtable(mono_domain_get(), arrayType), length, &error); RuntimeException *exc = mono_error_convert_to_exception(&error); if (exc) mono_raise_exception(exc); return retVal; } inline RuntimeArray* GenArrayNew(RuntimeClass* arrayType, il2cpp_array_size_t* dimensions) { // We need to convert to the platform-sized integer type Mono uses. This doesn't look nice, maybe we should change this. std::vector monoDimensions = il2cpp_to_mono_array_dimensions(dimensions, mono_class_get_rank(arrayType)); MonoError error; RuntimeArray *retVal = mono_array_new_full_checked(mono_domain_get(), arrayType, &monoDimensions[0], NULL, &error); RuntimeException *exc = mono_error_convert_to_exception(&error); if (exc) mono_raise_exception(exc); return retVal; } // Performance optimization as detailed here: http://blogs.msdn.com/b/clrcodegeneration/archive/2009/08/13/array-bounds-check-elimination-in-the-clr.aspx // Since array size is a signed int32_t, a single unsigned check can be performed to determine if index is less than array size. // Negative indices will map to a unsigned number greater than or equal to 2^31 which is larger than allowed for a valid array. #define IL2CPP_ARRAY_BOUNDS_CHECK(index, length) \ do { \ if (((uint32_t)(index)) >= ((uint32_t)length)) mono_raise_exception(mono_get_exception_index_out_of_range()); \ } while (0) inline bool il2cpp_codegen_class_is_assignable_from(RuntimeClass *klass, RuntimeClass *oklass) { return mono_class_is_assignable_from(klass, oklass); } inline RuntimeObject* il2cpp_codegen_object_new(RuntimeClass *klass) { return mono_object_new(mono_domain_get(), klass); } inline Il2CppMethodPointer il2cpp_codegen_resolve_icall(const RuntimeMethod* icallMethod) { return (Il2CppMethodPointer)mono_lookup_internal_call(const_cast(icallMethod)); } template inline FunctionPointerType il2cpp_codegen_resolve_pinvoke(const RuntimeMethod* pinvokeMethod) { const char *exc_class, *exc_arg; FunctionPointerType result = reinterpret_cast(mono_lookup_pinvoke_call(const_cast(pinvokeMethod), &exc_class, &exc_arg)); if (exc_class) { mono_raise_exception(mono_exception_from_name_msg(mono_unity_image_get_mscorlib(), "System", exc_class, exc_arg)); il2cpp_codegen_no_return(); } return result; } template inline T* il2cpp_codegen_marshal_allocate_array(size_t length) { MonoError unused; return (T*)mono_marshal_alloc((il2cpp_array_size_t)(sizeof(T) * length), &unused); } inline char* il2cpp_codegen_marshal_string(Il2CppCodeGenString* il2CppString) { return mono::vm::PlatformInvoke::MarshalCSharpStringToCppString((Il2CppString*)il2CppString); } inline void il2cpp_codegen_marshal_string_fixed(Il2CppCodeGenString* il2CppString, char* buffer, int numberOfCharacters) { return mono::vm::PlatformInvoke::MarshalCSharpStringToCppStringFixed((Il2CppString*)il2CppString, buffer, numberOfCharacters); } inline Il2CppChar* il2cpp_codegen_marshal_wstring(Il2CppCodeGenString* il2CppString) { return mono::vm::PlatformInvoke::MarshalCSharpStringToCppWString((Il2CppString*)il2CppString); } inline void il2cpp_codegen_marshal_wstring_fixed(Il2CppCodeGenString* il2CppString, Il2CppChar* buffer, int numberOfCharacters) { return mono::vm::PlatformInvoke::MarshalCSharpStringToCppWStringFixed((Il2CppString*)il2CppString, buffer, numberOfCharacters); } inline Il2CppChar* il2cpp_codegen_marshal_bstring(Il2CppCodeGenString* il2CppString) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); return NULL; } inline Il2CppCodeGenString* il2cpp_codegen_marshal_string_result(const char* value) { return (Il2CppCodeGenString*)mono::vm::PlatformInvoke::MarshalCppStringToCSharpStringResult(value); } inline Il2CppCodeGenString* il2cpp_codegen_marshal_wstring_result(const Il2CppChar* value) { return (Il2CppCodeGenString*)mono::vm::PlatformInvoke::MarshalCppWStringToCSharpStringResult(value); } inline Il2CppCodeGenString* il2cpp_codegen_marshal_bstring_result(const Il2CppChar* value) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); return NULL; } inline void il2cpp_codegen_marshal_free_bstring(Il2CppChar* value) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); } inline char* il2cpp_codegen_marshal_string_builder(Il2CppCodeGenStringBuilder* stringBuilder) { return mono::vm::PlatformInvoke::MarshalStringBuilder((Il2CppStringBuilder*)stringBuilder); } inline Il2CppChar* il2cpp_codegen_marshal_wstring_builder(Il2CppCodeGenStringBuilder* stringBuilder) { return mono::vm::PlatformInvoke::MarshalWStringBuilder((Il2CppStringBuilder*)stringBuilder); } inline void il2cpp_codegen_marshal_string_builder_result(Il2CppCodeGenStringBuilder* stringBuilder, char* buffer) { mono::vm::PlatformInvoke::MarshalStringBuilderResult((Il2CppStringBuilder*)stringBuilder, buffer); } inline void il2cpp_codegen_marshal_wstring_builder_result(Il2CppCodeGenStringBuilder* stringBuilder, Il2CppChar* buffer) { mono::vm::PlatformInvoke::MarshalWStringBuilderResult((Il2CppStringBuilder*)stringBuilder, buffer); } inline Il2CppHString il2cpp_codegen_create_hstring(Il2CppCodeGenString* str) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); return NULL; } inline Il2CppCodeGenString* il2cpp_codegen_marshal_hstring_result(Il2CppHString hstring) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); return NULL; } inline void il2cpp_codegen_marshal_free_hstring(Il2CppHString hstring) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); } inline void il2cpp_codegen_marshal_free(void* ptr) { mono_marshal_free(ptr); } inline Il2CppMethodPointer il2cpp_codegen_marshal_delegate(Il2CppCodeGenMulticastDelegate* d) { return (Il2CppMethodPointer)mono::vm::PlatformInvoke::MarshalDelegate((Il2CppDelegate*)d).m_value; } template inline T* il2cpp_codegen_marshal_function_ptr_to_delegate(Il2CppMethodPointer functionPtr, RuntimeClass* delegateType) { return (T*)mono::vm::PlatformInvoke::MarshalFunctionPointerToDelegate(reinterpret_cast(functionPtr), delegateType); } inline void il2cpp_codegen_marshal_store_last_error() { mono_marshal_set_last_error(); } class il2cpp_native_wrapper_vm_thread_attacher { public: il2cpp_native_wrapper_vm_thread_attacher() : _threadWasAttached(false) { if (!mono_thread_is_attached()) { mono_thread_attach(mono_get_root_domain()); _threadWasAttached = true; } } ~il2cpp_native_wrapper_vm_thread_attacher() { if (_threadWasAttached) mono_thread_detach(mono_thread_current()); } private: bool _threadWasAttached; bool mono_thread_is_attached() { return mono_domain_get() != NULL; } }; #if _DEBUG struct ScopedMarshallingAllocationCheck { }; struct ScopedMarshalingAllocationClearer { }; #endif inline void NullCheck(void* this_ptr) { if (this_ptr != NULL) return; mono_raise_exception(mono_get_exception_null_reference()); #if !IL2CPP_TARGET_IOS il2cpp_codegen_no_return(); #endif } inline void DivideByZeroCheck(int64_t denominator) { if (denominator != 0) return; mono_raise_exception(mono_get_exception_divide_by_zero()); #if !IL2CPP_TARGET_IOS il2cpp_codegen_no_return(); #endif } inline void Initobj(RuntimeClass* type, void* data) { mono_unity_object_init(data, type); } inline bool MethodIsStatic(const RuntimeMethod* method) { return mono_unity_method_is_static(const_cast(method)); } inline bool MethodHasParameters(const RuntimeMethod* method) { return mono_signature_get_param_count(mono_method_signature(const_cast(method))) != 0; } //#define IL2CPP_RUNTIME_CLASS_INIT(klass) do { if((klass)->has_cctor && !(klass)->cctor_finished) il2cpp::vm::Runtime::ClassInit ((klass)); } while (0) #define IL2CPP_RUNTIME_CLASS_INIT(klass) RuntimeInit(klass) inline void* il2cpp_codegen_mono_class_rgctx(RuntimeClass* klass, Il2CppRGCTXDataType rgctxType, int rgctxIndex, bool useSharedVersion) { return il2cpp_mono_class_rgctx(klass, rgctxType, rgctxIndex, useSharedVersion); } inline void* il2cpp_codegen_mono_method_rgctx(RuntimeMethod* method, Il2CppRGCTXDataType rgctxType, int rgctxIndex, bool useSharedVersion) { return il2cpp_mono_method_rgctx(method, rgctxType, rgctxIndex, useSharedVersion); } inline void ArrayElementTypeCheck(RuntimeArray* array, void* value) { if (!value) return; RuntimeClass *aclass = mono_unity_array_get_class(array); RuntimeClass *eclass = mono_unity_class_get_element_class(aclass); RuntimeClass *oclass = mono_unity_object_get_class((RuntimeObject*)value); if (!mono_class_is_assignable_from(eclass, oclass)) mono_raise_exception(mono_get_exception_array_type_mismatch()); } inline const RuntimeMethod* GetVirtualMethodInfo(RuntimeObject* pThis, const RuntimeMethod* method) { if (!pThis) mono_raise_exception(mono_get_exception_null_reference()); return mono_object_get_virtual_method(pThis, const_cast(method)); } inline const RuntimeMethod* GetInterfaceMethodInfo(RuntimeObject* pThis, RuntimeMethod *slot, RuntimeClass* declaringInterface) { if (!pThis) mono_raise_exception(mono_get_exception_null_reference()); return mono_object_get_virtual_method(pThis, slot); } inline void il2cpp_codegen_memory_barrier() { mono_unity_memory_barrier(); } inline void il2cpp_codegen_initialize_method(uint32_t index) { il2cpp_mono_initialize_method_metadata(index); } inline bool il2cpp_codegen_type_implements_virtual_method(RuntimeClass* type, RuntimeMethod *slot) { return mono_unity_method_get_class(slot) == type; } inline Il2CppCodeGenMethodBase* il2cpp_codegen_get_method_object(const RuntimeMethod* method) { if (unity_mono_method_is_inflated(const_cast(method))) method = mono_unity_method_get_generic_definition(const_cast(method)); return (Il2CppCodeGenMethodBase*)mono_unity_method_get_object(const_cast(method)); } inline Il2CppCodeGenType* il2cpp_codegen_get_type(Il2CppMethodPointer getTypeFunction, Il2CppCodeGenString* typeName, const char* assemblyName) { typedef Il2CppCodeGenType* (*getTypeFuncType)(RuntimeObject*, Il2CppCodeGenString*, const RuntimeMethod*); MonoString* assemblyQualifiedTypeName = mono_unity_string_append_assembly_name_if_necessary((MonoString*)typeName, assemblyName); // Try to find the type using a hint about about calling assembly. If it is not found, fall back to calling GetType without the hint. Il2CppCodeGenType* type = ((getTypeFuncType)getTypeFunction)(NULL, (Il2CppCodeGenString*)assemblyQualifiedTypeName, NULL); if (type == NULL) return ((getTypeFuncType)getTypeFunction)(NULL, typeName, NULL); return type; } inline Il2CppCodeGenType* il2cpp_codegen_get_type(Il2CppMethodPointer getTypeFunction, Il2CppCodeGenString* typeName, bool throwOnError, const char* assemblyName) { typedef Il2CppCodeGenType* (*getTypeFuncType)(RuntimeObject*, Il2CppCodeGenString*, bool, const RuntimeMethod*); MonoString* assemblyQualifiedTypeName = mono_unity_string_append_assembly_name_if_necessary((MonoString*)typeName, assemblyName); // Try to find the type using a hint about about calling assembly. If it is not found, fall back to calling GetType without the hint. Il2CppCodeGenType* type = ((getTypeFuncType)getTypeFunction)(NULL, (Il2CppCodeGenString*)assemblyQualifiedTypeName, throwOnError, NULL); if (type == NULL) return ((getTypeFuncType)getTypeFunction)(NULL, typeName, throwOnError, NULL); return type; } inline Il2CppCodeGenType* il2cpp_codegen_get_type(Il2CppMethodPointer getTypeFunction, Il2CppCodeGenString* typeName, bool throwOnError, bool ignoreCase, const char* assemblyName) { typedef Il2CppCodeGenType* (*getTypeFuncType)(RuntimeObject*, Il2CppCodeGenString*, bool, bool, const RuntimeMethod*); MonoString* assemblyQualifiedTypeName = mono_unity_string_append_assembly_name_if_necessary((MonoString*)typeName, assemblyName); // Try to find the type using a hint about about calling assembly. If it is not found, fall back to calling GetType without the hint. Il2CppCodeGenType* type = ((getTypeFuncType)getTypeFunction)(NULL, (Il2CppCodeGenString*)assemblyQualifiedTypeName, throwOnError, ignoreCase, NULL); if (type == NULL) return ((getTypeFuncType)getTypeFunction)(NULL, typeName, throwOnError, ignoreCase, NULL); return type; } inline Il2CppCodeGenAssembly* il2cpp_codegen_get_executing_assembly(const RuntimeMethod* method) { return (Il2CppCodeGenAssembly*)mono_assembly_get_object(mono_domain_get(), mono_unity_class_get_assembly(mono_unity_method_get_class(method))); } // Atomic inline void* il2cpp_codegen_atomic_compare_exchange_pointer(void* volatile* dest, void* exchange, void* comparand) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); return NULL; } template inline T* il2cpp_codegen_atomic_compare_exchange_pointer(T* volatile* dest, T* newValue, T* oldValue) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); return NULL; } // COM inline void il2cpp_codegen_com_marshal_variant(RuntimeObject* obj, Il2CppVariant* variant) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); } inline RuntimeObject* il2cpp_codegen_com_marshal_variant_result(Il2CppVariant* variant) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); return NULL; } inline void il2cpp_codegen_com_destroy_variant(Il2CppVariant* variant) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); } inline Il2CppSafeArray* il2cpp_codegen_com_marshal_safe_array(Il2CppChar type, RuntimeArray* managedArray) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); return NULL; } inline RuntimeArray* il2cpp_codegen_com_marshal_safe_array_result(Il2CppChar variantType, RuntimeClass* type, Il2CppSafeArray* safeArray) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); return NULL; } inline Il2CppSafeArray* il2cpp_codegen_com_marshal_safe_array_bstring(RuntimeArray* managedArray) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); return NULL; } inline RuntimeArray* il2cpp_codegen_com_marshal_safe_array_bstring_result(RuntimeClass* type, Il2CppSafeArray* safeArray) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); return NULL; } inline void il2cpp_codegen_com_destroy_safe_array(Il2CppSafeArray* safeArray) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); } inline void il2cpp_codegen_com_create_instance(const Il2CppGuid& clsid, Il2CppIUnknown** identity) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); } inline void il2cpp_codegen_com_register_rcw(Il2CppComObject* rcw) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); } template inline T* il2cpp_codegen_com_get_or_create_rcw_from_iunknown(Il2CppIUnknown* unknown, RuntimeClass* fallbackClass) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); return NULL; } template inline T* il2cpp_codegen_com_get_or_create_rcw_from_iinspectable(Il2CppIInspectable* unknown, RuntimeClass* fallbackClass) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); return NULL; } template inline T* il2cpp_codegen_com_get_or_create_rcw_for_sealed_class(Il2CppIUnknown* unknown, RuntimeClass* objectClass) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); return NULL; } inline void il2cpp_codegen_il2cpp_com_object_cleanup(Il2CppComObject* rcw) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); } template inline InterfaceType* il2cpp_codegen_com_get_or_create_ccw(RuntimeObject* obj) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); return NULL; } inline Il2CppCodeGenIntPtr il2cpp_codegen_com_get_iunknown_for_object(RuntimeObject* obj) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); return Il2CppCodeGenIntPtr(); } inline void il2cpp_codegen_com_raise_exception(il2cpp_hresult_t hr) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); } inline void il2cpp_codegen_com_raise_exception_if_failed(il2cpp_hresult_t hr, bool defaultToCOMException) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); } inline RuntimeException* il2cpp_codegen_com_get_exception(il2cpp_hresult_t hr, bool defaultToCOMException) { NOT_IMPLEMENTED("Not implemented yet."); } inline RuntimeException* il2cpp_codegen_com_get_exception_for_invalid_iproperty_cast(RuntimeObject* value, const char* a, const char* b) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); } inline Il2CppIActivationFactory* il2cpp_codegen_windows_runtime_get_activation_factory(const il2cpp::utils::StringView& runtimeClassName) { NOT_IMPLEMENTED("COM is not yet supported with the libmonoruntime backend."); return NULL; } // delegate inline Il2CppAsyncResult* il2cpp_codegen_delegate_begin_invoke(Il2CppDelegate* delegate, void** params, Il2CppDelegate* asyncCallback, RuntimeObject* state) { return il2cpp_mono_delegate_begin_invoke(delegate, params, asyncCallback, state); } inline RuntimeObject* il2cpp_codegen_delegate_end_invoke(Il2CppAsyncResult* asyncResult, void **out_args) { return il2cpp_mono_delegate_end_invoke(asyncResult, out_args); } inline const Il2CppGenericInst* il2cpp_codegen_get_generic_class_inst(RuntimeClass* genericClass) { NOT_IMPLEMENTED("Windows runtime is not yet supported with the libmonoruntime backend."); return NULL; } inline RuntimeClass* il2cpp_codegen_inflate_generic_class(RuntimeClass* genericClassDefinition, const Il2CppGenericInst* genericInst) { //return il2cpp::vm::Class::GetInflatedGenericInstanceClass(genericClassDefinition, genericInst); NOT_IMPLEMENTED("Windows runtime is not yet supported with the libmonoruntime backend."); return NULL; } inline RuntimeAssembly* il2cpp_codegen_mono_corlib() { return mono_unity_assembly_get_mscorlib(); } inline RuntimeClass* il2cpp_codegen_mono_class(AssemblyIndex assemblyIndex, uint32_t classToken) { return mono_class_get(mono_assembly_get_image(il2cpp_mono_assembly_from_index(assemblyIndex)), classToken); } inline RuntimeClass* il2cpp_codegen_mono_class(RuntimeAssembly* assembly, uint32_t classToken) { return mono_class_get(mono_assembly_get_image(assembly), classToken); } inline RuntimeMethod* il2cpp_codegen_mono_method(AssemblyIndex index, uint32_t methodToken) { return mono_get_method(mono_assembly_get_image(il2cpp_mono_assembly_from_index(index)), methodToken, NULL); } inline RuntimeMethod* il2cpp_codegen_mono_method(RuntimeAssembly* assembly, uint32_t methodToken) { return mono_get_method(mono_assembly_get_image(assembly), methodToken, NULL); } inline void il2cpp_codegen_mono_set_static_field(RuntimeClass* klass, RuntimeField* field, void* value) { mono_field_static_set_value(mono_class_vtable(mono_domain_get(), klass), field, value); } inline void il2cpp_codegen_mono_get_static_field(RuntimeClass* klass, RuntimeField* field, void* value) { mono_field_static_get_value(mono_class_vtable(mono_domain_get(), klass), field, value); } inline void* il2cpp_codegen_mono_get_static_field_address(RuntimeClass* klass, RuntimeField* field) { return mono_unity_get_field_address(NULL, mono_class_vtable(mono_domain_get(), klass), field); } inline RuntimeField* il2cpp_codegen_mono_class_get_field(RuntimeClass* klass, uint32_t fieldToken) { return mono_class_get_field(klass, fieldToken); } inline Il2CppMethodPointer il2cpp_codegen_get_method_pointer(const RuntimeMethod* method) { MonoError unused; il2cpp_mono_method_initialize_function_pointers(const_cast(method), &unused); return (Il2CppMethodPointer)mono_unity_method_get_method_pointer(const_cast(method)); } inline RuntimeType* il2cpp_codegen_method_return_type(const RuntimeMethod* method) { return mono_signature_get_return_type(mono_method_signature(const_cast(method))); } template T il2cpp_mono_cast_nullable_method_param(const RuntimeMethod *method, int index, void *value) { if (value) return *((T*)value); T retVal; RuntimeClass *klass = mono_unity_signature_get_class_for_param(mono_method_signature(const_cast(method)), index); mono_nullable_init((uint8_t*)&retVal, NULL, klass); return retVal; } inline const RuntimeMethod* il2cpp_codegen_vtable_slot_method(const RuntimeClass* klass, RuntimeMethod* slot) { return slot; } inline Il2CppMethodPointer il2cpp_codegen_vtable_slot_method_pointer(const RuntimeClass* klass, RuntimeMethod* slot) { MonoError unused; il2cpp_mono_method_initialize_function_pointers(slot, &unused); return (Il2CppMethodPointer)mono_unity_method_get_method_pointer(slot); } inline bool il2cpp_codegen_is_import_or_windows_runtime(const RuntimeObject *object) { assert(0 && "Not implemented yet."); return false; } inline std::string il2cpp_codegen_format_exception(const RuntimeException* ex) { return il2cpp_mono_format_exception(ex); } ================================================ FILE: unity_decoder/libil2cpp/codegen/il2cpp-codegen.h ================================================ #pragma once #if RUNTIME_MONO typedef MonoClass RuntimeClass; typedef MonoMethod RuntimeMethod; typedef MonoClassField RuntimeField; typedef MonoType RuntimeType; typedef MonoObject RuntimeObject; typedef MonoImage RuntimeImage; typedef MonoException RuntimeException; typedef MonoArray RuntimeArray; typedef MonoAssembly RuntimeAssembly; #include "il2cpp-codegen-mono.h" #else struct TypeInfo; struct MethodInfo; struct FieldInfo; struct Il2CppType; typedef Il2CppClass RuntimeClass; typedef MethodInfo RuntimeMethod; typedef FieldInfo RuntimeField; typedef Il2CppType RuntimeType; typedef Il2CppObject RuntimeObject; typedef Il2CppImage RuntimeImage; typedef Il2CppException RuntimeException; typedef Il2CppArray RuntimeArray; typedef Il2CppAssembly RuntimeAssembly; #include "il2cpp-codegen-il2cpp.h" #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/agent.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "agent.h" #include "id-bank.h" #include "transport-tcp.h" #include "protocol/protocol.h" #include "protocol/events.h" #include "protocol/commands/event.h" #include "../os/Atomic.h" #include "../os/Thread.h" #include "../il2cpp-api.h" #include "../class-internals.h" #include "../il2cpp-api-types.h" #include using namespace il2cpp::debugger; bool is_debugger_thread() { return Agent::instance().IsDebuggerThread(); } AgentConfig AgentConfig::Default; const char* default_host = "localhost"; int32_t default_port = 9876; AgentConfig::AgentConfig() : server(true), host(default_host), port(default_port) { } AgentConfig::AgentConfig(const char *host, int32_t port) : server(true), host(host), port(port) { } Agent Agent::_instance; #if IL2CPP_UNIT_TESTS_ENABLED Il2CppApiTestForwarder Agent::TestForwarder; #endif // IL2CPP_UNIT_TESTS_ENABLED Agent::Agent() : _thread(0), _managed_debugger_thread(0), _event_req_list(*this, true), _transport(0), _is_notifying_pending_events(false), _ss_data(0), _notify_pending_events_on_first_invoke(false), _is_initialized(false), _currently_invoking_method(false) { } Agent::~Agent() { _managed_debugger_thread = 0; if (_thread != 0) { delete _thread; _thread = 0; } if (_transport != 0) { delete _transport; _transport = 0; } } void Agent::Initialize(const AgentConfig &config) { std::stringstream message; message << "Listening on " << config.host << ":" << config.port; LOG(message.str()); _config = config; _transport = new TCPDataTransport(_config.host, _config.port); _transport->Setup(); // The only implemented mode right now is 'server' // if(config.server) _transport->WaitForClient(); // Protocol should take care of buffering the events until a client is connected _protocol.Setup(_transport); if (!_protocol.Handshake()) { LOG("handshake was not successfull"); return; // false } _is_initialized = true; } bool Agent::IsInitialized() { return _is_initialized; } void Agent::InvalidateBreakpointData() { std::list::iterator it = _bp_data.begin(); while (it != _bp_data.end()) { INVALIDATE_BREAKPOINT_DATA(*it); ++it; } } void Agent::ClearBreakpointData() { std::list::iterator it = _bp_data.begin(); while (it != _bp_data.end()) { delete *it; ++it; } _bp_data.clear(); } void Agent::ClearSingleStepData() { if (_ss_data != 0) { delete _ss_data; _ss_data = 0; } } SingleStepData *Agent::PrepareSingleStepData(EventRequest *request, Il2CppThread *thread, StepSizeKind size, StepDepthKind depth) { SingleStepData *data = new SingleStepData(); data->size = size; data->depth = depth; data->thread = thread; data->request = request; data->last_line = -1; data->last_method = 0; data->stack_depth = -1; IL2CPP_ASSERT(size == kStepSizeKindLine && "Only kStepSizeKindLine is supported for single stepping for now."); Il2CppStackFrameInfo top_frame; if (!il2cpp_thread_get_top_frame(thread, top_frame)) return data; if (size == kStepSizeKindLine) { data->last_method = top_frame.method; data->stack_depth = il2cpp_thread_get_stack_depth(thread); const Il2CppDebugMethodInfo *debug_method = top_frame.method->debug_info; if (debug_method != 0) { const int32_t *offset_table = il2cpp_debug_method_get_offset_table(debug_method); // An offset_table might be empty. In case it is, we skip the lineno. // Same thing for the il_offset. if (offset_table[0] != -1 && top_frame.il_offset != -1) { int32_t i; const int32_t il_offset = top_frame.il_offset; for (i = 2; offset_table[i] >= 0; i += 2) { const int32_t start = offset_table[i - 2]; const int32_t end = offset_table[i]; if (start <= il_offset && end > il_offset) { data->last_line = offset_table[i - 1]; break; } } if (data->last_line == -1) { const int32_t last_offset = offset_table[i - 2]; if (il_offset <= debug_method->code_size && il_offset >= last_offset) data->last_line = offset_table[i - 1]; } } } } if (depth == kStepDepthKindOver) { if (top_frame.il_offset != -1) { // if (ss_req->depth == STEP_DEPTH_OVER) { // frame_index = 1; // /* // * Find the first sequence point in the current or in a previous frame which // * is not the last in its method. // */ // while (sp && sp->next_len == 0) { // sp = NULL; // if (tls && frame_index < tls->frame_count) { // StackFrame *frame = tls->frames [frame_index]; // method = frame->method; // if (frame->il_offset != -1) { // sp = find_seq_point (frame->domain, frame->method, frame->il_offset, &info); // } // frame_index ++; // } // } // if (sp && sp->next_len > 0) { // use_bp = TRUE; // for (i = 0; i < sp->next_len; ++i) { // next_sp = &info->seq_points [sp->next [i]]; // bp = set_breakpoint (method, next_sp->il_offset, ss_req->req); // ss_req->bps = g_slist_append (ss_req->bps, bp); // } // } //} } } //if (ss_req->depth == STEP_DEPTH_OVER) { // StackFrame *frame; // compute_frame_info (thread, tls); // IL2CPP_ASSERT(tls->frame_count); // frame = tls->frames [0]; // if (frame->il_offset != -1) { // /* FIXME: Sort the table and use a binary search */ // sp = find_seq_point (frame->domain, frame->method, frame->il_offset, &info); // if (!sp) return ERR_NOT_IMPLEMENTED; // This can happen with exceptions when stepping // method = frame->method; // } //} return data; } void Agent::Dispose() { LOG("Disposing debugger agent"); StopListeningThread(); _protocol.Dispose(); delete _transport; _transport = 0; _event_req_list.ClearAllRequests(); ClearSingleStepData(); ClearBreakpointData(); _is_initialized = false; } bool Agent::IsDebuggerThread() { if (_thread == 0) return false; return _thread->Id() == os::Thread::CurrentThreadId(); } void Agent::NotifyVmStart() { LOG("Notifying VM Start"); VmStartEvent vm_start(il2cpp_thread_current()); NotifyEvent(vm_start, _event_req_list); // NotifyAllPendingEvents(); LOG("VM Start notified"); } void Agent::NotifyVmDeath() { LOG("Notifying VM Death"); VmDeathEvent vm_death(il2cpp_thread_current()); NotifyEvent(vm_death, _event_req_list); LOG("VM Death notified"); StopListeningThread(); } void Agent::NotifyUserBreak() { LOG("Notifying User Break"); UserBreakEvent user_break(il2cpp_thread_current()); NotifyEvent(user_break, _event_req_list); LOG("User Break notified"); } void Agent::NotifyBreakPointHit(const MethodInfo *method, uint64_t offset, BreakpointData &bp_data) { LOG("Notifying Break Point hit"); EventRequestList request_list(*this, false); // TODO: there might be multiple requests matching a given breakpoint in case of multiple // threads running the same method. Need to deal with that. request_list.AddEventRequest(bp_data.request); BreakPointEvent breakpoint_event(il2cpp_thread_current()); breakpoint_event.method((MethodInfo*)method); breakpoint_event.il_offset(offset); NotifyEvent(breakpoint_event, request_list); LOG("Break Point hit notified"); } void Agent::NotifyStepHit(const MethodInfo *method, uint64_t offset, SingleStepData &ss_data) { LOG("Notifying Step event"); EventRequestList request_list(*this, false); request_list.AddEventRequest(ss_data.request); StepEvent step_event(il2cpp_thread_current()); step_event.method((MethodInfo*)method); step_event.il_offset(offset); NotifyEvent(step_event, request_list); LOG("Step event notified"); } void Agent::NotifyAppDomainCreate(Il2CppDomain *domain) { LOG("Notifying AppDomainCreate " << (uintptr_t)domain); AppDomainCreateEvent create_event(il2cpp_thread_current()); create_event.domain(domain); NotifyEvent(create_event, _event_req_list); LOG("Done notifying AppDomainCreate " << (uintptr_t)domain); } void Agent::NotifyAssemblyLoad(const Il2CppAssembly *assembly) { LOG("Notifying AssemblyLoad " << (uintptr_t)assembly); AssemblyLoadEvent load_event(il2cpp_thread_current()); load_event.assembly(const_cast(assembly)); NotifyEvent(load_event, _event_req_list); LOG("Done notifying AssemblyLoad " << (uintptr_t)assembly); } void Agent::NotifyTypeLoad(Il2CppClass *type) { LOG("Notifying TypeLoad " << il2cpp_class_get_namespace(type) << "." << il2cpp_class_get_name(type)); TypeLoadEvent load_event(il2cpp_thread_current()); load_event.type(type); NotifyEvent(load_event, _event_req_list); LOG("Done notifying TypeLoad " << il2cpp_class_get_namespace(type) << "." << il2cpp_class_get_name(type)); } void Agent::NotifyThreadStart(Il2CppThread *thread) { LOG("Notifying ThreadStart " << (uintptr_t)thread); ThreadStartEvent thread_start_event(thread); NotifyEvent(thread_start_event, _event_req_list); LOG("Done notifying ThreadStart " << (uintptr_t)thread); } void Agent::NotifyThreadDeath(Il2CppThread *thread) { LOG("Notifying ThreadDeath " << (uintptr_t)thread); ThreadDeathEvent thread_death_event(thread); NotifyEvent(thread_death_event, _event_req_list); LOG("Done notifying ThreadDeath " << (uintptr_t)thread); } void Agent::OnEventSkipped(const Event &evt) { if (_is_notifying_pending_events) return; // The event has been skipped. Based on the type, let's record it to be sent later switch (evt.kind()) { case kEventKindAppDomainCreate: _pending_domains.insert(((const AppDomainCreateEvent&)evt).domain()); break; case kEventKindAssemblyLoad: _pending_assemblies.insert(((const AssemblyLoadEvent&)evt).assembly()); break; case kEventKindTypeLoad: _pending_types.insert(((const TypeLoadEvent&)evt).type()); break; case kEventKindAppDomainUnload: LOG("OnEventSkipped: kEventKindAppDomainUnload not implemented"); break; case kEventKindAssemblyUnload: LOG("OnEventSkipped: kEventKindAssemblyUnload not implemented"); break; case kEventKindThreadStart: _pending_threads.insert(evt.thread()); break; case kEventKindThreadDeath: { // If a thread dies while events are still pending, we can get rid of it std::set::const_iterator it = _pending_threads.find(evt.thread()); if (it != _pending_threads.end()) _pending_threads.erase(it); } break; case kEventKindVmStart: case kEventKindVmDeath: case kEventKindMethodEntry: case kEventKindMethodExit: case kEventKindBreakpoint: case kEventKindStep: case kEventKindException: case kEventKindKeepAlive: case kEventKindUserBreak: case kEventKindUserLog: break; } } void Agent::NotifyAllPendingEvents() { LOG("NotifyAllPendingEvents"); NotifyAppDomainCreatePendingEvents(); NotifyThreadStartPendingEvents(); NotifyAssemblyLoadPendingEvents(); NotifyTypeLoadPendingEvents(); } void Agent::NotifyAppDomainCreatePendingEvents() { LOG("Notifying pending AppDomainCreate events"); _is_notifying_pending_events = true; std::set::const_iterator dit = _pending_domains.begin(); while (dit != _pending_domains.end()) { NotifyAppDomainCreate(*dit); ++dit; } _pending_domains.clear(); _is_notifying_pending_events = false; LOG("Done notifying pending AppDomainCreate events"); } void Agent::NotifyAssemblyLoadPendingEvents() { LOG("Notifying pending AssemblyLoad events"); _is_notifying_pending_events = true; std::set::const_iterator dit = _pending_assemblies.begin(); while (dit != _pending_assemblies.end()) { NotifyAssemblyLoad(*dit); ++dit; } _pending_assemblies.clear(); _is_notifying_pending_events = false; LOG("Done notifying pending AssemblyLoad events"); } void Agent::NotifyTypeLoadPendingEvents() { LOG("Notifying pending TypeLoad events"); _is_notifying_pending_events = true; std::set::const_iterator dit = _pending_types.begin(); while (dit != _pending_types.end()) { NotifyTypeLoad(*dit); ++dit; } _pending_types.clear(); _is_notifying_pending_events = false; LOG("Done notifying pending TypeLoad events"); } void Agent::NotifyThreadStartPendingEvents() { LOG("Notifying pending ThreadStart events"); _is_notifying_pending_events = true; std::set::const_iterator dit = _pending_threads.begin(); while (dit != _pending_threads.end()) { NotifyThreadStart(*dit); ++dit; } _pending_threads.clear(); _is_notifying_pending_events = false; LOG("Done notifying pending ThreadStart events"); } void Agent::NotifyPendingEventsOfKind(EventKind kind) { switch (kind) { case kEventKindAppDomainCreate: NotifyAppDomainCreatePendingEvents(); break; case kEventKindAssemblyLoad: NotifyAssemblyLoadPendingEvents(); break; case kEventKindTypeLoad: NotifyTypeLoadPendingEvents(); break; case kEventKindAppDomainUnload: LOG("NotifyPendingEventsOfKind: kEventKindAppDomainUnload not implemented"); break; case kEventKindAssemblyUnload: LOG("NotifyPendingEventsOfKind: kEventKindAssemblyUnload not implemented"); break; case kEventKindThreadStart: NotifyThreadStartPendingEvents(); break; case kEventKindThreadDeath: case kEventKindVmStart: case kEventKindVmDeath: case kEventKindMethodEntry: case kEventKindMethodExit: case kEventKindBreakpoint: case kEventKindStep: case kEventKindException: case kEventKindKeepAlive: case kEventKindUserBreak: case kEventKindUserLog: break; } } bool Agent::ShouldSendPendingEventsOnFirstMethodEntry() { return _notify_pending_events_on_first_invoke; } void Agent::NotifyEvent(const Event &evt, EventRequestList &event_reqs) { if (!_event_req_list.IsClientInterested(evt)) { LOG("Skipping event, client not interested!"); OnEventSkipped(evt); return; } IL2CPP_ASSERT(evt.thread() != 0 && "A debugger event is being sent with a NULL thread_id, which is not allowed (aka: something very bad happened)."); EventRequestList::FilterInfo filter_info; filter_info.exception = 0; filter_info.klass = 0; std::vector ids; event_reqs.RequestIdsFor(ids, evt, filter_info); SuspendPolicy suspend_policy = kSuspendPolicyNone; std::vector::iterator it = ids.begin(); while (it != ids.end()) { const EventRequest *req = event_reqs.GetEventRequestById(*it); if (req != NULL) suspend_policy = std::max(suspend_policy, req->suspend_policy()); ++it; } EventCompositeCommand command; it = ids.begin(); while (it != ids.end()) { command.AddEvent(*it, &evt); ++it; } if (evt.kind() == kEventKindVmStart) { IL2CPP_ASSERT(!IsDebuggerThread() && "Unexpected VmStart event sent from the debugger thread. Only VM threads are allowed to send it."); // TODO: move this somewhere else, or split the NotifyEvent logic if needed // (suspend=y) suspend_policy = kSuspendPolicyAll; StartListeningThread(); } else { if (IsDebuggerThread()) { LOG("The event is being sent from the debugger thread. Disabling suspend."); suspend_policy = kSuspendPolicyNone; } } // We always suspend in case a Step Event is fired if (evt.kind() == kEventKindStep) suspend_policy = kSuspendPolicyAll; if (suspend_policy == kSuspendPolicyAll) RequestSuspend(); command.suspend_policy(suspend_policy); _protocol.SendCommand(&command); if (!IsDebuggerThread()) SuspendCurrentThreadIfNeeded(); } void Agent::OnMethodEntry(const Il2CppStackFrameInfo &info) { if (ShouldSendPendingEventsOnFirstMethodEntry()) { NotifyAllPendingEvents(); _notify_pending_events_on_first_invoke = false; } } void Agent::OnMethodExit(const Il2CppStackFrameInfo &info) { } void Agent::OnThreadAttach(Il2CppThread *thread) { if (IsDebuggerThread()) return; _thread_data.NotifyThreadAttach(thread); NotifyThreadStart(thread); SuspendCurrentThreadIfNeeded(); } void Agent::OnThreadDetach(Il2CppThread *thread) { if (IsDebuggerThread()) return; NotifyThreadDeath(thread); _thread_data.NotifyThreadDetach(thread); } bool Agent::IsSuspended() { return il2cpp::os::Atomic::CompareExchange(&suspend_count, suspend_count, 0) != 0; } void Agent::RequestSuspend() { LOG("Requesting VM suspend"); il2cpp::os::Atomic::Increment(&suspend_count); } void Agent::WaitForSuspend() { LOG("Waiting for all the managed threads to be suspended."); LOG("Agent::WaitForSuspend has a dummy implementation for now."); suspend_semaphore.Wait(); LOG("VM suspended"); } void Agent::RequestResume() { LOG("Requesting VM resume"); il2cpp::os::Atomic::Decrement(&suspend_count); IL2CPP_ASSERT(suspend_count >= 0 && "RequestResume has been invoked more times than RequestSuspend!"); } void Agent::SuspendCurrentThreadIfNeeded() { IL2CPP_ASSERT(!IsDebuggerThread() && "The debugger thread cannot be suspended!"); if (il2cpp::os::Atomic::CompareExchange(&suspend_count, suspend_count, 0) == 0) return; LOG("Suspending current thread"); suspend_semaphore.Post(1, NULL); ThreadData* current_thread_data = _thread_data.ThreadDataFor(CALL_IL2CPP_API(il2cpp_thread_current)()); while (il2cpp::os::Atomic::CompareExchange(&suspend_count, suspend_count, 0) != 0) { il2cpp::os::Thread::Sleep(1); InvokeMethodIfOneIsReady(current_thread_data); } current_thread_data->InvalidateFramesCache(); LOG("Resuming current thread"); } void Agent::SequencePointHit(int64_t uid, int32_t offset) { // Note: SequencePointHit locks in case a breakpoint or a single step is hit, and returns only when the VM is resumed. // LOG("Sequence point hit (uid: " << uid << ", offset: " << std::uppercase << std::hex << offset << std::dec << std::nouppercase << ")"); if (_currently_invoking_method) return; il2cpp_debug_update_frame_il_offset(offset); SuspendCurrentThreadIfNeeded(); BreakpointData *bp_data = BreakpointDataAt(uid, offset); if (IS_BREAKPOINT_DATA_INVALID(bp_data)) { LOG("Breakpoint hit (request id: " << bp_data->request->id() << ")"); ClearSingleStepData(); NotifyBreakPointHit(bp_data->method, offset, *bp_data); } else { // TODO: we probably need to do something different in case there // were both a bp and a single step at the same line. ProcessSingleStepIfNeeded(uid, offset); } } BreakpointData *Agent::BreakpointDataAt(int64_t uid, int32_t offset) { Il2CppStackFrameInfo frame; if (!il2cpp_current_thread_get_top_frame(frame)) { IL2CPP_ASSERT(0 && "Not implemented"); } const Il2CppDebugMethodInfo *info = il2cpp_debug_get_method_info(frame.method); return (BreakpointData*)il2cpp_debug_method_get_breakpoint_data_at(info, uid, offset); } bool Agent::ShouldProcessStepRequest(Il2CppThread *current_thread, const Il2CppStackFrameInfo *top_frame, int32_t stack_depth, bool *can_break_at_the_same_line) { if (_ss_data == 0) return false; *can_break_at_the_same_line = true; switch (_ss_data->depth) { case kStepDepthKindInto: { if (_ss_data->last_method != top_frame->method) { Il2CppStackFrameInfo second_top_frame; if (!il2cpp_thread_get_frame_at(current_thread, -1, second_top_frame)) return false; if (_ss_data->last_method != second_top_frame.method) return false; } else { // In this case, we perform a simple step over. return true; } } break; case kStepDepthKindOver: *can_break_at_the_same_line = false; if (_ss_data->last_method != top_frame->method) { if (stack_depth < _ss_data->stack_depth) { // We stepped over the last sequence point of a function invocation. // In this case, we perform a step out. return true; } else { return false; } } else { if (stack_depth == _ss_data->stack_depth) { // Regular step over. return true; } else if (stack_depth < _ss_data->stack_depth) { // We stepped over the last sequence point of a recursive function invocation. // In this case, we perform a step out. // In this case, we might also be at the last instruction of a recursive function: this // means that, after the simulation of the step out, we end up on the same line we were before. // In this case, we should still allow the agent to break. *can_break_at_the_same_line = true; return true; } else { // We are inside a recursive function. In this case we need to skip the step. return false; } } break; case kStepDepthKindOut: if (_ss_data->last_method == top_frame->method) { if (stack_depth >= _ss_data->stack_depth) return false; // In this case, we are probably stepping out of a recursive function. In this case // we can proceed simulating a step over. return true; } if (stack_depth >= _ss_data->stack_depth) return false; IL2CPP_ASSERT((_ss_data->stack_depth - stack_depth) == 1 && "Stepping out jumped more than one stack frame: not supported yet (probably hitting a native stack frame)"); break; } return true; } bool Agent::ProcessSingleStepIfNeeded(int64_t uid, int32_t offset) { if (_ss_data == 0) return false; Il2CppThread *current_thread = il2cpp_thread_current(); if (_ss_data->thread != current_thread) return false; IL2CPP_ASSERT(_ss_data->size == kStepSizeKindLine && "Only line stepping is supported for now"); Il2CppStackFrameInfo top_frame; if (!il2cpp_current_thread_get_top_frame(top_frame)) return false; if (top_frame.il_offset == -1) return false; bool can_break_at_the_same_line = true; const int32_t stack_depth = il2cpp_current_thread_get_stack_depth(); if (!ShouldProcessStepRequest(current_thread, &top_frame, stack_depth, &can_break_at_the_same_line)) return false; const Il2CppDebugMethodInfo *debug_method = top_frame.method->debug_info; if (debug_method == 0) return false; _ss_data->stack_depth = stack_depth; _ss_data->last_method = top_frame.method; int32_t lineno = -1; const int32_t *offset_table = il2cpp_debug_method_get_offset_table(debug_method); // An offset_table might be empty. In case it is, we skip the lineno. // Same thing for the il_offset. if (offset_table[0] != -1 && top_frame.il_offset != -1) { int32_t i; const int32_t il_offset = top_frame.il_offset; for (i = 2; offset_table[i] >= 0; i += 2) { const int32_t start = offset_table[i - 2]; const int32_t end = offset_table[i]; if (start <= il_offset && end > il_offset) { lineno = offset_table[i - 1]; break; } } if (lineno == -1) { const int32_t last_offset = offset_table[i - 2]; if (il_offset <= debug_method->code_size && il_offset >= last_offset) lineno = offset_table[i - 1]; } } if (lineno == -1 || (lineno == _ss_data->last_line && !can_break_at_the_same_line)) return false; SingleStepData ss_data_copy = *_ss_data; ss_data_copy.last_line = lineno; ClearSingleStepData(); NotifyStepHit(ss_data_copy.last_method, offset, ss_data_copy); return true; } static void start_debugger_agent_thread(void *data) { Agent *agent = (Agent*)data; agent->ListenForClientMessages(); } void Agent::StartListeningThread() { IL2CPP_ASSERT(_thread == 0 && "Listening thread is already running!"); _thread = new os::Thread(); _thread->Run(start_debugger_agent_thread, this); } void Agent::StopListeningThread() { if (_thread == 0) return; _protocol.Dispose(); _thread->Join(); delete _thread; _thread = 0; } #define DELETE_LOCAL(v) \ if(v != 0) \ delete v; \ v = 0; void Agent::ListenForClientMessages() { LOG("Listening for incoming messages."); // Attach the thread where the debugger is running so that the GC will work // correctly with managed objects used in the debugger thread. _managed_debugger_thread = il2cpp_thread_attach(il2cpp_domain_get()); while (true) { const Command *command = _protocol.WaitForCommand(); if (command == NULL) { LOG("The socket was shut down while reading the header"); break; } const Reply *reply = Process(command); if (reply != NULL) { if (!_protocol.SendReply(reply)) { DELETE_LOCAL(reply); DELETE_LOCAL(command); LOG("The socket was shut down while sending the reply"); break; } } if (command->is(kCommandSetVm, kCommandSetVmDispose)) { DELETE_LOCAL(reply); DELETE_LOCAL(command); break; } DELETE_LOCAL(reply); DELETE_LOCAL(command); } LOG("Debugger thread is being stopped"); _protocol.Dispose(); il2cpp_thread_detach(il2cpp_thread_current()); } void Agent::InvokeMethodIfOneIsReady(ThreadData* thread_data) { const MethodInfo* method = thread_data->GetMethodToInvoke(); if (method) { CurrentlyInvokingMethodHelper helper(_currently_invoking_method); thread_data->SetReturnValueOfMethodToInvoke(CALL_IL2CPP_API(il2cpp_runtime_invoke)(method, NULL, NULL, NULL)); thread_data->ClearMethodToInvoke(); thread_data->SignalMethodInvokeComplete(); } } #define PROCESS_COMMAND(s, c) \ if(command->is(kCommandSet ## s, kCommandSet ## s ## c)) \ return Process((const s ## c ## Command*)command) const Reply *Agent::Process(const Command *command) { PROCESS_COMMAND(StackFrame, GetValues); PROCESS_COMMAND(StackFrame, SetValues); PROCESS_COMMAND(StackFrame, GetThis); PROCESS_COMMAND(Assembly, GetObject); PROCESS_COMMAND(Assembly, GetEntryPoint); PROCESS_COMMAND(Assembly, GetManifestModule); PROCESS_COMMAND(Assembly, GetName); PROCESS_COMMAND(Assembly, GetLocation); PROCESS_COMMAND(Assembly, GetType); PROCESS_COMMAND(InternalError, NotImplemented); PROCESS_COMMAND(Vm, SetProtocolVersion); PROCESS_COMMAND(Vm, Suspend); PROCESS_COMMAND(Vm, AllThreads); PROCESS_COMMAND(Vm, Version); PROCESS_COMMAND(Vm, Dispose); PROCESS_COMMAND(Vm, AbortInvoke); PROCESS_COMMAND(Vm, Resume); PROCESS_COMMAND(Vm, Exit); PROCESS_COMMAND(Vm, InvokeMethod); PROCESS_COMMAND(StringRef, GetValue); PROCESS_COMMAND(ObjectRef, GetType); PROCESS_COMMAND(ObjectRef, GetDomain); PROCESS_COMMAND(ObjectRef, IsCollected); PROCESS_COMMAND(ObjectRef, SetValues); PROCESS_COMMAND(ObjectRef, GetAddress); PROCESS_COMMAND(ObjectRef, GetValues); PROCESS_COMMAND(Type, GetProperties); PROCESS_COMMAND(Type, GetSourceFiles2); PROCESS_COMMAND(Type, GetPropertyCAttrs); PROCESS_COMMAND(Type, GetFieldCAttrs); PROCESS_COMMAND(Type, GetInfo); PROCESS_COMMAND(Type, IsAssignableFrom); PROCESS_COMMAND(Type, GetCAttrs); PROCESS_COMMAND(Type, GetSourceFiles); PROCESS_COMMAND(Type, GetValues); PROCESS_COMMAND(Type, GetObject); PROCESS_COMMAND(Type, GetFields); PROCESS_COMMAND(Type, SetValues); PROCESS_COMMAND(Type, GetMethods); PROCESS_COMMAND(Thread, GetName); PROCESS_COMMAND(Thread, GetFrameInfo); PROCESS_COMMAND(Thread, GetInfo); PROCESS_COMMAND(Thread, GetState); PROCESS_COMMAND(Thread, GetId); PROCESS_COMMAND(ArrayRef, GetValues); PROCESS_COMMAND(ArrayRef, GetLength); PROCESS_COMMAND(ArrayRef, SetValues); PROCESS_COMMAND(EventRequest, Clear); PROCESS_COMMAND(EventRequest, ClearAllBreakpoints); PROCESS_COMMAND(EventRequest, Set); PROCESS_COMMAND(AppDomain, GetFriendlyName); PROCESS_COMMAND(AppDomain, CreateString); PROCESS_COMMAND(AppDomain, GetEntryAssembly); PROCESS_COMMAND(AppDomain, GetRootDomain); PROCESS_COMMAND(AppDomain, CreateBoxedValue); PROCESS_COMMAND(AppDomain, GetAssemblies); PROCESS_COMMAND(AppDomain, GetCorlib); PROCESS_COMMAND(Method, GetParamInfo); PROCESS_COMMAND(Method, GetName); PROCESS_COMMAND(Method, GetDeclaringType); PROCESS_COMMAND(Method, GetLocalsInfo); PROCESS_COMMAND(Method, GetInfo); PROCESS_COMMAND(Method, GetDebugInfo); PROCESS_COMMAND(Method, ResolveToken); PROCESS_COMMAND(Method, GetBody); PROCESS_COMMAND(Module, GetInfo); PROCESS_COMMAND(Event, Composite); return NULL; } const Protocol& Agent::GetProtocol() { return _protocol; } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/agent.h ================================================ #pragma once #include #include #include "common.h" #include "thread-data.h" #include "protocol/protocol.h" #include "event-request.h" #include "il2cpp-api-test-forwarder.h" #include "../os/Thread.h" #include "../os/Semaphore.h" struct Il2CppStackFrameInfo; namespace il2cpp { namespace debugger { class Event; class Reply; class Command; class IDataTransport; struct StackFrameGetValuesCommand; struct StackFrameSetValuesCommand; struct StackFrameGetThisCommand; struct AssemblyGetObjectCommand; struct AssemblyGetEntryPointCommand; struct AssemblyGetManifestModuleCommand; struct AssemblyGetNameCommand; struct AssemblyGetLocationCommand; struct AssemblyGetTypeCommand; struct InternalErrorNotImplementedCommand; struct InternalErrorInvalidCommand; struct VmSetProtocolVersionCommand; struct VmSuspendCommand; struct VmAllThreadsCommand; struct VmVersionCommand; struct VmDisposeCommand; struct VmAbortInvokeCommand; struct VmResumeCommand; struct VmExitCommand; struct VmInvokeMethodCommand; struct StringRefGetValueCommand; struct ObjectRefGetTypeCommand; struct ObjectRefGetDomainCommand; struct ObjectRefIsCollectedCommand; struct ObjectRefSetValuesCommand; struct ObjectRefGetAddressCommand; struct ObjectRefGetValuesCommand; struct TypeGetPropertiesCommand; struct TypeGetSourceFiles2Command; struct TypeGetPropertyCAttrsCommand; struct TypeGetFieldCAttrsCommand; struct TypeGetInfoCommand; struct TypeIsAssignableFromCommand; struct TypeGetCAttrsCommand; struct TypeGetSourceFilesCommand; struct TypeGetValuesCommand; struct TypeGetObjectCommand; struct TypeGetFieldsCommand; struct TypeSetValuesCommand; struct TypeGetMethodsCommand; struct ThreadGetNameCommand; struct ThreadGetFrameInfoCommand; struct ThreadGetInfoCommand; struct ThreadGetStateCommand; struct ThreadGetIdCommand; struct ArrayRefGetValuesCommand; struct ArrayRefGetLengthCommand; struct ArrayRefSetValuesCommand; struct EventRequestClearCommand; struct EventRequestClearAllBreakpointsCommand; struct EventRequestSetCommand; struct AppDomainGetFriendlyNameCommand; struct AppDomainCreateStringCommand; struct AppDomainGetEntryAssemblyCommand; struct AppDomainGetRootDomainCommand; struct AppDomainCreateBoxedValueCommand; struct AppDomainGetAssembliesCommand; struct AppDomainGetCorlibCommand; struct MethodGetParamInfoCommand; struct MethodGetNameCommand; struct MethodGetDeclaringTypeCommand; struct MethodGetLocalsInfoCommand; struct MethodGetInfoCommand; struct MethodGetDebugInfoCommand; struct MethodResolveTokenCommand; struct MethodGetBodyCommand; struct ModuleGetInfoCommand; class EventCompositeCommand; struct AgentConfig { bool server; const char *host; int32_t port; AgentConfig(); AgentConfig(const char *host, int32_t port); static AgentConfig Default; }; static int32_t suspend_count = 0; static os::Semaphore suspend_semaphore = 0; #define INVALIDATE_BREAKPOINT_DATA(bp) \ (bp)->method = (MethodInfo*)0xCAFFECAFFE #define IS_BREAKPOINT_DATA_INVALID(bp) \ ((bp) != 0 && (bp)->method != (MethodInfo*)0xCAFFECAFFE) struct BreakpointData { const MethodInfo *method; const EventRequest *request; uint64_t location; }; struct SingleStepData { StepSizeKind size; StepDepthKind depth; const Il2CppThread *thread; const EventRequest *request; const MethodInfo *last_method; int32_t last_line; int32_t stack_depth; }; class Agent { public: inline static Agent &instance() { return Agent::_instance; } void Initialize(const AgentConfig &config); void Dispose(); bool IsInitialized(); void ListenForClientMessages(); void SequencePointHit(int64_t uid, int32_t offset); void NotifyVmStart(); void NotifyVmDeath(); void NotifyUserBreak(); void NotifyBreakPointHit(const MethodInfo *method, uint64_t offset, BreakpointData &bp_data); void NotifyStepHit(const MethodInfo *method, uint64_t offset, SingleStepData &ss_data); void NotifyAppDomainCreate(Il2CppDomain *domain); void NotifyAssemblyLoad(const Il2CppAssembly *assembly); void NotifyTypeLoad(Il2CppClass *type); void NotifyThreadStart(Il2CppThread *thread); void NotifyThreadDeath(Il2CppThread *thread); void OnMethodEntry(const Il2CppStackFrameInfo &info); void OnMethodExit(const Il2CppStackFrameInfo &info); void OnThreadAttach(Il2CppThread *thread); void OnThreadDetach(Il2CppThread *thread); bool IsDebuggerThread(); const Reply *Process(const Command *command); const Protocol& GetProtocol(); bool IsSuspended(); void RequestSuspend(); void RequestResume(); void SuspendCurrentThreadIfNeeded(); #if IL2CPP_UNIT_TESTS_ENABLED static Il2CppApiTestForwarder TestForwarder; #endif // IL2CPP_UNIT_TESTS_ENABLED private: static Agent _instance; Agent(); ~Agent(); void InvalidateBreakpointData(); void ClearBreakpointData(); void ClearSingleStepData(); void StartListeningThread(); void StopListeningThread(); void WaitForSuspend(); bool ProcessSingleStepIfNeeded(int64_t uid, int32_t offset); bool ShouldProcessStepRequest(Il2CppThread *current_thread, const Il2CppStackFrameInfo *top_frame, int32_t stack_depth, bool *can_break_at_the_same_line); BreakpointData *BreakpointDataAt(int64_t uid, int32_t offset); void NotifyAllPendingEvents(); void NotifyAppDomainCreatePendingEvents(); void NotifyAssemblyLoadPendingEvents(); void NotifyTypeLoadPendingEvents(); void NotifyThreadStartPendingEvents(); void NotifyPendingEventsOfKind(EventKind kind); void NotifyEvent(const Event &evt, EventRequestList &event_reqs); void OnEventSkipped(const Event &evt); void InvokeMethodIfOneIsReady(ThreadData* current_thread_data); SingleStepData *PrepareSingleStepData(EventRequest *request, Il2CppThread *thread, StepSizeKind size, StepDepthKind depth); bool ShouldSendPendingEventsOnFirstMethodEntry(); const Reply *Process(const StackFrameGetValuesCommand *command); const Reply *Process(const StackFrameSetValuesCommand *command); const Reply *Process(const StackFrameGetThisCommand *command); const Reply *Process(const AssemblyGetObjectCommand *command); const Reply *Process(const AssemblyGetEntryPointCommand *command); const Reply *Process(const AssemblyGetManifestModuleCommand *command); const Reply *Process(const AssemblyGetNameCommand *command); const Reply *Process(const AssemblyGetLocationCommand *command); const Reply *Process(const AssemblyGetTypeCommand *command); const Reply *Process(const InternalErrorNotImplementedCommand *command); const Reply *Process(const VmSetProtocolVersionCommand *command); const Reply *Process(const VmSuspendCommand *command); const Reply *Process(const VmAllThreadsCommand *command); const Reply *Process(const VmVersionCommand *command); const Reply *Process(const VmDisposeCommand *command); const Reply *Process(const VmAbortInvokeCommand *command); const Reply *Process(const VmResumeCommand *command); const Reply *Process(const VmExitCommand *command); const Reply *Process(const VmInvokeMethodCommand *command); const Reply *Process(const StringRefGetValueCommand *command); const Reply *Process(const ObjectRefGetTypeCommand *command); const Reply *Process(const ObjectRefGetDomainCommand *command); const Reply *Process(const ObjectRefIsCollectedCommand *command); const Reply *Process(const ObjectRefSetValuesCommand *command); const Reply *Process(const ObjectRefGetAddressCommand *command); const Reply *Process(const ObjectRefGetValuesCommand *command); const Reply *Process(const TypeGetPropertiesCommand *command); const Reply *Process(const TypeGetSourceFiles2Command *command); const Reply *Process(const TypeGetPropertyCAttrsCommand *command); const Reply *Process(const TypeGetFieldCAttrsCommand *command); const Reply *Process(const TypeGetInfoCommand *command); const Reply *Process(const TypeIsAssignableFromCommand *command); const Reply *Process(const TypeGetCAttrsCommand *command); const Reply *Process(const TypeGetSourceFilesCommand *command); const Reply *Process(const TypeGetValuesCommand *command); const Reply *Process(const TypeGetObjectCommand *command); const Reply *Process(const TypeGetFieldsCommand *command); const Reply *Process(const TypeSetValuesCommand *command); const Reply *Process(const TypeGetMethodsCommand *command); const Reply *Process(const ThreadGetNameCommand *command); const Reply *Process(const ThreadGetFrameInfoCommand *command); const Reply *Process(const ThreadGetInfoCommand *command); const Reply *Process(const ThreadGetStateCommand *command); const Reply *Process(const ThreadGetIdCommand *command); const Reply *Process(const ArrayRefGetValuesCommand *command); const Reply *Process(const ArrayRefGetLengthCommand *command); const Reply *Process(const ArrayRefSetValuesCommand *command); const Reply *Process(const EventRequestClearCommand *command); const Reply *Process(const EventRequestClearAllBreakpointsCommand *command); const Reply *Process(const EventRequestSetCommand *command); const Reply *Process(const AppDomainGetFriendlyNameCommand *command); const Reply *Process(const AppDomainCreateStringCommand *command); const Reply *Process(const AppDomainGetEntryAssemblyCommand *command); const Reply *Process(const AppDomainGetRootDomainCommand *command); const Reply *Process(const AppDomainCreateBoxedValueCommand *command); const Reply *Process(const AppDomainGetAssembliesCommand *command); const Reply *Process(const AppDomainGetCorlibCommand *command); const Reply *Process(const MethodGetParamInfoCommand *command); const Reply *Process(const MethodGetNameCommand *command); const Reply *Process(const MethodGetDeclaringTypeCommand *command); const Reply *Process(const MethodGetLocalsInfoCommand *command); const Reply *Process(const MethodGetInfoCommand *command); const Reply *Process(const MethodGetDebugInfoCommand *command); const Reply *Process(const MethodResolveTokenCommand *command); const Reply *Process(const MethodGetBodyCommand *command); const Reply *Process(const ModuleGetInfoCommand *command); const Reply *Process(const EventCompositeCommand *command); AgentConfig _config; Protocol _protocol; os::Thread *_thread; Il2CppThread *_managed_debugger_thread; EventRequestList _event_req_list; IDataTransport *_transport; bool _is_notifying_pending_events; std::list _bp_data; SingleStepData *_ss_data; bool _notify_pending_events_on_first_invoke; bool _is_initialized; bool _currently_invoking_method; std::set _pending_types; std::set _pending_threads; std::set _pending_domains; std::set _pending_assemblies; ThreadDataMap _thread_data; DISALLOW_COPY(Agent); }; class CurrentlyInvokingMethodHelper { public: CurrentlyInvokingMethodHelper(bool& currently_invoking_method) : _currently_invoking_method(currently_invoking_method) { _currently_invoking_method = true; } ~CurrentlyInvokingMethodHelper() { _currently_invoking_method = false; } private: bool& _currently_invoking_method; }; } /* namespace debugger */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/debugger/command-line-parser.cpp ================================================ #include #include #include #include #include "command-line-parser.h" using namespace il2cpp::debugger; bool CommandLineParser::Parse(int argc, char* argv[], CommandLineOptions* options) { options->print_help = false; bool hostFound = false; bool portFound = false; int i = 1; while (i < argc) { if (strcmp(argv[i], debugger_host_option) == 0) { options->host = argv[i + 1]; hostFound = true; i += 2; } else if (strcmp(argv[i], debugger_port_option) == 0) { options->port = atoi(argv[i + 1]); portFound = true; i += 2; } else if (strcmp(argv[i], debugger_help_option) == 0) { options->print_help = true; i += 1; } else { i += 1; } } return !options->print_help && hostFound && portFound; } void CommandLineParser::PrintUsage(std::ostream& out) { out << "Usage: --debugger-host (optional) --debugger-port (optional) --help (optional)"; } ================================================ FILE: unity_decoder/libil2cpp/debugger/command-line-parser.h ================================================ #pragma once #include #include #include namespace il2cpp { namespace debugger { struct CommandLineOptions { char* host; int32_t port; bool print_help; }; static const char* debugger_host_option = "--debugger-host"; static const char* debugger_port_option = "--debugger-port"; static const char* debugger_help_option = "--help"; class CommandLineParser { public: static bool Parse(int argc, char* argv[], CommandLineOptions* options); static void PrintUsage(std::ostream& out); }; } /* namespace debugger */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/debugger/common.h ================================================ #pragma once #include #include #include #include #include "il2cpp-config.h" #include "../os/Thread.h" struct Il2CppAssembly; struct Il2CppClass; struct Il2CppObject; struct Il2CppImage; struct Il2CppDomain; struct MethodInfo; struct FieldInfo; struct PropertyInfo; struct Il2CppThread; struct Il2CppType; extern bool is_debugger_thread(); #define DISALLOW_COPY(t) \ private: \ t(const t&); \ t& operator=(const t&); #if IL2CPP_DEBUGGER_LOG #define LOG(msg) \ {\ std::cout << "[debugger:"<< il2cpp::os::Thread::CurrentThreadId() << "/" << (is_debugger_thread() ? "dbg" : "vm") << "] " << msg << std::endl; \ } #else #define LOG(msg) do{} while(0) #endif enum SuspendPolicy { kSuspendPolicyNone = 0, kSuspendPolicyEventThread = 1, kSuspendPolicyAll = 2 }; ================================================ FILE: unity_decoder/libil2cpp/debugger/data-buffer.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "data-buffer.h" #include "common.h" #include "variant.h" #include "id-bank.h" using namespace il2cpp::debugger; Buffer::Buffer(size_t size) : _data(0), _ptr(0), _tail(0), _end(0) { AssureRoomFor(size); memset(_data, 0, buffer_size()); } Buffer::~Buffer() { if (_data != 0) { delete[] _data; _data = 0; _ptr = 0; _tail = 0; _end = 0; } } void Buffer::Reset() { memset(_data, 0, buffer_size()); _ptr = _data; _tail = _data; } void Buffer::Reset(size_t sz) { if (sz > buffer_size()) { delete[] _data; _data = new uint8_t[((sz / GrowStep) + 1) * GrowStep]; _ptr = _data; _tail = _data; _end = _data + sz; } Reset(); } void Buffer::Seek(int32_t offset) { const int32_t dist = (offset - (int32_t)buffer_size()); if (dist > 0) AssureRoomFor(dist); _ptr = _data + offset; if (_ptr > _tail) _tail = _ptr; } void Buffer::AssureRoomFor(size_t size) { const size_t pos = position(); const size_t new_size = buffer_size() + size; const size_t tail_pos = length(); if (pos + size <= buffer_size()) return; uint8_t *new_data = new uint8_t[((new_size / GrowStep) + 1) * GrowStep]; if (_data != 0) { memcpy(new_data, _data, buffer_size()); delete[] _data; } _data = new_data; _ptr = _data + pos; _tail = _data + tail_pos; _end = _data + new_size; } void Buffer::WriteInt(uint32_t value) { AssureRoomFor(4); *(_ptr + 0) = (value >> 24) & 0xFF; *(_ptr + 1) = (value >> 16) & 0xFF; *(_ptr + 2) = (value >> 8) & 0xFF; *(_ptr + 3) = (value >> 0) & 0xFF; _ptr += 4; if (_ptr > _tail) _tail = _ptr; } void Buffer::WriteString(const char *value) { if (value != 0) { const size_t len = strlen(value); WriteInt(len); WriteData((uint8_t*)value, len); } else { WriteInt(0); } } void Buffer::WriteString(const std::string &value) { WriteInt(value.size()); WriteData((uint8_t*)value.c_str(), value.size()); } void Buffer::WriteData(const uint8_t *data, size_t size) { AssureRoomFor(size); std::copy(data, data + size, _ptr); _ptr += size; if (_ptr > _tail) _tail = _ptr; } void Buffer::WriteData(const Buffer &data) { WriteData(data.raw(), data.length()); } void Buffer::WriteByte(uint8_t value) { AssureRoomFor(1); *_ptr = value; ++_ptr; if (_ptr > _tail) _tail = _ptr; } void Buffer::WriteBool(bool value) { WriteByte((uint8_t)value); } void Buffer::WriteLong(uint64_t value) { WriteInt((value >> 32) & 0xffffffff); WriteInt((value >> 0) & 0xffffffff); } void Buffer::WritePtrId(const Id &id) { WriteInt(id.id); } void Buffer::WriteAssemblyId(const Il2CppAssembly *assembly) { WritePtrId(AssemblyId(assembly)); } void Buffer::WriteObjectId(const Il2CppObject *object) { WritePtrId(ObjectId(object)); } void Buffer::WriteThreadId(const Il2CppThread *thread) { WritePtrId(ObjectId((Il2CppObject*)thread)); } void Buffer::WriteModuleId(const Il2CppImage *image) { WritePtrId(ModuleId(image)); } void Buffer::WriteTypeId(const Il2CppClass *klass) { WritePtrId(TypeId(klass)); } void Buffer::WriteDomainId(const Il2CppDomain *domain) { WritePtrId(DomainId(domain)); } void Buffer::WriteMethodId(const MethodInfo *method) { WritePtrId(MethodId(method)); } void Buffer::WriteFieldId(const FieldInfo *field) { WritePtrId(FieldId(field)); } void Buffer::WritePropertyId(const PropertyInfo *prop) { WritePtrId(PropertyId(prop)); } void Buffer::WriteVariant(const Variant &value) { value.WriteTo(*this); } int32_t Buffer::ReadInt() { IL2CPP_ASSERT(position() + 4 <= length() && "Cannot read past the end of the buffer!"); uint8_t *c = _ptr; _ptr += 4; if (_ptr > _tail) _tail = _ptr; return (((int32_t)c[0]) << 24) | (((int32_t)c[1]) << 16) | (((int32_t)c[2]) << 8) | (((int32_t)c[3]) << 0); } uint8_t Buffer::ReadByte() { IL2CPP_ASSERT(position() + 1 <= length() && "Cannot read past the end of the buffer!"); uint8_t *c = _ptr; _ptr += 1; if (_ptr > _tail) _tail = _ptr; return (uint8_t)c[0]; } bool Buffer::ReadBool() { return ReadByte() ? true : false; } Il2CppClass *Buffer::ReadType() { return TypeFromId(ReadInt()); } Il2CppObject *Buffer::ReadObject() { Id id; id.type = kIdTypeObject; id.id = ReadInt(); return ObjectFromId(id); } Il2CppThread *Buffer::ReadThread() { Id id; id.type = kIdTypeObject; id.id = ReadInt(); return (Il2CppThread*)ObjectFromId(id); } uint64_t Buffer::ReadLong() { uint32_t high = ReadInt(); uint32_t low = ReadInt(); return ((((uint64_t)high) << 32) | ((uint64_t)low)); } Il2CppDomain *Buffer::ReadDomain() { Id id; id.type = kIdTypeDomain; id.id = ReadInt(); return DomainFromId(id); } Il2CppAssembly *Buffer::ReadAssembly() { Id id; id.type = kIdTypeAssembly; id.id = ReadInt(); return AssemblyFromId(id); } Il2CppImage *Buffer::ReadModule() { Id id; id.type = kIdTypeModule; id.id = ReadInt(); return ModuleFromId(id); } MethodInfo *Buffer::ReadMethod() { Id id; id.type = kIdTypeMethod; id.id = ReadInt(); return MethodFromId(id); } FieldInfo *Buffer::ReadField() { Id id; id.type = kIdTypeField; id.id = ReadInt(); return FieldFromId(id); } PropertyInfo *Buffer::ReadProperty() { Id id; id.type = kIdTypeProperty; id.id = ReadInt(); return PropertyFromId(id); } std::string Buffer::ReadString() { const size_t len = ReadInt(); std::string value; value.resize(len); memcpy(&value[0], _ptr, len); _ptr += len; return value; } void Buffer::MarkReadRaw(size_t size) { IL2CPP_ASSERT(size <= buffer_size() && "A raw read was performed, but too many bytes were read. Memory overwrite!"); _tail += size; } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/data-buffer.h ================================================ #pragma once #include "common.h" #include #include struct Il2CppClass; namespace il2cpp { namespace debugger { struct Id; class Variant; class Buffer { public: static const int32_t GrowStep = 32; explicit Buffer(size_t size); ~Buffer(); void Seek(int32_t offset); void Reset(); void Reset(size_t size); void AssureRoomFor(size_t size); void WriteInt(uint32_t value); void WriteData(const uint8_t *data, size_t size); void WriteData(const Buffer &data); void WriteString(const char *value); void WriteString(const std::string &value); void WriteBool(bool value); void WriteByte(uint8_t value); void WritePtrId(const Id &id); void WriteObjectId(const Il2CppObject *object); void WriteThreadId(const Il2CppThread *thread); void WriteAssemblyId(const Il2CppAssembly *assembly); void WriteMethodId(const MethodInfo *method); void WriteFieldId(const FieldInfo *field); void WritePropertyId(const PropertyInfo *prop); void WriteModuleId(const Il2CppImage *image); void WriteTypeId(const Il2CppClass *klass); void WriteDomainId(const Il2CppDomain *domain); void WriteLong(uint64_t value); void WriteVariant(const Variant &value); int32_t ReadInt(); uint8_t ReadByte(); bool ReadBool(); Il2CppClass *ReadType(); Il2CppDomain *ReadDomain(); Il2CppObject *ReadObject(); Il2CppAssembly *ReadAssembly(); Il2CppImage *ReadModule(); MethodInfo *ReadMethod(); FieldInfo *ReadField(); PropertyInfo *ReadProperty(); std::string ReadString(); uint64_t ReadLong(); Il2CppThread *ReadThread(); void MarkReadRaw(size_t size); template inline T ReadEnum() { return (T)ReadByte(); } inline const int32_t position() const { return (((uintptr_t)_ptr) - ((uintptr_t)_data)); } inline const size_t length() const { return (((uintptr_t)_tail) - ((uintptr_t)_data)); } inline const size_t buffer_size() const { return (((uintptr_t)_end) - ((uintptr_t)_data)); } inline uint8_t *raw() { return _data; } inline const uint8_t *raw() const { return _data; } private: uint8_t *_data; uint8_t *_ptr; uint8_t *_tail; uint8_t *_end; DISALLOW_COPY(Buffer); }; } /* namespace debugger */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/debugger/event-request.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "event-request.h" #include "../os/Atomic.h" #include "../il2cpp-api.h" #include "protocol/protocol.h" using namespace il2cpp::debugger; EventRequest::EventRequest(EventKind kind, SuspendPolicy suspend_policy, const std::vector &modifiers) : _id((int32_t)il2cpp::os::Atomic::Increment(&event_request_id)), _kind(kind), _suspend_policy(suspend_policy), _modifiers(modifiers), _breakpoint_data(0), _single_step_data(0) { } EventRequestList::EventRequestList(Agent &agent, bool owns_requests) : _agent(agent), _owns_requests(owns_requests) { } EventRequestList::~EventRequestList() { if (!_owns_requests) return; ClearAllRequests(); } void EventRequestList::ClearAllRequests() { IL2CPP_ASSERT(_owns_requests && "EventRequestList::ClearAllRequests cannot be invoked on a list that does not own the requests"); std::list::const_iterator it = _requests.begin(); while (it != _requests.end()) { delete (*it); ++it; } _requests.clear(); } bool EventRequestList::IsClientInterested(const Event &evt) const { if (evt.kind() == kEventKindVmStart || evt.kind() == kEventKindVmDeath) return true; std::list::const_iterator it = _requests.begin(); while (it != _requests.end()) { if ((*it)->kind() == evt.kind()) return true; ++it; } return false; } int32_t EventRequestList::RequestIdsFor(std::vector &ids, const Event &evt, FilterInfo &filter) const { if (evt.kind() == kEventKindVmStart || evt.kind() == kEventKindVmDeath) ids.push_back(0); else { std::list::const_iterator it = _requests.begin(); while (it != _requests.end()) { const EventRequest* req = *it; if (req->kind() == evt.kind()) { bool filtered = false; std::vector::const_iterator mit = req->modifiers().begin(); while (mit != req->modifiers().end()) { Modifier *modifier = *mit; switch (modifier->kind) { case kModifierKindCount: filtered = ((modifier->data.count > 0) && (--modifier->data.count > 0)); break; case kModifierKindLocationOnly: IL2CPP_ASSERT(0 && "kModifierKindLocationOnly modifier filter not supported!"); break; case kModifierKindStep: IL2CPP_ASSERT(0 && "kModifierKindStep modifier filter not supported!"); break; case kModifierKindThreadOnly: filtered = (modifier->data.thread != il2cpp_thread_current()); break; case kModifierKindExceptionOnly: IL2CPP_ASSERT(0 && "kModifierKindExceptionOnly modifier filter not supported!"); break; case kModifierKindAssemblyOnly: IL2CPP_ASSERT(0 && "kModifierKindAssemblyOnly modifier filter not supported!"); // int k; // gboolean found = FALSE; // MonoAssembly **assemblies = mod->data.assemblies; // if (assemblies) { // for (k = 0; assemblies [k]; ++k) // if (assemblies [k] == klass->image->assembly) // found = TRUE; // } // if (!found) // filtered = TRUE; break; } ++mit; } if (!filtered) ids.push_back(req->id()); } ++it; } } return ids.size(); } const EventRequest *EventRequestList::GetEventRequestById(int32_t id) const { std::list::const_iterator it = _requests.begin(); while (it != _requests.end()) { if ((*it)->id() == id) return *it; ++it; } return NULL; } void EventRequestList::AddEventRequest(const EventRequest *request) { _requests.push_back(request); } const EventRequest* EventRequestList::RemoveEventRequest(EventKind kind, int32_t id) { std::list::iterator it = _requests.begin(); while (it != _requests.end()) { if ((*it)->kind() == kind && (*it)->id() == id) { const EventRequest* req = *it; _requests.erase(it); return req; } ++it; } return NULL; } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/event-request.h ================================================ #pragma once #include "common.h" #include #include #include "protocol/globals.h" struct Il2CppClass; namespace il2cpp { namespace debugger { class Event; class Agent; struct BreakpointData; struct SingleStepData; static int32_t event_request_id; class EventRequest { public: EventRequest(EventKind kind, SuspendPolicy suspend_policy, const std::vector &modifiers); inline int32_t id() const { return _id; } inline EventKind kind() const { return _kind; } inline SuspendPolicy suspend_policy() const { return _suspend_policy; } inline const std::vector &modifiers() const { return _modifiers; } inline bool has_modifiers() const { return _modifiers.size() > 0; } inline BreakpointData *breakpoint_data() const { return _breakpoint_data; } inline void breakpoint_data(BreakpointData *value) { _breakpoint_data = value; } inline SingleStepData *single_step_data() const { return _single_step_data; } inline void single_step_data(SingleStepData *value) { _single_step_data = value; } private: int32_t _id; EventKind _kind; SuspendPolicy _suspend_policy; std::vector _modifiers; BreakpointData *_breakpoint_data; SingleStepData *_single_step_data; DISALLOW_COPY(EventRequest); friend class Agent; }; class EventRequestList { public: struct FilterInfo { Il2CppClass *klass; Il2CppObject *exception; FilterInfo() : klass(0), exception(0) { } }; EventRequestList(Agent &agent, bool owns_requests); ~EventRequestList(); inline const std::list requests() const { return _requests; } int32_t RequestIdsFor(std::vector &ids, const Event &evt, FilterInfo &filter) const; bool IsClientInterested(const Event &evt) const; const EventRequest *GetEventRequestById(int32_t id) const; void AddEventRequest(const EventRequest *request); const EventRequest* RemoveEventRequest(EventKind kind, int32_t id); void ClearAllRequests(); private: Agent &_agent; bool _owns_requests; std::list _requests; DISALLOW_COPY(EventRequestList); }; } /* namespace debugger */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/debugger/handlers/app-domain.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #pragma once #include #include "../../il2cpp-api.h" #include "../agent.h" #include "../protocol/commands/app-domain.h" #include "../protocol/commands/internal-error.h" using namespace il2cpp::debugger; const Reply *Agent::Process(const AppDomainGetRootDomainCommand *command) { AppDomainGetRootDomainCommand::Reply *app_domain_get_root_domain_reply = command->reply(); app_domain_get_root_domain_reply->domain(CALL_IL2CPP_API(il2cpp_domain_get)()); return app_domain_get_root_domain_reply; } const Reply *Agent::Process(const AppDomainGetCorlibCommand *command) { AppDomainGetCorlibCommand::Reply *get_corlib_reply = command->reply(); Il2CppDomain *domain = command->domain(); const Il2CppImage *image = il2cpp_get_corlib(); get_corlib_reply->assembly(const_cast(il2cpp_image_get_assembly(image))); return get_corlib_reply; } const Reply *Agent::Process(const AppDomainGetFriendlyNameCommand *command) { AppDomainGetFriendlyNameCommand::Reply *get_friendly_name_reply = command->reply(); Il2CppDomain *domain = command->domain(); LOG("warning: `AppDomainGetFriendlyNameCommand` not implemented properly. Returning a stub name for now!"); get_friendly_name_reply->friendly_name("[ROOT_DOMAIN]"); return get_friendly_name_reply; } const Reply *Agent::Process(const AppDomainCreateStringCommand *command) { AppDomainCreateStringCommand::Reply *create_string_reply = command->reply(); const Il2CppDomain *domain = command->domain(); const std::string str = command->string(); create_string_reply->object((Il2CppObject*)il2cpp_string_new(str.c_str())); return create_string_reply; } const Reply *Agent::Process(const AppDomainGetEntryAssemblyCommand *command) { LOG("warning: `AppDomainGetEntryAssemblyCommand` not implemented. Returning a `NotImplemented` reply!"); IL2CPP_ASSERT(0); return new InternalErrorNotImplementedReply(command); } const Reply *Agent::Process(const AppDomainCreateBoxedValueCommand *command) { LOG("warning: `AppDomainCreateBoxedValueCommand` not implemented. Returning a `NotImplemented` reply!"); IL2CPP_ASSERT(0); return new InternalErrorNotImplementedReply(command); } const Reply *Agent::Process(const AppDomainGetAssembliesCommand *command) { AppDomainGetAssembliesCommand::Reply *get_assemblies_reply = command->reply(); size_t number_of_assemblies; const Il2CppAssembly** assemblies = il2cpp_domain_get_assemblies(NULL, &number_of_assemblies); get_assemblies_reply->number_of_assemblies(number_of_assemblies); for (size_t i = 0; i < number_of_assemblies; ++i) get_assemblies_reply->assemblies().push_back(const_cast(assemblies[i])); return get_assemblies_reply; } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/handlers/array-ref.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #pragma once #include "../../il2cpp-api.h" #include "../../class-internals.h" #include "../../object-internals.h" #include "../agent.h" #include "../protocol/commands/array-ref.h" #include "../protocol/commands/internal-error.h" namespace il2cpp { namespace debugger { const Reply *Agent::Process(const ArrayRefGetValuesCommand *command) { ArrayRefGetValuesCommand::Reply *get_values_reply = command->reply(); Il2CppArray *arr = (Il2CppArray*)command->object(); if (arr == 0) return get_values_reply; Il2CppClass *array_klass = il2cpp_object_get_class(arr); int32_t element_size = il2cpp_array_element_size(array_klass); for (int32_t i = command->index(); i < command->index() + command->length(); ++i) { void *element = (void*)((uint8_t*)arr + kIl2CppSizeOfArray + (i * element_size)); get_values_reply->values().push_back( Variant(array_klass->element_class->byval_arg, element)); } return get_values_reply; } const Reply *Agent::Process(const ArrayRefGetLengthCommand *command) { ArrayRefGetLengthCommand::Reply *get_length_reply = command->reply(); Il2CppArray *arr = (Il2CppArray*)command->object(); if (arr == 0) return get_length_reply; Il2CppClass *array_klass = il2cpp_object_get_class(arr); get_length_reply->rank(array_klass->rank); if (!arr->bounds) { get_length_reply->lengths().push_back(arr->max_length); get_length_reply->lower_bounds().push_back(0); } else { for (uint8_t i = 0; i < array_klass->rank; ++i) { get_length_reply->lengths().push_back(arr->bounds[i].length); get_length_reply->lower_bounds().push_back(arr->bounds[i].lower_bound); } } return get_length_reply; } const Reply *Agent::Process(const ArrayRefSetValuesCommand *command) { LOG("warning: `ArrayRefSetValuesCommand` not implemented. Returning a `NotImplemented` reply!"); IL2CPP_ASSERT(0); return new InternalErrorNotImplementedReply(command); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/handlers/assembly.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #pragma once #include #include "../../il2cpp-api.h" #include "../../tabledefs.h" #include "../../class-internals.h" #include "../agent.h" #include "../protocol/commands/assembly.h" #include "../protocol/commands/internal-error.h" #include "../../vm/Assembly.h" #include "../../vm/AssemblyName.h" namespace il2cpp { namespace debugger { const Reply *Agent::Process(const AssemblyGetTypeCommand *command) { AssemblyGetTypeCommand::Reply *get_type_reply = command->reply(); /*char *s = decode_string (p, &p, end); gboolean ignorecase = decode_byte (p, &p, end); MonoTypeNameParse info; MonoType *t; gboolean type_resolve; if (!mono_reflection_parse_type (s, &info)) { t = NULL; } else { if (info.assembly.name) NOT_IMPLEMENTED; t = mono_reflection_get_type (ass->image, &info, ignorecase, &type_resolve); } buffer_add_typeid (buf, domain, t ? mono_class_from_mono_type (t) : NULL); mono_reflection_free_type_info (&info); g_free (s);*/ LOG("warning: Implement proper name parsing for `AssemblyGetType` command"); if (command->ignore_case()) LOG("warning: AssemblyGetType not implemented for ignore_case = true"); std::string ns; std::string name; const size_t last_dot_index = command->name().find_last_of("."); if (last_dot_index != std::string::npos) { ns.assign(command->name().begin(), command->name().begin() + last_dot_index); name.assign(command->name().begin() + last_dot_index + 1, command->name().end()); } else { name = command->name(); } Il2CppClass *type = il2cpp_class_from_name( il2cpp_assembly_get_image(command->assembly()), ns.c_str(), name.c_str()); if (type == 0) LOG("warning: AssemblyGetType command not mocked up for type " << command->name()); get_type_reply->type(type); return get_type_reply; } const Reply *Agent::Process(const AssemblyGetObjectCommand *command) { LOG("warning: `AssemblyGetObjectCommand` not implemented. Returning a `NotImplemented` reply!"); IL2CPP_ASSERT(0); return new InternalErrorNotImplementedReply(command); } const Reply *Agent::Process(const AssemblyGetEntryPointCommand *command) { LOG("warning: `AssemblyGetEntryPointCommand` not implemented. Returning a `NotImplemented` reply!"); IL2CPP_ASSERT(0); return new InternalErrorNotImplementedReply(command); } const Reply *Agent::Process(const AssemblyGetManifestModuleCommand *command) { AssemblyGetManifestModuleCommand::Reply *reply = command->reply(); reply->module(il2cpp_assembly_get_image(command->assembly())); return reply; } const Reply *Agent::Process(const AssemblyGetNameCommand *command) { AssemblyGetNameCommand::Reply *reply = command->reply(); const Il2CppAssembly *assembly = command->assembly(); reply->name(il2cpp::vm::AssemblyName::AssemblyNameToString(assembly->aname)); return reply; } const Reply *Agent::Process(const AssemblyGetLocationCommand *command) { AssemblyGetLocationCommand::Reply *reply = command->reply(); reply->location( il2cpp_image_get_filename( il2cpp_assembly_get_image(command->assembly()))); return reply; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/handlers/event-request.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #pragma once #include "../../il2cpp-api.h" #include "../agent.h" #include "../protocol/commands/event-request.h" #include "../protocol/commands/internal-error.h" namespace il2cpp { namespace debugger { const Reply *Agent::Process(const EventRequestSetCommand *command) { SuspendPolicy suspend_policy = command->suspend_policy(); // We always suspend in case of breakpoint or single step events if (command->kind() == kEventKindBreakpoint || command->kind() == kEventKindStep) suspend_policy = kSuspendPolicyAll; EventRequest *request = new EventRequest( command->kind(), suspend_policy, command->modifiers()); // TODO: if something was wrong, please make sure to set reply->error(...) _event_req_list.AddEventRequest(request); switch (command->kind()) { case kEventKindAssemblyLoad: case kEventKindAssemblyUnload: case kEventKindThreadStart: case kEventKindThreadDeath: case kEventKindUserBreak: case kEventKindUserLog: case kEventKindException: case kEventKindVmDeath: case kEventKindVmStart: case kEventKindAppDomainCreate: case kEventKindAppDomainUnload: // Nothing special to do here break; case kEventKindTypeLoad: // Note: this should be set to true only if defer=y _notify_pending_events_on_first_invoke = true; break; case kEventKindBreakpoint: { IL2CPP_ASSERT(command->method() != 0 && "kEventKindBreakpoint expects a method and a location to be set!"); BreakpointData *data = new BreakpointData(); data->method = command->method(); data->request = request; data->location = command->location(); _bp_data.push_back(data); request->breakpoint_data(data); il2cpp_debug_method_set_breakpoint_data_at( (Il2CppDebugMethodInfo*)il2cpp_debug_get_method_info(command->method()), command->location(), data); } break; case kEventKindStep: { IL2CPP_ASSERT(command->thread() != 0 && "kEventKindStep expects a thread, size and depth to be set!"); // TODO: we probably need to clear also the SingleStepData state, if any. if (_ss_data != 0) ClearSingleStepData(); _ss_data = PrepareSingleStepData( request, command->thread(), (StepSizeKind)command->size(), (StepDepthKind)command->depth()); request->single_step_data(_ss_data); } break; case kEventKindMethodEntry: /*req->info = set_breakpoint (NULL, METHOD_ENTRY_IL_OFFSET, req);*/ IL2CPP_ASSERT(0 && "Not implemented request kEventKindMethodEntry"); break; case kEventKindMethodExit: /*req->info = set_breakpoint (NULL, METHOD_EXIT_IL_OFFSET, req);*/ IL2CPP_ASSERT(0 && "Not implemented request kEventKindMethodExit"); break; case kEventKindKeepAlive: // Was empty IL2CPP_ASSERT(0 && "Not implemented request kEventKindKeepAlive"); break; default: LOG("Not implemented request ??(" << command->kind() << ") with modifiers"); IL2CPP_ASSERT(0 && "Not implemented request"); } EventRequestSetCommand::Reply *event_request_set_reply = command->reply(); event_request_set_reply->request_id(request->id()); /*LOG("NotifyPendingEventsOfKind is being invoked from the debugger agent thread, which is WRONG. Only the VM thread should send these events."); NotifyPendingEventsOfKind(command->kind());*/ return event_request_set_reply; } const Reply *Agent::Process(const EventRequestClearCommand *command) { EventRequestClearCommand::Reply *empty_reply = command->reply(); const EventRequest *request = _event_req_list.RemoveEventRequest( (EventKind)command->event_kind(), command->request_id()); if (request == 0) { LOG("EventRequestClearCommand: invalid request Id: " << command->request_id()); return empty_reply; } BreakpointData *data = request->breakpoint_data(); if (data != 0) { LOG("EventRequestClearCommand: breakpoint_data found, deleting it"); _bp_data.remove(data); il2cpp_debug_method_clear_breakpoint_data_at( (Il2CppDebugMethodInfo*)il2cpp_debug_get_method_info(data->method), data->location); delete data; } delete request; return empty_reply; } const Reply *Agent::Process(const EventRequestClearAllBreakpointsCommand *command) { EventRequestClearAllBreakpointsCommand::Reply *empty_reply = command->reply(); std::list::iterator it = _bp_data.begin(); while (it != _bp_data.end()) { BreakpointData* data = *it; il2cpp_debug_method_clear_breakpoint_data( (Il2CppDebugMethodInfo*)il2cpp_debug_get_method_info(data->method)); delete data; ++it; } _bp_data.clear(); return empty_reply; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/handlers/event.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #pragma once #include "../../il2cpp-api.h" #include "../agent.h" #include "../protocol/commands/event.h" #include "../protocol/commands/internal-error.h" namespace il2cpp { namespace debugger { const Reply *Agent::Process(const EventCompositeCommand *command) { LOG("warning: `EventCompositeCommand` not implemented. Returning a `NotImplemented` reply!"); IL2CPP_ASSERT(0); return new InternalErrorNotImplementedReply(command); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/handlers/internal-error.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #pragma once #include "../../il2cpp-api.h" #include "../agent.h" #include "../protocol/commands/internal-error.h" namespace il2cpp { namespace debugger { const Reply *Agent::Process(const InternalErrorNotImplementedCommand *command) { return new InternalErrorNotImplementedReply(command); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/handlers/method.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #pragma once #include "../../il2cpp-api.h" #include "../agent.h" #include "../protocol/commands/method.h" #include "../protocol/commands/internal-error.h" namespace il2cpp { namespace debugger { const Reply *Agent::Process(const MethodGetParamInfoCommand *command) { MethodGetParamInfoCommand::Reply *get_param_info_reply = command->reply(); LOG("warning: `MethodGetParamInfoCommand` not implemented properly yet."); const MethodInfo *method = command->method(); get_param_info_reply->call_convention(0 /* IL2CPP_CALL_DEFAULT */); get_param_info_reply->generic_param_count(0); get_param_info_reply->return_type( il2cpp_class_from_type( (Il2CppType*)il2cpp_method_get_return_type(method))); const size_t count = il2cpp_method_get_param_count(method); for (uint32_t i = 0; i < count; ++i) { MethodGetParamInfoCommand::Reply::ParamInfo param; param.type = il2cpp_class_from_type( (Il2CppType*)il2cpp_method_get_param(method, i)); param.name = il2cpp_method_get_param_name(method, i); get_param_info_reply->params().push_back(param); } return get_param_info_reply; } const Reply *Agent::Process(const MethodGetNameCommand *command) { MethodGetNameCommand::Reply *get_name_reply = command->reply(); get_name_reply->name(il2cpp_method_get_name(command->method())); return get_name_reply; } const Reply *Agent::Process(const MethodGetDeclaringTypeCommand *command) { MethodGetDeclaringTypeCommand::Reply *get_declaring_type_reply = command->reply(); get_declaring_type_reply->type(il2cpp_method_get_declaring_type(command->method())); return get_declaring_type_reply; } const Reply *Agent::Process(const MethodGetDebugInfoCommand *command) { MethodGetDebugInfoCommand::Reply *get_debug_info_reply = command->reply(); const Il2CppDebugMethodInfo *info = il2cpp_debug_get_method_info(command->method()); const Il2CppDebugDocument *document = il2cpp_debug_method_get_document(info); if (info == 0 || document == 0) return get_debug_info_reply; std::string filename; filename += il2cpp_debug_document_get_directory(document); filename += il2cpp_debug_document_get_filename(document); const int32_t *offset_table = il2cpp_debug_method_get_offset_table(info); get_debug_info_reply->code_size(il2cpp_debug_method_get_code_size(info)); get_debug_info_reply->file_name(filename); for (int32_t i = 0; offset_table[i] >= 0; i += 2) { get_debug_info_reply->offsets().push_back(std::pair(offset_table[i], offset_table[i + 1])); } return get_debug_info_reply; } const Reply *Agent::Process(const MethodGetBodyCommand *command) { MethodGetBodyCommand::Reply *get_body_reply = command->reply(); LOG("warning: `MethodGetBodyCommand` always return an empty byte array for now"); return get_body_reply; } const Reply *Agent::Process(const MethodResolveTokenCommand *command) { LOG("warning: `MethodResolveTokenCommand` not implemented. Returning a `NotImplemented` reply!"); IL2CPP_ASSERT(0); return new InternalErrorNotImplementedReply(command); } const Reply *Agent::Process(const MethodGetLocalsInfoCommand *command) { MethodGetLocalsInfoCommand::Reply *get_locals_info_reply = command->reply(); const Il2CppDebugMethodInfo *info = il2cpp_debug_get_method_info(command->method()); const Il2CppDebugLocalsInfo **locals = il2cpp_debug_method_get_locals_info(info); while (*locals != NULL) { MethodGetLocalsInfoCommand::Reply::LocalInfo local; local.type = il2cpp_debug_local_get_type(*locals); local.name = il2cpp_debug_local_get_name(*locals); local.begin_scope = il2cpp_debug_local_get_start_offset(*locals); local.end_scope = il2cpp_debug_local_get_end_offset(*locals); if (local.end_scope == 0) { local.begin_scope = 0; local.end_scope = il2cpp_debug_method_get_code_size(info); } get_locals_info_reply->locals().push_back(local); ++locals; } return get_locals_info_reply; } const Reply *Agent::Process(const MethodGetInfoCommand *command) { MethodGetInfoCommand::Reply *reply = command->reply(); uint32_t iflags = 0; reply->flags( il2cpp_method_get_flags(command->method(), &iflags)); reply->token( il2cpp_method_get_token(command->method())); reply->implementation_flags(iflags); return reply; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/handlers/module.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #pragma once #include "../../il2cpp-api.h" #include "../agent.h" #include "../protocol/commands/module.h" namespace il2cpp { namespace debugger { const Reply *Agent::Process(const ModuleGetInfoCommand *command) { ModuleGetInfoCommand::Reply *get_info_reply = command->reply(); Il2CppImage *image = command->module(); LOG("warning: `ModuleGetInfoCommand` is not implemented properly."); get_info_reply->basename("FAKE BASENAME"); get_info_reply->scope_name("FAKE SCOPE NAME"); get_info_reply->fullname(il2cpp_image_get_name(image)); get_info_reply->guid("FAKE GUID"); get_info_reply->assembly(const_cast(il2cpp_image_get_assembly(image))); return get_info_reply; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/handlers/object-ref.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #pragma once #include "../../il2cpp-api.h" #include "../agent.h" #include "../protocol/commands/object-ref.h" #include "../protocol/commands/internal-error.h" using namespace il2cpp::debugger; const Reply *Agent::Process(const ObjectRefGetTypeCommand *command) { ObjectRefGetTypeCommand::Reply *get_type_reply = command->reply(); Il2CppObject *object = command->object(); get_type_reply->type(il2cpp_object_get_class(object)); return get_type_reply; } const Reply *Agent::Process(const ObjectRefGetDomainCommand *command) { ObjectRefGetDomainCommand::Reply *get_domain_reply = command->reply(); Il2CppObject *object = command->object(); // TODO: use `object` even if we don't really have domains in il2cpp? get_domain_reply->domain(il2cpp_domain_get()); return get_domain_reply; } const Reply *Agent::Process(const ObjectRefIsCollectedCommand *command) { LOG("warning: `ObjectRefIsCollectedCommand` not implemented. Returning a `NotImplemented` reply!"); IL2CPP_ASSERT(0); return new InternalErrorNotImplementedReply(command); } const Reply *Agent::Process(const ObjectRefSetValuesCommand *command) { LOG("warning: `ObjectRefSetValuesCommand` not implemented. Returning a `NotImplemented` reply!"); IL2CPP_ASSERT(0); return new InternalErrorNotImplementedReply(command); } const Reply *Agent::Process(const ObjectRefGetAddressCommand *command) { LOG("warning: `ObjectRefGetAddressCommand` not implemented. Returning a `NotImplemented` reply!"); IL2CPP_ASSERT(0); return new InternalErrorNotImplementedReply(command); } const Reply *Agent::Process(const ObjectRefGetValuesCommand *command) { LOG("warning: `ObjectRefGetValuesCommand` not implemented. Returning a `NotImplemented` reply!"); IL2CPP_ASSERT(0); return new InternalErrorNotImplementedReply(command); } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/handlers/stack-frame.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #pragma once #include #include "../../il2cpp-api.h" #include "../../class-internals.h" #include "../agent.h" #include "../protocol/commands/stack-frame.h" #include "../protocol/commands/internal-error.h" namespace il2cpp { namespace debugger { struct FrameFinderData { int32_t frame_id; int32_t counter; const Il2CppStackFrameInfo *info; }; static void find_stack_frame(Il2CppThread* thread, const Il2CppStackFrameInfo *info, void *user_data) { FrameFinderData *data = (FrameFinderData*)user_data; if (++data->counter == data->frame_id) data->info = info; } const Reply *Agent::Process(const StackFrameGetValuesCommand *command) { ThreadData *data = _thread_data.ThreadDataFor(command->thread()); IL2CPP_ASSERT(data->IsFramesCacheValid() && "ThreadData frames cache is invalid when invoking StackFrameGetValuesCommand"); const Il2CppStackFrameInfo *frame = data->FrameById(command->frame_id()); IL2CPP_ASSERT(frame != NULL && "Couldn't find a stack frame with the given ID."); const MethodInfo *method = frame->method; StackFrameGetValuesCommand::Reply *get_values_reply = command->reply(); std::vector::const_iterator it = command->positions().begin(); while (it != command->positions().end()) { int32_t pos = *it; const Il2CppType *type = 0; void *addr = 0; if (pos < 0) { pos = -pos - 1; IL2CPP_ASSERT(pos < frame->method->parameters_count && "StackFrameGetValuesCommand was invoked with an outside of range param position"); type = frame->method->parameters[pos].parameter_type; addr = frame->params[pos]; } else { IL2CPP_ASSERT(pos < (int32_t)frame->locals_count && "StackFrameGetValuesCommand was invoked with an outside of range local position"); type = frame->method->debug_info->locals[pos]->type->byval_arg; addr = frame->locals[pos]; } get_values_reply->values().push_back(Variant(type, addr)); ++it; } return get_values_reply; } const Reply *Agent::Process(const StackFrameSetValuesCommand *command) { ThreadData *data = _thread_data.ThreadDataFor(command->thread()); IL2CPP_ASSERT(data->IsFramesCacheValid() && "ThreadData frames cache is invalid when invoking StackFrameSetValuesCommand"); const Il2CppStackFrameInfo *frame = data->FrameById(command->frame_id()); IL2CPP_ASSERT(frame != NULL && "Couldn't find a stack frame with the given ID."); const MethodInfo *method = frame->method; const int32_t count = command->values_count(); Buffer &buffer = command->command_buffer(); StackFrameSetValuesCommand::Reply *empty_reply = command->reply(); for (int32_t i = 0; i < count; ++i) { int32_t pos = buffer.ReadInt(); const Il2CppType *expected_type = 0; void *addr = 0; if (pos < 0) { pos = -pos - 1; IL2CPP_ASSERT(pos < frame->method->parameters_count && "StackFrameSetValuesCommand was invoked with an outside of range param position"); expected_type = frame->method->parameters[pos].parameter_type; addr = frame->params[pos]; } else { IL2CPP_ASSERT(pos < (int32_t)frame->locals_count && "StackFrameSetValuesCommand was invoked with an outside of range local position"); expected_type = frame->method->debug_info->locals[pos]->type->byval_arg; addr = frame->locals[pos]; } Variant::ReadInto(buffer, expected_type, addr); } return empty_reply; } const Reply *Agent::Process(const StackFrameGetThisCommand *command) { ThreadData *data = _thread_data.ThreadDataFor(command->thread()); IL2CPP_ASSERT(data->IsFramesCacheValid() && "ThreadData frames cache is invalid when invoking StackFrameGetThis"); const Il2CppStackFrameInfo *frame = data->FrameById(command->frame_id()); IL2CPP_ASSERT(frame != NULL && "Couldn't find a stack frame with the given ID."); const MethodInfo *method = frame->method; StackFrameGetThisCommand::Reply *get_this_reply = command->reply(); get_this_reply->this_object = VTypeVariant( method->declaring_type->byval_arg, frame->this_ptr); return get_this_reply; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/handlers/string-ref.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #pragma once #include "../../il2cpp-api.h" #include "../../utils/StringUtils.h" #include "../agent.h" #include "../protocol/commands/string-ref.h" #include "../protocol/commands/internal-error.h" namespace il2cpp { namespace debugger { const Reply *Agent::Process(const StringRefGetValueCommand *command) { StringRefGetValueCommand::Reply *get_value_reply = command->reply(); Il2CppString *str = (Il2CppString*)command->object(); if (str == 0) return get_value_reply; get_value_reply->value( utils::StringUtils::Utf16ToUtf8( il2cpp_string_chars(str))); return get_value_reply; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/handlers/thread.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #pragma once #include "../../il2cpp-api.h" #include "../agent.h" #include "../protocol/commands/thread.h" #include "../protocol/commands/internal-error.h" namespace il2cpp { namespace debugger { const Reply *Agent::Process(const ThreadGetIdCommand *command) { ThreadGetIdCommand::Reply *get_id_reply = command->reply(); get_id_reply->id((uintptr_t)command->thread()); return get_id_reply; } const Reply *Agent::Process(const ThreadGetNameCommand *command) { ThreadGetNameCommand::Reply *get_name_reply = command->reply(); uint32_t len = 0; char *name = il2cpp_thread_get_name(command->thread(), &len); get_name_reply->name(std::string(name, len)); if (name) delete name; return get_name_reply; } const Reply *Agent::Process(const ThreadGetInfoCommand *command) { ThreadGetInfoCommand::Reply *get_info_reply = command->reply(); LOG("warning: `ThreadGetInfoCommand` is not implemented properly"); // TODO: assuming thread is never in a pool for now get_info_reply->is_thread_pool(false); return get_info_reply; } const Reply *Agent::Process(const ThreadGetFrameInfoCommand *command) { ThreadGetFrameInfoCommand::Reply *get_frame_info_reply = command->reply(); // TODO: assert that the VM is suspended or suspending; in the second case, wait for the suspension to // complete. // if(IsSuspending()) WaitForSuspend(); IL2CPP_ASSERT(IsSuspended() && "`ThreadGetFrameInfoCommand` can only be invoked with the VM suspended or suspending."); ThreadData *data = _thread_data.ThreadDataFor(command->thread()); data->UpdateFramesCacheIfNeeded(); std::vector::const_iterator it = data->frames_cache().begin(); while (it != data->frames_cache().end()) { const Il2CppStackFrameInfo *frame = *it; ThreadGetFrameInfoCommand::Reply::FrameInfo frame_info; frame_info.flags = 0; frame_info.frame_id = frame->id; frame_info.il_offset = frame->il_offset; frame_info.method = frame->method; get_frame_info_reply->infos().push_back(frame_info); ++it; } return get_frame_info_reply; } const Reply *Agent::Process(const ThreadGetStateCommand *command) { LOG("warning: `ThreadGetStateCommand` not implemented. Returning a `NotImplemented` reply!"); IL2CPP_ASSERT(0); return new InternalErrorNotImplementedReply(command); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/handlers/type.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #pragma once #include "../../il2cpp-api.h" #include "../../blob.h" #include "../../tabledefs.h" #include "../../class-internals.h" #include "../../object-internals.h" #include "../../vm/Class.h" #include "../agent.h" #include "../variant.h" #include "../protocol/commands/type.h" #include "../protocol/commands/internal-error.h" using il2cpp::vm::Class; namespace il2cpp { namespace debugger { const Reply *Agent::Process(const TypeGetInfoCommand *command) { TypeGetInfoCommand::Reply *get_info_reply = command->reply(); Il2CppClass *klass = command->type(); const Il2CppImage *image = il2cpp_class_get_image(klass); const Il2CppType *type = il2cpp_class_get_type(klass); char *fullname = il2cpp_type_get_name(type); get_info_reply->ns(il2cpp_class_get_namespace(klass)); get_info_reply->name(il2cpp_class_get_name(klass)); get_info_reply->fullname(fullname); get_info_reply->assembly(const_cast(il2cpp_image_get_assembly(image))); get_info_reply->module(const_cast(image)); get_info_reply->parent_type(il2cpp_class_get_parent(klass)); if (klass->rank || klass->byval_arg->type == IL2CPP_TYPE_PTR) get_info_reply->underlying_type(il2cpp_class_get_element_class(klass)); // TODO: fix else get_info_reply->underlying_type(0); get_info_reply->type_token(il2cpp_type_get_type(type)); get_info_reply->rank(klass->rank); get_info_reply->flags(il2cpp_class_get_flags(klass)); // get_info_reply->nested_types(); // TODO: fix uint8_t by_val_flags = 0; if (type->type == IL2CPP_TYPE_PTR) by_val_flags |= (1 << 1); if (!type->byref && (((type->type >= IL2CPP_TYPE_BOOLEAN) && (type->type <= IL2CPP_TYPE_R8)) || (type->type == IL2CPP_TYPE_I) || (type->type == IL2CPP_TYPE_U))) by_val_flags |= (1 << 2); if (type->type == IL2CPP_TYPE_VALUETYPE) by_val_flags |= (1 << 3); if (klass->enumtype) by_val_flags |= (1 << 4); if (Class::IsGeneric(klass)) by_val_flags |= (1 << 5); if (Class::IsGeneric(klass) || klass->generic_class) by_val_flags |= (1 << 6); get_info_reply->by_val_flags(by_val_flags); delete[] fullname; LOG("warning: `TypeGetInfoReply` is not properly set up yet in `Agent::Process(const TypeGetInfoCommand *command)`."); return get_info_reply; } const Reply *Agent::Process(const TypeGetSourceFilesCommand *command) { TypeGetSourceFilesCommand::Reply *get_source_files_reply = command->reply(); const Il2CppClass *type = command->type(); const Il2CppDebugTypeInfo *debug_info = il2cpp_debug_get_class_info(type); if (!debug_info) return get_source_files_reply; const Il2CppDebugDocument *document = il2cpp_debug_class_get_document(debug_info); if (!document) return get_source_files_reply; std::string basename = il2cpp_debug_document_get_filename(document); // TODO: we need to iterate through all the methods and register the documents where the method is defined LOG("warning: `TypeGetSourceFiles` still doesn't deal with partial type definitions. Only one source file is always returned."); get_source_files_reply->source_files().insert(basename); return get_source_files_reply; } const Reply *Agent::Process(const TypeGetSourceFiles2Command *command) { TypeGetSourceFiles2Command::Reply *get_source_files_reply = command->reply(); const Il2CppClass *type = command->type(); const Il2CppDebugTypeInfo *debug_info = il2cpp_debug_get_class_info(type); if (!debug_info) return get_source_files_reply; const Il2CppDebugDocument *document = il2cpp_debug_class_get_document(debug_info); if (!document) return get_source_files_reply; std::string basename = il2cpp_debug_document_get_filename(document); std::string path = il2cpp_debug_document_get_directory(document); // TODO: we need to iterate through all the methods and register the documents where the method is defined LOG("warning: `TypeGetSourceFiles2Command` still doesn't deal with partial type definitions. Only one source file is always returned."); IL2CPP_ASSERT((path.size() == 0 || (path.back() == '/' || path.back() == '\\')) && "Il2CppDebugDocument::directory is expected to end with a platform-specific trailing slash."); get_source_files_reply->source_files().insert(path + basename); return get_source_files_reply; } const Reply *Agent::Process(const TypeGetPropertiesCommand *command) { TypeGetPropertiesCommand::Reply *get_properties_reply = command->reply(); void* iterator = NULL; const PropertyInfo *prop = NULL; while (prop = il2cpp_class_get_properties(command->type(), &iterator)) { get_properties_reply->properties.push_back(prop); } return get_properties_reply; } const Reply *Agent::Process(const TypeGetPropertyCAttrsCommand *command) { TypeGetPropertyCAttrsCommand::Reply *get_cattrs_reply = command->reply(); get_cattrs_reply->fake_count(0); LOG("warning: `TypeGetPropertyCAttrsCommand` needs to be implemented properly. For now it only returns 0 attributes!"); return get_cattrs_reply; } const Reply *Agent::Process(const TypeGetFieldCAttrsCommand *command) { TypeGetFieldCAttrsCommand::Reply *get_cattrs_reply = command->reply(); get_cattrs_reply->fake_count(0); LOG("warning: `TypeGetFieldCAttrsCommand` needs to be implemented properly. For now it only returns 0 attributes!"); return get_cattrs_reply; } const Reply *Agent::Process(const TypeIsAssignableFromCommand *command) { LOG("warning: `TypeIsAssignableFromCommand` not implemented. Returning a `NotImplemented` reply!"); IL2CPP_ASSERT(0); return new InternalErrorNotImplementedReply(command); } const Reply *Agent::Process(const TypeGetCAttrsCommand *command) { TypeGetCAttrsCommand::Reply *get_cattrs_reply = command->reply(); get_cattrs_reply->fake_count(0); LOG("warning: `TypeGetCAttrsCommand` needs to be implemented properly. For now it only returns 0 attributes!"); return get_cattrs_reply; } const Reply *Agent::Process(const TypeGetValuesCommand *command) { TypeGetValuesCommand::Reply *get_values_reply = command->reply(); std::vector::const_iterator it = command->fields().begin(); while (it != command->fields().end()) { FieldInfo *field = *it; if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) { LOG("error: TypeGetValuesCommand is expected to receive only static field IDs"); get_values_reply->error_code(kErrorCodeInvalidFieldId); break; } /*if (il2cpp_class_field_is_special_static (field)) { LOG("error: TypeGetValuesCommand is expected to receive only static field IDs"); get_values_reply->error_code(kErrorCodeInvalidFieldId); break; }*/ bool found = false; for (Il2CppClass *t = command->type(); t != 0; t = t->parent) { if (t == field->parent) { found = true; break; } } if (!found) { LOG("error: TypeGetValuesCommand is expected to receive valid field IDs"); get_values_reply->error_code(kErrorCodeInvalidFieldId); break; } get_values_reply->values().push_back( Variant( field->type, ((char*)field->parent->static_fields) + field->offset)); ++it; } return get_values_reply; } const Reply *Agent::Process(const TypeGetObjectCommand *command) { TypeGetObjectCommand::Reply *get_object_reply = command->reply(); get_object_reply->object( il2cpp_type_get_object(command->type()->byval_arg)); return get_object_reply; } const Reply *Agent::Process(const TypeGetFieldsCommand *command) { TypeGetFieldsCommand::Reply *get_fields_reply = command->reply(); void* iterator = NULL; FieldInfo *field = NULL; while (field = il2cpp_class_get_fields(command->type(), &iterator)) { get_fields_reply->fields.push_back(field); } return get_fields_reply; } const Reply *Agent::Process(const TypeSetValuesCommand *command) { LOG("warning: `TypeSetValuesCommand` not implemented. Returning a `NotImplemented` reply!"); IL2CPP_ASSERT(0); return new InternalErrorNotImplementedReply(command); } const Reply *Agent::Process(const TypeGetMethodsCommand *command) { TypeGetMethodsCommand::Reply *get_methods_reply = command->reply(); void* iterator = NULL; const MethodInfo *method = NULL; while (method = il2cpp_class_get_methods(command->type(), &iterator)) { get_methods_reply->methods().push_back(method); } return get_methods_reply; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/handlers/vm.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #pragma once #include "../../il2cpp-api.h" #include "../../metadata.h" #include "../agent.h" #include "../protocol/commands/vm.h" #include "../protocol/commands/internal-error.h" namespace il2cpp { namespace debugger { const Reply *Agent::Process(const VmVersionCommand *command) { VmVersionCommand::Reply *vm_version_reply = command->reply(); vm_version_reply->name("il2cpp 0.0.1"); vm_version_reply->major_version(_protocol.major_version()); vm_version_reply->minor_version(_protocol.minor_version()); return vm_version_reply; } const Reply *Agent::Process(const VmSetProtocolVersionCommand *command) { _protocol.major_version(command->major_version()); _protocol.minor_version(command->minor_version()); LOG("Protocol version " << Protocol::MajorVersion << "." << Protocol::MinorVersion << ", client protocol version " << _protocol.major_version() << "." << _protocol.minor_version() << "."); return command->reply(); } const Reply *Agent::Process(const VmResumeCommand *command) { VmResumeCommand::Reply *empty_reply = command->reply(); if (!IsSuspended()) empty_reply->error_code(kErrorCodeNotSuspended); else RequestResume(); return empty_reply; } const Reply *Agent::Process(const VmAllThreadsCommand *command) { VmAllThreadsCommand::Reply *all_threads_reply = command->reply(); size_t size = 0; Il2CppThread **threads = CALL_IL2CPP_API(il2cpp_thread_get_all_attached_threads) (&size); for (size_t i = 0; i < size; ++i) { Il2CppThread *thread = threads[i]; if (!CALL_IL2CPP_API(il2cpp_is_vm_thread)(thread)) continue; if (thread == _managed_debugger_thread) continue; all_threads_reply->threads().push_back(thread); } return all_threads_reply; } const Reply *Agent::Process(const VmDisposeCommand *command) { VmDisposeCommand::Reply *empty_reply = command->reply(); LOG("warning: probably we should use a global lock here to avoid contention on event_req_list."); InvalidateBreakpointData(); _event_req_list.ClearAllRequests(); while (IsSuspended()) RequestResume(); return empty_reply; } const Reply *Agent::Process(const VmSuspendCommand *command) { VmSuspendCommand::Reply *empty_reply = command->reply(); if (!IsSuspended()) { RequestSuspend(); WaitForSuspend(); } return empty_reply; } const Reply *Agent::Process(const VmAbortInvokeCommand *command) { LOG("warning: `VmAbortInvokeCommand` not implemented. Returning a `NotImplemented` reply!"); IL2CPP_ASSERT(0); return new InternalErrorNotImplementedReply(command); } const Reply *Agent::Process(const VmExitCommand *command) { LOG("warning: `VmExitCommand` not implemented. Returning a `NotImplemented` reply!"); IL2CPP_ASSERT(0); return new InternalErrorNotImplementedReply(command); } const Reply *Agent::Process(const VmInvokeMethodCommand *command) { VmInvokeMethodCommand::Reply *reply = command->reply(); if (!IsSuspended()) { reply->error_code(kErrorCodeNotSuspended); return reply; } Il2CppThread *vm_thread = command->vm_thread(); int32_t flags = command->flags(); const MethodInfo* method = command->method(); ThreadData* vm_thread_data = _thread_data.ThreadDataFor(vm_thread); vm_thread_data->SetMethodToInvoke(method); vm_thread_data->WaitForMethodToBeInvoked(); reply->method_did_not_throw_exception(true); const Il2CppType* return_type = CALL_IL2CPP_API(il2cpp_method_get_return_type)(method); reply->return_type(return_type->type); if (return_type->type == IL2CPP_TYPE_VOID) { reply->skip_return_value = true; } else { int32_t actual_return = *(int32_t*)(CALL_IL2CPP_API(il2cpp_object_unbox)(vm_thread_data->GetReturnValueOfMethodToInvoke())); reply->return_value(actual_return); } return reply; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/id-bank.h ================================================ #pragma once #include "common.h" struct Il2CppClass; struct Il2CppObject; struct Il2CppDomain; struct Il2CppAssembly; struct Il2CppImage; namespace il2cpp { namespace debugger { enum IdType { // Note: kIdTypeObject is used only internally, it should never // be sent to the client 'cause it is invalid. kIdTypeObject = -1, kIdTypeAssembly = 0, kIdTypeModule = 1, kIdTypeType = 2, kIdTypeMethod = 3, kIdTypeField = 4, kIdTypeDomain = 5, kIdTypeProperty = 6, kIdTypeCount }; struct Id { IdType type; int32_t id; }; Id AssemblyId(const Il2CppAssembly *assembly); Id ModuleId(const Il2CppImage *image); Id TypeId(const Il2CppClass *type); Id DomainId(const Il2CppDomain *domain); Id ObjectId(const Il2CppObject *object); Id MethodId(const MethodInfo *method); Id FieldId(const FieldInfo *field); Id PropertyId(const PropertyInfo *prop); Il2CppClass *TypeFromId(Id &id); Il2CppClass *TypeFromId(int32_t id); Il2CppObject *ObjectFromId(Id &id); Il2CppDomain *DomainFromId(Id &id); Il2CppAssembly *AssemblyFromId(Id &id); MethodInfo *MethodFromId(Id &id); FieldInfo *FieldFromId(Id &id); PropertyInfo *PropertyFromId(Id &id); Il2CppImage *ModuleFromId(Id &id); } /* namespace debugger */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/debugger/id-brank.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "id-bank.h" #include #include "../os/Atomic.h" using namespace il2cpp::debugger; // Mono stores the ID map per domain. We don't support domains, so we can store it globally static std::map > gTypesMap; static int32_t get_or_create_id_for(IdType type, const void *ptr) { if (ptr == 0) return 0; // Note: we don't use GCHandles here as long as `ptr` is always supposed to point to // memory statically allocated or managed directly by il2cpp (like Il2CppClass*, Il2CppType*, etc). if (gTypesMap.find(type) == gTypesMap.end()) { gTypesMap[type] = std::map(); } const uintptr_t value_ptr = (uintptr_t)ptr; std::map &type_map = gTypesMap[type]; std::map::iterator it = type_map.find(value_ptr); if (it == type_map.end()) { type_map[value_ptr] = type_map.size() + 1; } return type_map[value_ptr]; } static void *get_ptr_from_id(IdType type, int32_t id) { if (id == 0) return 0; std::map >::const_iterator itt = gTypesMap.find(type); if (itt == gTypesMap.end()) return 0; const std::map &type_map = itt->second; std::map::const_iterator it = type_map.begin(); // Slooooooow while (it != type_map.end()) { if (it->second == id) return (void*)it->first; ++it; } return 0; } typedef uintptr_t GCHandle; struct ObjectRef { uint64_t id; GCHandle gc_handle; // This will be a week ref GC handle to the Object }; static int32_t obj_reference_id = 0; static std::map gIdToRefMap; static std::map gObjToRefMap; // TODO: these il2cpp_gc_* functions need to be replaced with the right implementations later static GCHandle il2cpp_gc_handle_new_weakref(const Il2CppObject *object, bool) { return (uintptr_t)object; } static bool il2cpp_gc_weak_ref_is_alive(GCHandle gc_handle) { return true; } static int32_t get_or_create_object_id(const Il2CppObject *object) { if (object == 0) return 0; const uintptr_t uid = (uintptr_t)(~((uintptr_t)object)); std::map::iterator it = gObjToRefMap.find(uid); if (it != gObjToRefMap.end() && il2cpp_gc_weak_ref_is_alive(it->second.gc_handle)) return it->second.id; ObjectRef ref; ref.id = il2cpp::os::Atomic::Increment(&obj_reference_id); ref.gc_handle = il2cpp_gc_handle_new_weakref(object, false); gObjToRefMap[uid] = ref; gIdToRefMap[ref.id] = ref; return ref.id; } static Il2CppObject *get_object_from_id(int32_t id) { if (id == 0) return 0; std::map::iterator it = gIdToRefMap.find(id); if (it == gIdToRefMap.end()) { LOG("Invalid object ID"); return 0; } return (Il2CppObject*)it->second.gc_handle; } namespace il2cpp { namespace debugger { Id TypeId(const Il2CppClass *type) { Id id; id.type = kIdTypeType; id.id = get_or_create_id_for(id.type, type); return id; } Id AssemblyId(const Il2CppAssembly *assembly) { Id id; id.type = kIdTypeAssembly; id.id = get_or_create_id_for(id.type, assembly); return id; } Id ModuleId(const Il2CppImage *image) { Id id; id.type = kIdTypeModule; id.id = get_or_create_id_for(id.type, image); return id; } Id DomainId(const Il2CppDomain *domain) { Id id; id.type = kIdTypeDomain; id.id = get_or_create_id_for(id.type, domain); return id; } Id ObjectId(const Il2CppObject *object) { Id id; id.type = kIdTypeObject; id.id = get_or_create_object_id(object); return id; } Id MethodId(const MethodInfo *method) { Id id; id.type = kIdTypeMethod; id.id = get_or_create_id_for(id.type, method); return id; } Id FieldId(const FieldInfo *field) { Id id; id.type = kIdTypeField; id.id = get_or_create_id_for(id.type, field); return id; } Id PropertyId(const PropertyInfo *prop) { Id id; id.type = kIdTypeProperty; id.id = get_or_create_id_for(id.type, prop); return id; } Il2CppClass *TypeFromId(int32_t id) { return (Il2CppClass*)get_ptr_from_id(kIdTypeType, id); } Il2CppClass *TypeFromId(Id &id) { IL2CPP_ASSERT(id.type == kIdTypeType && "TypeFromId can only be used on kIdTypeType ids."); return TypeFromId(id.id); } Il2CppObject *ObjectFromId(Id &id) { IL2CPP_ASSERT(id.type == kIdTypeObject && "ObjectFromId can only be used on kIdTypeObject ids."); return get_object_from_id(id.id); } Il2CppDomain *DomainFromId(Id &id) { IL2CPP_ASSERT(id.type == kIdTypeDomain && "DomainFromId can only be used on kIdTypeDomain ids."); return (Il2CppDomain*)get_ptr_from_id(id.type, id.id); } Il2CppAssembly *AssemblyFromId(Id &id) { IL2CPP_ASSERT(id.type == kIdTypeAssembly && "AssemblyFromId can only be used on kIdTypeAssembly ids."); return (Il2CppAssembly*)get_ptr_from_id(id.type, id.id); } Il2CppImage *ModuleFromId(Id &id) { IL2CPP_ASSERT(id.type == kIdTypeModule && "ModuleFromId can only be used on kIdTypeModule ids."); return (Il2CppImage*)get_ptr_from_id(id.type, id.id); } MethodInfo *MethodFromId(Id &id) { IL2CPP_ASSERT(id.type == kIdTypeMethod && "MethodFromId can only be used on kIdTypeMethod ids."); return (MethodInfo*)get_ptr_from_id(id.type, id.id); } FieldInfo *FieldFromId(Id &id) { IL2CPP_ASSERT(id.type == kIdTypeField && "FieldFromId can only be used on kIdTypeField ids."); return (FieldInfo*)get_ptr_from_id(id.type, id.id); } PropertyInfo *PropertyFromId(Id &id) { IL2CPP_ASSERT(id.type == kIdTypeProperty && "PropertyFromId can only be used on kIdTypeProperty ids."); return (PropertyInfo*)get_ptr_from_id(id.type, id.id); } } /* namespace debugger */ } /* namespace il2cpp */ #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/il2cpp-api-test-forwarder.cpp ================================================ #if IL2CPP_UNIT_TESTS_ENABLED #include "il2cpp-api-test-forwarder.h" #include "agent.h" using namespace il2cpp::debugger; const Il2CppApiTestForwarder Il2CppApiTestForwarderAutoClear::zero_forwarder = {}; Il2CppApiTestForwarderAutoClear::Il2CppApiTestForwarderAutoClear() { ClearAllForwardingMethods(); } Il2CppApiTestForwarderAutoClear::~Il2CppApiTestForwarderAutoClear() { ClearAllForwardingMethods(); } void Il2CppApiTestForwarderAutoClear::ClearAllForwardingMethods() { Agent::instance().TestForwarder = zero_forwarder; } #endif // IL2CPP_UNIT_TESTS_ENABLED ================================================ FILE: unity_decoder/libil2cpp/debugger/il2cpp-api-test-forwarder.h ================================================ #pragma once #include namespace il2cpp { namespace debugger { #if IL2CPP_UNIT_TESTS_ENABLED struct Il2CppApiTestForwarder { Il2CppDomain* (*il2cpp_domain_get)(); Il2CppThread* (*il2cpp_thread_current)(); Il2CppThread** (*il2cpp_thread_get_all_attached_threads)(size_t *size); bool (*il2cpp_is_vm_thread)(Il2CppThread *thread); Il2CppObject* (*il2cpp_runtime_invoke)(MethodInfo *method, void *obj, void **params, Il2CppObject **exc); const Il2CppType* (*il2cpp_method_get_return_type)(MethodInfo* method); void* (*il2cpp_object_unbox)(Il2CppObject* obj); }; class Il2CppApiTestForwarderAutoClear { public: Il2CppApiTestForwarderAutoClear(); ~Il2CppApiTestForwarderAutoClear(); private: void ClearAllForwardingMethods(); static const Il2CppApiTestForwarder zero_forwarder; }; #define CALL_IL2CPP_API(x) Agent::instance().TestForwarder.x #define ENABLE_IL2CPP_API_METHOD_FORWARDING Il2CppApiTestForwarderAutoClear __define_ENABLE_IL2CPP_API_METHOD_FORWARDING_before_forwarding_any_methods_consider_using_Il2CppApiForwardingTestFixture; #define FORWARD_IL2CPP_API_METHOD_UNSAFE(method, target) Agent::instance().TestForwarder.method = target; #define FORWARD_IL2CPP_API_METHOD(method, target) \ __define_ENABLE_IL2CPP_API_METHOD_FORWARDING_before_forwarding_any_methods_consider_using_Il2CppApiForwardingTestFixture;\ FORWARD_IL2CPP_API_METHOD_UNSAFE(method, target) #else #define CALL_IL2CPP_API(x) x #define ENABLE_IL2CPP_API_METHOD_FORWARDING #define FORWARD_IL2CPP_API_METHOD_UNSAFE(method, target) #define FORWARD_IL2CPP_API_METHOD(method, target) #endif // IL2CPP_UNIT_TESTS_ENABLED } /* namspace debugger */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/debugger/meta.h ================================================ #pragma once #include #include #include #include "common.h" #include "data-buffer.h" namespace il2cpp { namespace debugger { template struct Property; #define DEFINE_SIMPLE_PROP_STD(Type, Writer, Reader) \ template<> \ struct Property \ { \ inline const Type &operator()() const { return _storage; } \ inline void operator()(const Type &v) { _storage = v; } \ inline void WriteTo(Buffer &out) const { out. Writer (_storage); } \ inline Type ReadFrom(Buffer &in) { return _storage = in. Reader (); } \ inline operator Type() { return _storage; } \ private: \ Type _storage; \ } #define DEFINE_SIMPLE_PROP_INIT(Type, Writer, Reader) \ template<> \ struct Property \ { \ Property() : _storage( 0 ) {} \ inline Type operator()() const { return _storage; } \ inline void operator()(Type v) { _storage = v; } \ inline void WriteTo(Buffer &out) const { out. Writer (_storage); } \ inline void ReadFrom(Buffer &in) { _storage = in. Reader (); } \ inline operator Type() { return _storage; } \ private: \ Type _storage; \ } #define DEFINE_LIST_PROP(Type, Writer, Reader) \ template<> \ struct Property > \ { \ Property() { } \ inline std::vector &operator()() { return _storage; } \ inline const std::vector &operator()() const { return _storage; } \ inline operator std::vector &() { return _storage; } \ inline void WriteTo(Buffer &out) const { \ out.WriteInt(_storage.size()); \ std::vector::const_iterator it = _storage.begin(); \ while(it != _storage.end()) { \ out. Writer (*it); \ ++it; \ } \ } \ inline void ReadFrom(Buffer &in) { \ const int32_t len = in.ReadInt(); \ _storage.resize(len); \ for(int32_t i = 0; i < len; ++i) { \ _storage[i] = in. Reader (); \ } \ } \ private: \ std::vector _storage; \ }; #define DEFINE_SET_PROP(Type, Writer, Reader) \ template<> \ struct Property > \ { \ Property() { } \ inline std::set &operator()() { return _storage; } \ inline operator std::set &() { return _storage; } \ inline void WriteTo(Buffer &out) const { \ out.WriteInt(_storage.size()); \ std::set::const_iterator it = _storage.begin(); \ while(it != _storage.end()) { \ out. Writer (*it); \ ++it; \ } \ } \ inline void ReadFrom(Buffer &in) { \ const int32_t len = in.ReadInt(); \ for(int32_t i = 0; i < len; ++i) { \ _storage.insert(in. Reader ()); \ } \ } \ private: \ std::set _storage; \ }; DEFINE_SIMPLE_PROP_STD(std::string, WriteString, ReadString); DEFINE_SIMPLE_PROP_INIT(bool, WriteBool, ReadBool); DEFINE_SIMPLE_PROP_INIT(int32_t, WriteInt, ReadInt); DEFINE_SIMPLE_PROP_INIT(uint8_t, WriteByte, ReadByte); DEFINE_SIMPLE_PROP_INIT(uint64_t, WriteLong, ReadLong); DEFINE_SIMPLE_PROP_INIT(Il2CppAssembly*, WriteAssemblyId, ReadAssembly); DEFINE_SIMPLE_PROP_INIT(Il2CppClass*, WriteTypeId, ReadType); DEFINE_SIMPLE_PROP_INIT(const MethodInfo*, WriteMethodId, ReadMethod); DEFINE_SIMPLE_PROP_INIT(Il2CppImage*, WriteModuleId, ReadModule); DEFINE_SIMPLE_PROP_INIT(Il2CppDomain*, WriteDomainId, ReadDomain); DEFINE_SIMPLE_PROP_INIT(Il2CppObject*, WriteObjectId, ReadObject); DEFINE_SIMPLE_PROP_INIT(Il2CppThread*, WriteThreadId, ReadThread); DEFINE_SIMPLE_PROP_INIT(FieldInfo*, WriteFieldId, ReadField); DEFINE_SIMPLE_PROP_INIT(const Il2CppImage*, WriteModuleId, ReadModule); DEFINE_LIST_PROP(std::string, WriteString, ReadString); DEFINE_LIST_PROP(bool, WriteBool, ReadBool); DEFINE_LIST_PROP(int32_t, WriteInt, ReadInt); DEFINE_LIST_PROP(uint8_t, WriteByte, ReadByte); DEFINE_LIST_PROP(uint64_t, WriteLong, ReadLong); DEFINE_LIST_PROP(Il2CppAssembly*, WriteAssemblyId, ReadAssembly); DEFINE_LIST_PROP(Il2CppClass*, WriteTypeId, ReadType); DEFINE_LIST_PROP(const MethodInfo*, WriteMethodId, ReadMethod); DEFINE_LIST_PROP(Il2CppImage*, WriteModuleId, ReadModule); DEFINE_LIST_PROP(Il2CppDomain*, WriteDomainId, ReadDomain); DEFINE_LIST_PROP(Il2CppObject*, WriteObjectId, ReadObject); DEFINE_LIST_PROP(Il2CppThread*, WriteThreadId, ReadThread); DEFINE_LIST_PROP(FieldInfo*, WriteFieldId, ReadField); DEFINE_SET_PROP(std::string, WriteString, ReadString); DEFINE_SET_PROP(bool, WriteBool, ReadBool); DEFINE_SET_PROP(int32_t, WriteInt, ReadInt); DEFINE_SET_PROP(uint8_t, WriteByte, ReadByte); DEFINE_SET_PROP(uint64_t, WriteLong, ReadLong); DEFINE_SET_PROP(Il2CppAssembly*, WriteAssemblyId, ReadAssembly); DEFINE_SET_PROP(Il2CppClass*, WriteTypeId, ReadType); DEFINE_SET_PROP(const MethodInfo*, WriteMethodId, ReadMethod); DEFINE_SET_PROP(Il2CppImage*, WriteModuleId, ReadModule); DEFINE_SET_PROP(Il2CppDomain*, WriteDomainId, ReadDomain); DEFINE_SET_PROP(Il2CppObject*, WriteObjectId, ReadObject); DEFINE_SET_PROP(Il2CppThread*, WriteThreadId, ReadThread); DEFINE_SET_PROP(FieldInfo*, WriteFieldId, ReadField); } /* namespace debugger */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/app-domain.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "app-domain.h" using namespace il2cpp::debugger; #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/app-domain.h ================================================ #pragma once #include "../../common.h" #include "../protocol-utils.h" namespace il2cpp { namespace debugger { struct AppDomainGetRootDomainCommand : public CustomCommand { struct Reply : public CustomReply { Property domain; void WriteContentTo(Buffer &out) const { domain.WriteTo(out); } }; CUSTOM_COMMAND(AppDomain, GetRootDomain); }; struct AppDomainGetCorlibCommand : public CustomCommand { struct Reply : public CustomReply { Property assembly; void WriteContentTo(Buffer &out) const { assembly.WriteTo(out); } }; CUSTOM_COMMAND(AppDomain, GetCorlib); Property domain; void ReadProperties(Buffer &in) { domain.ReadFrom(in); } }; struct AppDomainGetFriendlyNameCommand : public CustomCommand { struct Reply : public CustomReply { Property friendly_name; void WriteContentTo(Buffer &out) const { friendly_name.WriteTo(out); } }; CUSTOM_COMMAND(AppDomain, GetFriendlyName); Property domain; void ReadProperties(Buffer &in) { domain.ReadFrom(in); } }; struct AppDomainCreateStringCommand : public CustomCommand { struct Reply : public CustomReply { Property object; void WriteContentTo(Buffer &out) const { object.WriteTo(out); } }; CUSTOM_COMMAND(AppDomain, CreateString); Property domain; Property string; void ReadProperties(Buffer &in) { domain.ReadFrom(in); string.ReadFrom(in); } }; struct AppDomainGetEntryAssemblyCommand : public CustomCommand { struct Reply : public CustomReply { void WriteContentTo(Buffer &out) const { IL2CPP_ASSERT(0 && "Not implemented"); } }; CUSTOM_COMMAND(AppDomain, GetEntryAssembly); Property domain; void ReadProperties(Buffer &in) { domain.ReadFrom(in); } }; struct AppDomainCreateBoxedValueCommand : public CustomCommand { struct Reply : public CustomReply { void WriteContentTo(Buffer &out) const { IL2CPP_ASSERT(0 && "Not implemented"); } }; CUSTOM_COMMAND(AppDomain, CreateBoxedValue); Property domain; void ReadProperties(Buffer &in) { domain.ReadFrom(in); } }; struct AppDomainGetAssembliesCommand : public CustomCommand { struct Reply : public CustomReply { Property number_of_assemblies; Property > assemblies; void WriteContentTo(Buffer &out) const { number_of_assemblies.WriteTo(out); assemblies.WriteTo(out); } }; CUSTOM_COMMAND(AppDomain, GetAssemblies); Property domain; void ReadProperties(Buffer &in) { domain.ReadFrom(in); } }; } } ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/array-ref.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "array-ref.h" using namespace il2cpp::debugger; void ArrayRefGetValuesCommand::Reply::WriteContentTo(Buffer &out) const { for (std::vector::const_iterator it = _values.begin(); it != _values.end(); ++it) { out.WriteVariant(*it); } } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/array-ref.h ================================================ #pragma once #include "../../common.h" #include "../../variant.h" #include "../protocol-utils.h" namespace il2cpp { namespace debugger { struct ArrayRefGetValuesCommand : public CustomCommand { struct Reply : public CustomReply { inline std::vector &values() { return _values; } void WriteContentTo(Buffer &out) const; private: std::vector _values; }; CUSTOM_COMMAND(ArrayRef, GetValues); Property object; Property index; Property length; void ReadProperties(Buffer &in) { object.ReadFrom(in); index.ReadFrom(in); length.ReadFrom(in); } }; struct ArrayRefGetLengthCommand : public CustomCommand { struct Reply : public CustomReply { Property rank; Property > lengths; Property > lower_bounds; void WriteContentTo(Buffer &out) const { rank.WriteTo(out); for (size_t i = 0; i < lengths().size(); ++i) { out.WriteInt(lengths().at(i)); out.WriteInt(lower_bounds().at(i)); } } }; CUSTOM_COMMAND(ArrayRef, GetLength); Property object; void ReadProperties(Buffer &in) { object.ReadFrom(in); } }; struct ArrayRefSetValuesCommand : public CustomCommand { struct Reply : public CustomReply { void WriteContentTo(Buffer &out) const { IL2CPP_ASSERT(0 && "Not implemented"); } }; CUSTOM_COMMAND(ArrayRef, SetValues); }; } } ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/assembly.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "assembly.h" using namespace il2cpp::debugger; #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/assembly.h ================================================ #pragma once #include "../../common.h" #include "../protocol-utils.h" namespace il2cpp { namespace debugger { struct AssemblyGetTypeCommand : public CustomCommand { struct Reply : public CustomReply { Property type; void WriteContentTo(Buffer &out) const { type.WriteTo(out); } }; CUSTOM_COMMAND(Assembly, GetType); Property assembly; Property name; Property ignore_case; void ReadProperties(Buffer &in) { assembly.ReadFrom(in); name.ReadFrom(in); ignore_case.ReadFrom(in); } }; struct AssemblyGetObjectCommand : public CustomCommand { struct Reply : public CustomReply { void WriteContentTo(Buffer &out) const { IL2CPP_ASSERT(0 && "Not implemented"); } }; CUSTOM_COMMAND(Assembly, GetObject); }; struct AssemblyGetEntryPointCommand : public CustomCommand { struct Reply : public CustomReply { void WriteContentTo(Buffer &out) const { IL2CPP_ASSERT(0 && "Not implemented"); } }; CUSTOM_COMMAND(Assembly, GetEntryPoint); }; struct AssemblyGetManifestModuleCommand : public CustomCommand { struct Reply : public CustomReply { Property module; void WriteContentTo(Buffer &out) const { module.WriteTo(out); } }; CUSTOM_COMMAND(Assembly, GetManifestModule); Property assembly; void ReadProperties(Buffer &in) { assembly.ReadFrom(in); } }; struct AssemblyGetNameCommand : public CustomCommand { struct Reply : public CustomReply { Property name; void WriteContentTo(Buffer &out) const { name.WriteTo(out); } }; CUSTOM_COMMAND(Assembly, GetName); Property assembly; void ReadProperties(Buffer &in) { assembly.ReadFrom(in); } }; struct AssemblyGetLocationCommand : public CustomCommand { struct Reply : public CustomReply { Property location; void WriteContentTo(Buffer &out) const { location.WriteTo(out); } }; CUSTOM_COMMAND(Assembly, GetLocation); Property assembly; void ReadProperties(Buffer &in) { assembly.ReadFrom(in); } }; } } ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/event-request.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "event-request.h" using namespace il2cpp::debugger; void EventRequestSetCommand::ReadProperties(Buffer &in) { _kind = in.ReadEnum(); _suspend_policy = in.ReadEnum(); const int32_t nmodifiers = in.ReadByte(); for (int i = 0; i < nmodifiers; ++i) { Modifier *modifier = new Modifier(); modifier->kind = in.ReadEnum(); switch (modifier->kind) { case kModifierKindCount: modifier->data.count = in.ReadInt(); break; case kModifierKindLocationOnly: IL2CPP_ASSERT(method() == 0 && "Duplicated kModifierKindLocationOnly modifier!"); method.ReadFrom(in); location.ReadFrom(in); break; case kModifierKindStep: IL2CPP_ASSERT(thread() == 0 && "Duplicated kModifierKindStep modifier!"); thread.ReadFrom(in); size.ReadFrom(in); depth.ReadFrom(in); break; case kModifierKindThreadOnly: IL2CPP_ASSERT(modifier->data.thread == 0 && "Duplicated kModifierKindThreadOnly modifier!"); modifier->data.thread = in.ReadThread(); break; case kModifierKindExceptionOnly: modifier->data.exc_class = in.ReadType(); modifier->caught = in.ReadBool(); modifier->uncaught = in.ReadBool(); // DEBUG(1, fprintf (log_file, "[dbg] \tEXCEPTION_ONLY filter (%s%s%s).\n", exc_class ? exc_class->name : "all", req->modifiers [i].caught ? ", caught" : "", req->modifiers [i].uncaught ? ", uncaught" : "")); if (modifier->data.exc_class != 0) { /* if (!mono_class_is_assignable_from (mono_defaults.exception_class, exc_class)) { g_free (req); return ERR_INVALID_ARGUMENT; }*/ } break; case kModifierKindAssemblyOnly: { const int32_t count = in.ReadInt(); modifier->data.assemblies = new Il2CppAssembly*[count]; for (int32_t i = 0; i < count; ++i) modifier->data.assemblies[i] = in.ReadAssembly(); } break; default: LOG("Not implemented EventRequestSetCommand+??(" << modifier->kind << ")"); exit(1); } _modifiers.push_back(modifier); } } EventRequestSetCommand::~EventRequestSetCommand() { std::vector::iterator it = _modifiers.begin(); while (it != _modifiers.end()) { delete *it; ++it; } _modifiers.clear(); } void EventRequestClearCommand::ReadProperties(Buffer &in) { event_kind.ReadFrom(in); request_id.ReadFrom(in); } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/event-request.h ================================================ #pragma once #include #include "../../common.h" #include "../protocol-utils.h" namespace il2cpp { namespace debugger { struct EventRequestSetCommand : public CustomCommand { struct Reply : public CustomReply { Property request_id; void WriteContentTo(Buffer &out) const { request_id.WriteTo(out); } }; CUSTOM_COMMAND(EventRequest, Set); ~EventRequestSetCommand(); Property method; Property location; Property thread; Property size; Property depth; inline EventKind kind() const { return _kind; } inline SuspendPolicy suspend_policy() const { return _suspend_policy; } inline const std::vector &modifiers() const { return _modifiers; } void ReadProperties(Buffer & in); private: EventKind _kind; SuspendPolicy _suspend_policy; std::vector _modifiers; }; struct EventRequestClearCommand : public CustomCommand { CUSTOM_COMMAND_EMPTY_REPLY(EventRequest, Clear); Property event_kind; Property request_id; void ReadProperties(Buffer & in); }; struct EventRequestClearAllBreakpointsCommand : public CustomCommand { CUSTOM_COMMAND_EMPTY_REPLY(EventRequest, ClearAllBreakpoints); }; } } ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/event.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "event.h" #include "../../data-buffer.h" #include "../../../os/Atomic.h" using namespace il2cpp::debugger; static int32_t event_packed_id = 0; EventCompositeCommand::EventCompositeCommand() : Command(kCommandSetEvent, kCommandSetEventComposite, (int32_t)il2cpp::os::Atomic::Increment(&event_packed_id)), _suspend_policy(kSuspendPolicyNone) { } EventCompositeCommand::EventCompositeCommand(int32_t /*ignored*/) : Command(kCommandSetEvent, kCommandSetEventComposite, (int32_t)il2cpp::os::Atomic::Increment(&event_packed_id)), _suspend_policy(kSuspendPolicyNone) { } void EventCompositeCommand::AddEvent(int32_t req_id, const Event *evt) { _events[req_id] = evt; } void EventCompositeCommand::WriteContentTo(Buffer &out) const { const size_t count = _events.size(); std::map::const_iterator it = _events.begin(); // VM_START event suspend policy might be configured by the user, thus allowing // the debugger to suspend as soon as the VM start. out.WriteByte(_suspend_policy); out.WriteInt(count); while (it != _events.end()) { it->second->WriteTo(out, it->first); ++it; } } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/event.h ================================================ #pragma once #include "../../common.h" #include "../../meta.h" #include "../protocol.h" namespace il2cpp { namespace debugger { class EventCompositeCommand : public Command { public: EventCompositeCommand(); explicit EventCompositeCommand(int32_t /*ignored*/); inline SuspendPolicy suspend_policy() const { return _suspend_policy; } inline void suspend_policy(SuspendPolicy v) { _suspend_policy = v; } void AddEvent(int32_t req_id, const Event *evt); protected: void WriteContentTo(Buffer &out) const; private: SuspendPolicy _suspend_policy; std::map _events; PROTOCOL_COMMAND(Event, Composite); DISALLOW_COPY(EventCompositeCommand); }; } } ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/internal-error.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "internal-error.h" using namespace il2cpp::debugger; InternalErrorNotImplementedCommand::InternalErrorNotImplementedCommand(int32_t id) : Command(kCommandSetInternalError, kCommandSetInternalErrorNotImplemented, id) { } InternalErrorNotImplementedReply::InternalErrorNotImplementedReply(const Command *command) : Reply(command) { _error_code = kErrorCodeNotImplemented; } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/internal-error.h ================================================ #pragma once #include "../../common.h" #include "../../meta.h" #include "../protocol.h" namespace il2cpp { namespace debugger { struct InternalErrorNotImplementedCommand : public Command { public: explicit InternalErrorNotImplementedCommand(int32_t id); PROTOCOL_COMMAND(InternalError, NotImplemented); DISALLOW_COPY(InternalErrorNotImplementedCommand); }; struct InternalErrorNotImplementedReply : public Reply { public: explicit InternalErrorNotImplementedReply(const Command *command); DISALLOW_COPY(InternalErrorNotImplementedReply); }; } } ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/method.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "method.h" using namespace il2cpp::debugger; void MethodGetDebugInfoCommand::Reply::WriteContentTo(Buffer &out) const { code_size.WriteTo(out); file_name.WriteTo(out); out.WriteInt(_offsets.size()); std::vector >::const_iterator it = _offsets.begin(); while (it != _offsets.end()) { out.WriteInt((*it).first); out.WriteInt((*it).second); ++it; } } void MethodGetParamInfoCommand::Reply::WriteContentTo(Buffer &out) const { call_convention.WriteTo(out); out.WriteInt(_params.size()); generic_param_count.WriteTo(out); return_type.WriteTo(out); std::vector::const_iterator it = _params.begin(); while (it != _params.end()) { out.WriteTypeId((*it).type); ++it; } it = _params.begin(); while (it != _params.end()) { out.WriteString((*it).name); ++it; } } void MethodGetLocalsInfoCommand::Reply::WriteContentTo(Buffer &out) const { out.WriteInt(_locals.size()); std::vector::const_iterator it; for (it = _locals.begin(); it != _locals.end(); ++it) { out.WriteTypeId((Il2CppClass*)(*it).type); } for (it = _locals.begin(); it != _locals.end(); ++it) { out.WriteString((*it).name); } for (it = _locals.begin(); it != _locals.end(); ++it) { out.WriteInt((*it).begin_scope); out.WriteInt((*it).end_scope); } } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/method.h ================================================ #pragma once #include #include #include "../../common.h" #include "../protocol-utils.h" namespace il2cpp { namespace debugger { struct MethodGetDeclaringTypeCommand : public CustomCommand { struct Reply : public CustomReply { Property type; void WriteContentTo(Buffer &out) const { type.WriteTo(out); } }; CUSTOM_COMMAND(Method, GetDeclaringType); Property method; void ReadProperties(Buffer &in) { method.ReadFrom(in); } }; struct MethodGetDebugInfoCommand : public CustomCommand { struct Reply : public CustomReply { Property code_size; Property file_name; inline std::vector > &offsets() { return _offsets; } void WriteContentTo(Buffer &out) const; private: std::vector > _offsets; }; CUSTOM_COMMAND(Method, GetDebugInfo); Property method; void ReadProperties(Buffer &in) { method.ReadFrom(in); } }; struct MethodGetNameCommand : public CustomCommand { struct Reply : public CustomReply { Property name; void WriteContentTo(Buffer &out) const { name.WriteTo(out); } }; CUSTOM_COMMAND(Method, GetName); Property method; void ReadProperties(Buffer &in) { method.ReadFrom(in); } }; struct MethodGetParamInfoCommand : public CustomCommand { struct Reply : public CustomReply { struct ParamInfo { const char *name; Il2CppClass *type; }; Property call_convention; Property generic_param_count; Property return_type; inline std::vector ¶ms() { return _params; } void WriteContentTo(Buffer &out) const; private: std::vector _params; }; CUSTOM_COMMAND(Method, GetParamInfo); Property method; void ReadProperties(Buffer &in) { method.ReadFrom(in); } }; struct MethodGetBodyCommand : public CustomCommand { struct Reply : public CustomReply { Property > bytes; void WriteContentTo(Buffer &out) const { bytes.WriteTo(out); } }; CUSTOM_COMMAND(Method, GetBody); Property method; void ReadProperties(Buffer &in) { method.ReadFrom(in); } }; struct MethodGetLocalsInfoCommand : public CustomCommand { struct Reply : public CustomReply { struct LocalInfo { const Il2CppClass *type; std::string name; uint32_t begin_scope; uint32_t end_scope; }; inline std::vector &locals() { return _locals; } void WriteContentTo(Buffer &out) const; private: std::vector _locals; }; CUSTOM_COMMAND(Method, GetLocalsInfo); Property method; void ReadProperties(Buffer &in) { method.ReadFrom(in); } }; struct MethodGetInfoCommand : public CustomCommand { struct Reply : public CustomReply { Property flags; Property implementation_flags; Property token; void WriteContentTo(Buffer &out) const { flags.WriteTo(out); implementation_flags.WriteTo(out); token.WriteTo(out); } }; CUSTOM_COMMAND(Method, GetInfo); Property method; void ReadProperties(Buffer &in) { method.ReadFrom(in); } }; struct MethodResolveTokenCommand : public CustomCommand { struct Reply : public CustomReply { void WriteContentTo(Buffer &out) const { IL2CPP_ASSERT(0 && "Not implemented"); } }; CUSTOM_COMMAND(Method, ResolveToken); Property method; void ReadProperties(Buffer &in) { method.ReadFrom(in); } }; } } ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/module.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "module.h" using namespace il2cpp::debugger; #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/module.h ================================================ #pragma once #include #include "../../common.h" #include "../protocol-utils.h" namespace il2cpp { namespace debugger { struct ModuleGetInfoCommand : public CustomCommand { struct Reply : public CustomReply { Property basename; Property fullname; Property guid; Property scope_name; Property assembly; void WriteContentTo(Buffer &out) const { basename.WriteTo(out); scope_name.WriteTo(out); fullname.WriteTo(out); guid.WriteTo(out); assembly.WriteTo(out); } }; CUSTOM_COMMAND(Module, GetInfo); Property module; void ReadProperties(Buffer &in) { module.ReadFrom(in); } }; } } ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/object-ref.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "object-ref.h" using namespace il2cpp::debugger; #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/object-ref.h ================================================ #pragma once #include "../../common.h" #include "../protocol-utils.h" namespace il2cpp { namespace debugger { struct ObjectRefGetTypeCommand : public CustomCommand { struct Reply : public CustomReply { Property type; void WriteContentTo(Buffer &out) const { type.WriteTo(out); } }; CUSTOM_COMMAND(ObjectRef, GetType); Property object; void ReadProperties(Buffer &in) { object.ReadFrom(in); } }; struct ObjectRefGetDomainCommand : public CustomCommand { struct Reply : public CustomReply { Property domain; void WriteContentTo(Buffer &out) const { domain.WriteTo(out); } }; CUSTOM_COMMAND(ObjectRef, GetDomain); Property object; void ReadProperties(Buffer &in) { object.ReadFrom(in); } }; struct ObjectRefIsCollectedCommand : public CustomCommand { struct Reply : public CustomReply { void WriteContentTo(Buffer &out) const { IL2CPP_ASSERT(0 && "Not implemented!"); } }; CUSTOM_COMMAND(ObjectRef, IsCollected); Property object; void ReadProperties(Buffer &in) { object.ReadFrom(in); } }; struct ObjectRefSetValuesCommand : public CustomCommand { struct Reply : public CustomReply { void WriteContentTo(Buffer &out) const { IL2CPP_ASSERT(0 && "Not implemented!"); } }; CUSTOM_COMMAND(ObjectRef, SetValues); Property object; void ReadProperties(Buffer &in) { object.ReadFrom(in); } }; struct ObjectRefGetAddressCommand : public CustomCommand { struct Reply : public CustomReply { void WriteContentTo(Buffer &out) const { IL2CPP_ASSERT(0 && "Not implemented!"); } }; CUSTOM_COMMAND(ObjectRef, GetAddress); Property object; void ReadProperties(Buffer &in) { object.ReadFrom(in); } }; struct ObjectRefGetValuesCommand : public CustomCommand { struct Reply : public CustomReply { void WriteContentTo(Buffer &out) const { IL2CPP_ASSERT(0 && "Not implemented!"); } }; CUSTOM_COMMAND(ObjectRef, GetValues); Property object; void ReadProperties(Buffer &in) { object.ReadFrom(in); } }; } } ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/stack-frame.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "stack-frame.h" using namespace il2cpp::debugger; void StackFrameGetValuesCommand::Reply::WriteContentTo(Buffer &out) const { for (std::vector::const_iterator it = _values.begin(); it != _values.end(); ++it) { out.WriteVariant(*it); } } void StackFrameSetValuesCommand::ReadProperties(Buffer &in) { thread.ReadFrom(in); frame_id.ReadFrom(in); values_count.ReadFrom(in); // Note: we need to copy the data, as long as the incoming // buffer survives only for the duration of the command parsing. // We might want to change this in the future _command_buffer = new Buffer(in.length()); _command_buffer->WriteData(in.raw(), in.length()); _command_buffer->Seek(in.position()); } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/stack-frame.h ================================================ #pragma once #include #include "../../common.h" #include "../../variant.h" #include "../protocol-utils.h" namespace il2cpp { namespace debugger { struct StackFrameGetValuesCommand : public CustomCommand { struct Reply : public CustomReply { inline std::vector &values() { return _values; } void WriteContentTo(Buffer &out) const; private: std::vector _values; }; CUSTOM_COMMAND(StackFrame, GetValues); Property frame_id; Property thread; Property > positions; void ReadProperties(Buffer &in) { thread.ReadFrom(in); frame_id.ReadFrom(in); positions.ReadFrom(in); } }; struct StackFrameSetValuesCommand : public CustomCommand { CUSTOM_COMMAND_EMPTY_REPLY(StackFrame, SetValues); Property frame_id; Property thread; Property values_count; inline Buffer &command_buffer() const { return *_command_buffer; } void ReadProperties(Buffer & in); ~StackFrameSetValuesCommand() { delete _command_buffer; } private: Buffer *_command_buffer; }; struct StackFrameGetThisCommand : public CustomCommand { struct Reply : public CustomReply { Variant this_object; void WriteContentTo(Buffer &out) const { out.WriteVariant(this_object); } }; CUSTOM_COMMAND(StackFrame, GetThis); Property frame_id; Property thread; void ReadProperties(Buffer &in) { thread.ReadFrom(in); frame_id.ReadFrom(in); } }; } } ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/string-ref.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "string-ref.h" using namespace il2cpp::debugger; #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/string-ref.h ================================================ #pragma once #include "../../common.h" #include "../protocol-utils.h" namespace il2cpp { namespace debugger { struct StringRefGetValueCommand : public CustomCommand { struct Reply : public CustomReply { Property value; void WriteContentTo(Buffer &out) const { value.WriteTo(out); } }; CUSTOM_COMMAND(StringRef, GetValue); Property object; void ReadProperties(Buffer &in) { object.ReadFrom(in); } }; } } ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/thread.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "thread.h" using namespace il2cpp::debugger; void ThreadGetFrameInfoCommand::Reply::WriteContentTo(Buffer &out) const { std::vector::const_iterator it = _infos.begin(); out.WriteInt(_infos.size()); while (it != _infos.end()) { out.WriteInt((*it).frame_id); out.WriteMethodId((*it).method); out.WriteInt((*it).il_offset); out.WriteByte((*it).flags); ++it; } } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/thread.h ================================================ #pragma once #include #include "../../common.h" #include "../protocol-utils.h" struct MethodInfo; namespace il2cpp { namespace debugger { struct ThreadGetIdCommand : public CustomCommand { struct Reply : public CustomReply { Property id; void WriteContentTo(Buffer &out) const { id.WriteTo(out); } }; CUSTOM_COMMAND(Thread, GetId); Property thread; void ReadProperties(Buffer &in) { thread.ReadFrom(in); } }; struct ThreadGetNameCommand : public CustomCommand { struct Reply : public CustomReply { Property name; void WriteContentTo(Buffer &out) const { name.WriteTo(out); } }; CUSTOM_COMMAND(Thread, GetName); Property thread; void ReadProperties(Buffer &in) { thread.ReadFrom(in); } }; struct ThreadGetInfoCommand : public CustomCommand { struct Reply : public CustomReply { Property is_thread_pool; void WriteContentTo(Buffer &out) const { is_thread_pool.WriteTo(out); } }; CUSTOM_COMMAND(Thread, GetInfo); Property thread; void ReadProperties(Buffer &in) { thread.ReadFrom(in); } }; struct ThreadGetFrameInfoCommand : public CustomCommand { struct Reply : public CustomReply { struct FrameInfo { int32_t frame_id; const MethodInfo *method; int32_t il_offset; uint8_t flags; }; inline std::vector &infos() { return _infos; } void WriteContentTo(Buffer &out) const; private: std::vector _infos; }; CUSTOM_COMMAND(Thread, GetFrameInfo); Property thread; Property stack_frame; Property length; void ReadProperties(Buffer &in) { thread.ReadFrom(in); stack_frame.ReadFrom(in); length.ReadFrom(in); } }; struct ThreadGetStateCommand : public CustomCommand { struct Reply : public CustomReply { Property state; void WriteContentTo(Buffer &out) const { state.WriteTo(out); } }; CUSTOM_COMMAND(Thread, GetState); Property thread; void ReadProperties(Buffer &in) { thread.ReadFrom(in); } }; } } ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/type.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "type.h" using namespace il2cpp::debugger; void TypeGetValuesCommand::Reply::WriteContentTo(Buffer &out) const { for (std::vector::const_iterator it = _values.begin(); it != _values.end(); ++it) { out.WriteVariant(*it); } } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/type.h ================================================ #pragma once #include #include #include #include "../../common.h" #include "../../variant.h" #include "../../../class-internals.h" #include "../../../il2cpp-api.h" #include "../protocol-utils.h" namespace il2cpp { namespace debugger { struct TypeGetInfoCommand : public CustomCommand { struct Reply : public CustomReply { Property ns; Property name; Property fullname; Property assembly; Property module; Property parent_type; Property underlying_type; Property type_token; Property rank; Property flags; Property by_val_flags; Property > nested_types; void WriteContentTo(Buffer &out) const { ns.WriteTo(out); name.WriteTo(out); fullname.WriteTo(out); assembly.WriteTo(out); module.WriteTo(out); parent_type.WriteTo(out); underlying_type.WriteTo(out); type_token.WriteTo(out); rank.WriteTo(out); flags.WriteTo(out); by_val_flags.WriteTo(out); nested_types.WriteTo(out); } }; CUSTOM_COMMAND(Type, GetInfo); Property type; void ReadProperties(Buffer &in) { type.ReadFrom(in); } }; struct TypeGetSourceFilesCommand : public CustomCommand { struct Reply : public CustomReply { Property > source_files; void WriteContentTo(Buffer &out) const { source_files.WriteTo(out); } }; CUSTOM_COMMAND(Type, GetSourceFiles); Property type; void ReadProperties(Buffer &in) { type.ReadFrom(in); } }; struct TypeGetPropertiesCommand : public CustomCommand { struct Reply : public CustomReply { std::vector properties; void WriteContentTo(Buffer &out) const { out.WriteInt(properties.size()); std::vector::const_iterator it = properties.begin(); while (it != properties.end()) { const PropertyInfo *prop = *it; out.WritePropertyId(prop); out.WriteString(prop->name); out.WriteMethodId(prop->get); out.WriteMethodId(prop->set); out.WriteInt(prop->attrs); ++it; } } }; CUSTOM_COMMAND(Type, GetProperties); Property type; void ReadProperties(Buffer &in) { type.ReadFrom(in); } }; struct TypeGetSourceFiles2Command : public CustomCommand { struct Reply : public CustomReply { Property > source_files; void WriteContentTo(Buffer &out) const { source_files.WriteTo(out); } }; CUSTOM_COMMAND(Type, GetSourceFiles2); Property type; void ReadProperties(Buffer &in) { type.ReadFrom(in); } }; struct TypeGetPropertyCAttrsCommand : public CustomCommand { struct Reply : public CustomReply { Property fake_count; void WriteContentTo(Buffer &out) const { fake_count.WriteTo(out); } }; CUSTOM_COMMAND(Type, GetPropertyCAttrs); Property type; Property attr_type; void ReadProperties(Buffer &in) { type.ReadFrom(in); attr_type.ReadFrom(in); } }; struct TypeGetFieldCAttrsCommand : public CustomCommand { struct Reply : public CustomReply { Property fake_count; void WriteContentTo(Buffer &out) const { fake_count.WriteTo(out); } }; CUSTOM_COMMAND(Type, GetFieldCAttrs); Property type; Property attr_type; void ReadProperties(Buffer &in) { type.ReadFrom(in); attr_type.ReadFrom(in); } }; struct TypeIsAssignableFromCommand : public CustomCommand { struct Reply : public CustomReply { void WriteContentTo(Buffer &out) const { IL2CPP_ASSERT(0 && "Not implemented!"); } }; CUSTOM_COMMAND(Type, IsAssignableFrom); Property type; void ReadProperties(Buffer &in) { type.ReadFrom(in); } }; struct TypeGetCAttrsCommand : public CustomCommand { struct Reply : public CustomReply { Property fake_count; void WriteContentTo(Buffer &out) const { fake_count.WriteTo(out); } }; CUSTOM_COMMAND(Type, GetCAttrs); Property type; Property attr_type; void ReadProperties(Buffer &in) { type.ReadFrom(in); attr_type.ReadFrom(in); } }; struct TypeGetValuesCommand : public CustomCommand { struct Reply : public CustomReply { inline std::vector &values() { return _values; } void WriteContentTo(Buffer &out) const; private: std::vector _values; }; CUSTOM_COMMAND(Type, GetValues); Property type; Property > fields; void ReadProperties(Buffer &in) { type.ReadFrom(in); fields.ReadFrom(in); } }; struct TypeGetObjectCommand : public CustomCommand { struct Reply : public CustomReply { Property object; void WriteContentTo(Buffer &out) const { object.WriteTo(out); } }; CUSTOM_COMMAND(Type, GetObject); Property type; void ReadProperties(Buffer &in) { type.ReadFrom(in); } }; struct TypeGetFieldsCommand : public CustomCommand { struct Reply : public CustomReply { std::vector fields; void WriteContentTo(Buffer &out) const { out.WriteInt(fields.size()); std::vector::const_iterator it = fields.begin(); while (it != fields.end()) { FieldInfo *field = *it; out.WriteFieldId(field); out.WriteString(field->name); out.WriteTypeId(il2cpp_class_from_il2cpp_type(field->type)); out.WriteInt(field->type->attrs); ++it; } } }; CUSTOM_COMMAND(Type, GetFields); Property type; void ReadProperties(Buffer &in) { type.ReadFrom(in); } }; struct TypeSetValuesCommand : public CustomCommand { struct Reply : public CustomReply { void WriteContentTo(Buffer &out) const { IL2CPP_ASSERT(0 && "Not implemented!"); } }; CUSTOM_COMMAND(Type, SetValues); Property type; void ReadProperties(Buffer &in) { type.ReadFrom(in); } }; struct TypeGetMethodsCommand : public CustomCommand { struct Reply : public CustomReply { Property > methods; void WriteContentTo(Buffer &out) const { methods.WriteTo(out); } }; CUSTOM_COMMAND(Type, GetMethods); Property type; void ReadProperties(Buffer &in) { type.ReadFrom(in); } }; } } ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/vm.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "vm.h" using namespace il2cpp::debugger; #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/commands/vm.h ================================================ #pragma once #include #include "../../common.h" #include "../protocol-utils.h" namespace il2cpp { namespace debugger { struct VmSetProtocolVersionCommand : public CustomCommand { CUSTOM_COMMAND_EMPTY_REPLY(Vm, SetProtocolVersion); Property major_version; Property minor_version; void ReadProperties(Buffer &in) { major_version.ReadFrom(in); minor_version.ReadFrom(in); } }; struct VmVersionCommand : public CustomCommand { struct Reply : public CustomReply { Property name; Property major_version; Property minor_version; void WriteContentTo(Buffer &out) const { name.WriteTo(out); major_version.WriteTo(out); minor_version.WriteTo(out); } }; CUSTOM_COMMAND(Vm, Version); }; struct VmResumeCommand : public CustomCommand { CUSTOM_COMMAND_EMPTY_REPLY(Vm, Resume); }; struct VmDisposeCommand : public CustomCommand { CUSTOM_COMMAND_EMPTY_REPLY(Vm, Dispose); }; struct VmSuspendCommand : public CustomCommand { CUSTOM_COMMAND_EMPTY_REPLY(Vm, Suspend); }; struct VmAllThreadsCommand : public CustomCommand { struct Reply : public CustomReply { Property > threads; void WriteContentTo(Buffer &out) const { threads.WriteTo(out); } }; CUSTOM_COMMAND(Vm, AllThreads); }; struct VmExitCommand : public CustomCommand { struct Reply : public CustomReply { Property exit_code; void WriteContentTo(Buffer &out) const { exit_code.WriteTo(out); } }; CUSTOM_COMMAND(Vm, Exit); }; struct VmAbortInvokeCommand : public CustomCommand { struct Reply : public CustomReply { void WriteContentTo(Buffer &out) const { IL2CPP_ASSERT(0 && "Not implemented!"); } }; CUSTOM_COMMAND(Vm, AbortInvoke); }; struct VmInvokeMethodCommand : public CustomCommand { struct Reply : public CustomReply { Reply() : skip_return_value(false) {} Property method_did_not_throw_exception; Property return_type; Property return_value; bool skip_return_value; void WriteContentTo(Buffer &out) const { method_did_not_throw_exception.WriteTo(out); return_type.WriteTo(out); if (!skip_return_value) return_value.WriteTo(out); } }; CUSTOM_COMMAND(Vm, InvokeMethod); Property vm_thread; Property flags; Property method; void ReadProperties(Buffer &in) { vm_thread.ReadFrom(in); flags.ReadFrom(in); method.ReadFrom(in); } }; } } ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/events.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "events.h" #include "../../il2cpp-api.h" #include "../agent.h" #include "../id-bank.h" #include "../data-buffer.h" using namespace il2cpp::debugger; VmStartEvent::VmStartEvent() { } VmStartEvent::VmStartEvent(Il2CppThread *thread) : Event(thread) { } void VmStartEvent::WriteContentTo(Buffer &out) const { out.WritePtrId(DomainId(il2cpp_domain_get())); } VmDeathEvent::VmDeathEvent() { } VmDeathEvent::VmDeathEvent(Il2CppThread *thread) : Event(thread) { } void VmDeathEvent::WriteContentTo(Buffer &out) const { } UserBreakEvent::UserBreakEvent() { } UserBreakEvent::UserBreakEvent(Il2CppThread *thread) : Event(thread) { } void UserBreakEvent::WriteContentTo(Buffer &out) const { } AppDomainCreateEvent::AppDomainCreateEvent(Il2CppThread *thread) : Event(thread) { } void AppDomainCreateEvent::WriteContentTo(Buffer &out) const { domain.WriteTo(out); } AssemblyLoadEvent::AssemblyLoadEvent(Il2CppThread *thread) : Event(thread) { } void AssemblyLoadEvent::WriteContentTo(Buffer &out) const { assembly.WriteTo(out); } TypeLoadEvent::TypeLoadEvent(Il2CppThread *thread) : Event(thread) { } void TypeLoadEvent::WriteContentTo(Buffer &out) const { type.WriteTo(out); } BreakPointEvent::BreakPointEvent() { } BreakPointEvent::BreakPointEvent(Il2CppThread *thread) : Event(thread) { } void BreakPointEvent::WriteContentTo(Buffer &out) const { method.WriteTo(out); il_offset.WriteTo(out); } StepEvent::StepEvent() { } StepEvent::StepEvent(Il2CppThread *thread) : Event(thread) { } void StepEvent::WriteContentTo(Buffer &out) const { method.WriteTo(out); il_offset.WriteTo(out); } ThreadStartEvent::ThreadStartEvent(Il2CppThread *thread) : Event(thread) { } void ThreadStartEvent::WriteContentTo(Buffer &out) const { } ThreadDeathEvent::ThreadDeathEvent(Il2CppThread *thread) : Event(thread) { } void ThreadDeathEvent::WriteContentTo(Buffer &out) const { } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/events.h ================================================ #pragma once #include "../common.h" #include "../meta.h" #include "protocol.h" namespace il2cpp { namespace debugger { class Buffer; class Command; class VmStartEvent : public Event { public: VmStartEvent(); explicit VmStartEvent(Il2CppThread *thread); inline EventKind kind() const { return kEventKindVmStart; } protected: void WriteContentTo(Buffer &out) const; DISALLOW_COPY(VmStartEvent); }; class VmDeathEvent : public Event { public: VmDeathEvent(); explicit VmDeathEvent(Il2CppThread *thread); inline EventKind kind() const { return kEventKindVmDeath; } protected: void WriteContentTo(Buffer &out) const; DISALLOW_COPY(VmDeathEvent); }; class UserBreakEvent : public Event { public: UserBreakEvent(); explicit UserBreakEvent(Il2CppThread *thread); inline EventKind kind() const { return kEventKindUserBreak; } protected: void WriteContentTo(Buffer &out) const; DISALLOW_COPY(UserBreakEvent); }; class AppDomainCreateEvent : public Event { public: AppDomainCreateEvent(); explicit AppDomainCreateEvent(Il2CppThread *thread); inline EventKind kind() const { return kEventKindAppDomainCreate; } Property domain; protected: void WriteContentTo(Buffer &out) const; DISALLOW_COPY(AppDomainCreateEvent); }; class AssemblyLoadEvent : public Event { public: AssemblyLoadEvent(); explicit AssemblyLoadEvent(Il2CppThread *thread); inline EventKind kind() const { return kEventKindAssemblyLoad; } Property assembly; protected: void WriteContentTo(Buffer &out) const; DISALLOW_COPY(AssemblyLoadEvent); }; class TypeLoadEvent : public Event { public: TypeLoadEvent(); explicit TypeLoadEvent(Il2CppThread *thread); inline EventKind kind() const { return kEventKindTypeLoad; } Property type; protected: void WriteContentTo(Buffer &out) const; DISALLOW_COPY(TypeLoadEvent); }; class BreakPointEvent : public Event { public: BreakPointEvent(); explicit BreakPointEvent(Il2CppThread *thread); inline EventKind kind() const { return kEventKindBreakpoint; } Property method; Property il_offset; protected: void WriteContentTo(Buffer &out) const; DISALLOW_COPY(BreakPointEvent); }; class StepEvent : public Event { public: StepEvent(); explicit StepEvent(Il2CppThread *thread); inline EventKind kind() const { return kEventKindStep; } Property method; Property il_offset; protected: void WriteContentTo(Buffer &out) const; DISALLOW_COPY(StepEvent); }; class ThreadStartEvent : public Event { public: ThreadStartEvent(); explicit ThreadStartEvent(Il2CppThread *thread); inline EventKind kind() const { return kEventKindThreadStart; } protected: void WriteContentTo(Buffer &out) const; DISALLOW_COPY(ThreadStartEvent); }; class ThreadDeathEvent : public Event { public: ThreadDeathEvent(); explicit ThreadDeathEvent(Il2CppThread *thread); inline EventKind kind() const { return kEventKindThreadDeath; } protected: void WriteContentTo(Buffer &out) const; DISALLOW_COPY(ThreadDeathEvent); }; } /* namespace debugger */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/globals.h ================================================ #pragma once #include "../common.h" namespace il2cpp { namespace debugger { enum CommandSet { kCommandSetInternalError = -1, kCommandSetVm = 1, kCommandSetObjectRef = 9, kCommandSetStringRef = 10, kCommandSetThread = 11, kCommandSetArrayRef = 13, kCommandSetEventRequest = 15, kCommandSetStackFrame = 16, kCommandSetAppDomain = 20, kCommandSetAssembly = 21, kCommandSetMethod = 22, kCommandSetType = 23, kCommandSetModule = 24, kCommandSetEvent = 64 }; enum CommandSetInternalError { kCommandSetInternalErrorNotImplemented = 1 }; enum CommandSetVm { kCommandSetVmVersion = 1, kCommandSetVmAllThreads = 2, kCommandSetVmSuspend = 3, kCommandSetVmResume = 4, kCommandSetVmExit = 5, kCommandSetVmDispose = 6, kCommandSetVmInvokeMethod = 7, kCommandSetVmSetProtocolVersion = 8, kCommandSetVmAbortInvoke = 9 }; enum CommandSetThread { kCommandSetThreadGetFrameInfo = 1, kCommandSetThreadGetName = 2, kCommandSetThreadGetState = 3, kCommandSetThreadGetInfo = 4, kCommandSetThreadGetId = 5 }; enum CommandSetEventRequest { kCommandSetEventRequestSet = 1, kCommandSetEventRequestClear = 2, kCommandSetEventRequestClearAllBreakpoints = 3 }; enum CommandSetEvent { kCommandSetEventComposite = 100 }; enum CommandSetAppDomain { kCommandSetAppDomainGetRootDomain = 1, kCommandSetAppDomainGetFriendlyName = 2, kCommandSetAppDomainGetAssemblies = 3, kCommandSetAppDomainGetEntryAssembly = 4, kCommandSetAppDomainCreateString = 5, kCommandSetAppDomainGetCorlib = 6, kCommandSetAppDomainCreateBoxedValue = 7, }; enum CommandSetAssembly { kCommandSetAssemblyGetLocation = 1, kCommandSetAssemblyGetEntryPoint = 2, kCommandSetAssemblyGetManifestModule = 3, kCommandSetAssemblyGetObject = 4, kCommandSetAssemblyGetType = 5, kCommandSetAssemblyGetName = 6 }; enum CommandSetModule { kCommandSetModuleGetInfo = 1, }; enum CommandSetMethod { kCommandSetMethodGetName = 1, kCommandSetMethodGetDeclaringType = 2, kCommandSetMethodGetDebugInfo = 3, kCommandSetMethodGetParamInfo = 4, kCommandSetMethodGetLocalsInfo = 5, kCommandSetMethodGetInfo = 6, kCommandSetMethodGetBody = 7, kCommandSetMethodResolveToken = 8, }; enum CommandSetType { kCommandSetTypeGetInfo = 1, kCommandSetTypeGetMethods = 2, kCommandSetTypeGetFields = 3, kCommandSetTypeGetValues = 4, kCommandSetTypeGetObject = 5, kCommandSetTypeGetSourceFiles = 6, kCommandSetTypeSetValues = 7, kCommandSetTypeIsAssignableFrom = 8, kCommandSetTypeGetProperties = 9, kCommandSetTypeGetCAttrs = 10, kCommandSetTypeGetFieldCAttrs = 11, kCommandSetTypeGetPropertyCAttrs = 12, kCommandSetTypeGetSourceFiles2 = 13, }; enum CommandSetStackFrame { kCommandSetStackFrameGetValues = 1, kCommandSetStackFrameGetThis = 2, kCommandSetStackFrameSetValues = 3 }; enum CommandSetArrayRef { kCommandSetArrayRefGetLength = 1, kCommandSetArrayRefGetValues = 2, kCommandSetArrayRefSetValues = 3, }; enum CommandSetStringRef { kCommandSetStringRefGetValue = 1, }; enum CommandSetObjectRef { kCommandSetObjectRefGetType = 1, kCommandSetObjectRefGetValues = 2, kCommandSetObjectRefIsCollected = 3, kCommandSetObjectRefGetAddress = 4, kCommandSetObjectRefGetDomain = 5, kCommandSetObjectRefSetValues = 6 }; enum ErrorCode { kErrorCodeNone = 0, kErrorCodeInvalidObject = 20, kErrorCodeInvalidFieldId = 25, kErrorCodeInvalidFrameId = 30, kErrorCodeNotImplemented = 100, kErrorCodeNotSuspended = 101, kErrorCodeInvalidArgument = 102, kErrorCodeUnloaded = 103, kErrorCodeNoInvocation = 104, kErrorCodeAbsentInformation = 105 }; enum EventKind { kEventKindVmStart = 0, kEventKindVmDeath = 1, kEventKindThreadStart = 2, kEventKindThreadDeath = 3, kEventKindAppDomainCreate = 4, kEventKindAppDomainUnload = 5, kEventKindMethodEntry = 6, kEventKindMethodExit = 7, kEventKindAssemblyLoad = 8, kEventKindAssemblyUnload = 9, kEventKindBreakpoint = 10, kEventKindStep = 11, kEventKindTypeLoad = 12, kEventKindException = 13, kEventKindKeepAlive = 14, kEventKindUserBreak = 15, kEventKindUserLog = 16, kEventKindInvalid = -1 }; enum ModifierKind { kModifierKindInvalid = -1, kModifierKindCount = 1, kModifierKindThreadOnly = 3, kModifierKindLocationOnly = 7, kModifierKindExceptionOnly = 8, kModifierKindStep = 10, kModifierKindAssemblyOnly = 11 }; enum StepDepthKind { kStepDepthKindInto = 0, kStepDepthKindOver = 1, kStepDepthKindOut = 2 }; enum StepSizeKind { kStepSizeKindMin = 0, kStepSizeKindLine = 1 }; struct Modifier { ModifierKind kind; union { int count; // kModifierKindCount Il2CppThread *thread; // kModifierKindThreadOnly Il2CppClass *exc_class; // kModifierKindExceptionOnly Il2CppAssembly **assemblies; // kModifierKindAssemblyOnly } data; bool caught; bool uncaught; // kModifierKindExceptionOnly Modifier() : kind(kModifierKindInvalid), caught(false), uncaught(false) { data.count = 0; data.thread = 0; data.exc_class = 0; data.assemblies = 0; } ~Modifier() { if (kind == kModifierKindAssemblyOnly && data.assemblies != 0) { delete[] data.assemblies; data.assemblies = 0; } } }; } /* namespace debugger */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/protocol-utils.h ================================================ #pragma once #include #include "../common.h" #include "../meta.h" #include "protocol.h" namespace il2cpp { namespace debugger { template struct CustomCommand : public Command { explicit CustomCommand(int32_t id) : Command(Cmd::SetKind, Cmd::CommandKind, id) { } }; #define _CUSTOM_COMMAND(TSet, TCommand) \ public: \ static const CommandSet SetKind = kCommandSet ## TSet; \ static const int32_t CommandKind = kCommandSet ## TSet ## TCommand; \ inline static Command *Factory(Header &header, Buffer &in) \ { \ Command * command = new TSet ## TCommand ## Command(header.id()); \ command->ReadProperties(in); \ return command; \ } \ explicit TSet ## TCommand ## Command(int32_t id) : \ CustomCommand(id) {} #define CUSTOM_COMMAND(TSet, TCommand) \ _CUSTOM_COMMAND(TSet, TCommand) \ TSet ## TCommand ## Command::Reply * reply() const \ { \ TSet ## TCommand ## Command::Reply *reply = new TSet ## TCommand ## Command::Reply(); \ reply->command(this); \ return reply; \ } #define CUSTOM_COMMAND_EMPTY_REPLY(TSet, TCommand) \ _CUSTOM_COMMAND(TSet, TCommand) \ struct Reply : public EmptyReply \ { \ explicit Reply(const Command *command) : EmptyReply(command) {} \ }; \ TSet ## TCommand ## Command::Reply * reply() const \ { \ return new TSet ## TCommand ## Command::Reply(this); \ } struct CustomReply : public Reply { CustomReply() : Reply(NULL) { } inline void command(const Command *v) { _command = v; } }; } } ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/protocol.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "protocol.h" #include "../../il2cpp-api.h" #include "../data-buffer.h" #include "../id-bank.h" #include "../transport.h" #include "../agent.h" #include "utils.h" #include "commands/type.h" #include "commands/vm.h" #include "commands/app-domain.h" #include "commands/array-ref.h" #include "commands/assembly.h" #include "commands/event.h" #include "commands/event-request.h" #include "commands/internal-error.h" #include "commands/method.h" #include "commands/module.h" #include "commands/object-ref.h" #include "commands/stack-frame.h" #include "commands/string-ref.h" #include "commands/thread.h" using namespace il2cpp::debugger; Header::Header(HeaderType type) : _packet_size(0), _id(0), _flags(type), _data(0) { } void Header::ReadHeader(Header &header, Buffer &in) { const int32_t length = in.ReadInt(); const int32_t id = in.ReadInt(); const HeaderType type = in.ReadEnum(); const uint16_t data = (in.ReadByte() << 8) | in.ReadByte(); IL2CPP_ASSERT(header.type() == type && "Incompatible Header types: incoming header is not of the expected type"); header.packet_size(length); header.id(id); if (header.is_command()) { header.set((CommandSet)((data >> 8) & 0xFF)); header.command(data & 0xFF); } else { header.error_code((ErrorCode)data); } } void Header::WriteTo(Buffer &out) const { out.WriteInt(packet_size()); out.WriteInt(id()); out.WriteByte(_flags); out.WriteByte((_data >> 8) & 0xFF); out.WriteByte(_data & 0xFF); } Command::Command(CommandSet set, int32_t command, int32_t id) : _id(id), _set(set), _command(command) { } Command::~Command() { } void Command::ReadProperties(Buffer &in) { } void Command::WriteTo(Buffer &out) const { out.Seek(Header::Length); WriteContentTo(out); Header header(kHeaderTypeCommand); header.packet_size(out.length()); header.id(_id); header.set(set()); header.command(command()); out.Seek(0); header.WriteTo(out); out.Seek(header.packet_size()); } void Command::WriteContentTo(Buffer &out) const { } Event::Event() : _thread(il2cpp_thread_current()) { } Event::Event(Il2CppThread *thread) : _thread(thread) { } Event::~Event() { } void Event::WriteTo(Buffer &out, int32_t req_id) const { out.WriteByte(kind()); out.WriteInt(req_id); out.WritePtrId(ObjectId((Il2CppObject*)_thread)); WriteContentTo(out); } void Event::WriteContentTo(Buffer &out) const { } Reply::Reply(const Command *command) : _command(command), _error_code(kErrorCodeNone) { } Reply::~Reply() { } void Reply::WriteTo(Buffer &out) const { // Reserve space for the header out.Seek(Header::Length); if (error_code() == kErrorCodeNone) WriteContentTo(out); else LOG("Reply returned an error: " << error_code()); Header header(kHeaderTypeReply); header.packet_size(out.length()); header.id(_command ? _command->id() : 0); header.error_code(error_code()); out.Seek(0); header.WriteTo(out); out.Seek(header.packet_size()); } void Reply::WriteContentTo(Buffer &out) const { } EmptyReply::EmptyReply(const Command *command) : Reply(command) { } Protocol::Protocol() : _minor_version(Protocol::MinorVersion), _major_version(Protocol::MajorVersion), _transport(0) { } Protocol::~Protocol() { _transport = 0; } void Protocol::Setup(IDataTransport *transport) { IL2CPP_ASSERT(transport != NULL && "Invalid data transport"); _transport = transport; RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); RegisterCommand(); } Command *Protocol::CreateCommand(Header &header, Buffer &in) const { IL2CPP_ASSERT(header.is_command() && "CommandFactory::Create can only be used with `command` headers."); const CommandUId uid = CommandIdFor(header.set(), header.command()); std::map::const_iterator it = _command_factories.find(uid); if (it == _command_factories.end()) { LOG("Command not found: " << command_set_to_string(header.set()) << "+" << command_to_string(header.set(), header.command()) << "(" << header.set() << ":" << header.command() << ")"); return NULL; } return it->second(header, in); } Protocol::CommandUId Protocol::CommandIdFor(Header &header) const { return CommandIdFor(header.set(), header.command()); } Protocol::CommandUId Protocol::CommandIdFor(CommandSet set, int32_t command) const { return ((((int32_t)set) & 0xFF) << 8) | (command & 0xFF); } bool Protocol::Handshake() { const char *handshake_msg = "DWP-Handshake"; const size_t msg_length = strlen(handshake_msg); Buffer in(128); Buffer out(128); out.WriteData((const uint8_t*)handshake_msg, msg_length); int32_t sent_bytes = _transport->Send(out.raw(), out.length()); if (sent_bytes != out.length()) { LOG("DWP handshake failed."); return false; } int32_t received_bytes = _transport->Recv(in.raw(), msg_length); if ((received_bytes != msg_length) || (memcmp(in.raw(), handshake_msg, msg_length != 0))) { LOG("DWP handshake failed."); return false; } return true; } const Command *Protocol::WaitForCommand() { // In/Out buffers are allocated at every iteration. This needs to be improved Buffer in(Header::Length); int32_t read_bytes = _transport->Recv(in.raw(), Header::Length); if (read_bytes != Header::Length) { LOG("Couldn't parse the header. Expecting " << Header::Length << " bytes, but got " << read_bytes << ". Shutting down."); return NULL; } in.MarkReadRaw(read_bytes); Header header(kHeaderTypeCommand); Header::ReadHeader(header, in); LOG("Received command " << command_set_to_string(header.set()) << " " << command_to_string(header.set(), header.command()) << "(" << header.command() << "), id=" << header.id() << "."); if (header.message_size() > 0) { in.Reset(header.message_size()); if (is_disposed()) return NULL; int32_t received = _transport->Recv(in.raw(), header.message_size()); if (received != header.message_size()) { LOG("Expecting a command of " << header.message_size() << " bytes. Got " << received << ". Shutting down."); exit(1); } in.MarkReadRaw(received); } Command *command = CreateCommand(header, in); if (command == NULL) { LOG("Not implemented command"); command = new InternalErrorNotImplementedCommand(header.id()); } return command; } bool Protocol::SendReply(const Reply *reply) { // For now, every reply has its own 'out' buffer as long as SendReply might // be called from different threads. This needs to be improved. if (is_disposed()) { LOG("The protocol was disposed. Reply can not be sent."); return false; } Buffer out(128); reply->WriteTo(out); if (!_transport->Send(out.raw(), out.length())) { LOG("The socket was shut down while sending the header"); return false; } return true; } bool Protocol::SendCommand(const Command *command) { // For now, every reply has its own 'out' buffer as long as SendReply might // be called from different threads. This needs to be improved. if (is_disposed()) { LOG("The protocol was disposed. Command can not be sent."); return false; } Buffer out(128); command->WriteTo(out); if (!_transport->Send(out.raw(), out.length())) { LOG("The socket was shut down while sending the header"); return false; } return true; } void Protocol::Dispose() { if (_transport == 0) return; _transport->Close(); _transport = 0; } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/protocol.h ================================================ #pragma once #include "../common.h" #include #include "globals.h" #include "utils.h" struct Il2CppThread; namespace il2cpp { namespace debugger { class Reply; class Buffer; class Command; class IDataTransport; enum HeaderType { kHeaderTypeCommand = 0x00, kHeaderTypeReply = 0x80 }; class Header { public: static const int32_t Length = 11; explicit Header(HeaderType type); inline HeaderType type() const { return (HeaderType)_flags; } inline bool is_command() const { return _flags == kHeaderTypeCommand; } inline bool is_reply() const { return _flags == kHeaderTypeReply; } inline size_t message_size() const { return _packet_size - Header::Length; } inline int32_t id() const { return _id; } inline void id(int32_t v) { _id = v; } inline size_t packet_size() const { return _packet_size; } inline void packet_size(size_t v) { _packet_size = v; } inline CommandSet set() const { IL2CPP_ASSERT(is_command() && "Header::set() can only be invoked on `Command` headers"); return (CommandSet)((_data >> 8) & 0xFF); } inline void set(CommandSet v) { IL2CPP_ASSERT(is_command() && "Header::set(CommandSet) can only be invoked on `Command` headers"); _data = (v << 8) | (_data & 0xFF); } inline int32_t command() const { IL2CPP_ASSERT(is_command() && "Header::command() can only be invoked on `Command` headers"); return _data & 0xFF; } inline void command(int32_t v) { IL2CPP_ASSERT(is_command() && "Header::command(int32_t) can only be invoked on `Command` headers"); _data = (_data & 0xFF00) | (v & 0xFF); } inline ErrorCode error_code() const { IL2CPP_ASSERT(is_reply() && "Header::error_code() can only be invoked on `Reply` headers"); return (ErrorCode)_data; } inline void error_code(ErrorCode v) { IL2CPP_ASSERT(is_reply() && "Header::error_code(ErrorCode) can only be invoked on `Command` headers"); _data = v; } static void ReadHeader(Header & header, Buffer & in); void WriteTo(Buffer &out) const; private: size_t _packet_size; int32_t _id; uint8_t _flags; uint16_t _data; DISALLOW_COPY(Header); }; #define PROTOCOL_COMMAND(TSet, TCommand) \ public: \ static const CommandSet SetKind = kCommandSet ## TSet; \ static const int32_t CommandKind = kCommandSet ## TSet ## TCommand; \ inline static Command *Factory(Header &header, Buffer &in) \ { \ Command * command = new TSet ## TCommand ## Command(header.id()); \ command->ReadProperties(in); \ return command; \ } class Command { public: Command(CommandSet set, int32_t command, int32_t id); virtual ~Command(); inline CommandSet set() const { return _set; } inline int32_t command() const { return _command; } inline int32_t id() const { return _id; } inline bool is(CommandSet set, int32_t command) const { return _set == set && _command == command; } void WriteTo(Buffer &out) const; virtual void ReadProperties(Buffer & in); protected: virtual void WriteContentTo(Buffer &out) const; int32_t _id; CommandSet _set; int32_t _command; DISALLOW_COPY(Command); }; class Reply { public: explicit Reply(const Command *command); virtual ~Reply(); inline const Command *command() const { return _command; } inline ErrorCode error_code() const { return _error_code; } inline void error_code(ErrorCode code) { _error_code = code; } void WriteTo(Buffer &out) const; protected: virtual void WriteContentTo(Buffer &out) const; const Command *_command; ErrorCode _error_code; DISALLOW_COPY(Reply); }; class EmptyReply : public Reply { public: explicit EmptyReply(const Command *command); DISALLOW_COPY(EmptyReply); }; class Event { public: Event(); explicit Event(Il2CppThread *thread); virtual ~Event(); inline virtual EventKind kind() const { return kEventKindInvalid; } inline Il2CppThread *thread() const { return _thread; } inline void thread(Il2CppThread *v) { _thread = v; } void WriteTo(Buffer &out, int32_t req_id) const; protected: virtual void WriteContentTo(Buffer &out) const; Il2CppThread *_thread; DISALLOW_COPY(Event); }; class Protocol { typedef uint16_t CommandUId; typedef Command* (*CommandGenerator)(Header &header, Buffer &in); public: static const int32_t MajorVersion = 2; static const int32_t MinorVersion = 1; Protocol(); ~Protocol(); inline IDataTransport *transport() { return _transport; } inline int32_t major_version() const { return _major_version; } inline void major_version(int32_t v) { _major_version = v; } inline int32_t minor_version() const { return _minor_version; } inline void minor_version(int32_t v) { _minor_version = v; } inline bool is_disposed() const { return _transport == 0; } void Setup(IDataTransport *transport); void Dispose(); bool Handshake(); // Note WaitForCommand gives ownership of the Command object away for now. // It is responsability of the invoker to delete the Command when done. const Command *WaitForCommand(); bool SendReply(const Reply *reply); bool SendCommand(const Command *command); private: template inline void RegisterCommand() { LOG("Registering " << command_to_string(TCommand::SetKind, TCommand::CommandKind) << " with id: " << CommandIdFor(TCommand::SetKind, TCommand::CommandKind)); _command_factories[CommandIdFor(TCommand::SetKind, TCommand::CommandKind)] = &TCommand::Factory; } Command *CreateCommand(Header & header, Buffer & in) const; CommandUId CommandIdFor(Header &header) const; CommandUId CommandIdFor(CommandSet set, int32_t command) const; int32_t _major_version; int32_t _minor_version; IDataTransport *_transport; std::map _command_factories; DISALLOW_COPY(Protocol); }; } /* namespace debugger */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/utils.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "utils.h" namespace il2cpp { namespace debugger { const char* command_set_to_string(CommandSet command_set) { switch (command_set) { case kCommandSetInternalError: return "INTERNAL_ERROR"; case kCommandSetVm: return "VM"; case kCommandSetObjectRef: return "OBJECT_REF"; case kCommandSetStringRef: return "STRING_REF"; case kCommandSetThread: return "THREAD"; case kCommandSetArrayRef: return "ARRAY_REF"; case kCommandSetEventRequest: return "EVENT_REQUEST"; case kCommandSetStackFrame: return "STACK_FRAME"; case kCommandSetAppDomain: return "APPDOMAIN"; case kCommandSetAssembly: return "ASSEMBLY"; case kCommandSetMethod: return "METHOD"; case kCommandSetType: return "TYPE"; case kCommandSetModule: return "MODULE"; case kCommandSetEvent: return "EVENT"; default: return ""; } } const char* command_to_string(CommandSet command_set, int command) { switch (command_set) { case kCommandSetInternalError: { switch ((CommandSetInternalError)command) { case kCommandSetInternalErrorNotImplemented: return "CMD_INT_ERR_NOT_IMPL"; default: return ""; } } case kCommandSetVm: { switch ((CommandSetVm)command) { case kCommandSetVmVersion: return "CMD_VM_VERSION"; case kCommandSetVmAllThreads: return "CMD_VM_ALL_THREADS"; case kCommandSetVmSuspend: return "CMD_VM_SUSPEND"; case kCommandSetVmResume: return "CMD_VM_RESUME"; case kCommandSetVmExit: return "CMD_VM_EXIT"; case kCommandSetVmDispose: return "CMD_VM_DISPOSE"; case kCommandSetVmInvokeMethod: return "CMD_VM_INVOKE_METHOD"; case kCommandSetVmSetProtocolVersion: return "CMD_VM_SET_PROTOCOL_VERSION"; case kCommandSetVmAbortInvoke: return "CMD_VM_ABORT_INVOKE"; default: return ""; } } case kCommandSetObjectRef: { switch ((CommandSetObjectRef)command) { case kCommandSetObjectRefGetType: return "CMD_OBJECT_REF_GET_TYPE"; case kCommandSetObjectRefGetValues: return "CMD_OBJECT_REF_GET_VALUES"; case kCommandSetObjectRefIsCollected: return "CMD_OBJECT_REF_IS_COLLECTED"; case kCommandSetObjectRefGetAddress: return "CMD_OBJECT_REF_GET_ADDRESS"; case kCommandSetObjectRefGetDomain: return "CMD_OBJECT_REF_GET_DOMAIN"; case kCommandSetObjectRefSetValues: return "CMD_OBJECT_REF_SET_VALUES"; default: return ""; } } case kCommandSetStringRef: { switch ((CommandSetStringRef)command) { case kCommandSetStringRefGetValue: return "CMD_STRING_REF_GET_VALUE"; default: return ""; } } case kCommandSetThread: { switch ((CommandSetThread)command) { case kCommandSetThreadGetName: return "CMD_THREAD_GET_NAME"; case kCommandSetThreadGetFrameInfo: return "CMD_THREAD_GET_FRAME_INFO"; case kCommandSetThreadGetState: return "CMD_THREAD_GET_STATE"; case kCommandSetThreadGetInfo: return "CMD_THREAD_GET_INFO"; case kCommandSetThreadGetId: return "CMD_THREAD_GET_ID"; default: return ""; } } case kCommandSetArrayRef: { switch ((CommandSetArrayRef)command) { case kCommandSetArrayRefGetLength: return "CMD_ARRAY_REF_GET_LENGTH"; case kCommandSetArrayRefGetValues: return "CMD_ARRAY_REF_GET_VALUES"; case kCommandSetArrayRefSetValues: return "CMD_ARRAY_REF_SET_VALUES"; default: return ""; } } case kCommandSetEventRequest: { switch ((CommandSetEvent)command) { case kCommandSetEventRequestSet: return "CMD_EVENT_REQUEST_SET"; case kCommandSetEventRequestClear: return "CMD_EVENT_REQUEST_CLEAR"; case kCommandSetEventRequestClearAllBreakpoints: return "CMD_EVENT_REQUEST_CLEAR_ALL_BREAKPOINTS"; default: return ""; } } case kCommandSetStackFrame: { switch ((CommandSetStackFrame)command) { case kCommandSetStackFrameGetValues: return "CMD_STACK_FRAME_GET_VALUES"; case kCommandSetStackFrameGetThis: return "CMD_STACK_FRAME_GET_THIS"; case kCommandSetStackFrameSetValues: return "CMD_STACK_FRAME_SET_VALUES"; default: return ""; } } case kCommandSetAppDomain: { switch ((CommandSetAppDomain)command) { case kCommandSetAppDomainGetRootDomain: return "CMD_APPDOMAIN_GET_ROOT_DOMAIN"; case kCommandSetAppDomainGetFriendlyName: return "CMD_APPDOMAIN_GET_FRIENDLY_NAME"; case kCommandSetAppDomainGetAssemblies: return "CMD_APPDOMAIN_GET_ASSEMBLIES"; case kCommandSetAppDomainGetEntryAssembly: return "CMD_APPDOMAIN_GET_ENTRY_ASSEMBLY"; case kCommandSetAppDomainCreateString: return "CMD_APPDOMAIN_CREATE_STRING"; case kCommandSetAppDomainGetCorlib: return "CMD_APPDOMAIN_GET_CORLIB"; case kCommandSetAppDomainCreateBoxedValue: return "CMD_APPDOMAIN_CREATE_BOXED_VALUE"; default: return ""; } } case kCommandSetAssembly: { switch ((CommandSetAssembly)command) { case kCommandSetAssemblyGetLocation: return "CMD_ASSEMBLY_GET_LOCATION"; case kCommandSetAssemblyGetEntryPoint: return "CMD_ASSEMBLY_GET_ENTRY_POINT"; case kCommandSetAssemblyGetManifestModule: return "CMD_ASSEMBLY_GET_MANIFEST_MODULE"; case kCommandSetAssemblyGetObject: return "CMD_ASSEMBLY_GET_OBJECT"; case kCommandSetAssemblyGetType: return "CMD_ASSEMBLY_GET_TYPE"; case kCommandSetAssemblyGetName: return "CMD_ASSEMBLY_GET_NAME"; default: return ""; } } case kCommandSetMethod: { switch ((CommandSetMethod)command) { case kCommandSetMethodGetName: return "CMD_METHOD_GET_NAME"; case kCommandSetMethodGetDeclaringType: return "CMD_METHOD_GET_DECLARING_TYPE"; case kCommandSetMethodGetDebugInfo: return "CMD_METHOD_GET_DEBUG_INFO"; case kCommandSetMethodGetParamInfo: return "CMD_METHOD_GET_PARAM_INFO"; case kCommandSetMethodGetLocalsInfo: return "CMD_METHOD_GET_LOCALS_INFO"; case kCommandSetMethodGetInfo: return "CMD_METHOD_GET_INFO"; case kCommandSetMethodGetBody: return "CMD_METHOD_GET_BODY"; case kCommandSetMethodResolveToken: return "CMD_METHOD_RESOLVE_TOKEN"; default: return ""; } } case kCommandSetType: { switch ((CommandSetType)command) { case kCommandSetTypeGetInfo: return "CMD_TYPE_GET_INFO"; case kCommandSetTypeGetMethods: return "CMD_TYPE_GET_METHODS"; case kCommandSetTypeGetFields: return "CMD_TYPE_GET_FIELDS"; case kCommandSetTypeGetValues: return "CMD_TYPE_GET_VALUES"; case kCommandSetTypeGetObject: return "CMD_TYPE_GET_OBJECT"; case kCommandSetTypeGetSourceFiles: return "CMD_TYPE_GET_SOURCE_FILES"; case kCommandSetTypeSetValues: return "CMD_TYPE_SET_VALUES"; case kCommandSetTypeIsAssignableFrom: return "CMD_TYPE_IS_ASSIGNABLE_FROM"; case kCommandSetTypeGetProperties: return "CMD_TYPE_GET_PROPERTIES"; case kCommandSetTypeGetCAttrs: return "CMD_TYPE_GET_CATTRS"; case kCommandSetTypeGetFieldCAttrs: return "CMD_TYPE_GET_FIELD_CATTRS"; case kCommandSetTypeGetPropertyCAttrs: return "CMD_TYPE_GET_PROPERTY_CATTRS"; case kCommandSetTypeGetSourceFiles2: return "CMD_TYPE_GET_SOURCE_FILES_2"; default: return ""; } } case kCommandSetModule: { switch ((CommandSetModule)command) { case kCommandSetModuleGetInfo: return "CMD_MODULE_GET_INFO"; default: return ""; } } case kCommandSetEvent: { switch ((CommandSetEvent)command) { case kCommandSetEventComposite: return "CMD_COMPOSITE"; default: return ""; } } default: return ""; } } const char* event_to_string(EventKind evt) { switch (evt) { case kEventKindVmStart: return "VM_START"; case kEventKindVmDeath: return "VM_DEATH"; case kEventKindThreadStart: return "THREAD_START"; case kEventKindThreadDeath: return "THREAD_DEATH"; case kEventKindAppDomainCreate: return "APPDOMAIN_CREATE"; case kEventKindAppDomainUnload: return "APPDOMAIN_UNLOAD"; case kEventKindMethodEntry: return "METHOD_ENTRY"; case kEventKindMethodExit: return "METHOD_EXIT"; case kEventKindAssemblyLoad: return "ASSEMBLY_LOAD"; case kEventKindAssemblyUnload: return "ASSEMBLY_UNLOAD"; case kEventKindBreakpoint: return "BREAKPOINT"; case kEventKindStep: return "STEP"; case kEventKindTypeLoad: return "TYPE_LOAD"; case kEventKindException: return "EXCEPTION"; default: return "INVALID"; } } } /* namespace debugger */ } /* namespace il2cpp */ #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/protocol/utils.h ================================================ #pragma once #include "../common.h" #include "globals.h" namespace il2cpp { namespace debugger { const char* event_to_string(EventKind evt); const char* command_set_to_string(CommandSet command_set); const char* command_to_string(CommandSet command_set, int command); } /* namespace debugger */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/debugger/thread-data.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "thread-data.h" #include "../os/Mutex.h" #include "../os/Atomic.h" #include "../os/Event.h" #include "../il2cpp-api.h" using namespace il2cpp::debugger; ThreadData::ThreadData(Il2CppThread *thread) : _thread(thread), _write_sync(new os::Mutex), _is_frames_cache_valid(0), _method_to_invoke_sync(new os::Mutex), _method_to_invoke_complete(new os::Event) { } ThreadData::~ThreadData() { _frames_cache.clear(); _thread = 0; } struct ThreadDataUpdateInfo { ThreadData *data; std::vector new_frames; }; bool ThreadData::IsFramesCacheValid() { return os::Atomic::CompareExchange(&_is_frames_cache_valid, _is_frames_cache_valid, 0) != 0; } const Il2CppStackFrameInfo *ThreadData::FrameById(int32_t id) { std::vector::const_iterator fit = _frames_cache.begin(); while (fit != _frames_cache.end()) { const Il2CppStackFrameInfo *frame = *fit; if (frame->id == id) return frame; ++fit; } return 0; } void ThreadData::UpdateFramesCacheIfNeeded() { os::AutoLock lock(_write_sync.get()); if (os::Atomic::CompareExchange(&_is_frames_cache_valid, _is_frames_cache_valid, 0) != 0) return; ThreadDataUpdateInfo info; info.data = this; il2cpp_thread_walk_frame_stack(_thread, ThreadData::UpdateStackFrame, &info); _frames_cache = info.new_frames; os::Atomic::Increment(&_is_frames_cache_valid); } void ThreadData::UpdateStackFrame(const Il2CppStackFrameInfo *info, void *user_data) { ThreadDataUpdateInfo *data = (ThreadDataUpdateInfo*)user_data; Il2CppStackFrameInfo *w_info = const_cast(info); if (w_info->id != -1) { // Let's try to recycle the frame id if possible std::vector::const_iterator it = data->data->frames_cache().begin(); std::vector::const_iterator end = data->data->frames_cache().end(); while (it != end) { const Il2CppStackFrameInfo *frame = *it; if ((uintptr_t)frame == (uintptr_t)info && (uintptr_t)frame->locals == (uintptr_t)info->locals) { // In this case, the frame is considered to be unchanged and we can keep the old ID. break; } ++it; } if (it == end) w_info->id = os::Atomic::Increment(&frame_id); } else w_info->id = os::Atomic::Increment(&frame_id); data->new_frames.push_back(info); } void ThreadData::InvalidateFramesCache() { os::AutoLock lock(_write_sync.get()); if (os::Atomic::CompareExchange(&_is_frames_cache_valid, _is_frames_cache_valid, 0) == 0) return; // Invalidate the frames cache os::Atomic::Decrement(&_is_frames_cache_valid); } void ThreadData::SetMethodToInvoke(const MethodInfo* method) { os::AutoLock lock(_method_to_invoke_sync.get()); IL2CPP_ASSERT(_method_to_invoke_data.method_to_invoke == NULL && "ThreadData::SetMethodToInvoke called with a method to invoke, when one is already waiting to be invoked"); _method_to_invoke_data.method_to_invoke = method; } const MethodInfo* ThreadData::GetMethodToInvoke() const { os::AutoLock lock(_method_to_invoke_sync.get()); return _method_to_invoke_data.method_to_invoke; } void ThreadData::ClearMethodToInvoke() { os::AutoLock lock(_method_to_invoke_sync.get()); _method_to_invoke_data.method_to_invoke = NULL; } void ThreadData::SetReturnValueOfMethodToInvoke(Il2CppObject* return_value) { os::AutoLock lock(_method_to_invoke_sync.get()); _method_to_invoke_data.return_value = return_value; } Il2CppObject* ThreadData::GetReturnValueOfMethodToInvoke() const { os::AutoLock lock(_method_to_invoke_sync.get()); return _method_to_invoke_data.return_value; } void ThreadData::WaitForMethodToBeInvoked() { _method_to_invoke_complete->Wait(); } void ThreadData::SignalMethodInvokeComplete() { _method_to_invoke_complete->Set(); } ThreadDataMap::ThreadDataMap() : _thread_to_data_sync(0) { _thread_to_data_sync = new os::Mutex(); } ThreadDataMap::~ThreadDataMap() { std::map::iterator it = _thread_to_data.begin(); while (it != _thread_to_data.end()) { ThreadData* data = it->second; delete data; ++it; } _thread_to_data.clear(); delete _thread_to_data_sync; _thread_to_data_sync = 0; } void ThreadDataMap::NotifyThreadAttach(Il2CppThread *thread) { os::AutoLock lock(_thread_to_data_sync); IL2CPP_ASSERT(_thread_to_data.find(thread) == _thread_to_data.end() && "ThreadDataMap::NotifyThreadAttach is being called twice on the same thread"); _thread_to_data[thread] = new ThreadData(thread); } void ThreadDataMap::NotifyThreadDetach(Il2CppThread *thread) { os::AutoLock lock(_thread_to_data_sync); std::map::const_iterator it = _thread_to_data.find(thread); IL2CPP_ASSERT(it != _thread_to_data.end() && "ThreadDataMap::NotifyThreadDetach is being called on a thread that was not attached"); delete it->second; _thread_to_data.erase(it); } bool ThreadDataMap::HasThreadDataForThread(const Il2CppThread *thread) const { os::AutoLock lock(_thread_to_data_sync); return _thread_to_data.find(thread) != _thread_to_data.end(); } bool ThreadDataMap::HasThreadDataForCurrentThread() const { return HasThreadDataForThread(il2cpp_thread_current()); } ThreadData *ThreadDataMap::ThreadDataFor(const Il2CppThread *thread) { os::AutoLock lock(_thread_to_data_sync); std::map::const_iterator it = _thread_to_data.find(thread); if (it == _thread_to_data.end()) return NULL; return it->second; } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/thread-data.h ================================================ #pragma once #include #include #include "common.h" #include "protocol/globals.h" struct Il2CppThread; struct Il2CppStackFrameInfo; namespace il2cpp { namespace os { class Mutex; class Event; } /* namespace os */ namespace debugger { struct MethodInvokeData { MethodInvokeData() : method_to_invoke(NULL), return_value(NULL) {} const MethodInfo* method_to_invoke; Il2CppObject* return_value; }; static int32_t frame_id = 0; class ThreadData { public: explicit ThreadData(Il2CppThread *thread); ~ThreadData(); inline Il2CppThread *thread() { return _thread; } inline std::vector &frames_cache() { return _frames_cache; } inline const std::vector &frames_cache() const { return _frames_cache; } void UpdateFramesCacheIfNeeded(); void InvalidateFramesCache(); bool IsFramesCacheValid(); const Il2CppStackFrameInfo *FrameById(int32_t id); void SetMethodToInvoke(const MethodInfo* method); const MethodInfo* GetMethodToInvoke() const; void ClearMethodToInvoke(); void SetReturnValueOfMethodToInvoke(Il2CppObject* return_value); Il2CppObject* GetReturnValueOfMethodToInvoke() const; void WaitForMethodToBeInvoked(); void SignalMethodInvokeComplete(); private: static void UpdateStackFrame(const Il2CppStackFrameInfo *info, void *user_data); Il2CppThread *_thread; const std::auto_ptr _write_sync; int32_t _is_frames_cache_valid; std::vector _frames_cache; const std::auto_ptr _method_to_invoke_sync; const std::auto_ptr _method_to_invoke_complete; MethodInvokeData _method_to_invoke_data; DISALLOW_COPY(ThreadData); }; class ThreadDataMap { public: ThreadDataMap(); ~ThreadDataMap(); void NotifyThreadAttach(Il2CppThread *thread); void NotifyThreadDetach(Il2CppThread *thread); bool HasThreadDataForThread(const Il2CppThread *thread) const; bool HasThreadDataForCurrentThread() const; ThreadData *ThreadDataFor(const Il2CppThread *thread); private: os::Mutex *_thread_to_data_sync; std::map _thread_to_data; DISALLOW_COPY(ThreadDataMap); }; } /* namespace debugger */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/debugger/transport-tcp.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "transport-tcp.h" #include #include #include namespace il2cpp { namespace debugger { struct TCPDataTransportHandle { int32_t listen_fd; int32_t client_fd; HANDLE send_mutex; TCPDataTransportHandle() : listen_fd(INVALID_SOCKET), client_fd(INVALID_SOCKET) { send_mutex = CreateMutex(0, false, L"send_mutex"); } ~TCPDataTransportHandle() { CloseHandle(send_mutex); send_mutex = 0; } }; } /* namespace debugger */ } /* namespace il2cpp */ using namespace il2cpp::debugger; TCPDataTransport::TCPDataTransport(const char *host, int32_t port) : _host(host), _port(port), _connected(false), _handle(new TCPDataTransportHandle()) { } TCPDataTransport::~TCPDataTransport() { delete _handle; _handle = 0; } bool TCPDataTransport::Setup() { int err; // Initialize Winsock WSADATA wsaData; err = WSAStartup(MAKEWORD(2, 2), &wsaData); if (err != 0) { LOG("WSAStartup failed with error: " << err); return false; } // Prepare connection std::stringstream oss; oss << _port; addrinfo hints; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_flags = 0; hints.ai_protocol = 0; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; addrinfo *result; err = getaddrinfo(_host, oss.str().c_str(), &hints, &result); if (err != 0) { LOG("Unable to connect to " << _host << ":" << _port << ": " << gai_strerror(err)); return false; } int socket_fd; for (addrinfo *rp = result; rp != NULL; rp = rp->ai_next) { socket_fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (socket_fd == INVALID_SOCKET) continue; err = bind(socket_fd, rp->ai_addr, rp->ai_addrlen); if (err != 0) continue; err = listen(socket_fd, 16); if (err != 0) continue; _handle->listen_fd = socket_fd; break; } freeaddrinfo(result); return true; } bool TCPDataTransport::WaitForClient() { // Wait for a client to connect .. _handle->client_fd = accept(_handle->listen_fd, NULL, NULL); if (_handle->client_fd == INVALID_SOCKET) { LOG("Unable to listen on " << _handle->listen_fd); return false; } LOG("Accepted connection from client, connection fd=" << _handle->listen_fd); _connected = true; // Set the socket as non blocking int flag = 1; int err = setsockopt(_handle->client_fd, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof(int)); if (err != 0) { LOG("Error setting TCP_NODELAY."); Close(); return false; } return true; } int32_t TCPDataTransport::Send(const uint8_t *data, size_t length, int flags) { // Note: still not sure a mutex is needed here. WaitForSingleObject(_handle->send_mutex, INFINITE); int32_t result = send(_handle->client_fd, (const char*)data, length, flags); ReleaseMutex(_handle->send_mutex); return result; } int32_t TCPDataTransport::Recv(uint8_t *data, size_t length, int flags) { int32_t read; size_t total_read = 0; do { read = recv(_handle->client_fd, (char*)data + total_read, length - total_read, flags); if (read > 0) total_read += read; } while ((read > 0 && total_read < length) || (read == -1 && errno == EINTR)); return total_read; } void TCPDataTransport::Close() { if (!_connected) return; shutdown(_handle->client_fd, SD_BOTH); shutdown(_handle->listen_fd, SD_BOTH); closesocket(_handle->client_fd); closesocket(_handle->listen_fd); _handle->listen_fd = INVALID_SOCKET; _handle->client_fd = INVALID_SOCKET; _connected = false; } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/transport-tcp.h ================================================ #pragma once #include "common.h" #include "transport.h" namespace il2cpp { namespace debugger { struct TCPDataTransportHandle; class TCPDataTransport : public IDataTransport { public: TCPDataTransport(const char *host, int32_t port); ~TCPDataTransport(); inline const char *host() const { return _host; } inline int32_t port() const { return _port; } inline bool connected() const { return _connected; } bool Setup(); bool WaitForClient(); int32_t Send(const uint8_t *data, size_t length, int flags = 0); int32_t Recv(uint8_t *data, size_t length, int flags = 0); void Close(); private: const char *_host; int32_t _port; bool _connected; TCPDataTransportHandle *_handle; DISALLOW_COPY(TCPDataTransport); }; } /* namespace debugger */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/debugger/transport.h ================================================ #pragma once #include "common.h" namespace il2cpp { namespace debugger { class IDataTransport { public: IDataTransport() {} virtual ~IDataTransport() {} virtual bool Setup() = 0; virtual bool WaitForClient() = 0; virtual int32_t Send(const uint8_t *data, size_t length, int flags = 0) = 0; virtual int32_t Recv(uint8_t *data, size_t length, int flags = 0) = 0; virtual void Close() = 0; DISALLOW_COPY(IDataTransport); }; } /* namespace debugger */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/debugger/variant.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "variant.h" #include "data-buffer.h" #include "../il2cpp-api.h" #include "../blob.h" #include "../tabledefs.h" #include "../class-internals.h" #include "../object-internals.h" #include "vm/Type.h" using namespace il2cpp::debugger; #define VALUE_TYPE_ID_NULL 0xF0 Variant::Variant() : _type(0), _value(0) { } Variant::Variant(const Il2CppType *type, void *value) : _type(type), _value(value) { } void Variant::WriteTo(Buffer &out) const { switch (_type->type) { case IL2CPP_TYPE_VOID: out.WriteByte(_type->type); break; case IL2CPP_TYPE_BOOLEAN: case IL2CPP_TYPE_I1: case IL2CPP_TYPE_U1: out.WriteByte(_type->type); out.WriteInt(*((int8_t*)_value)); break; case IL2CPP_TYPE_CHAR: case IL2CPP_TYPE_I2: case IL2CPP_TYPE_U2: out.WriteByte(_type->type); out.WriteInt(*((int16_t*)_value)); break; case IL2CPP_TYPE_I4: case IL2CPP_TYPE_U4: case IL2CPP_TYPE_R4: out.WriteByte(_type->type); out.WriteInt(*((int32_t*)_value)); break; case IL2CPP_TYPE_I8: case IL2CPP_TYPE_U8: case IL2CPP_TYPE_R8: out.WriteByte(_type->type); out.WriteLong(*((int64_t*)_value)); break; case IL2CPP_TYPE_I: case IL2CPP_TYPE_U: VTypeVariant(_type, _value).WriteTo(out); break; case IL2CPP_TYPE_PTR: out.WriteByte(_type->type); out.WriteLong(*((size_t*)_value)); break; // handle_ref: case IL2CPP_TYPE_STRING: case IL2CPP_TYPE_SZARRAY: case IL2CPP_TYPE_OBJECT: case IL2CPP_TYPE_CLASS: case IL2CPP_TYPE_ARRAY: { Il2CppObject *obj = *(Il2CppObject**)_value; if (!obj) { out.WriteByte(VALUE_TYPE_ID_NULL); } else { if (obj->klass->valuetype) { VTypeVariant(obj->klass->byval_arg, il2cpp_object_unbox(obj)).WriteTo(out); } else { if (obj->klass->rank) out.WriteByte(obj->klass->byval_arg->type); else if (obj->klass->byval_arg->type == IL2CPP_TYPE_GENERICINST) out.WriteByte(IL2CPP_TYPE_CLASS); else out.WriteByte(obj->klass->byval_arg->type); out.WriteObjectId(obj); } } } break; case IL2CPP_TYPE_VALUETYPE: VTypeVariant(_type, _value).WriteTo(out); break; case IL2CPP_TYPE_GENERICINST: LOG("Encoding of generic instance types not supported yet."); IL2CPP_ASSERT(0 && "Variant::WriteTo: encoding of generic instance types not supported yet"); break; default: IL2CPP_ASSERT(0 && "Variant::WriteTo: unexpected type"); break; } } ErrorCode Variant::ReadInto(Buffer &in, const Il2CppType *expected_type, void *addr) { // TODO: probably nullables need to be dealt with in a special way. Test it. int32_t type_code = in.ReadByte(); switch (type_code) { case IL2CPP_TYPE_BOOLEAN: *(uint8_t*)addr = in.ReadInt(); break; case IL2CPP_TYPE_CHAR: *(uint16_t*)addr = in.ReadInt(); break; case IL2CPP_TYPE_I1: *(int8_t*)addr = in.ReadInt(); break; case IL2CPP_TYPE_U1: *(uint8_t*)addr = in.ReadInt(); break; case IL2CPP_TYPE_I2: *(int16_t*)addr = in.ReadInt(); break; case IL2CPP_TYPE_U2: *(uint16_t*)addr = in.ReadInt(); break; case IL2CPP_TYPE_I4: *(int32_t*)addr = in.ReadInt(); break; case IL2CPP_TYPE_U4: *(uint32_t*)addr = in.ReadInt(); break; case IL2CPP_TYPE_I8: *(int64_t*)addr = in.ReadLong(); break; case IL2CPP_TYPE_U8: *(uint64_t*)addr = in.ReadLong(); break; case IL2CPP_TYPE_R4: *(uint32_t*)addr = in.ReadInt(); break; case IL2CPP_TYPE_R8: *(uint64_t*)addr = in.ReadLong(); break; case IL2CPP_TYPE_PTR: *(size_t*)addr = in.ReadLong(); break; case IL2CPP_TYPE_GENERICINST: /*if (IL2CPP_TYPE_ISSTRUCT (t)) goto handle_vtype; else goto handle_ref;*/ LOG("Decoding of generic instance types not supported yet."); IL2CPP_ASSERT(0 && "Variant::ReadFrom: encoding of generic instance types not supported yet"); break; // handle_vtype: case IL2CPP_TYPE_I: case IL2CPP_TYPE_U: case IL2CPP_TYPE_VALUETYPE: { bool is_enum = in.ReadBool(); IL2CPP_ASSERT(!is_enum && "Variant::ReadFrom: is_enum not implemented!"); Il2CppClass *klass = in.ReadType(); void *iter = 0; FieldInfo *field; int32_t fields_count = in.ReadInt(); while ((field = il2cpp_class_get_fields(klass, &iter))) { if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) continue; /*if(il2cpp_field_is_deleted (field)) continue;*/ Variant::ReadInto(in, field->type, (uint8_t*)addr + field->offset - sizeof(Il2CppObject)); --fields_count; } IL2CPP_ASSERT(fields_count == 0 && "Variant::ReadFrom: some fields have not been decoded properly!"); } break; // handle_ref: default: { IL2CPP_ASSERT(!vm::Type::IsValueType(expected_type) && "Variant::ReadFrom: expecting a reference type!"); switch (type_code) { case IL2CPP_TYPE_OBJECT: { Il2CppObject *obj = in.ReadObject(); if (obj && !il2cpp_class_is_assignable_from(il2cpp_class_from_il2cpp_type(expected_type), obj->klass)) return kErrorCodeInvalidArgument; *(Il2CppObject**)addr = obj; } break; case VALUE_TYPE_ID_NULL: *(Il2CppObject**)addr = NULL; break; default: IL2CPP_ASSERT(0 && "Variant::ReadFrom: unexpected type code!"); break; } } break; } return kErrorCodeNone; } VTypeVariant::VTypeVariant() : Variant(0, 0) { } VTypeVariant::VTypeVariant(const Il2CppType *type, void *value) : Variant(type, value) { } void VTypeVariant::WriteTo(Buffer &out) const { switch (type()->type) { case IL2CPP_TYPE_BOOLEAN: case IL2CPP_TYPE_I1: case IL2CPP_TYPE_U1: case IL2CPP_TYPE_CHAR: case IL2CPP_TYPE_I2: case IL2CPP_TYPE_U2: case IL2CPP_TYPE_I4: case IL2CPP_TYPE_U4: case IL2CPP_TYPE_R4: case IL2CPP_TYPE_I8: case IL2CPP_TYPE_U8: case IL2CPP_TYPE_R8: case IL2CPP_TYPE_I: case IL2CPP_TYPE_U: case IL2CPP_TYPE_PTR: case IL2CPP_TYPE_VALUETYPE: { FieldInfo *field_info; Il2CppClass *klass = il2cpp_class_from_il2cpp_type(type()); out.WriteByte(IL2CPP_TYPE_VALUETYPE); out.WriteByte(klass->enumtype); out.WriteTypeId(klass); size_t nfields = 0; void *iter = NULL; while ((field_info = il2cpp_class_get_fields(klass, &iter))) { if (field_info->type->attrs & FIELD_ATTRIBUTE_STATIC) continue; /*if (il2cpp_field_is_deleted(field_info)) continue;*/ nfields++; } out.WriteInt(nfields); iter = NULL; while ((field_info = il2cpp_class_get_fields(klass, &iter))) { if (field_info->type->attrs & FIELD_ATTRIBUTE_STATIC) continue; /*if (il2cpp_field_is_deleted(field_info)) continue;*/ Variant(field_info->type, (uint8_t*)value() + field_info->offset - sizeof(Il2CppObject)).WriteTo(out); } } break; default: Variant::WriteTo(out); break; } } #endif ================================================ FILE: unity_decoder/libil2cpp/debugger/variant.h ================================================ #pragma once #include "common.h" #include "protocol/globals.h" namespace il2cpp { namespace debugger { class Buffer; class Variant { public: Variant(); Variant(const Il2CppType *type, void *value); inline const Il2CppType *type() const { return _type; } inline void *value() const { return _value; } virtual void WriteTo(Buffer &out) const; static ErrorCode ReadInto(Buffer & in, const Il2CppType * expected_type, void *addr); private: const Il2CppType *_type; void *_value; }; class VTypeVariant : public Variant { public: VTypeVariant(); VTypeVariant(const Il2CppType *type, void *value); virtual void WriteTo(Buffer &out) const; }; } /* namespace debugger */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/external/google/sparsehash/dense_hash_map.h ================================================ // Copyright (c) 2005, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ---- // Author: Craig Silverstein // // This is just a very thin wrapper over densehashtable.h, just // like sgi stl's stl_hash_map is a very thin wrapper over // stl_hashtable. The major thing we define is operator[], because // we have a concept of a data_type which stl_hashtable doesn't // (it only has a key and a value). // // NOTE: this is exactly like sparse_hash_map.h, with the word // "sparse" replaced by "dense", except for the addition of // set_empty_key(). // // YOU MUST CALL SET_EMPTY_KEY() IMMEDIATELY AFTER CONSTRUCTION. // // Otherwise your program will die in mysterious ways. // // In other respects, we adhere mostly to the STL semantics for // hash-map. One important exception is that insert() invalidates // iterators entirely. On the plus side, though, erase() doesn't // invalidate iterators at all, or even change the ordering of elements. // // Here are a few "power user" tips: // // 1) set_deleted_key(): // If you want to use erase() you must call set_deleted_key(), // in addition to set_empty_key(), after construction. // The deleted and empty keys must differ. // // 2) resize(0): // When an item is deleted, its memory isn't freed right // away. This allows you to iterate over a hashtable, // and call erase(), without invalidating the iterator. // To force the memory to be freed, call resize(0). // // Guide to what kind of hash_map to use: // (1) dense_hash_map: fastest, uses the most memory // (2) sparse_hash_map: slowest, uses the least memory // (3) hash_map (STL): in the middle // Typically I use sparse_hash_map when I care about space and/or when // I need to save the hashtable on disk. I use hash_map otherwise. I // don't personally use dense_hash_map ever; the only use of // dense_hash_map I know of is to work around malloc() bugs in some // systems (dense_hash_map has a particularly simple allocation scheme). // // - dense_hash_map has, typically, a factor of 2 memory overhead (if your // data takes up X bytes, the hash_map uses X more bytes in overhead). // - sparse_hash_map has about 2 bits overhead per entry. // - sparse_hash_map can be 3-7 times slower than the others for lookup and, // especially, inserts. See time_hash_map.cc for details. // // See /usr/(local/)?doc/sparsehash-0.1/dense_hash_map.html // for information about how to use this class. #ifndef _DENSE_HASH_MAP_H_ #define _DENSE_HASH_MAP_H_ //#include #include // for FILE * in read()/write() #include // for the default template args #include // for equal_to #include // for alloc<> #include // for pair<> //#include // defined in config.h #include "densehashtable.h" using std::pair; template , class Alloc = std::allocator< std::pair > > class dense_hash_map { private: // Apparently select1st is not stl-standard, so we define our own struct SelectKey { const Key& operator()(const pair& p) const { return p.first; } }; // The actual data typedef dense_hashtable, Key, HashFcn, SelectKey, EqualKey, Alloc> ht; ht rep; public: typedef typename ht::key_type key_type; typedef T data_type; typedef T mapped_type; typedef typename ht::value_type value_type; typedef typename ht::hasher hasher; typedef typename ht::key_equal key_equal; typedef typename ht::size_type size_type; typedef typename ht::difference_type difference_type; typedef typename ht::pointer pointer; typedef typename ht::const_pointer const_pointer; typedef typename ht::reference reference; typedef typename ht::const_reference const_reference; typedef typename ht::iterator iterator; typedef typename ht::const_iterator const_iterator; // Iterator functions iterator begin() { return rep.begin(); } iterator end() { return rep.end(); } const_iterator begin() const { return rep.begin(); } const_iterator end() const { return rep.end(); } // Accessor functions hasher hash_funct() const { return rep.hash_funct(); } key_equal key_eq() const { return rep.key_eq(); } // Constructors explicit dense_hash_map(size_type n = 0, const hasher& hf = hasher(), const key_equal& eql = key_equal()) : rep(n, hf, eql) { } template dense_hash_map(InputIterator f, InputIterator l, size_type n = 0, const hasher& hf = hasher(), const key_equal& eql = key_equal()) : rep(n, hf, eql) { rep.insert(f, l); } // We use the default copy constructor // We use the default operator=() // We use the default destructor void clear() { rep.clear(); } // This clears the hash map without resizing it down to the minimum // bucket count, but rather keeps the number of buckets constant void clear_no_resize() { rep.clear_no_resize(); } void swap(dense_hash_map& hs) { rep.swap(hs.rep); } // Functions concerning size size_type size() const { return rep.size(); } size_type max_size() const { return rep.max_size(); } bool empty() const { return rep.empty(); } size_type bucket_count() const { return rep.bucket_count(); } size_type max_bucket_count() const { return rep.max_bucket_count(); } void resize(size_type hint) { rep.resize(hint); } // Lookup routines iterator find(const key_type& key) { return rep.find(key); } const_iterator find(const key_type& key) const { return rep.find(key); } data_type& operator[](const key_type& key) { // This is our value-add! iterator it = find(key); if (it != end()) { return it->second; } else { return insert(value_type(key, data_type())).first->second; } } size_type count(const key_type& key) const { return rep.count(key); } pair equal_range(const key_type& key) { return rep.equal_range(key); } pair equal_range(const key_type& key) const { return rep.equal_range(key); } // Insertion routines pair insert(const value_type& obj) { return rep.insert(obj); } template void insert(InputIterator f, InputIterator l) { rep.insert(f, l); } void insert(const_iterator f, const_iterator l) { rep.insert(f, l); } // required for std::insert_iterator; the passed-in iterator is ignored iterator insert(iterator, const value_type& obj) { return insert(obj).first; } // Deletion and empty routines // THESE ARE NON-STANDARD! I make you specify an "impossible" key // value to identify deleted and empty buckets. You can change the // deleted key as time goes on, or get rid of it entirely to be insert-only. void set_empty_key(const key_type& key) { // YOU MUST CALL THIS! rep.set_empty_key(value_type(key, data_type())); // rep wants a value } void set_deleted_key(const key_type& key) { rep.set_deleted_key(value_type(key, data_type())); // rep wants a value } void clear_deleted_key() { rep.clear_deleted_key(); } // These are standard size_type erase(const key_type& key) { return rep.erase(key); } void erase(iterator it) { rep.erase(it); } void erase(iterator f, iterator l) { rep.erase(f, l); } // Comparison bool operator==(const dense_hash_map& hs) const { return rep == hs.rep; } bool operator!=(const dense_hash_map& hs) const { return rep != hs.rep; } }; // We need a global swap as well template inline void swap(dense_hash_map& hm1, dense_hash_map& hm2) { hm1.swap(hm2); } #endif /* _DENSE_HASH_MAP_H_ */ ================================================ FILE: unity_decoder/libil2cpp/external/google/sparsehash/dense_hash_set.h ================================================ // Copyright (c) 2005, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // --- // Author: Craig Silverstein // // This is just a very thin wrapper over densehashtable.h, just // like sgi stl's stl_hash_set is a very thin wrapper over // stl_hashtable. The major thing we define is operator[], because // we have a concept of a data_type which stl_hashtable doesn't // (it only has a key and a value). // // This is more different from dense_hash_map than you might think, // because all iterators for sets are const (you obviously can't // change the key, and for sets there is no value). // // NOTE: this is exactly like sparse_hash_set.h, with the word // "sparse" replaced by "dense", except for the addition of // set_empty_key(). // // YOU MUST CALL SET_EMPTY_KEY() IMMEDIATELY AFTER CONSTRUCTION. // // Otherwise your program will die in mysterious ways. // // In other respects, we adhere mostly to the STL semantics for // hash-set. One important exception is that insert() invalidates // iterators entirely. On the plus side, though, erase() doesn't // invalidate iterators at all, or even change the ordering of elements. // // Here are a few "power user" tips: // // 1) set_deleted_key(): // If you want to use erase() you must call set_deleted_key(), // in addition to set_empty_key(), after construction. // The deleted and empty keys must differ. // // 2) resize(0): // When an item is deleted, its memory isn't freed right // away. This allows you to iterate over a hashtable, // and call erase(), without invalidating the iterator. // To force the memory to be freed, call resize(0). // // Guide to what kind of hash_set to use: // (1) dense_hash_set: fastest, uses the most memory // (2) sparse_hash_set: slowest, uses the least memory // (3) hash_set (STL): in the middle // Typically I use sparse_hash_set when I care about space and/or when // I need to save the hashtable on disk. I use hash_set otherwise. I // don't personally use dense_hash_set ever; the only use of // dense_hash_set I know of is to work around malloc() bugs in some // systems (dense_hash_set has a particularly simple allocation scheme). // // - dense_hash_set has, typically, a factor of 2 memory overhead (if your // data takes up X bytes, the hash_set uses X more bytes in overhead). // - sparse_hash_set has about 2 bits overhead per entry. // - sparse_hash_map can be 3-7 times slower than the others for lookup and, // especially, inserts. See time_hash_map.cc for details. // // See /usr/(local/)?doc/sparsehash-0.1/dense_hash_set.html // for information about how to use this class. #ifndef _DENSE_HASH_SET_H_ #define _DENSE_HASH_SET_H_ //#include #include // for FILE * in read()/write() #include // for the default template args #include // for equal_to #include // for alloc<> #include // for pair<> //#include HASH_FUN_H // defined in config.h #include "densehashtable.h" using std::pair; template , class Alloc = std::allocator > class dense_hash_set { private: // Apparently identity is not stl-standard, so we define our own struct Identity { Value& operator()(Value& v) const { return v; } const Value& operator()(const Value& v) const { return v; } }; // The actual data typedef dense_hashtable ht; ht rep; public: typedef typename ht::key_type key_type; typedef typename ht::value_type value_type; typedef typename ht::hasher hasher; typedef typename ht::key_equal key_equal; typedef typename ht::size_type size_type; typedef typename ht::difference_type difference_type; typedef typename ht::const_pointer pointer; typedef typename ht::const_pointer const_pointer; typedef typename ht::const_reference reference; typedef typename ht::const_reference const_reference; typedef typename ht::const_iterator iterator; typedef typename ht::const_iterator const_iterator; // Iterator functions -- recall all iterators are const iterator begin() const { return rep.begin(); } iterator end() const { return rep.end(); } // Accessor functions hasher hash_funct() const { return rep.hash_funct(); } key_equal key_eq() const { return rep.key_eq(); } // Constructors explicit dense_hash_set(size_type n = 0, const hasher& hf = hasher(), const key_equal& eql = key_equal()) : rep(n, hf, eql) { } template dense_hash_set(InputIterator f, InputIterator l, size_type n = 0, const hasher& hf = hasher(), const key_equal& eql = key_equal()) : rep(n, hf, eql) { rep.insert(f, l); } // We use the default copy constructor // We use the default operator=() // We use the default destructor void clear() { rep.clear(); } // This clears the hash set without resizing it down to the minimum // bucket count, but rather keeps the number of buckets constant void clear_no_resize() { rep.clear_no_resize(); } void swap(dense_hash_set& hs) { rep.swap(hs.rep); } // Functions concerning size size_type size() const { return rep.size(); } size_type max_size() const { return rep.max_size(); } bool empty() const { return rep.empty(); } size_type bucket_count() const { return rep.bucket_count(); } size_type max_bucket_count() const { return rep.max_bucket_count(); } void resize(size_type hint) { rep.resize(hint); } // Lookup routines iterator find(const key_type& key) const { return rep.find(key); } size_type count(const key_type& key) const { return rep.count(key); } pair equal_range(const key_type& key) const { return rep.equal_range(key); } // Insertion routines pair insert(const value_type& obj) { pair p = rep.insert(obj); return pair(p.first, p.second); // const to non-const } template void insert(InputIterator f, InputIterator l) { rep.insert(f, l); } void insert(const_iterator f, const_iterator l) { rep.insert(f, l); } // required for std::insert_iterator; the passed-in iterator is ignored iterator insert(iterator, const value_type& obj) { return insert(obj).first; } // Deletion and empty routines // THESE ARE NON-STANDARD! I make you specify an "impossible" key // value to identify deleted and empty buckets. You can change the // deleted key as time goes on, or get rid of it entirely to be insert-only. void set_empty_key(const key_type& key) { rep.set_empty_key(key); } void set_deleted_key(const key_type& key) { rep.set_deleted_key(key); } void clear_deleted_key() { rep.clear_deleted_key(); } // These are standard size_type erase(const key_type& key) { return rep.erase(key); } void erase(iterator it) { rep.erase(it); } void erase(iterator f, iterator l) { rep.erase(f, l); } // Comparison bool operator==(const dense_hash_set& hs) const { return rep == hs.rep; } bool operator!=(const dense_hash_set& hs) const { return rep != hs.rep; } }; template inline void swap(dense_hash_set& hs1, dense_hash_set& hs2) { hs1.swap(hs2); } #endif /* _DENSE_HASH_SET_H_ */ ================================================ FILE: unity_decoder/libil2cpp/external/google/sparsehash/densehashtable.h ================================================ // Copyright (c) 2005, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // --- // Author: Craig Silverstein // // A dense hashtable is a particular implementation of // a hashtable: one that is meant to minimize memory allocation. // It does this by using an array to store all the data. We // steal a value from the key space to indicate "empty" array // elements (ie indices where no item lives) and another to indicate // "deleted" elements. // // (Note it is possible to change the value of the delete key // on the fly; you can even remove it, though after that point // the hashtable is insert_only until you set it again. The empty // value however can't be changed.) // // To minimize allocation and pointer overhead, we use internal // probing, in which the hashtable is a single table, and collisions // are resolved by trying to insert again in another bucket. The // most cache-efficient internal probing schemes are linear probing // (which suffers, alas, from clumping) and quadratic probing, which // is what we implement by default. // // Type requirements: value_type is required to be Copy Constructible // and Default Constructible. It is not required to be (and commonly // isn't) Assignable. // // You probably shouldn't use this code directly. Use // or instead. // You can change the following below: // HT_OCCUPANCY_FLT -- how full before we double size // HT_EMPTY_FLT -- how empty before we halve size // HT_MIN_BUCKETS -- default smallest bucket size // // How to decide what values to use? // HT_EMPTY_FLT's default of .4 * OCCUPANCY_FLT, is probably good. // HT_MIN_BUCKETS is probably unnecessary since you can specify // (indirectly) the starting number of buckets at construct-time. // For HT_OCCUPANCY_FLT, you can use this chart to try to trade-off // expected lookup time to the space taken up. By default, this // code uses quadratic probing, though you can change it to linear // via _JUMP below if you really want to. // // From http://www.augustana.ca/~mohrj/courses/1999.fall/csc210/lecture_notes/hashing.html // NUMBER OF PROBES / LOOKUP Successful Unsuccessful // Quadratic collision resolution 1 - ln(1-L) - L/2 1/(1-L) - L - ln(1-L) // Linear collision resolution [1+1/(1-L)]/2 [1+1/(1-L)2]/2 // // -- HT_OCCUPANCY_FLT -- 0.10 0.50 0.60 0.75 0.80 0.90 0.99 // QUADRATIC COLLISION RES. // probes/successful lookup 1.05 1.44 1.62 2.01 2.21 2.85 5.11 // probes/unsuccessful lookup 1.11 2.19 2.82 4.64 5.81 11.4 103.6 // LINEAR COLLISION RES. // probes/successful lookup 1.06 1.5 1.75 2.5 3.0 5.5 50.5 // probes/unsuccessful lookup 1.12 2.5 3.6 8.5 13.0 50.0 5000.0 #ifndef _DENSEHASHTABLE_H_ #define _DENSEHASHTABLE_H_ // The probing method // Linear probing // #define JUMP_(key, num_probes) ( 1 ) // Quadratic-ish probing #define JUMP_(key, num_probes) ( num_probes ) // Hashtable class, used to implement the hashed associative containers // hash_set and hash_map. //#include #include // Use Unity's assertion pathways // #include "Runtime/Logging/LogAssert.h" //#include // for abort() //#include // For swap(), eg //#include // For cerr #include // For uninitialized_fill, uninitialized_copy //#include // for pair<> //#include // for facts about iterator tags #include "type_traits.h" // for true_type, integral_constant, etc. using std::pair; template class dense_hashtable; template struct dense_hashtable_iterator; template struct dense_hashtable_const_iterator; // We're just an array, but we need to skip over empty and deleted elements template struct dense_hashtable_iterator { public: typedef dense_hashtable_iterator iterator; typedef dense_hashtable_const_iterator const_iterator; typedef std::forward_iterator_tag iterator_category; typedef V value_type; typedef std::ptrdiff_t difference_type; typedef size_t size_type; typedef V& reference; // Value typedef V* pointer; // "Real" constructor and default constructor dense_hashtable_iterator(const dense_hashtable *h, pointer it, pointer it_end, bool advance) : ht(h), pos(it), end(it_end) { if (advance) advance_past_empty_and_deleted(); } dense_hashtable_iterator() { } // The default destructor is fine; we don't define one // The default operator= is fine; we don't define one // Happy dereferencer reference operator*() const { return *pos; } pointer operator->() const { return &(operator*()); } // Arithmetic. The only hard part is making sure that // we're not on an empty or marked-deleted array element void advance_past_empty_and_deleted() { while ( pos != end && (ht->test_empty(*this) || ht->test_deleted(*this)) ) ++pos; } iterator& operator++() { Assert(pos != end); ++pos; advance_past_empty_and_deleted(); return *this; } iterator operator++(int) { iterator tmp(*this); ++*this; return tmp; } // Comparison. bool operator==(const iterator& it) const { return pos == it.pos; } bool operator!=(const iterator& it) const { return pos != it.pos; } // The actual data const dense_hashtable *ht; pointer pos, end; }; // Now do it all again, but with const-ness! template struct dense_hashtable_const_iterator { public: typedef dense_hashtable_iterator iterator; typedef dense_hashtable_const_iterator const_iterator; typedef std::forward_iterator_tag iterator_category; typedef V value_type; typedef std::ptrdiff_t difference_type; typedef size_t size_type; typedef const V& reference; // Value typedef const V* pointer; // "Real" constructor and default constructor dense_hashtable_const_iterator(const dense_hashtable *h, pointer it, pointer it_end, bool advance) : ht(h), pos(it), end(it_end) { if (advance) advance_past_empty_and_deleted(); } dense_hashtable_const_iterator() { } // This lets us convert regular iterators to const iterators dense_hashtable_const_iterator(const iterator &it) : ht(it.ht), pos(it.pos), end(it.end) { } // The default destructor is fine; we don't define one // The default operator= is fine; we don't define one // Happy dereferencer reference operator*() const { return *pos; } pointer operator->() const { return &(operator*()); } // Arithmetic. The only hard part is making sure that // we're not on an empty or marked-deleted array element void advance_past_empty_and_deleted() { while ( pos != end && (ht->test_empty(*this) || ht->test_deleted(*this)) ) ++pos; } const_iterator& operator++() { Assert(pos != end); ++pos; advance_past_empty_and_deleted(); return *this; } const_iterator operator++(int) { const_iterator tmp(*this); ++*this; return tmp; } // Comparison. bool operator==(const const_iterator& it) const { return pos == it.pos; } bool operator!=(const const_iterator& it) const { return pos != it.pos; } // The actual data const dense_hashtable *ht; pointer pos, end; }; template class dense_hashtable { public: typedef Key key_type; typedef Value value_type; typedef HashFcn hasher; typedef EqualKey key_equal; typedef size_t size_type; typedef std::ptrdiff_t difference_type; typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; typedef dense_hashtable_iterator iterator; typedef dense_hashtable_const_iterator const_iterator; // How full we let the table get before we resize. Knuth says .8 is // good -- higher causes us to probe too much, though saves memory static const float HT_OCCUPANCY_FLT; // = 0.8; // How empty we let the table get before we resize lower. // (0.0 means never resize lower.) // It should be less than OCCUPANCY_FLT / 2 or we thrash resizing static const float HT_EMPTY_FLT; // = 0.4 * HT_OCCUPANCY_FLT // Minimum size we're willing to let hashtables be. // Must be a power of two, and at least 4. // Note, however, that for a given hashtable, the initial size is a // function of the first constructor arg, and may be >HT_MIN_BUCKETS. static const size_t HT_MIN_BUCKETS = 32; // ITERATOR FUNCTIONS iterator begin() { return iterator(this, table, table + num_buckets, true); } iterator end() { return iterator(this, table + num_buckets, table + num_buckets, true); } const_iterator begin() const { return const_iterator(this, table, table+num_buckets,true);} const_iterator end() const { return const_iterator(this, table + num_buckets, table+num_buckets,true);} // ACCESSOR FUNCTIONS for the things we templatize on, basically hasher hash_funct() const { return hash; } key_equal key_eq() const { return equals; } // Annoyingly, we can't copy values around, because they might have // const components (they're probably pair). We use // explicit destructor invocation and placement new to get around // this. Arg. private: void set_value(value_type* dst, const value_type& src) { dst->~value_type(); new(dst) value_type(src); } void destroy_buckets(size_type first, size_type last) { for ( ; first != last; ++first) table[first].~value_type(); } // DELETE HELPER FUNCTIONS // This lets the user describe a key that will indicate deleted // table entries. This key should be an "impossible" entry -- // if you try to insert it for real, you won't be able to retrieve it! // (NB: while you pass in an entire value, only the key part is looked // at. This is just because I don't know how to assign just a key.) private: void squash_deleted() { // gets rid of any deleted entries we have if ( num_deleted ) { // get rid of deleted before writing dense_hashtable tmp(*this); // copying will get rid of deleted swap(tmp); // now we are tmp } Assert(num_deleted == 0); } public: void set_deleted_key(const value_type &val) { // the empty indicator (if specified) and the deleted indicator // must be different Assert(!use_empty || !equals(get_key(val), get_key(emptyval))); // It's only safe to change what "deleted" means if we purge deleted guys squash_deleted(); use_deleted = true; set_value(&delval, val); } void clear_deleted_key() { squash_deleted(); use_deleted = false; } // These are public so the iterators can use them // True if the item at position bucknum is "deleted" marker bool test_deleted(size_type bucknum) const { // The num_deleted test is crucial for read(): after read(), the ht values // are garbage, and we don't want to think some of them are deleted. return (use_deleted && num_deleted > 0 && equals(get_key(delval), get_key(table[bucknum]))); } bool test_deleted(const iterator &it) const { return (use_deleted && num_deleted > 0 && equals(get_key(delval), get_key(*it))); } bool test_deleted(const const_iterator &it) const { return (use_deleted && num_deleted > 0 && equals(get_key(delval), get_key(*it))); } // Set it so test_deleted is true. true if object didn't used to be deleted // See below (at erase()) to explain why we allow const_iterators bool set_deleted(const_iterator &it) { Assert(use_deleted); // bad if set_deleted_key() wasn't called bool retval = !test_deleted(it); // &* converts from iterator to value-type set_value(const_cast(&(*it)), delval); return retval; } // Set it so test_deleted is false. true if object used to be deleted bool clear_deleted(const_iterator &it) { Assert(use_deleted); // bad if set_deleted_key() wasn't called // happens automatically when we assign something else in its place return test_deleted(it); } // EMPTY HELPER FUNCTIONS // This lets the user describe a key that will indicate empty (unused) // table entries. This key should be an "impossible" entry -- // if you try to insert it for real, you won't be able to retrieve it! // (NB: while you pass in an entire value, only the key part is looked // at. This is just because I don't know how to assign just a key.) public: // These are public so the iterators can use them // True if the item at position bucknum is "empty" marker bool test_empty(size_type bucknum) const { Assert(use_empty); // we always need to know what's empty! return equals(get_key(emptyval), get_key(table[bucknum])); } bool test_empty(const iterator &it) const { Assert(use_empty); // we always need to know what's empty! return equals(get_key(emptyval), get_key(*it)); } bool test_empty(const const_iterator &it) const { Assert(use_empty); // we always need to know what's empty! return equals(get_key(emptyval), get_key(*it)); } private: // You can either set a range empty or an individual element void set_empty(size_type bucknum) { Assert(use_empty); set_value(&table[bucknum], emptyval); } void fill_range_with_empty(value_type* table_start, value_type* table_end) { // Like set_empty(range), but doesn't destroy previous contents std::uninitialized_fill(table_start, table_end, emptyval); } void set_empty(size_type buckstart, size_type buckend) { Assert(use_empty); destroy_buckets(buckstart, buckend); fill_range_with_empty(table + buckstart, table + buckend); } public: // TODO(csilvers): change all callers of this to pass in a key instead, // and take a const key_type instead of const value_type. void set_empty_key(const value_type &val) { // Once you set the empty key, you can't change it Assert(!use_empty); // The deleted indicator (if specified) and the empty indicator // must be different. Assert(!use_deleted || !equals(get_key(val), get_key(delval))); use_empty = true; set_value(&emptyval, val); Assert(!table); // must set before first use // num_buckets was set in constructor even though table was NULL table = _Alval.allocate(num_buckets); Assert(table); fill_range_with_empty(table, table + num_buckets); } // FUNCTIONS CONCERNING SIZE public: size_type size() const { return num_elements - num_deleted; } // Buckets are always a power of 2 size_type max_size() const { return (size_type(-1) >> 1U) + 1; } bool empty() const { return size() == 0; } size_type bucket_count() const { return num_buckets; } size_type max_bucket_count() const { return max_size(); } size_type nonempty_bucket_count() const { return num_elements; } private: // Because of the above, size_type(-1) is never legal; use it for errors static const size_type ILLEGAL_BUCKET = size_type(-1); private: // This is the smallest size a hashtable can be without being too crowded // If you like, you can give a min #buckets as well as a min #elts size_type min_size(size_type num_elts, size_type min_buckets_wanted) { size_type sz = HT_MIN_BUCKETS; // min buckets allowed while ( sz < min_buckets_wanted || num_elts >= sz * HT_OCCUPANCY_FLT ) sz *= 2; return sz; } // Used after a string of deletes void maybe_shrink() { Assert(num_elements >= num_deleted); Assert((bucket_count() & (bucket_count()-1)) == 0); // is a power of two Assert(bucket_count() >= HT_MIN_BUCKETS); if ( (num_elements-num_deleted) < shrink_threshold && bucket_count() > HT_MIN_BUCKETS ) { size_type sz = bucket_count() / 2; // find how much we should shrink while ( sz > HT_MIN_BUCKETS && (num_elements - num_deleted) < sz * HT_EMPTY_FLT ) sz /= 2; // stay a power of 2 dense_hashtable tmp(*this, sz); // Do the actual resizing swap(tmp); // now we are tmp } consider_shrink = false; // because we just considered it } // We'll let you resize a hashtable -- though this makes us copy all! // When you resize, you say, "make it big enough for this many more elements" void resize_delta(size_type delta, size_type min_buckets_wanted = 0) { if ( consider_shrink ) // see if lots of deletes happened maybe_shrink(); if ( bucket_count() > min_buckets_wanted && (num_elements + delta) <= enlarge_threshold ) return; // we're ok as we are // Sometimes, we need to resize just to get rid of all the // "deleted" buckets that are clogging up the hashtable. So when // deciding whether to resize, count the deleted buckets (which // are currently taking up room). But later, when we decide what // size to resize to, *don't* count deleted buckets, since they // get discarded during the resize. const size_type needed_size = min_size(num_elements + delta, min_buckets_wanted); if ( needed_size > bucket_count() ) { // we don't have enough buckets const size_type resize_to = min_size(num_elements - num_deleted + delta, min_buckets_wanted); dense_hashtable tmp(*this, resize_to); swap(tmp); // now we are tmp } } // Increase number of buckets, assuming value_type has trivial copy // constructor and destructor. (Really, we want it to have "trivial // move", because that's what realloc does. But there's no way to // capture that using type_traits, so we pretend that move(x, y) is // equivalent to "x.~T(); new(x) T(y);" which is pretty much // correct, if a bit conservative.) void expand_array(size_t resize_to, dense_hash_map_traits::true_type) { value_type* new_table = _Alval.allocate(resize_to); Assert(new_table); if(table) { std::uninitialized_copy(table, table + num_buckets, new_table); _Alval.deallocate(table, num_buckets); } fill_range_with_empty(new_table + num_buckets, new_table + resize_to); table = new_table; Assert(table); } // Increase number of buckets, without special assumptions about value_type. // TODO(austern): make this exception safe. Handle exceptions from // value_type's copy constructor. void expand_array(size_t resize_to, dense_hash_map_traits::false_type) { value_type* new_table = _Alval.allocate(resize_to); Assert(new_table); std::uninitialized_copy(table, table + std::min(num_buckets,resize_to), new_table); fill_range_with_empty(new_table + num_buckets, new_table + resize_to); destroy_buckets(0, num_buckets); _Alval.deallocate(table, num_buckets); table = new_table; } // Used to actually do the rehashing when we grow/shrink a hashtable void copy_from(const dense_hashtable &ht, size_type min_buckets_wanted = 0) { clear(); // clear table, set num_deleted to 0 // If we need to change the size of our table, do it now const size_type resize_to = min_size(ht.size(), min_buckets_wanted); if ( resize_to > bucket_count() ) { // we don't have enough buckets typedef dense_hash_map_traits::integral_constant::value && dense_hash_map_traits::has_trivial_destructor::value)> realloc_ok; // we pretend mv(x,y) == "x.~T(); new(x) T(y)" expand_array(resize_to, realloc_ok()); num_buckets = resize_to; reset_thresholds(); } // We use a normal iterator to get non-deleted bcks from ht // We could use insert() here, but since we know there are // no duplicates and no deleted items, we can be more efficient Assert((bucket_count() & (bucket_count()-1)) == 0); // a power of two for ( const_iterator it = ht.begin(); it != ht.end(); ++it ) { size_type num_probes = 0; // how many times we've probed size_type bucknum; const size_type bucket_count_minus_one = bucket_count() - 1; for (bucknum = hash(get_key(*it)) & bucket_count_minus_one; !test_empty(bucknum); // not empty bucknum = (bucknum + JUMP_(key, num_probes)) & bucket_count_minus_one) { ++num_probes; Assert(num_probes < bucket_count()); // or else the hashtable is full } set_value(&table[bucknum], *it); // copies the value to here num_elements++; } } // Required by the spec for hashed associative container public: // Though the docs say this should be num_buckets, I think it's much // more useful as req_elements. As a special feature, calling with // req_elements==0 will cause us to shrink if we can, saving space. void resize(size_type req_elements) { // resize to this or larger if ( consider_shrink || req_elements == 0 ) maybe_shrink(); if ( req_elements > num_elements ) return resize_delta(req_elements - num_elements, 0); } // CONSTRUCTORS -- as required by the specs, we take a size, // but also let you specify a hashfunction, key comparator, // and key extractor. We also define a copy constructor and =. // DESTRUCTOR -- needs to free the table explicit dense_hashtable(size_type n = 0, const HashFcn& hf = HashFcn(), const EqualKey& eql = EqualKey(), const ExtractKey& ext = ExtractKey()) : hash(hf), equals(eql), get_key(ext), num_deleted(0), use_deleted(false), use_empty(false), delval(), emptyval(), table(NULL), num_buckets(min_size(0, n)), num_elements(0) { // table is NULL until emptyval is set. However, we set num_buckets // here so we know how much space to allocate once emptyval is set reset_thresholds(); } // As a convenience for resize(), we allow an optional second argument // which lets you make this new hashtable a different size than ht dense_hashtable(const dense_hashtable& ht, size_type min_buckets_wanted = 0) : hash(ht.hash), equals(ht.equals), get_key(ht.get_key), num_deleted(0), use_deleted(ht.use_deleted), use_empty(ht.use_empty), delval(ht.delval), emptyval(ht.emptyval), table(NULL), num_buckets(0), num_elements(0) { reset_thresholds(); copy_from(ht, min_buckets_wanted); // copy_from() ignores deleted entries } dense_hashtable& operator= (const dense_hashtable& ht) { if (&ht == this) return *this; // don't copy onto ourselves clear(); hash = ht.hash; equals = ht.equals; get_key = ht.get_key; use_deleted = ht.use_deleted; use_empty = ht.use_empty; set_value(&delval, ht.delval); set_value(&emptyval, ht.emptyval); copy_from(ht); // sets num_deleted to 0 too return *this; } ~dense_hashtable() { if (table) { destroy_buckets(0, num_buckets); _Alval.deallocate(table, num_buckets); } } // Many STL algorithms use swap instead of copy constructors void swap(dense_hashtable& ht) { std::swap(hash, ht.hash); std::swap(equals, ht.equals); std::swap(get_key, ht.get_key); std::swap(num_deleted, ht.num_deleted); std::swap(use_deleted, ht.use_deleted); std::swap(use_empty, ht.use_empty); { value_type tmp; // for annoying reasons, swap() doesn't work set_value(&tmp, delval); set_value(&delval, ht.delval); set_value(&ht.delval, tmp); } { value_type tmp; // for annoying reasons, swap() doesn't work set_value(&tmp, emptyval); set_value(&emptyval, ht.emptyval); set_value(&ht.emptyval, tmp); } std::swap(table, ht.table); std::swap(num_buckets, ht.num_buckets); std::swap(num_elements, ht.num_elements); reset_thresholds(); ht.reset_thresholds(); } // It's always nice to be able to clear a table without deallocating it void clear() { if (table) destroy_buckets(0, num_buckets); size_type old_bucket_count = num_buckets; num_buckets = min_size(0,0); // our new size reset_thresholds(); value_type* new_table = _Alval.allocate(num_buckets); Assert(new_table); if(table) _Alval.deallocate(table, old_bucket_count); table = new_table; Assert(table); fill_range_with_empty(table, table + num_buckets); num_elements = 0; num_deleted = 0; } // Clear the table without resizing it. // Mimicks the stl_hashtable's behaviour when clear()-ing in that it // does not modify the bucket count void clear_no_resize() { if (table) { set_empty(0, num_buckets); } // don't consider to shrink before another erase() reset_thresholds(); num_elements = 0; num_deleted = 0; } // LOOKUP ROUTINES private: // Returns a pair of positions: 1st where the object is, 2nd where // it would go if you wanted to insert it. 1st is ILLEGAL_BUCKET // if object is not found; 2nd is ILLEGAL_BUCKET if it is. // Note: because of deletions where-to-insert is not trivial: it's the // first deleted bucket we see, as long as we don't find the key later pair find_position(const key_type &key) const { size_type num_probes = 0; // how many times we've probed const size_type bucket_count_minus_one = bucket_count() - 1; size_type bucknum = hash(key) & bucket_count_minus_one; size_type insert_pos = ILLEGAL_BUCKET; // where we would insert while ( 1 ) { // probe until something happens if ( test_empty(bucknum) ) { // bucket is empty if ( insert_pos == ILLEGAL_BUCKET ) // found no prior place to insert return pair(ILLEGAL_BUCKET, bucknum); else return pair(ILLEGAL_BUCKET, insert_pos); } else if ( test_deleted(bucknum) ) {// keep searching, but mark to insert if ( insert_pos == ILLEGAL_BUCKET ) insert_pos = bucknum; } else if ( equals(key, get_key(table[bucknum])) ) { return pair(bucknum, ILLEGAL_BUCKET); } ++num_probes; // we're doing another probe bucknum = (bucknum + JUMP_(key, num_probes)) & bucket_count_minus_one; Assert(num_probes < bucket_count()); // don't probe too many times! } } public: iterator find(const key_type& key) { if ( size() == 0 ) return end(); pair pos = find_position(key); if ( pos.first == ILLEGAL_BUCKET ) // alas, not there return end(); else return iterator(this, table + pos.first, table + num_buckets, false); } const_iterator find(const key_type& key) const { if ( size() == 0 ) return end(); pair pos = find_position(key); if ( pos.first == ILLEGAL_BUCKET ) // alas, not there return end(); else return const_iterator(this, table + pos.first, table+num_buckets, false); } // Counts how many elements have key key. For maps, it's either 0 or 1. size_type count(const key_type &key) const { pair pos = find_position(key); return pos.first == ILLEGAL_BUCKET ? 0 : 1; } // Likewise, equal_range doesn't really make sense for us. Oh well. pair equal_range(const key_type& key) { const iterator pos = find(key); // either an iterator or end return pair(pos, pos); } pair equal_range(const key_type& key) const { const const_iterator pos = find(key); // either an iterator or end return pair(pos, pos); } // INSERTION ROUTINES private: // If you know *this is big enough to hold obj, use this routine pair insert_noresize(const value_type& obj) { const pair pos = find_position(get_key(obj)); if ( pos.first != ILLEGAL_BUCKET) { // object was already there return pair(iterator(this, table + pos.first, table + num_buckets, false), false); // false: we didn't insert } else { // pos.second says where to put it if ( test_deleted(pos.second) ) { // just replace if it's been del. const_iterator delpos(this, table + pos.second, // shrug: table + num_buckets, false);// shouldn't need const clear_deleted(delpos); Assert( num_deleted > 0); --num_deleted; // used to be, now it isn't } else { ++num_elements; // replacing an empty bucket } set_value(&table[pos.second], obj); return pair(iterator(this, table + pos.second, table + num_buckets, false), true); // true: we did insert } } public: // This is the normal insert routine, used by the outside world pair insert(const value_type& obj) { resize_delta(1); // adding an object, grow if need be return insert_noresize(obj); } // When inserting a lot at a time, we specialize on the type of iterator template void insert(InputIterator f, InputIterator l) { // specializes on iterator type insert(f, l, typename std::iterator_traits::iterator_category()); } // Iterator supports operator-, resize before inserting template void insert(ForwardIterator f, ForwardIterator l, std::forward_iterator_tag) { size_type n = std::distance(f, l); // TODO(csilvers): standard? resize_delta(n); for ( ; n > 0; --n, ++f) insert_noresize(*f); } // Arbitrary iterator, can't tell how much to resize template void insert(InputIterator f, InputIterator l, std::input_iterator_tag) { for ( ; f != l; ++f) insert(*f); } // DELETION ROUTINES size_type erase(const key_type& key) { const_iterator pos = find(key); // shrug: shouldn't need to be const if ( pos != end() ) { Assert(!test_deleted(pos)); // or find() shouldn't have returned it set_deleted(pos); ++num_deleted; consider_shrink = true; // will think about shrink after next insert return 1; // because we deleted one thing } else { return 0; // because we deleted nothing } } // This is really evil: really it should be iterator, not const_iterator. // But...the only reason keys are const is to allow lookup. // Since that's a moot issue for deleted keys, we allow const_iterators void erase(const_iterator pos) { if ( pos == end() ) return; // sanity check if ( set_deleted(pos) ) { // true if object has been newly deleted ++num_deleted; consider_shrink = true; // will think about shrink after next insert } } void erase(const_iterator f, const_iterator l) { for ( ; f != l; ++f) { if ( set_deleted(f) ) // should always be true ++num_deleted; } consider_shrink = true; // will think about shrink after next insert } // COMPARISON bool operator==(const dense_hashtable& ht) const { if (size() != ht.size()) { return false; } else if (this == &ht) { return true; } else { // Iterate through the elements in "this" and see if the // corresponding element is in ht for ( const_iterator it = begin(); it != end(); ++it ) { const_iterator it2 = ht.find(get_key(*it)); if ((it2 == ht.end()) || (*it != *it2)) { return false; } } return true; } } bool operator!=(const dense_hashtable& ht) const { return !(*this == ht); } private: // The actual data hasher hash; // required by hashed_associative_container key_equal equals; ExtractKey get_key; size_type num_deleted; // how many occupied buckets are marked deleted bool use_deleted; // false until delval has been set bool use_empty; // you must do this before you start value_type delval; // which key marks deleted entries value_type emptyval; // which key marks unused entries value_type *table; size_type num_buckets; size_type num_elements; size_type shrink_threshold; // num_buckets * HT_EMPTY_FLT size_type enlarge_threshold; // num_buckets * HT_OCCUPANCY_FLT bool consider_shrink; // true if we should try to shrink before next insert Alloc _Alval; // allocator object for value_type void reset_thresholds() { enlarge_threshold = static_cast(num_buckets*HT_OCCUPANCY_FLT); shrink_threshold = static_cast(num_buckets*HT_EMPTY_FLT); consider_shrink = false; // whatever caused us to reset already considered } }; // We need a global swap as well template inline void swap(dense_hashtable &x, dense_hashtable &y) { x.swap(y); } #undef JUMP_ template const typename dense_hashtable::size_type dense_hashtable::ILLEGAL_BUCKET; // How full we let the table get before we resize. Knuth says .8 is // good -- higher causes us to probe too much, though saves memory template const float dense_hashtable::HT_OCCUPANCY_FLT = 0.5f; // How empty we let the table get before we resize lower. // It should be less than OCCUPANCY_FLT / 2 or we thrash resizing template const float dense_hashtable::HT_EMPTY_FLT = 0.4f * dense_hashtable::HT_OCCUPANCY_FLT; #endif /* _DENSEHASHTABLE_H_ */ ================================================ FILE: unity_decoder/libil2cpp/external/google/sparsehash/type_traits.h ================================================ // Copyright (c) 2006, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ---- // Author: Matt Austern // // Define a small subset of tr1 type traits. The traits we define are: // is_integral // is_floating_point // is_pointer // is_reference // is_pod // has_trivial_constructor // has_trivial_copy // has_trivial_assign // has_trivial_destructor // remove_const // remove_volatile // remove_cv // remove_reference // remove_pointer // is_convertible // We can add more type traits as required. #ifndef BASE_TYPE_TRAITS_H_ #define BASE_TYPE_TRAITS_H_ //#include #include // For pair namespace dense_hash_map_traits { // integral_constant, defined in tr1, is a wrapper for an integer // value. We don't really need this generality; we could get away // with hardcoding the integer type to bool. We use the fully // general integer_constant for compatibility with tr1. template struct integral_constant { static const T value = v; typedef T value_type; typedef integral_constant type; }; template const T integral_constant::value; // Abbreviations: true_type and false_type are structs that represent // boolean true and false values. typedef integral_constant true_type; typedef integral_constant false_type; // Types small_ and big_ are guaranteed such that sizeof(small_) < // sizeof(big_) typedef char small_; struct big_ { char dummy[2]; }; // is_integral is false except for the built-in integer types. template struct is_integral : false_type { }; template<> struct is_integral : true_type { }; template<> struct is_integral : true_type { }; template<> struct is_integral : true_type { }; template<> struct is_integral : true_type { }; #if defined(_MSC_VER) // wchar_t is not by default a distinct type from unsigned short in // Microsoft C. // See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx template<> struct is_integral<__wchar_t> : true_type { }; #else template<> struct is_integral : true_type { }; #endif template<> struct is_integral : true_type { }; template<> struct is_integral : true_type { }; template<> struct is_integral : true_type { }; template<> struct is_integral : true_type { }; template<> struct is_integral : true_type { }; template<> struct is_integral : true_type { }; #ifdef HAVE_LONG_LONG template<> struct is_integral : true_type { }; template<> struct is_integral : true_type { }; #endif // is_floating_point is false except for the built-in floating-point types. template struct is_floating_point : false_type { }; template<> struct is_floating_point : true_type { }; template<> struct is_floating_point : true_type { }; template<> struct is_floating_point : true_type { }; // is_pointer is false except for pointer types. template struct is_pointer : false_type { }; template struct is_pointer : true_type { }; // is_reference is false except for reference types. template struct is_reference : false_type {}; template struct is_reference : true_type {}; // We can't get is_pod right without compiler help, so fail conservatively. // We will assume it's false except for arithmetic types and pointers, // and const versions thereof. Note that std::pair is not a POD. template struct is_pod : integral_constant::value || is_floating_point::value || is_pointer::value)> { }; template struct is_pod : is_pod { }; // We can't get has_trivial_constructor right without compiler help, so // fail conservatively. We will assume it's false except for: (1) types // for which is_pod is true. (2) std::pair of types with trivial // constructors. (3) array of a type with a trivial constructor. // (4) const versions thereof. template struct has_trivial_constructor : is_pod { }; template struct has_trivial_constructor > : integral_constant::value && has_trivial_constructor::value)> { }; template struct has_trivial_constructor : has_trivial_constructor { }; template struct has_trivial_constructor : has_trivial_constructor { }; // We can't get has_trivial_copy right without compiler help, so fail // conservatively. We will assume it's false except for: (1) types // for which is_pod is true. (2) std::pair of types with trivial copy // constructors. (3) array of a type with a trivial copy constructor. // (4) const versions thereof. template struct has_trivial_copy : is_pod { }; template struct has_trivial_copy > : integral_constant::value && has_trivial_copy::value)> { }; template struct has_trivial_copy : has_trivial_copy { }; template struct has_trivial_copy : has_trivial_copy { }; // We can't get has_trivial_assign right without compiler help, so fail // conservatively. We will assume it's false except for: (1) types // for which is_pod is true. (2) std::pair of types with trivial copy // constructors. (3) array of a type with a trivial assign constructor. template struct has_trivial_assign : is_pod { }; template struct has_trivial_assign > : integral_constant::value && has_trivial_assign::value)> { }; template struct has_trivial_assign : has_trivial_assign { }; // We can't get has_trivial_destructor right without compiler help, so // fail conservatively. We will assume it's false except for: (1) types // for which is_pod is true. (2) std::pair of types with trivial // destructors. (3) array of a type with a trivial destructor. // (4) const versions thereof. template struct has_trivial_destructor : is_pod { }; template struct has_trivial_destructor > : integral_constant::value && has_trivial_destructor::value)> { }; template struct has_trivial_destructor : has_trivial_destructor { }; template struct has_trivial_destructor : has_trivial_destructor { }; // Specified by TR1 [4.7.1] template struct remove_const { typedef T type; }; template struct remove_const { typedef T type; }; template struct remove_volatile { typedef T type; }; template struct remove_volatile { typedef T type; }; template struct remove_cv { typedef typename remove_const::type>::type type; }; // Specified by TR1 [4.7.2] template struct remove_reference { typedef T type; }; template struct remove_reference { typedef T type; }; // Specified by TR1 [4.7.4] Pointer modifications. template struct remove_pointer { typedef T type; }; template struct remove_pointer { typedef T type; }; template struct remove_pointer { typedef T type; }; template struct remove_pointer { typedef T type; }; template struct remove_pointer { typedef T type; }; // Specified by TR1 [4.6] Relationships between types #ifndef _MSC_VER namespace internal_type_traits { // This class is an implementation detail for is_convertible, and you // don't need to know how it works to use is_convertible. For those // who care: we declare two different functions, one whose argument is // of type To and one with a variadic argument list. We give them // return types of different size, so we can use sizeof to trick the // compiler into telling us which function it would have chosen if we // had called it with an argument of type From. See Alexandrescu's // _Modern C++ Design_ for more details on this sort of trick. template struct ConvertHelper { static small_ Test(To); static big_ Test(...); static From Create(); }; } // namespace internal // Inherits from true_type if From is convertible to To, false_type otherwise. template struct is_convertible : integral_constant::Test( internal_type_traits::ConvertHelper::Create())) == sizeof(small_)> { }; #endif } #endif // BASE_TYPE_TRAITS_H_ ================================================ FILE: unity_decoder/libil2cpp/external/xamarin-android/README ================================================ Files copied by Unity to fix case 751744 (NetworkInterface.GetAllNetworkInterfaces method not working on Android). Source: https://github.com/xamarin/xamarin-android Revision: ff86ed81928b69118d14f1f97f4e22832fc5c7fb ================================================ FILE: unity_decoder/libil2cpp/external/xamarin-android/logger.h ================================================ #ifndef __MONODROID_LOGGER_H__ #define __MONODROID_LOGGER_H__ #ifdef __cplusplus extern "C" { #endif #ifndef ANDROID typedef enum android_LogPriority { ANDROID_LOG_UNKNOWN = 0, ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */ ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL, ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */ } android_LogPriority; #endif // Keep in sync with Mono.Android/src/Runtime/Logger.cs!LogCategories enum typedef enum _LogCategories { LOG_NONE = 0, LOG_DEFAULT = 1 << 0, LOG_ASSEMBLY = 1 << 1, LOG_DEBUGGER = 1 << 2, LOG_GC = 1 << 3, LOG_GREF = 1 << 4, LOG_LREF = 1 << 5, LOG_TIMING = 1 << 6, LOG_BUNDLE = 1 << 7, LOG_NET = 1 << 8, LOG_NETLINK = 1 << 9, } LogCategories; #if 0 extern unsigned int log_categories; #if DEBUG extern int gc_spew_enabled; #endif void init_categories(const char *override_dir); void log_error(LogCategories category, const char *format, ...); void log_fatal(LogCategories category, const char *format, ...); void log_info(LogCategories category, const char *format, ...); void log_warn(LogCategories category, const char *format, ...); void log_debug(LogCategories category, const char *format, ...); #else #define init_categories(override_dir) #define log_error(category, format, ...) #define log_fatal(category, format, ...) #define log_info(category, format, ...) #define log_warn(category, format, ...) #define log_debug(category, format, ...) #endif #ifdef __cplusplus } #endif #endif /* __MONODROID_LOGGER_H__ */ ================================================ FILE: unity_decoder/libil2cpp/external/xamarin-android/monodroid.h ================================================ #ifndef __MONODROID_H #define __MONODROID_H #ifdef __cplusplus extern "C" { #endif /* VS 2010 and later have stdint.h */ #if defined(_MSC_VER) #define MONO_API_EXPORT __declspec(dllexport) #define MONO_API_IMPORT __declspec(dllimport) #else /* defined(_MSC_VER */ #define MONO_API_EXPORT __attribute__ ((visibility ("default"))) #define MONO_API_IMPORT #endif /* !defined(_MSC_VER) */ #if defined(MONO_DLL_EXPORT) #define MONO_API MONO_API_EXPORT #elif defined(MONO_DLL_IMPORT) #define MONO_API MONO_API_IMPORT #else /* !defined(MONO_DLL_IMPORT) && !defined(MONO_API_IMPORT) */ #define MONO_API #endif /* MONO_DLL_EXPORT... */ enum FatalExitCodes { FATAL_EXIT_CANNOT_FIND_MONO = 1, FATAL_EXIT_ATTACH_JVM_FAILED = 2, FATAL_EXIT_DEBUGGER_CONNECT = 3, FATAL_EXIT_CANNOT_FIND_JNIENV = 4, FATAL_EXIT_CANNOT_FIND_APK = 10, FATAL_EXIT_TRIAL_EXPIRED = 11, FATAL_EXIT_PTHREAD_FAILED = 12, FATAL_EXIT_MISSING_ASSEMBLY = 13, FATAL_EXIT_CANNOT_LOAD_BUNDLE = 14, FATAL_EXIT_CANNOT_FIND_LIBMONOSGEN = 15, FATAL_EXIT_NO_ASSEMBLIES = 'A', FATAL_EXIT_MONO_MISSING_SYMBOLS = 'B', FATAL_EXIT_FORK_FAILED = 'F', FATAL_EXIT_MISSING_INIT = 'I', FATAL_EXIT_MISSING_TIMEZONE_MEMBERS = 'T', FATAL_EXIT_MISSING_ZIPALIGN = 'Z', FATAL_EXIT_OUT_OF_MEMORY = 'M', }; #ifdef __cplusplus } #endif #endif /* defined __MONODROID_H */ ================================================ FILE: unity_decoder/libil2cpp/external/xamarin-android/xamarin_getifaddrs.c ================================================ #include #include #if !defined(WIN32) && !defined(SN_TARGET_ORBIS) && !defined(SN_TARGET_PSP2) && !defined(NN_COMPILER_RVCT) #include #endif #include #include #include #include #if !defined(NN_COMPILER_RVCT) && !defined(SN_TARGET_PSP2) #include #endif #if !defined(WIN32) && !defined(NN_COMPILER_RVCT) #include #include #endif #if LINUX #include #include #include #endif /* def LINUX */ #if !defined(WIN32) && !defined(NN_COMPILER_RVCT) && !defined(SN_TARGET_PSP2) #include #endif #if ANDROID #include #endif #include "logger.h" #include "xamarin_getifaddrs.h" /* These aren't defined in android's rtnetlink.h (as of ndk 9d). We define fake values for them if * they aren't found so that the debug code works properly. We could skip them but future versions * of the NDK might include definitions for them. */ #ifndef IFLA_LINKINFO #define IFLA_LINKINFO 1000 #endif #ifndef IFLA_NET_NS_PID #define IFLA_NET_NS_PID 1001 #endif #ifndef IFLA_IFALIAS #define IFLA_IFALIAS 1002 #endif #ifndef IFLA_NUM_VF #define IFLA_NUM_VF 1003 #endif #ifndef IFLA_VFINFO_LIST #define IFLA_VFINFO_LIST 1004 #endif #ifndef IFLA_STATS64 #define IFLA_STATS64 1005 #endif #ifndef IFLA_VF_PORTS #define IFLA_VF_PORTS 1006 #endif #ifndef IFLA_PORT_SELF #define IFLA_PORT_SELF 1007 #endif #ifndef IFLA_AF_SPEC #define IFLA_AF_SPEC 1008 #endif #ifndef IFLA_GROUP #define IFLA_GROUP 1009 #endif #ifndef IFLA_NET_NS_FD #define IFLA_NET_NS_FD 1010 #endif #ifndef IFLA_EXT_MASK #define IFLA_EXT_MASK 1011 #endif #ifndef IFLA_PROMISCUITY #define IFLA_PROMISCUITY 1012 #endif #ifndef IFLA_NUM_TX_QUEUES #define IFLA_NUM_TX_QUEUES 1013 #endif #ifndef IFLA_NUM_RX_QUEUES #define IFLA_NUM_RX_QUEUES 1014 #endif #ifndef IFLA_CARRIER #define IFLA_CARRIER 1015 #endif #ifndef IFLA_PHYS_PORT_ID #define IFLA_PHYS_PORT_ID 1016 #endif /* The amount of data we read from the kernel in one call */ #define RESPONSE_BUFFER_SIZE 1024 /* Maximum interface address label size, should be more than enough */ #define MAX_IFA_LABEL_SIZE 1024 #if LINUX /* This is the message we send to the kernel */ typedef struct { struct nlmsghdr header; struct rtgenmsg message; } netlink_request; typedef struct { int sock_fd; int seq; struct sockaddr_nl them; /* kernel end */ struct sockaddr_nl us; /* our end */ struct msghdr message_header; /* for use with sendmsg */ struct iovec payload_vector; /* Used to send netlink_request */ } netlink_session; /* Turns out that quite a few link types have address length bigger than the 8 bytes allocated in * this structure as defined by the OS. Examples are Infiniband or ipv6 tunnel devices */ struct sockaddr_ll_extended { unsigned short int sll_family; unsigned short int sll_protocol; int sll_ifindex; unsigned short int sll_hatype; unsigned char sll_pkttype; unsigned char sll_halen; unsigned char sll_addr[24]; }; static int parse_netlink_reply(netlink_session *session, struct _monodroid_ifaddrs **ifaddrs_head, struct _monodroid_ifaddrs **last_ifaddr); static struct _monodroid_ifaddrs *get_link_info(const struct nlmsghdr *message); static struct _monodroid_ifaddrs *get_link_address(const struct nlmsghdr *message, struct _monodroid_ifaddrs **ifaddrs_head); static int open_netlink_session(netlink_session *session); static int send_netlink_dump_request(netlink_session *session, int type); static int append_ifaddr(struct _monodroid_ifaddrs *addr, struct _monodroid_ifaddrs **ifaddrs_head, struct _monodroid_ifaddrs **last_ifaddr); static int fill_ll_address(struct sockaddr_ll_extended **sa, struct ifinfomsg *net_interface, void *rta_data, int rta_payload_length); static int fill_sa_address(struct sockaddr **sa, struct ifaddrmsg *net_address, void *rta_data, int rta_payload_length); static void free_single_xamarin_ifaddrs(struct _monodroid_ifaddrs **ifap); static void get_ifaddrs_impl(int(**getifaddrs_impl) (struct _monodroid_ifaddrs **ifap), void(**freeifaddrs_impl) (struct _monodroid_ifaddrs *ifa)); static struct _monodroid_ifaddrs *find_interface_by_index(int index, struct _monodroid_ifaddrs **ifaddrs_head); static char *get_interface_name_by_index(int index, struct _monodroid_ifaddrs **ifaddrs_head); static int get_interface_flags_by_index(int index, struct _monodroid_ifaddrs **ifaddrs_head); static int calculate_address_netmask(struct _monodroid_ifaddrs *ifa, struct ifaddrmsg *net_address); #if DEBUG static void print_ifla_name(int id); static void print_address_list(char *title, struct _monodroid_ifaddrs *list); #endif /* We don't use 'struct ifaddrs' since that doesn't exist in Android's bionic, but since our * version of the structure is 100% compatible we can just use it instead */ typedef int (*getifaddrs_impl_fptr)(struct _monodroid_ifaddrs **); typedef void (*freeifaddrs_impl_fptr)(struct _monodroid_ifaddrs *ifa); static getifaddrs_impl_fptr getifaddrs_impl = NULL; static freeifaddrs_impl_fptr freeifaddrs_impl = NULL; void _monodroid_getifaddrs_init() { get_ifaddrs_impl(&getifaddrs_impl, &freeifaddrs_impl); } int _monodroid_getifaddrs(struct _monodroid_ifaddrs **ifap) { netlink_session session; struct _monodroid_ifaddrs *ifaddrs_head; struct _monodroid_ifaddrs *last_ifaddr; int ret = -1; if (getifaddrs_impl) return (*getifaddrs_impl)(ifap); if (!ifap) { goto cleanup; } *ifap = NULL; ifaddrs_head = 0; last_ifaddr = 0; if (open_netlink_session(&session) < 0) { goto cleanup; } /* Request information about the specified link. In our case it will be all of them since we request the root of the link tree below */ if ((send_netlink_dump_request(&session, RTM_GETLINK) < 0) || (parse_netlink_reply(&session, &ifaddrs_head, &last_ifaddr) < 0) || (send_netlink_dump_request(&session, RTM_GETADDR) < 0) || (parse_netlink_reply(&session, &ifaddrs_head, &last_ifaddr) < 0)) { _monodroid_freeifaddrs(ifaddrs_head); goto cleanup; } ret = 0; *ifap = ifaddrs_head; #if DEBUG print_address_list("Initial interfaces list", *ifap); #endif cleanup: if (session.sock_fd >= 0) { close(session.sock_fd); session.sock_fd = -1; } return ret; } void _monodroid_freeifaddrs(struct _monodroid_ifaddrs *ifa) { struct _monodroid_ifaddrs *cur, *next; if (!ifa) return; if (freeifaddrs_impl) { (*freeifaddrs_impl)(ifa); return; } #if DEBUG print_address_list("List passed to freeifaddrs", ifa); #endif cur = ifa; while (cur) { next = cur->ifa_next; free_single_xamarin_ifaddrs(&cur); cur = next; } } static void get_ifaddrs_impl(int(**getifaddrs_impl) (struct _monodroid_ifaddrs **ifap), void(**freeifaddrs_impl) (struct _monodroid_ifaddrs *ifa)) { void *libc; assert(getifaddrs_impl); assert(freeifaddrs_impl); libc = dlopen("libc.so", RTLD_NOW); if (libc) { *getifaddrs_impl = dlsym(libc, "getifaddrs"); if (*getifaddrs_impl) *freeifaddrs_impl = dlsym(libc, "freeifaddrs"); } if (!*getifaddrs_impl) log_info(LOG_NET, "This libc does not have getifaddrs/freeifaddrs, using Xamarin's\n"); else log_info(LOG_NET, "This libc has getifaddrs/freeifaddrs\n"); } static void free_single_xamarin_ifaddrs(struct _monodroid_ifaddrs **ifap) { struct _monodroid_ifaddrs *ifa = ifap ? *ifap : NULL; if (!ifa) return; if (ifa->ifa_name) free(ifa->ifa_name); if (ifa->ifa_addr) free(ifa->ifa_addr); if (ifa->ifa_netmask) free(ifa->ifa_netmask); if (ifa->_monodroid_ifa_broadaddr) free(ifa->_monodroid_ifa_broadaddr); if (ifa->ifa_data) free(ifa->ifa_data); free(ifa); *ifap = NULL; } static int open_netlink_session(netlink_session *session) { assert(session != 0); memset(session, 0, sizeof(*session)); session->sock_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (session->sock_fd == -1) { log_warn(LOG_NETLINK, "Failed to create a netlink socket. %s\n", strerror(errno)); return -1; } /* Fill out addresses */ session->us.nl_family = AF_NETLINK; session->us.nl_pid = getpid(); session->us.nl_groups = 0; session->them.nl_family = AF_NETLINK; if (bind(session->sock_fd, (struct sockaddr *)&session->us, sizeof(session->us)) < 0) { log_warn(LOG_NETLINK, "Failed to bind to the netlink socket. %s\n", strerror(errno)); return -1; } return 0; } static int send_netlink_dump_request(netlink_session *session, int type) { netlink_request request; memset(&request, 0, sizeof(request)); request.header.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)); /* Flags (from netlink.h): NLM_F_REQUEST - it's a request message NLM_F_DUMP - gives us the root of the link tree and returns all links matching our requested AF, which in our case means all of them (AF_PACKET) */ request.header.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT | NLM_F_MATCH; request.header.nlmsg_seq = ++session->seq; request.header.nlmsg_pid = session->us.nl_pid; request.header.nlmsg_type = type; /* AF_PACKET means we want to see everything */ request.message.rtgen_family = AF_PACKET; memset(&session->payload_vector, 0, sizeof(session->payload_vector)); session->payload_vector.iov_len = request.header.nlmsg_len; session->payload_vector.iov_base = &request; memset(&session->message_header, 0, sizeof(session->message_header)); session->message_header.msg_namelen = sizeof(session->them); session->message_header.msg_name = &session->them; session->message_header.msg_iovlen = 1; session->message_header.msg_iov = &session->payload_vector; if (sendmsg(session->sock_fd, (const struct msghdr*)&session->message_header, 0) < 0) { log_warn(LOG_NETLINK, "Failed to send netlink message. %s\n", strerror(errno)); return -1; } return 0; } static int append_ifaddr(struct _monodroid_ifaddrs *addr, struct _monodroid_ifaddrs **ifaddrs_head, struct _monodroid_ifaddrs **last_ifaddr) { assert(addr); assert(ifaddrs_head); assert(last_ifaddr); if (!*ifaddrs_head) { *ifaddrs_head = *last_ifaddr = addr; if (!*ifaddrs_head) return -1; } else if (!*last_ifaddr) { struct _monodroid_ifaddrs *last = *ifaddrs_head; while (last->ifa_next) last = last->ifa_next; *last_ifaddr = last; } addr->ifa_next = NULL; if (addr == *last_ifaddr) return 0; assert(addr != *last_ifaddr); (*last_ifaddr)->ifa_next = addr; *last_ifaddr = addr; assert((*last_ifaddr)->ifa_next == NULL); return 0; } static int parse_netlink_reply(netlink_session *session, struct _monodroid_ifaddrs **ifaddrs_head, struct _monodroid_ifaddrs **last_ifaddr) { ssize_t length; struct msghdr netlink_reply; struct iovec reply_vector; struct nlmsghdr *current_message; struct _monodroid_ifaddrs *addr; unsigned char response[RESPONSE_BUFFER_SIZE]; assert(session); assert(ifaddrs_head); assert(last_ifaddr); while (1) { memset(response, 0, RESPONSE_BUFFER_SIZE); memset(&reply_vector, 0, sizeof(reply_vector)); reply_vector.iov_len = RESPONSE_BUFFER_SIZE; reply_vector.iov_base = response; memset(&netlink_reply, 0, sizeof(netlink_reply)); netlink_reply.msg_namelen = sizeof(&session->them); netlink_reply.msg_name = &session->them; netlink_reply.msg_iovlen = 1; netlink_reply.msg_iov = &reply_vector; log_debug(LOG_NETLINK, "receiving message...\n"); length = recvmsg(session->sock_fd, &netlink_reply, 0); log_debug(LOG_NETLINK, " length == %d\n", (int)length); if (length < 0) { log_debug(LOG_NETLINK, "Failed to receive reply from netlink. %s\n", strerror(errno)); return -1; } if (length == 0) return 0; /* done, apparently */ for (current_message = (struct nlmsghdr*)response; current_message && NLMSG_OK(current_message, length); current_message = NLMSG_NEXT(current_message, length)) { log_debug(LOG_NETLINK, "next message... (type: %u)\n", current_message->nlmsg_type); switch (current_message->nlmsg_type) { /* See rtnetlink.h */ case RTM_NEWLINK: log_debug(LOG_NETLINK, " dumping link...\n"); addr = get_link_info(current_message); if (!addr || append_ifaddr(addr, ifaddrs_head, last_ifaddr) < 0) return -1; log_debug(LOG_NETLINK, " done\n"); break; case RTM_NEWADDR: log_debug(LOG_NETLINK, " got an address\n"); addr = get_link_address(current_message, ifaddrs_head); if (!addr || append_ifaddr(addr, ifaddrs_head, last_ifaddr) < 0) return -1; break; case NLMSG_DONE: log_debug(LOG_NETLINK, " message done\n"); return 0; } } } } static int fill_sa_address(struct sockaddr **sa, struct ifaddrmsg *net_address, void *rta_data, int rta_payload_length) { assert(sa); assert(net_address); assert(rta_data); switch (net_address->ifa_family) { case AF_INET: { struct sockaddr_in *sa4; assert(rta_payload_length == 4); /* IPv4 address length */ sa4 = (struct sockaddr_in*)calloc(1, sizeof(*sa4)); if (!sa4) return -1; sa4->sin_family = AF_INET; memcpy(&sa4->sin_addr, rta_data, rta_payload_length); *sa = (struct sockaddr*)sa4; break; } case AF_INET6: { struct sockaddr_in6 *sa6; assert(rta_payload_length == 16); /* IPv6 address length */ sa6 = (struct sockaddr_in6*)calloc(1, sizeof(*sa6)); if (!sa6) return -1; sa6->sin6_family = AF_INET6; memcpy(&sa6->sin6_addr, rta_data, rta_payload_length); if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&sa6->sin6_addr)) sa6->sin6_scope_id = net_address->ifa_index; *sa = (struct sockaddr*)sa6; break; } default: { struct sockaddr *sagen; assert(rta_payload_length <= sizeof(sagen->sa_data)); *sa = sagen = (struct sockaddr*)calloc(1, sizeof(*sagen)); if (sagen) return -1; sagen->sa_family = net_address->ifa_family; memcpy(&sagen->sa_data, rta_data, rta_payload_length); break; } } return 0; } static int fill_ll_address(struct sockaddr_ll_extended **sa, struct ifinfomsg *net_interface, void *rta_data, int rta_payload_length) { assert(sa); assert(net_interface); /* Always allocate, do not free - caller may reuse the same variable */ *sa = calloc(1, sizeof(**sa)); if (!*sa) return -1; (*sa)->sll_family = AF_PACKET; /* Always for physical links */ /* The assert can only fail for Iniband links, which are quite unlikely to be found * in any mobile devices */ log_debug(LOG_NETLINK, "rta_payload_length == %d; sizeof sll_addr == %d; hw type == 0x%X\n", rta_payload_length, sizeof((*sa)->sll_addr), net_interface->ifi_type); if (rta_payload_length > sizeof((*sa)->sll_addr)) { log_info(LOG_NETLINK, "Address is too long to place in sockaddr_ll (%d > %d)", rta_payload_length, sizeof((*sa)->sll_addr)); free(*sa); *sa = NULL; return -1; } (*sa)->sll_ifindex = net_interface->ifi_index; (*sa)->sll_hatype = net_interface->ifi_type; (*sa)->sll_halen = rta_payload_length; memcpy((*sa)->sll_addr, rta_data, rta_payload_length); return 0; } static struct _monodroid_ifaddrs * find_interface_by_index(int index, struct _monodroid_ifaddrs **ifaddrs_head) { struct _monodroid_ifaddrs *cur; if (!ifaddrs_head || !*ifaddrs_head) return NULL; /* Normally expensive, but with the small amount of links in the chain we'll deal with it's not * worth the extra houskeeping and memory overhead */ cur = *ifaddrs_head; while (cur) { if (cur->ifa_addr && cur->ifa_addr->sa_family == AF_PACKET && ((struct sockaddr_ll_extended*)cur->ifa_addr)->sll_ifindex == index) return cur; if (cur == cur->ifa_next) break; cur = cur->ifa_next; } return NULL; } static char * get_interface_name_by_index(int index, struct _monodroid_ifaddrs **ifaddrs_head) { struct _monodroid_ifaddrs *iface = find_interface_by_index(index, ifaddrs_head); if (!iface || !iface->ifa_name) return NULL; return iface->ifa_name; } static int get_interface_flags_by_index(int index, struct _monodroid_ifaddrs **ifaddrs_head) { struct _monodroid_ifaddrs *iface = find_interface_by_index(index, ifaddrs_head); if (!iface) return 0; return iface->ifa_flags; } static int calculate_address_netmask(struct _monodroid_ifaddrs *ifa, struct ifaddrmsg *net_address) { if (ifa->ifa_addr && ifa->ifa_addr->sa_family != AF_UNSPEC && ifa->ifa_addr->sa_family != AF_PACKET) { uint32_t prefix_length = 0; uint32_t data_length = 0; unsigned char *netmask_data = NULL; switch (ifa->ifa_addr->sa_family) { case AF_INET: { struct sockaddr_in *sa = (struct sockaddr_in*)calloc(1, sizeof(struct sockaddr_in)); if (!sa) return -1; ifa->ifa_netmask = (struct sockaddr*)sa; prefix_length = net_address->ifa_prefixlen; if (prefix_length > 32) prefix_length = 32; data_length = sizeof(sa->sin_addr); netmask_data = (unsigned char*)&sa->sin_addr; break; } case AF_INET6: { struct sockaddr_in6 *sa = (struct sockaddr_in6*)calloc(1, sizeof(struct sockaddr_in6)); if (!sa) return -1; ifa->ifa_netmask = (struct sockaddr*)sa; prefix_length = net_address->ifa_prefixlen; if (prefix_length > 128) prefix_length = 128; data_length = sizeof(sa->sin6_addr); netmask_data = (unsigned char*)&sa->sin6_addr; break; } } if (ifa->ifa_netmask && netmask_data) { /* Fill the first X bytes with 255 */ uint32_t prefix_bytes = prefix_length / 8; uint32_t postfix_bytes; int i; if (prefix_bytes > data_length) { errno = EINVAL; return -1; } postfix_bytes = data_length - prefix_bytes; memset(netmask_data, 0xFF, prefix_bytes); if (postfix_bytes > 0) memset(netmask_data + prefix_bytes + 1, 0x00, postfix_bytes); log_debug(LOG_NETLINK, " calculating netmask, prefix length is %u bits (%u bytes), data length is %u bytes\n", prefix_length, prefix_bytes, data_length); if (prefix_bytes + 2 < data_length) /* Set the rest of the mask bits in the byte following the last 0xFF value */ netmask_data[prefix_bytes + 1] = 0xff << (8 - (prefix_length % 8)); log_debug(LOG_NETLINK, " netmask is: "); for (i = 0; i < data_length; i++) { log_debug(LOG_NETLINK, "%s%u", i == 0 ? "" : ".", (unsigned char)ifa->ifa_netmask->sa_data[i]); } log_debug(LOG_NETLINK, "\n"); } } return 0; } static struct _monodroid_ifaddrs * get_link_address(const struct nlmsghdr *message, struct _monodroid_ifaddrs **ifaddrs_head) { size_t length; struct rtattr *attribute; struct ifaddrmsg *net_address; struct _monodroid_ifaddrs *ifa = NULL; struct sockaddr **sa; int payload_size; assert(message); net_address = NLMSG_DATA(message); length = IFA_PAYLOAD(message); if (length <= 0) { goto error; } ifa = calloc(1, sizeof(*ifa)); if (!ifa) { goto error; } ifa->ifa_flags = get_interface_flags_by_index(net_address->ifa_index, ifaddrs_head); attribute = IFA_RTA(net_address); while (RTA_OK(attribute, length)) { payload_size = RTA_PAYLOAD(attribute); sa = NULL; switch (attribute->rta_type) { case IFA_LABEL: { int room_for_trailing_null = 0; if (payload_size > MAX_IFA_LABEL_SIZE) { payload_size = MAX_IFA_LABEL_SIZE; room_for_trailing_null = 1; } if (payload_size > 0) { ifa->ifa_name = (char*)malloc(payload_size + room_for_trailing_null); if (!ifa->ifa_name) { goto error; } memcpy(ifa->ifa_name, RTA_DATA(attribute), payload_size); if (room_for_trailing_null) ifa->ifa_name[payload_size] = '\0'; } break; } case IFA_LOCAL: if (ifa->ifa_addr) { /* P2P protocol, set the dst/broadcast address union from the original address. * Since ifa_addr is set it means IFA_ADDRESST occured earlier and that address * is indeed the P2P destination one. */ ifa->_monodroid_ifa_dstaddr = ifa->ifa_addr; ifa->ifa_addr = 0; } sa = &ifa->ifa_addr; break; case IFA_BROADCAST: if (ifa->_monodroid_ifa_dstaddr) { /* IFA_LOCAL happened earlier, undo its effect here */ free(ifa->_monodroid_ifa_dstaddr); ifa->_monodroid_ifa_dstaddr = NULL; } sa = &ifa->_monodroid_ifa_broadaddr; break; case IFA_ADDRESS: if (ifa->ifa_addr) { /* Apparently IFA_LOCAL occured earlier and we have a P2P connection * here. IFA_LOCAL carries the destination address, move it there */ ifa->_monodroid_ifa_dstaddr = ifa->ifa_addr; ifa->ifa_addr = NULL; } sa = &ifa->ifa_addr; break; } if (sa) { if (fill_sa_address(sa, net_address, RTA_DATA(attribute), RTA_PAYLOAD(attribute)) < 0) { goto error; } } attribute = RTA_NEXT(attribute, length); } /* glibc stores the associated interface name in the address if IFA_LABEL never occured */ if (!ifa->ifa_name) { char *name = get_interface_name_by_index(net_address->ifa_index, ifaddrs_head); log_debug(LOG_NETLINK, " address has no name/label, getting one from interface\n"); ifa->ifa_name = name ? strdup(name) : NULL; } log_debug(LOG_NETLINK, " address label: %s\n", ifa->ifa_name); if (calculate_address_netmask(ifa, net_address) < 0) { goto error; } return ifa; error : { /* errno may be modified by free, or any other call inside the free_single_xamarin_ifaddrs * function. We don't care about errors in there since it is more important to know how we * failed to obtain the link address and not that we went OOM. Save and restore the value * after the resources are freed. */ int errno_save = errno; free_single_xamarin_ifaddrs(&ifa); errno = errno_save; return NULL; } } static struct _monodroid_ifaddrs * get_link_info(const struct nlmsghdr *message) { ssize_t length; struct rtattr *attribute; struct ifinfomsg *net_interface; struct _monodroid_ifaddrs *ifa = NULL; struct sockaddr_ll_extended *sa = NULL; assert(message); net_interface = NLMSG_DATA(message); length = message->nlmsg_len - NLMSG_LENGTH(sizeof(*net_interface)); if (length <= 0) { goto error; } ifa = calloc(1, sizeof(*ifa)); if (!ifa) { goto error; } ifa->ifa_flags = net_interface->ifi_flags; attribute = IFLA_RTA(net_interface); while (RTA_OK(attribute, length)) { switch (attribute->rta_type) { case IFLA_IFNAME: ifa->ifa_name = strdup(RTA_DATA(attribute)); if (!ifa->ifa_name) { goto error; } log_debug(LOG_NETLINK, " interface name (payload length: %d; string length: %d)\n", RTA_PAYLOAD(attribute), strlen(ifa->ifa_name)); log_debug(LOG_NETLINK, " %s\n", ifa->ifa_name); break; case IFLA_BROADCAST: log_debug(LOG_NETLINK, " interface broadcast (%d bytes)\n", RTA_PAYLOAD(attribute)); if (fill_ll_address(&sa, net_interface, RTA_DATA(attribute), RTA_PAYLOAD(attribute)) < 0) { goto error; } ifa->_monodroid_ifa_broadaddr = (struct sockaddr*)sa; break; case IFLA_ADDRESS: log_debug(LOG_NETLINK, " interface address (%d bytes)\n", RTA_PAYLOAD(attribute)); if (fill_ll_address(&sa, net_interface, RTA_DATA(attribute), RTA_PAYLOAD(attribute)) < 0) { goto error; } ifa->ifa_addr = (struct sockaddr*)sa; break; default: log_debug(LOG_NETLINK, " rta_type: "); #if DEBUG print_ifla_name(attribute->rta_type); #endif break; } attribute = RTA_NEXT(attribute, length); } log_debug(LOG_NETLINK, "link flags: 0x%X", ifa->ifa_flags); return ifa; error: if (sa) free(sa); free_single_xamarin_ifaddrs(&ifa); return NULL; } #else void _monodroid_getifaddrs_init(void) { } int _monodroid_getifaddrs(struct _monodroid_ifaddrs **ifap) { *ifap = NULL; return 0; } void _monodroid_freeifaddrs(struct _monodroid_ifaddrs *ifa) { } #endif #if LINUX && DEBUG #define ENUM_VALUE_ENTRY(enumvalue) { enumvalue, #enumvalue } struct enumvalue { int value; char *name; }; struct enumvalue iflas[] = { ENUM_VALUE_ENTRY(IFLA_UNSPEC), ENUM_VALUE_ENTRY(IFLA_ADDRESS), ENUM_VALUE_ENTRY(IFLA_BROADCAST), ENUM_VALUE_ENTRY(IFLA_IFNAME), ENUM_VALUE_ENTRY(IFLA_MTU), ENUM_VALUE_ENTRY(IFLA_LINK), ENUM_VALUE_ENTRY(IFLA_QDISC), ENUM_VALUE_ENTRY(IFLA_STATS), ENUM_VALUE_ENTRY(IFLA_COST), ENUM_VALUE_ENTRY(IFLA_PRIORITY), ENUM_VALUE_ENTRY(IFLA_MASTER), ENUM_VALUE_ENTRY(IFLA_WIRELESS), ENUM_VALUE_ENTRY(IFLA_PROTINFO), ENUM_VALUE_ENTRY(IFLA_TXQLEN), ENUM_VALUE_ENTRY(IFLA_MAP), ENUM_VALUE_ENTRY(IFLA_WEIGHT), ENUM_VALUE_ENTRY(IFLA_OPERSTATE), ENUM_VALUE_ENTRY(IFLA_LINKMODE), ENUM_VALUE_ENTRY(IFLA_LINKINFO), ENUM_VALUE_ENTRY(IFLA_NET_NS_PID), ENUM_VALUE_ENTRY(IFLA_IFALIAS), ENUM_VALUE_ENTRY(IFLA_NUM_VF), ENUM_VALUE_ENTRY(IFLA_VFINFO_LIST), ENUM_VALUE_ENTRY(IFLA_STATS64), ENUM_VALUE_ENTRY(IFLA_VF_PORTS), ENUM_VALUE_ENTRY(IFLA_PORT_SELF), ENUM_VALUE_ENTRY(IFLA_AF_SPEC), ENUM_VALUE_ENTRY(IFLA_GROUP), ENUM_VALUE_ENTRY(IFLA_NET_NS_FD), ENUM_VALUE_ENTRY(IFLA_EXT_MASK), ENUM_VALUE_ENTRY(IFLA_PROMISCUITY), ENUM_VALUE_ENTRY(IFLA_NUM_TX_QUEUES), ENUM_VALUE_ENTRY(IFLA_NUM_RX_QUEUES), ENUM_VALUE_ENTRY(IFLA_CARRIER), ENUM_VALUE_ENTRY(IFLA_PHYS_PORT_ID), { -1, 0 } }; static void print_ifla_name(int id) { int i = 0; while (1) { if (iflas[i].value == -1 && iflas[i].name == 0) { log_info(LOG_NETLINK, "Unknown ifla->name: unknown id %d\n", id); break; } if (iflas[i].value != id) { i++; continue; } log_info(LOG_NETLINK, "ifla->name: %s (%d)\n", iflas[i].name, iflas[i].value); break; } } static void print_address_list(char *title, struct _monodroid_ifaddrs *list) { struct _monodroid_ifaddrs *cur; char *msg, *tmp; if (!list) { log_info(LOG_NETLINK, "monodroid-net", "No list to print in %s", __FUNCTION__); return; } cur = list; msg = NULL; while (cur) { tmp = NULL; asprintf(&tmp, "%s%s%p (%s; %p)", msg ? msg : "", msg ? " -> " : "", cur, cur->ifa_name, cur->ifa_name); if (msg) free(msg); msg = tmp; cur = cur->ifa_next; } log_info(LOG_NETLINK, "%s: %s", title, msg ? msg : "[no addresses]"); free(msg); } #endif ================================================ FILE: unity_decoder/libil2cpp/external/xamarin-android/xamarin_getifaddrs.h ================================================ #ifndef __XAMARIN_GETIFADDRS_H #include "monodroid.h" #ifdef __cplusplus extern "C" { #endif /* We're implementing getifaddrs behavior, this is the structure we use. It is exactly the same as * struct ifaddrs defined in ifaddrs.h but since bionics doesn't have it we need to mirror it here. */ struct _monodroid_ifaddrs { struct _monodroid_ifaddrs *ifa_next; /* Pointer to the next structure. */ char *ifa_name; /* Name of this network interface. */ unsigned int ifa_flags; /* Flags as from SIOCGIFFLAGS ioctl. */ struct sockaddr *ifa_addr; /* Network address of this interface. */ struct sockaddr *ifa_netmask; /* Netmask of this interface. */ union { /* At most one of the following two is valid. If the IFF_BROADCAST bit is set in `ifa_flags', then `ifa_broadaddr' is valid. If the IFF_POINTOPOINT bit is set, then `ifa_dstaddr' is valid. It is never the case that both these bits are set at once. */ struct sockaddr *ifu_broadaddr; /* Broadcast address of this interface. */ struct sockaddr *ifu_dstaddr; /* Point-to-point destination address. */ } ifa_ifu; /* These very same macros are defined by for `struct ifaddr'. So if they are defined already, the existing definitions will be fine. */ # ifndef _monodroid_ifa_broadaddr # define _monodroid_ifa_broadaddr ifa_ifu.ifu_broadaddr # endif # ifndef _monodroid_ifa_dstaddr # define _monodroid_ifa_dstaddr ifa_ifu.ifu_dstaddr # endif void *ifa_data; /* Address-specific data (may be unused). */ }; void _monodroid_getifaddrs_init(void); MONO_API int _monodroid_getifaddrs(struct _monodroid_ifaddrs **ifap); MONO_API void _monodroid_freeifaddrs(struct _monodroid_ifaddrs *ifa); #ifdef __cplusplus } #endif #endif ================================================ FILE: unity_decoder/libil2cpp/external/zlib/adler32.c ================================================ /* adler32.c -- compute the Adler-32 checksum of a data stream * Copyright (C) 1995-2006 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #define ZLIB_INTERNAL #include "zlib.h" #define local static #ifdef _LARGEFILE64_SOURCE local uLong adler32_combine_(uLong adler1, uLong adler2, off64_t len2); #else local uLong adler32_combine_(uLong adler1, uLong adler2, z_off_t len2); #endif #define BASE 65521UL /* largest prime smaller than 65536 */ #define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ #define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); #define DO16(buf) DO8(buf,0); DO8(buf,8); /* use NO_DIVIDE if your processor does not do division in hardware */ #ifdef NO_DIVIDE # define MOD(a) \ do { \ if (a >= (BASE << 16)) a -= (BASE << 16); \ if (a >= (BASE << 15)) a -= (BASE << 15); \ if (a >= (BASE << 14)) a -= (BASE << 14); \ if (a >= (BASE << 13)) a -= (BASE << 13); \ if (a >= (BASE << 12)) a -= (BASE << 12); \ if (a >= (BASE << 11)) a -= (BASE << 11); \ if (a >= (BASE << 10)) a -= (BASE << 10); \ if (a >= (BASE << 9)) a -= (BASE << 9); \ if (a >= (BASE << 8)) a -= (BASE << 8); \ if (a >= (BASE << 7)) a -= (BASE << 7); \ if (a >= (BASE << 6)) a -= (BASE << 6); \ if (a >= (BASE << 5)) a -= (BASE << 5); \ if (a >= (BASE << 4)) a -= (BASE << 4); \ if (a >= (BASE << 3)) a -= (BASE << 3); \ if (a >= (BASE << 2)) a -= (BASE << 2); \ if (a >= (BASE << 1)) a -= (BASE << 1); \ if (a >= BASE) a -= BASE; \ } while (0) # define MOD4(a) \ do { \ if (a >= (BASE << 4)) a -= (BASE << 4); \ if (a >= (BASE << 3)) a -= (BASE << 3); \ if (a >= (BASE << 2)) a -= (BASE << 2); \ if (a >= (BASE << 1)) a -= (BASE << 1); \ if (a >= BASE) a -= BASE; \ } while (0) #else # define MOD(a) a %= BASE # define MOD4(a) a %= BASE #endif /* ========================================================================= */ uLong ZEXPORT adler32(adler, buf, len) uLong adler; const Bytef *buf; uInt len; { unsigned long sum2; unsigned n; /* split Adler-32 into component sums */ sum2 = (adler >> 16) & 0xffff; adler &= 0xffff; /* in case user likes doing a byte at a time, keep it fast */ if (len == 1) { adler += buf[0]; if (adler >= BASE) adler -= BASE; sum2 += adler; if (sum2 >= BASE) sum2 -= BASE; return adler | (sum2 << 16); } /* initial Adler-32 value (deferred check for len == 1 speed) */ if (buf == Z_NULL) return 1L; /* in case short lengths are provided, keep it somewhat fast */ if (len < 16) { while (len--) { adler += *buf++; sum2 += adler; } if (adler >= BASE) adler -= BASE; MOD4(sum2); /* only added so many BASE's */ return adler | (sum2 << 16); } /* do length NMAX blocks -- requires just one modulo operation */ while (len >= NMAX) { len -= NMAX; n = NMAX / 16; /* NMAX is divisible by 16 */ do { DO16(buf); /* 16 sums unrolled */ buf += 16; } while (--n); MOD(adler); MOD(sum2); } /* do remaining bytes (less than NMAX, still just one modulo) */ if (len) { /* avoid modulos if none remaining */ while (len >= 16) { len -= 16; DO16(buf); buf += 16; } while (len--) { adler += *buf++; sum2 += adler; } MOD(adler); MOD(sum2); } /* return recombined sums */ return adler | (sum2 << 16); } /* ========================================================================= */ local uLong adler32_combine_(adler1, adler2, len2) uLong adler1; uLong adler2; #ifdef _LARGEFILE64_SOURCE off64_t len2; #else z_off_t len2; #endif { unsigned long sum1; unsigned long sum2; unsigned rem; /* the derivation of this formula is left as an exercise for the reader */ rem = (unsigned)(len2 % BASE); sum1 = adler1 & 0xffff; sum2 = rem * sum1; MOD(sum2); sum1 += (adler2 & 0xffff) + BASE - 1; sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; if (sum1 > BASE) sum1 -= BASE; if (sum1 > BASE) sum1 -= BASE; if (sum2 > (BASE << 1)) sum2 -= (BASE << 1); if (sum2 > BASE) sum2 -= BASE; return sum1 | (sum2 << 16); } /* ========================================================================= */ uLong ZEXPORT adler32_combine(adler1, adler2, len2) uLong adler1; uLong adler2; z_off_t len2; { return adler32_combine_(adler1, adler2, len2); } #ifdef _LARGEFILE64_SOURCE uLong ZEXPORT adler32_combine64(adler1, adler2, len2) uLong adler1; uLong adler2; off64_t len2; { return adler32_combine_(adler1, adler2, len2); } #else uLong ZEXPORT adler32_combine64(adler1, adler2, len2) uLong adler1; uLong adler2; z_off_t len2; { return adler32_combine_(adler1, adler2, len2); } #endif ================================================ FILE: unity_decoder/libil2cpp/external/zlib/compress.c ================================================ /* compress.c -- compress a memory buffer * Copyright (C) 1995-2005 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #define ZLIB_INTERNAL #include "zlib.h" /* =========================================================================== Compresses the source buffer into the destination buffer. The level parameter has the same meaning as in deflateInit. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least 0.1% larger than sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) Bytef *dest; uLongf *destLen; const Bytef *source; uLong sourceLen; int level; { z_stream stream; int err; stream.next_in = (Bytef*)source; stream.avail_in = (uInt)sourceLen; #ifdef MAXSEG_64K /* Check for source > 64K on 16-bit machine: */ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; #endif stream.next_out = dest; stream.avail_out = (uInt)*destLen; if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; stream.opaque = (voidpf)0; err = deflateInit(&stream, level); if (err != Z_OK) return err; err = deflate(&stream, Z_FINISH); if (err != Z_STREAM_END) { deflateEnd(&stream); return err == Z_OK ? Z_BUF_ERROR : err; } *destLen = stream.total_out; err = deflateEnd(&stream); return err; } /* =========================================================================== */ int ZEXPORT compress (dest, destLen, source, sourceLen) Bytef *dest; uLongf *destLen; const Bytef *source; uLong sourceLen; { return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); } /* =========================================================================== If the default memLevel or windowBits for deflateInit() is changed, then this function needs to be updated. */ uLong ZEXPORT compressBound (sourceLen) uLong sourceLen; { return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13; } ================================================ FILE: unity_decoder/libil2cpp/external/zlib/crc32.c ================================================ /* crc32.c -- compute the CRC-32 of a data stream * Copyright (C) 1995-2006 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * * Thanks to Rodney Brown for his contribution of faster * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing * tables for updating the shift register in one step with three exclusive-ors * instead of four steps with four exclusive-ors. This results in about a * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. */ /* @(#) $Id$ */ /* Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore protection on the static variables used to control the first-use generation of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should first call get_crc_table() to initialize the tables before allowing more than one thread to use crc32(). */ #ifdef MAKECRCH # include # ifndef DYNAMIC_CRC_TABLE # define DYNAMIC_CRC_TABLE # endif /* !DYNAMIC_CRC_TABLE */ #endif /* MAKECRCH */ #include "zutil.h" /* for STDC and FAR definitions */ #define local static /* Find a four-byte integer type for crc32_little() and crc32_big(). */ #ifndef NOBYFOUR # ifdef STDC /* need ANSI C limits.h to determine sizes */ # include # define BYFOUR # if (UINT_MAX == 0xffffffffUL) typedef unsigned int u4; # else # if (ULONG_MAX == 0xffffffffUL) typedef unsigned long u4; # else # if (USHRT_MAX == 0xffffffffUL) typedef unsigned short u4; # else # undef BYFOUR /* can't find a four-byte integer type! */ # endif # endif # endif # endif /* STDC */ #endif /* !NOBYFOUR */ /* Definitions for doing the crc four data bytes at a time. */ #ifdef BYFOUR # define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ (((w)&0xff00)<<8)+(((w)&0xff)<<24)) local unsigned long crc32_little OF((unsigned long, const unsigned char FAR *, unsigned)); local unsigned long crc32_big OF((unsigned long, const unsigned char FAR *, unsigned)); # define TBLS 8 #else # define TBLS 1 #endif /* BYFOUR */ /* Local functions for crc concatenation */ local unsigned long gf2_matrix_times OF((unsigned long *mat, unsigned long vec)); local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); #ifdef _LARGEFILE64_SOURCE local uLong crc32_combine_(uLong crc1, uLong crc2, off64_t len2); #else local uLong crc32_combine_(uLong crc1, uLong crc2, z_off_t len2); #endif #ifdef DYNAMIC_CRC_TABLE local volatile int crc_table_empty = 1; local unsigned long FAR crc_table[TBLS][256]; local void make_crc_table OF((void)); #ifdef MAKECRCH local void write_table OF((FILE *, const unsigned long FAR *)); #endif /* MAKECRCH */ /* Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. Polynomials over GF(2) are represented in binary, one bit per coefficient, with the lowest powers in the most significant bit. Then adding polynomials is just exclusive-or, and multiplying a polynomial by x is a right shift by one. If we call the above polynomial p, and represent a byte as the polynomial q, also with the lowest power in the most significant bit (so the byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, where a mod b means the remainder after dividing a by b. This calculation is done using the shift-register method of multiplying and taking the remainder. The register is initialized to zero, and for each incoming bit, x^32 is added mod p to the register if the bit is a one (where x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x (which is shifting right by one and adding x^32 mod p if the bit shifted out is a one). We start with the highest power (least significant bit) of q and repeat for all eight bits of q. The first table is simply the CRC of all possible eight bit values. This is all the information needed to generate CRCs on data a byte at a time for all combinations of CRC register values and incoming bytes. The remaining tables allow for word-at-a-time CRC calculation for both big-endian and little- endian machines, where a word is four bytes. */ local void make_crc_table() { unsigned long c; int n, k; unsigned long poly; /* polynomial exclusive-or pattern */ /* terms of polynomial defining this crc (except x^32): */ static volatile int first = 1; /* flag to limit concurrent making */ static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; /* See if another task is already doing this (not thread-safe, but better than nothing -- significantly reduces duration of vulnerability in case the advice about DYNAMIC_CRC_TABLE is ignored) */ if (first) { first = 0; /* make exclusive-or pattern from polynomial (0xedb88320UL) */ poly = 0UL; for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) poly |= 1UL << (31 - p[n]); /* generate a crc for every 8-bit value */ for (n = 0; n < 256; n++) { c = (unsigned long)n; for (k = 0; k < 8; k++) c = c & 1 ? poly ^ (c >> 1) : c >> 1; crc_table[0][n] = c; } #ifdef BYFOUR /* generate crc for each value followed by one, two, and three zeros, and then the byte reversal of those as well as the first table */ for (n = 0; n < 256; n++) { c = crc_table[0][n]; crc_table[4][n] = REV(c); for (k = 1; k < 4; k++) { c = crc_table[0][c & 0xff] ^ (c >> 8); crc_table[k][n] = c; crc_table[k + 4][n] = REV(c); } } #endif /* BYFOUR */ crc_table_empty = 0; } else { /* not first */ /* wait for the other guy to finish (not efficient, but rare) */ while (crc_table_empty) ; } #ifdef MAKECRCH /* write out CRC tables to crc32.h */ { FILE *out; out = fopen("crc32.h", "w"); if (out == NULL) return; fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); fprintf(out, "local const unsigned long FAR "); fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); write_table(out, crc_table[0]); # ifdef BYFOUR fprintf(out, "#ifdef BYFOUR\n"); for (k = 1; k < 8; k++) { fprintf(out, " },\n {\n"); write_table(out, crc_table[k]); } fprintf(out, "#endif\n"); # endif /* BYFOUR */ fprintf(out, " }\n};\n"); fclose(out); } #endif /* MAKECRCH */ } #ifdef MAKECRCH local void write_table(out, table) FILE *out; const unsigned long FAR *table; { int n; for (n = 0; n < 256; n++) fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); } #endif /* MAKECRCH */ #else /* !DYNAMIC_CRC_TABLE */ /* ======================================================================== * Tables of CRC-32s of all single-byte values, made by make_crc_table(). */ #include "crc32.h" #endif /* DYNAMIC_CRC_TABLE */ /* ========================================================================= * This function can be used by asm versions of crc32() */ const unsigned long FAR * ZEXPORT get_crc_table() { #ifdef DYNAMIC_CRC_TABLE if (crc_table_empty) make_crc_table(); #endif /* DYNAMIC_CRC_TABLE */ return (const unsigned long FAR *)crc_table; } /* ========================================================================= */ #define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) #define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 /* ========================================================================= */ unsigned long ZEXPORT crc32(crc, buf, len) unsigned long crc; const unsigned char FAR *buf; unsigned len; { if (buf == Z_NULL) return 0UL; #ifdef DYNAMIC_CRC_TABLE if (crc_table_empty) make_crc_table(); #endif /* DYNAMIC_CRC_TABLE */ #ifdef BYFOUR if (sizeof(void *) == sizeof(ptrdiff_t)) { u4 endian; endian = 1; if (*((unsigned char *)(&endian))) return crc32_little(crc, buf, len); else return crc32_big(crc, buf, len); } #endif /* BYFOUR */ crc = crc ^ 0xffffffffUL; while (len >= 8) { DO8; len -= 8; } if (len) do { DO1; } while (--len); return crc ^ 0xffffffffUL; } #ifdef BYFOUR /* ========================================================================= */ #define DOLIT4 c ^= *buf4++; \ c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] #define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 /* ========================================================================= */ local unsigned long crc32_little(crc, buf, len) unsigned long crc; const unsigned char FAR *buf; unsigned len; { register u4 c; register const u4 FAR *buf4; c = (u4)crc; c = ~c; while (len && ((ptrdiff_t)buf & 3)) { c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); len--; } buf4 = (const u4 FAR *)(const void FAR *)buf; while (len >= 32) { DOLIT32; len -= 32; } while (len >= 4) { DOLIT4; len -= 4; } buf = (const unsigned char FAR *)buf4; if (len) do { c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); } while (--len); c = ~c; return (unsigned long)c; } /* ========================================================================= */ #define DOBIG4 c ^= *++buf4; \ c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 /* ========================================================================= */ local unsigned long crc32_big(crc, buf, len) unsigned long crc; const unsigned char FAR *buf; unsigned len; { register u4 c; register const u4 FAR *buf4; c = REV((u4)crc); c = ~c; while (len && ((ptrdiff_t)buf & 3)) { c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); len--; } buf4 = (const u4 FAR *)(const void FAR *)buf; buf4--; while (len >= 32) { DOBIG32; len -= 32; } while (len >= 4) { DOBIG4; len -= 4; } buf4++; buf = (const unsigned char FAR *)buf4; if (len) do { c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); } while (--len); c = ~c; return (unsigned long)(REV(c)); } #endif /* BYFOUR */ #define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ /* ========================================================================= */ local unsigned long gf2_matrix_times(mat, vec) unsigned long *mat; unsigned long vec; { unsigned long sum; sum = 0; while (vec) { if (vec & 1) sum ^= *mat; vec >>= 1; mat++; } return sum; } /* ========================================================================= */ local void gf2_matrix_square(square, mat) unsigned long *square; unsigned long *mat; { int n; for (n = 0; n < GF2_DIM; n++) square[n] = gf2_matrix_times(mat, mat[n]); } /* ========================================================================= */ local uLong crc32_combine_(crc1, crc2, len2) uLong crc1; uLong crc2; #ifdef _LARGEFILE64_SOURCE off64_t len2; #else z_off_t len2; #endif { int n; unsigned long row; unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ /* degenerate case */ if (len2 == 0) return crc1; /* put operator for one zero bit in odd */ odd[0] = 0xedb88320L; /* CRC-32 polynomial */ row = 1; for (n = 1; n < GF2_DIM; n++) { odd[n] = row; row <<= 1; } /* put operator for two zero bits in even */ gf2_matrix_square(even, odd); /* put operator for four zero bits in odd */ gf2_matrix_square(odd, even); /* apply len2 zeros to crc1 (first square will put the operator for one zero byte, eight zero bits, in even) */ do { /* apply zeros operator for this bit of len2 */ gf2_matrix_square(even, odd); if (len2 & 1) crc1 = gf2_matrix_times(even, crc1); len2 >>= 1; /* if no more bits set, then done */ if (len2 == 0) break; /* another iteration of the loop with odd and even swapped */ gf2_matrix_square(odd, even); if (len2 & 1) crc1 = gf2_matrix_times(odd, crc1); len2 >>= 1; /* if no more bits set, then done */ } while (len2 != 0); /* return combined crc */ crc1 ^= crc2; return crc1; } /* ========================================================================= */ uLong ZEXPORT crc32_combine(crc1, crc2, len2) uLong crc1; uLong crc2; z_off_t len2; { return crc32_combine_(crc1, crc2, len2); } #ifdef _LARGEFILE64_SOURCE uLong ZEXPORT crc32_combine64(crc1, crc2, len2) uLong crc1; uLong crc2; off64_t len2; { return crc32_combine_(crc1, crc2, len2); } #else uLong ZEXPORT crc32_combine64(crc1, crc2, len2) uLong crc1; uLong crc2; z_off_t len2; { return crc32_combine_(crc1, crc2, len2); } #endif ================================================ FILE: unity_decoder/libil2cpp/external/zlib/crc32.h ================================================ /* crc32.h -- tables for rapid CRC calculation * Generated automatically by crc32.c */ local const unsigned long FAR crc_table[TBLS][256] = { { 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, 0x2d02ef8dUL #ifdef BYFOUR }, { 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, 0x9324fd72UL }, { 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, 0xbe9834edUL }, { 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, 0xde0506f1UL }, { 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, 0x8def022dUL }, { 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, 0x72fd2493UL }, { 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, 0xed3498beUL }, { 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, 0xf10605deUL #endif } }; ================================================ FILE: unity_decoder/libil2cpp/external/zlib/deflate.c ================================================ /* deflate.c -- compress data using the deflation algorithm * Copyright (C) 1995-2006 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* * ALGORITHM * * The "deflation" process depends on being able to identify portions * of the input text which are identical to earlier input (within a * sliding window trailing behind the input currently being processed). * * The most straightforward technique turns out to be the fastest for * most input files: try all possible matches and select the longest. * The key feature of this algorithm is that insertions into the string * dictionary are very simple and thus fast, and deletions are avoided * completely. Insertions are performed at each input character, whereas * string matches are performed only when the previous match ends. So it * is preferable to spend more time in matches to allow very fast string * insertions and avoid deletions. The matching algorithm for small * strings is inspired from that of Rabin & Karp. A brute force approach * is used to find longer strings when a small match has been found. * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze * (by Leonid Broukhis). * A previous version of this file used a more sophisticated algorithm * (by Fiala and Greene) which is guaranteed to run in linear amortized * time, but has a larger average cost, uses more memory and is patented. * However the F&G algorithm may be faster for some highly redundant * files if the parameter max_chain_length (described below) is too large. * * ACKNOWLEDGEMENTS * * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and * I found it in 'freeze' written by Leonid Broukhis. * Thanks to many people for bug reports and testing. * * REFERENCES * * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". * Available in http://www.ietf.org/rfc/rfc1951.txt * * A description of the Rabin and Karp algorithm is given in the book * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. * * Fiala,E.R., and Greene,D.H. * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 * */ /* @(#) $Id$ */ #include "deflate.h" const char deflate_copyright[] = " deflate 1.2.3.3 Copyright 1995-2006 Jean-loup Gailly "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot include such an acknowledgment, I would appreciate that you keep this copyright string in the executable of your product. */ /* =========================================================================== * Function prototypes. */ typedef enum { need_more, /* block not completed, need more input or more output */ block_done, /* block flush performed */ finish_started, /* finish started, need only more output at next deflate */ finish_done /* finish done, accept no more input or output */ } block_state; typedef block_state (*compress_func) OF((deflate_state *s, int flush)); /* Compression function. Returns the block state after the call. */ local void fill_window OF((deflate_state *s)); local block_state deflate_stored OF((deflate_state *s, int flush)); local block_state deflate_fast OF((deflate_state *s, int flush)); #ifndef FASTEST local block_state deflate_slow OF((deflate_state *s, int flush)); #endif local void lm_init OF((deflate_state *s)); local void putShortMSB OF((deflate_state *s, uInt b)); local void flush_pending OF((z_streamp strm)); local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); #ifndef FASTEST #ifdef ASMV void match_init OF((void)); /* asm code initialization */ uInt longest_match OF((deflate_state *s, IPos cur_match)); #else local uInt longest_match OF((deflate_state *s, IPos cur_match)); #endif #endif local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); #ifdef DEBUG local void check_match OF((deflate_state *s, IPos start, IPos match, int length)); #endif /* =========================================================================== * Local data */ #define NIL 0 /* Tail of hash chains */ #ifndef TOO_FAR # define TOO_FAR 4096 #endif /* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) /* Minimum amount of lookahead, except at the end of the input file. * See deflate.c for comments about the MIN_MATCH+1. */ /* Values for max_lazy_match, good_match and max_chain_length, depending on * the desired pack level (0..9). The values given below have been tuned to * exclude worst case performance for pathological files. Better values may be * found for specific files. */ typedef struct config_s { ush good_length; /* reduce lazy search above this match length */ ush max_lazy; /* do not perform lazy search above this match length */ ush nice_length; /* quit search above this match length */ ush max_chain; compress_func func; } config; #ifdef FASTEST local const config configuration_table[2] = { /* good lazy nice chain */ /* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ /* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ #else local const config configuration_table[10] = { /* good lazy nice chain */ /* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ /* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ /* 2 */ {4, 5, 16, 8, deflate_fast}, /* 3 */ {4, 6, 32, 32, deflate_fast}, /* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ /* 5 */ {8, 16, 32, 32, deflate_slow}, /* 6 */ {8, 16, 128, 128, deflate_slow}, /* 7 */ {8, 32, 128, 256, deflate_slow}, /* 8 */ {32, 128, 258, 1024, deflate_slow}, /* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ #endif /* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 * For deflate_fast() (levels <= 3) good is ignored and lazy has a different * meaning. */ #define EQUAL 0 /* result of memcmp for equal strings */ #ifndef NO_DUMMY_DECL struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ #endif /* =========================================================================== * Update a hash value with the given input byte * IN assertion: all calls to to UPDATE_HASH are made with consecutive * input characters, so that a running hash key can be computed from the * previous key instead of complete recalculation each time. */ #define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) /* =========================================================================== * Insert string str in the dictionary and set match_head to the previous head * of the hash chain (the most recent string with same hash key). Return * the previous length of the hash chain. * If this file is compiled with -DFASTEST, the compression level is forced * to 1, and no hash chains are maintained. * IN assertion: all calls to to INSERT_STRING are made with consecutive * input characters and the first MIN_MATCH bytes of str are valid * (except for the last MIN_MATCH-1 bytes of the input file). */ #ifdef FASTEST #define INSERT_STRING(s, str, match_head) \ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ match_head = s->head[s->ins_h], \ s->head[s->ins_h] = (Pos)(str)) #else #define INSERT_STRING(s, str, match_head) \ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ s->head[s->ins_h] = (Pos)(str)) #endif /* =========================================================================== * Initialize the hash table (avoiding 64K overflow for 16 bit systems). * prev[] will be initialized on the fly. */ #define CLEAR_HASH(s) \ s->head[s->hash_size-1] = NIL; \ zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); /* ========================================================================= */ int ZEXPORT deflateInit_(strm, level, version, stream_size) z_streamp strm; int level; const char *version; int stream_size; { return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, version, stream_size); /* To do: ignore strm->next_in if we use it as window */ } /* ========================================================================= */ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, version, stream_size) z_streamp strm; int level; int method; int windowBits; int memLevel; int strategy; const char *version; int stream_size; { deflate_state *s; int wrap = 1; static const char my_version[] = ZLIB_VERSION; ushf *overlay; /* We overlay pending_buf and d_buf+l_buf. This works since the average * output size for (length,distance) codes is <= 24 bits. */ if (version == Z_NULL || version[0] != my_version[0] || stream_size != sizeof(z_stream)) { return Z_VERSION_ERROR; } if (strm == Z_NULL) return Z_STREAM_ERROR; strm->msg = Z_NULL; if (strm->zalloc == (alloc_func)0) { strm->zalloc = zcalloc; strm->opaque = (voidpf)0; } if (strm->zfree == (free_func)0) strm->zfree = zcfree; #ifdef FASTEST if (level != 0) level = 1; #else if (level == Z_DEFAULT_COMPRESSION) level = 6; #endif if (windowBits < 0) { /* suppress zlib wrapper */ wrap = 0; windowBits = -windowBits; } #ifdef GZIP else if (windowBits > 15) { wrap = 2; /* write gzip wrapper instead */ windowBits -= 16; } #endif if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { return Z_STREAM_ERROR; } if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); if (s == Z_NULL) return Z_MEM_ERROR; strm->state = (struct internal_state FAR *)s; s->strm = strm; s->wrap = wrap; s->gzhead = Z_NULL; s->w_bits = windowBits; s->w_size = 1 << s->w_bits; s->w_mask = s->w_size - 1; s->hash_bits = memLevel + 7; s->hash_size = 1 << s->hash_bits; s->hash_mask = s->hash_size - 1; s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); s->pending_buf = (uchf *) overlay; s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || s->pending_buf == Z_NULL) { s->status = FINISH_STATE; strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); deflateEnd (strm); return Z_MEM_ERROR; } s->d_buf = overlay + s->lit_bufsize/sizeof(ush); s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; s->level = level; s->strategy = strategy; s->method = (Byte)method; return deflateReset(strm); } /* ========================================================================= */ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) z_streamp strm; const Bytef *dictionary; uInt dictLength; { deflate_state *s; uInt length = dictLength; uInt n; IPos hash_head = 0; if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || strm->state->wrap == 2 || (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) return Z_STREAM_ERROR; s = strm->state; if (s->wrap) strm->adler = adler32(strm->adler, dictionary, dictLength); if (length < MIN_MATCH) return Z_OK; if (length > MAX_DIST(s)) { length = MAX_DIST(s); dictionary += dictLength - length; /* use the tail of the dictionary */ } zmemcpy(s->window, dictionary, length); s->strstart = length; s->block_start = (long)length; /* Insert all strings in the hash table (except for the last two bytes). * s->lookahead stays null, so s->ins_h will be recomputed at the next * call of fill_window. */ s->ins_h = s->window[0]; UPDATE_HASH(s, s->ins_h, s->window[1]); for (n = 0; n <= length - MIN_MATCH; n++) { INSERT_STRING(s, n, hash_head); } if (hash_head) hash_head = 0; /* to make compiler happy */ return Z_OK; } /* ========================================================================= */ int ZEXPORT deflateReset (strm) z_streamp strm; { deflate_state *s; if (strm == Z_NULL || strm->state == Z_NULL || strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { return Z_STREAM_ERROR; } strm->total_in = strm->total_out = 0; strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ strm->data_type = Z_UNKNOWN; s = (deflate_state *)strm->state; s->pending = 0; s->pending_out = s->pending_buf; if (s->wrap < 0) { s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ } s->status = s->wrap ? INIT_STATE : BUSY_STATE; strm->adler = #ifdef GZIP s->wrap == 2 ? crc32(0L, Z_NULL, 0) : #endif adler32(0L, Z_NULL, 0); s->last_flush = Z_NO_FLUSH; _tr_init(s); lm_init(s); return Z_OK; } /* ========================================================================= */ int ZEXPORT deflateSetHeader (strm, head) z_streamp strm; gz_headerp head; { if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; if (strm->state->wrap != 2) return Z_STREAM_ERROR; strm->state->gzhead = head; return Z_OK; } /* ========================================================================= */ int ZEXPORT deflatePrime (strm, bits, value) z_streamp strm; int bits; int value; { if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; strm->state->bi_valid = bits; strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); return Z_OK; } /* ========================================================================= */ int ZEXPORT deflateParams(strm, level, strategy) z_streamp strm; int level; int strategy; { deflate_state *s; compress_func func; int err = Z_OK; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; s = strm->state; #ifdef FASTEST if (level != 0) level = 1; #else if (level == Z_DEFAULT_COMPRESSION) level = 6; #endif if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { return Z_STREAM_ERROR; } func = configuration_table[s->level].func; if (func != configuration_table[level].func && strm->total_in != 0) { /* Flush the last buffer: */ err = deflate(strm, Z_PARTIAL_FLUSH); } if (s->level != level) { s->level = level; s->max_lazy_match = configuration_table[level].max_lazy; s->good_match = configuration_table[level].good_length; s->nice_match = configuration_table[level].nice_length; s->max_chain_length = configuration_table[level].max_chain; } s->strategy = strategy; return err; } /* ========================================================================= */ int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) z_streamp strm; int good_length; int max_lazy; int nice_length; int max_chain; { deflate_state *s; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; s = strm->state; s->good_match = good_length; s->max_lazy_match = max_lazy; s->nice_match = nice_length; s->max_chain_length = max_chain; return Z_OK; } /* ========================================================================= * For the default windowBits of 15 and memLevel of 8, this function returns * a close to exact, as well as small, upper bound on the compressed size. * They are coded as constants here for a reason--if the #define's are * changed, then this function needs to be changed as well. The return * value for 15 and 8 only works for those exact settings. * * For any setting other than those defaults for windowBits and memLevel, * the value returned is a conservative worst case for the maximum expansion * resulting from using fixed blocks instead of stored blocks, which deflate * can emit on compressed data for some combinations of the parameters. * * This function could be more sophisticated to provide closer upper bounds for * every combination of windowBits and memLevel. But even the conservative * upper bound of about 14% expansion does not seem onerous for output buffer * allocation. */ uLong ZEXPORT deflateBound(strm, sourceLen) z_streamp strm; uLong sourceLen; { deflate_state *s; uLong complen, wraplen; Bytef *str; /* conservative upper bound for compressed data */ complen = sourceLen + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; /* if can't get parameters, return conservative bound plus zlib wrapper */ if (strm == Z_NULL || strm->state == Z_NULL) return complen + 6; /* compute wrapper length */ s = strm->state; switch (s->wrap) { case 0: /* raw deflate */ wraplen = 0; break; case 1: /* zlib wrapper */ wraplen = 6 + (s->strstart ? 4 : 0); break; case 2: /* gzip wrapper */ wraplen = 18; if (s->gzhead != NULL) { /* user-supplied gzip header */ if (s->gzhead->extra != NULL) wraplen += 2 + s->gzhead->extra_len; str = s->gzhead->name; if (str != NULL) do { wraplen++; } while (*str++); str = s->gzhead->comment; if (str != NULL) do { wraplen++; } while (*str++); if (s->gzhead->hcrc) wraplen += 2; } break; default: /* for compiler happiness */ wraplen = 6; } /* if not default parameters, return conservative bound */ if (s->w_bits != 15 || s->hash_bits != 8 + 7) return complen + wraplen; /* default settings: return tight bound for that case */ return compressBound(sourceLen) - 6 + wraplen; } /* ========================================================================= * Put a short in the pending buffer. The 16-bit value is put in MSB order. * IN assertion: the stream state is correct and there is enough room in * pending_buf. */ local void putShortMSB (s, b) deflate_state *s; uInt b; { put_byte(s, (Byte)(b >> 8)); put_byte(s, (Byte)(b & 0xff)); } /* ========================================================================= * Flush as much pending output as possible. All deflate() output goes * through this function so some applications may wish to modify it * to avoid allocating a large strm->next_out buffer and copying into it. * (See also read_buf()). */ local void flush_pending(strm) z_streamp strm; { unsigned len = strm->state->pending; if (len > strm->avail_out) len = strm->avail_out; if (len == 0) return; zmemcpy(strm->next_out, strm->state->pending_out, len); strm->next_out += len; strm->state->pending_out += len; strm->total_out += len; strm->avail_out -= len; strm->state->pending -= len; if (strm->state->pending == 0) { strm->state->pending_out = strm->state->pending_buf; } } /* ========================================================================= */ int ZEXPORT deflate (strm, flush) z_streamp strm; int flush; { int old_flush; /* value of flush param for previous deflate call */ deflate_state *s; if (strm == Z_NULL || strm->state == Z_NULL || flush > Z_FINISH || flush < 0) { return Z_STREAM_ERROR; } s = strm->state; if (strm->next_out == Z_NULL || (strm->next_in == Z_NULL && strm->avail_in != 0) || (s->status == FINISH_STATE && flush != Z_FINISH)) { ERR_RETURN(strm, Z_STREAM_ERROR); } if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); s->strm = strm; /* just in case */ old_flush = s->last_flush; s->last_flush = flush; /* Write the header */ if (s->status == INIT_STATE) { #ifdef GZIP if (s->wrap == 2) { strm->adler = crc32(0L, Z_NULL, 0); put_byte(s, 31); put_byte(s, 139); put_byte(s, 8); if (s->gzhead == NULL) { put_byte(s, 0); put_byte(s, 0); put_byte(s, 0); put_byte(s, 0); put_byte(s, 0); put_byte(s, s->level == 9 ? 2 : (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? 4 : 0)); put_byte(s, OS_CODE); s->status = BUSY_STATE; } else { put_byte(s, (s->gzhead->text ? 1 : 0) + (s->gzhead->hcrc ? 2 : 0) + (s->gzhead->extra == Z_NULL ? 0 : 4) + (s->gzhead->name == Z_NULL ? 0 : 8) + (s->gzhead->comment == Z_NULL ? 0 : 16) ); put_byte(s, (Byte)(s->gzhead->time & 0xff)); put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); put_byte(s, s->level == 9 ? 2 : (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? 4 : 0)); put_byte(s, s->gzhead->os & 0xff); if (s->gzhead->extra != NULL) { put_byte(s, s->gzhead->extra_len & 0xff); put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); } if (s->gzhead->hcrc) strm->adler = crc32(strm->adler, s->pending_buf, s->pending); s->gzindex = 0; s->status = EXTRA_STATE; } } else #endif { uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; uInt level_flags; if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) level_flags = 0; else if (s->level < 6) level_flags = 1; else if (s->level == 6) level_flags = 2; else level_flags = 3; header |= (level_flags << 6); if (s->strstart != 0) header |= PRESET_DICT; header += 31 - (header % 31); s->status = BUSY_STATE; putShortMSB(s, header); /* Save the adler32 of the preset dictionary: */ if (s->strstart != 0) { putShortMSB(s, (uInt)(strm->adler >> 16)); putShortMSB(s, (uInt)(strm->adler & 0xffff)); } strm->adler = adler32(0L, Z_NULL, 0); } } #ifdef GZIP if (s->status == EXTRA_STATE) { if (s->gzhead->extra != NULL) { uInt beg = s->pending; /* start of bytes to update crc */ while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { if (s->pending == s->pending_buf_size) { if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); flush_pending(strm); beg = s->pending; if (s->pending == s->pending_buf_size) break; } put_byte(s, s->gzhead->extra[s->gzindex]); s->gzindex++; } if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); if (s->gzindex == s->gzhead->extra_len) { s->gzindex = 0; s->status = NAME_STATE; } } else s->status = NAME_STATE; } if (s->status == NAME_STATE) { if (s->gzhead->name != NULL) { uInt beg = s->pending; /* start of bytes to update crc */ int val; do { if (s->pending == s->pending_buf_size) { if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); flush_pending(strm); beg = s->pending; if (s->pending == s->pending_buf_size) { val = 1; break; } } val = s->gzhead->name[s->gzindex++]; put_byte(s, val); } while (val != 0); if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); if (val == 0) { s->gzindex = 0; s->status = COMMENT_STATE; } } else s->status = COMMENT_STATE; } if (s->status == COMMENT_STATE) { if (s->gzhead->comment != NULL) { uInt beg = s->pending; /* start of bytes to update crc */ int val; do { if (s->pending == s->pending_buf_size) { if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); flush_pending(strm); beg = s->pending; if (s->pending == s->pending_buf_size) { val = 1; break; } } val = s->gzhead->comment[s->gzindex++]; put_byte(s, val); } while (val != 0); if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); if (val == 0) s->status = HCRC_STATE; } else s->status = HCRC_STATE; } if (s->status == HCRC_STATE) { if (s->gzhead->hcrc) { if (s->pending + 2 > s->pending_buf_size) flush_pending(strm); if (s->pending + 2 <= s->pending_buf_size) { put_byte(s, (Byte)(strm->adler & 0xff)); put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); strm->adler = crc32(0L, Z_NULL, 0); s->status = BUSY_STATE; } } else s->status = BUSY_STATE; } #endif /* Flush as much pending output as possible */ if (s->pending != 0) { flush_pending(strm); if (strm->avail_out == 0) { /* Since avail_out is 0, deflate will be called again with * more output space, but possibly with both pending and * avail_in equal to zero. There won't be anything to do, * but this is not an error situation so make sure we * return OK instead of BUF_ERROR at next call of deflate: */ s->last_flush = -1; return Z_OK; } /* Make sure there is something to do and avoid duplicate consecutive * flushes. For repeated and useless calls with Z_FINISH, we keep * returning Z_STREAM_END instead of Z_BUF_ERROR. */ } else if (strm->avail_in == 0 && flush <= old_flush && flush != Z_FINISH) { ERR_RETURN(strm, Z_BUF_ERROR); } /* User must not provide more input after the first FINISH: */ if (s->status == FINISH_STATE && strm->avail_in != 0) { ERR_RETURN(strm, Z_BUF_ERROR); } /* Start a new block or continue the current one. */ if (strm->avail_in != 0 || s->lookahead != 0 || (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { block_state bstate; bstate = (*(configuration_table[s->level].func))(s, flush); if (bstate == finish_started || bstate == finish_done) { s->status = FINISH_STATE; } if (bstate == need_more || bstate == finish_started) { if (strm->avail_out == 0) { s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ } return Z_OK; /* If flush != Z_NO_FLUSH && avail_out == 0, the next call * of deflate should use the same flush parameter to make sure * that the flush is complete. So we don't have to output an * empty block here, this will be done at next call. This also * ensures that for a very small output buffer, we emit at most * one empty block. */ } if (bstate == block_done) { if (flush == Z_PARTIAL_FLUSH) { _tr_align(s); } else { /* FULL_FLUSH or SYNC_FLUSH */ _tr_stored_block(s, (char*)0, 0L, 0); /* For a full flush, this empty block will be recognized * as a special marker by inflate_sync(). */ if (flush == Z_FULL_FLUSH) { CLEAR_HASH(s); /* forget history */ } } flush_pending(strm); if (strm->avail_out == 0) { s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ return Z_OK; } } } Assert(strm->avail_out > 0, "bug2"); if (flush != Z_FINISH) return Z_OK; if (s->wrap <= 0) return Z_STREAM_END; /* Write the trailer */ #ifdef GZIP if (s->wrap == 2) { put_byte(s, (Byte)(strm->adler & 0xff)); put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); put_byte(s, (Byte)(strm->total_in & 0xff)); put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); } else #endif { putShortMSB(s, (uInt)(strm->adler >> 16)); putShortMSB(s, (uInt)(strm->adler & 0xffff)); } flush_pending(strm); /* If avail_out is zero, the application will call deflate again * to flush the rest. */ if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ return s->pending != 0 ? Z_OK : Z_STREAM_END; } /* ========================================================================= */ int ZEXPORT deflateEnd (strm) z_streamp strm; { int status; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; status = strm->state->status; if (status != INIT_STATE && status != EXTRA_STATE && status != NAME_STATE && status != COMMENT_STATE && status != HCRC_STATE && status != BUSY_STATE && status != FINISH_STATE) { return Z_STREAM_ERROR; } /* Deallocate in reverse order of allocations: */ TRY_FREE(strm, strm->state->pending_buf); TRY_FREE(strm, strm->state->head); TRY_FREE(strm, strm->state->prev); TRY_FREE(strm, strm->state->window); ZFREE(strm, strm->state); strm->state = Z_NULL; return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; } /* ========================================================================= * Copy the source state to the destination state. * To simplify the source, this is not supported for 16-bit MSDOS (which * doesn't have enough memory anyway to duplicate compression states). */ int ZEXPORT deflateCopy (dest, source) z_streamp dest; z_streamp source; { #ifdef MAXSEG_64K return Z_STREAM_ERROR; #else deflate_state *ds; deflate_state *ss; ushf *overlay; if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { return Z_STREAM_ERROR; } ss = source->state; zmemcpy(dest, source, sizeof(z_stream)); ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); if (ds == Z_NULL) return Z_MEM_ERROR; dest->state = (struct internal_state FAR *) ds; zmemcpy(ds, ss, sizeof(deflate_state)); ds->strm = dest; ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); ds->pending_buf = (uchf *) overlay; if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || ds->pending_buf == Z_NULL) { deflateEnd (dest); return Z_MEM_ERROR; } /* following zmemcpy do not work for 16-bit MSDOS */ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; ds->l_desc.dyn_tree = ds->dyn_ltree; ds->d_desc.dyn_tree = ds->dyn_dtree; ds->bl_desc.dyn_tree = ds->bl_tree; return Z_OK; #endif /* MAXSEG_64K */ } /* =========================================================================== * Read a new buffer from the current input stream, update the adler32 * and total number of bytes read. All deflate() input goes through * this function so some applications may wish to modify it to avoid * allocating a large strm->next_in buffer and copying from it. * (See also flush_pending()). */ local int read_buf(strm, buf, size) z_streamp strm; Bytef *buf; unsigned size; { unsigned len = strm->avail_in; if (len > size) len = size; if (len == 0) return 0; strm->avail_in -= len; if (strm->state->wrap == 1) { strm->adler = adler32(strm->adler, strm->next_in, len); } #ifdef GZIP else if (strm->state->wrap == 2) { strm->adler = crc32(strm->adler, strm->next_in, len); } #endif zmemcpy(buf, strm->next_in, len); strm->next_in += len; strm->total_in += len; return (int)len; } /* =========================================================================== * Initialize the "longest match" routines for a new zlib stream */ local void lm_init (s) deflate_state *s; { s->window_size = (ulg)2L*s->w_size; CLEAR_HASH(s); /* Set the default configuration parameters: */ s->max_lazy_match = configuration_table[s->level].max_lazy; s->good_match = configuration_table[s->level].good_length; s->nice_match = configuration_table[s->level].nice_length; s->max_chain_length = configuration_table[s->level].max_chain; s->strstart = 0; s->block_start = 0L; s->lookahead = 0; s->match_length = s->prev_length = MIN_MATCH-1; s->match_available = 0; s->ins_h = 0; #ifndef FASTEST #ifdef ASMV match_init(); /* initialize the asm code */ #endif #endif } #ifndef FASTEST /* =========================================================================== * Set match_start to the longest match starting at the given string and * return its length. Matches shorter or equal to prev_length are discarded, * in which case the result is equal to prev_length and match_start is * garbage. * IN assertions: cur_match is the head of the hash chain for the current * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 * OUT assertion: the match length is not greater than s->lookahead. */ #ifndef ASMV /* For 80x86 and 680x0, an optimized version will be provided in match.asm or * match.S. The code will be functionally equivalent. */ local uInt longest_match(s, cur_match) deflate_state *s; IPos cur_match; /* current match */ { unsigned chain_length = s->max_chain_length;/* max hash chain length */ register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *match; /* matched string */ register int len; /* length of current match */ int best_len = s->prev_length; /* best match length so far */ int nice_match = s->nice_match; /* stop if match long enough */ IPos limit = s->strstart > (IPos)MAX_DIST(s) ? s->strstart - (IPos)MAX_DIST(s) : NIL; /* Stop when cur_match becomes <= limit. To simplify the code, * we prevent matches with the string of window index 0. */ Posf *prev = s->prev; uInt wmask = s->w_mask; #ifdef UNALIGNED_OK /* Compare two bytes at a time. Note: this is not always beneficial. * Try with and without -DUNALIGNED_OK to check. */ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; register ush scan_start = *(ushf*)scan; register ush scan_end = *(ushf*)(scan+best_len-1); #else register Bytef *strend = s->window + s->strstart + MAX_MATCH; register Byte scan_end1 = scan[best_len-1]; register Byte scan_end = scan[best_len]; #endif /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. * It is easy to get rid of this optimization if necessary. */ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); /* Do not waste too much time if we already have a good match: */ if (s->prev_length >= s->good_match) { chain_length >>= 2; } /* Do not look for matches beyond the end of the input. This is necessary * to make deflate deterministic. */ if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); do { Assert(cur_match < s->strstart, "no future"); match = s->window + cur_match; /* Skip to next match if the match length cannot increase * or if the match length is less than 2. Note that the checks below * for insufficient lookahead only occur occasionally for performance * reasons. Therefore uninitialized memory will be accessed, and * conditional jumps will be made that depend on those values. * However the length of the match is limited to the lookahead, so * the output of deflate is not affected by the uninitialized values. */ #if (defined(UNALIGNED_OK) && MAX_MATCH == 258) /* This code assumes sizeof(unsigned short) == 2. Do not use * UNALIGNED_OK if your compiler uses a different size. */ if (*(ushf*)(match+best_len-1) != scan_end || *(ushf*)match != scan_start) continue; /* It is not necessary to compare scan[2] and match[2] since they are * always equal when the other bytes match, given that the hash keys * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at * strstart+3, +5, ... up to strstart+257. We check for insufficient * lookahead only every 4th comparison; the 128th check will be made * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is * necessary to put more guard bytes at the end of the window, or * to check more often for insufficient lookahead. */ Assert(scan[2] == match[2], "scan[2]?"); scan++, match++; do { } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && *(ushf*)(scan+=2) == *(ushf*)(match+=2) && *(ushf*)(scan+=2) == *(ushf*)(match+=2) && *(ushf*)(scan+=2) == *(ushf*)(match+=2) && scan < strend); /* The funny "do {}" generates better code on most compilers */ /* Here, scan <= window+strstart+257 */ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); if (*scan == *match) scan++; len = (MAX_MATCH - 1) - (int)(strend-scan); scan = strend - (MAX_MATCH-1); #else /* UNALIGNED_OK */ if (match[best_len] != scan_end || match[best_len-1] != scan_end1 || *match != *scan || *++match != scan[1]) continue; /* The check at best_len-1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that * the hash keys are equal and that HASH_BITS >= 8. */ scan += 2, match++; Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; * the 256th check will be made at strstart+258. */ do { } while (*++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && scan < strend); Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); len = MAX_MATCH - (int)(strend - scan); scan = strend - MAX_MATCH; #endif /* UNALIGNED_OK */ if (len > best_len) { s->match_start = cur_match; best_len = len; if (len >= nice_match) break; #ifdef UNALIGNED_OK scan_end = *(ushf*)(scan+best_len-1); #else scan_end1 = scan[best_len-1]; scan_end = scan[best_len]; #endif } } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length != 0); if ((uInt)best_len <= s->lookahead) return (uInt)best_len; return s->lookahead; } #endif /* ASMV */ #endif /* FASTEST */ /* --------------------------------------------------------------------------- * Optimized version for level == 1 or strategy == Z_RLE only */ local uInt longest_match_fast(s, cur_match) deflate_state *s; IPos cur_match; /* current match */ { register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *match; /* matched string */ register int len; /* length of current match */ register Bytef *strend = s->window + s->strstart + MAX_MATCH; /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. * It is easy to get rid of this optimization if necessary. */ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); Assert(cur_match < s->strstart, "no future"); match = s->window + cur_match; /* Return failure if the match length is less than 2: */ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; /* The check at best_len-1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that * the hash keys are equal and that HASH_BITS >= 8. */ scan += 2, match += 2; Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; * the 256th check will be made at strstart+258. */ do { } while (*++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && scan < strend); Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); len = MAX_MATCH - (int)(strend - scan); if (len < MIN_MATCH) return MIN_MATCH - 1; s->match_start = cur_match; return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; } #ifdef DEBUG /* =========================================================================== * Check that the match at match_start is indeed a match. */ local void check_match(s, start, match, length) deflate_state *s; IPos start, match; int length; { /* check that the match is indeed a match */ if (zmemcmp(s->window + match, s->window + start, length) != EQUAL) { fprintf(stderr, " start %u, match %u, length %d\n", start, match, length); do { fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); } while (--length != 0); z_error("invalid match"); } if (z_verbose > 1) { fprintf(stderr,"\\[%d,%d]", start-match, length); do { putc(s->window[start++], stderr); } while (--length != 0); } } #else # define check_match(s, start, match, length) #endif /* DEBUG */ /* =========================================================================== * Fill the window when the lookahead becomes insufficient. * Updates strstart and lookahead. * * IN assertion: lookahead < MIN_LOOKAHEAD * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD * At least one byte has been read, or avail_in == 0; reads are * performed for at least two bytes (required for the zip translate_eol * option -- not supported here). */ local void fill_window(s) deflate_state *s; { register unsigned n, m; register Posf *p; unsigned more; /* Amount of free space at the end of the window. */ uInt wsize = s->w_size; do { more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); /* Deal with !@#$% 64K limit: */ if (sizeof(int) <= 2) { if (more == 0 && s->strstart == 0 && s->lookahead == 0) { more = wsize; } else if (more == (unsigned)(-1)) { /* Very unlikely, but possible on 16 bit machine if * strstart == 0 && lookahead == 1 (input done a byte at time) */ more--; } } /* If the window is almost full and there is insufficient lookahead, * move the upper half to the lower one to make room in the upper half. */ if (s->strstart >= wsize+MAX_DIST(s)) { zmemcpy(s->window, s->window+wsize, (unsigned)wsize); s->match_start -= wsize; s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ s->block_start -= (long) wsize; /* Slide the hash table (could be avoided with 32 bit values at the expense of memory usage). We slide even when level == 0 to keep the hash table consistent if we switch back to level > 0 later. (Using level 0 permanently is not an optimal usage of zlib, so we don't care about this pathological case.) */ /* %%% avoid this when Z_RLE */ n = s->hash_size; p = &s->head[n]; do { m = *--p; *p = (Pos)(m >= wsize ? m-wsize : NIL); } while (--n); n = wsize; #ifndef FASTEST p = &s->prev[n]; do { m = *--p; *p = (Pos)(m >= wsize ? m-wsize : NIL); /* If n is not on any hash chain, prev[n] is garbage but * its value will never be used. */ } while (--n); #endif more += wsize; } if (s->strm->avail_in == 0) return; /* If there was no sliding: * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && * more == window_size - lookahead - strstart * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) * => more >= window_size - 2*WSIZE + 2 * In the BIG_MEM or MMAP case (not yet supported), * window_size == input_size + MIN_LOOKAHEAD && * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. * Otherwise, window_size == 2*WSIZE so more >= 2. * If there was sliding, more >= WSIZE. So in all cases, more >= 2. */ Assert(more >= 2, "more < 2"); n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); s->lookahead += n; /* Initialize the hash value now that we have some input: */ if (s->lookahead >= MIN_MATCH) { s->ins_h = s->window[s->strstart]; UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif } /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, * but this is not important since only literal bytes will be emitted. */ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); } /* =========================================================================== * Flush the current block, with given end-of-file flag. * IN assertion: strstart is set to the end of the current match. */ #define FLUSH_BLOCK_ONLY(s, eof) { \ _tr_flush_block(s, (s->block_start >= 0L ? \ (charf *)&s->window[(unsigned)s->block_start] : \ (charf *)Z_NULL), \ (ulg)((long)s->strstart - s->block_start), \ (eof)); \ s->block_start = s->strstart; \ flush_pending(s->strm); \ Tracev((stderr,"[FLUSH]")); \ } /* Same but force premature exit if necessary. */ #define FLUSH_BLOCK(s, eof) { \ FLUSH_BLOCK_ONLY(s, eof); \ if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ } /* =========================================================================== * Copy without compression as much as possible from the input stream, return * the current block state. * This function does not insert new strings in the dictionary since * uncompressible data is probably not useful. This function is used * only for the level=0 compression option. * NOTE: this function should be optimized to avoid extra copying from * window to pending_buf. */ local block_state deflate_stored(s, flush) deflate_state *s; int flush; { /* Stored blocks are limited to 0xffff bytes, pending_buf is limited * to pending_buf_size, and each stored block has a 5 byte header: */ ulg max_block_size = 0xffff; ulg max_start; if (max_block_size > s->pending_buf_size - 5) { max_block_size = s->pending_buf_size - 5; } /* Copy as much as possible from input to output: */ for (;;) { /* Fill the window as much as possible: */ if (s->lookahead <= 1) { Assert(s->strstart < s->w_size+MAX_DIST(s) || s->block_start >= (long)s->w_size, "slide too late"); fill_window(s); if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; if (s->lookahead == 0) break; /* flush the current block */ } Assert(s->block_start >= 0L, "block gone"); s->strstart += s->lookahead; s->lookahead = 0; /* Emit a stored block if pending_buf will be full: */ max_start = s->block_start + max_block_size; if (s->strstart == 0 || (ulg)s->strstart >= max_start) { /* strstart == 0 is possible when wraparound on 16-bit machine */ s->lookahead = (uInt)(s->strstart - max_start); s->strstart = (uInt)max_start; FLUSH_BLOCK(s, 0); } /* Flush if we may have to slide, otherwise block_start may become * negative and the data will be gone: */ if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { FLUSH_BLOCK(s, 0); } } FLUSH_BLOCK(s, flush == Z_FINISH); return flush == Z_FINISH ? finish_done : block_done; } /* =========================================================================== * Compress as much as possible from the input stream, return the current * block state. * This function does not perform lazy evaluation of matches and inserts * new strings in the dictionary only for unmatched strings or for short * matches. It is used only for the fast compression options. */ local block_state deflate_fast(s, flush) deflate_state *s; int flush; { IPos hash_head = NIL; /* head of the hash chain */ int bflush; /* set if current block must be flushed */ for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes * for the next match, plus MIN_MATCH bytes to insert the * string following the next match. */ if (s->lookahead < MIN_LOOKAHEAD) { fill_window(s); if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } /* Insert the string window[strstart .. strstart+2] in the * dictionary, and set hash_head to the head of the hash chain: */ if (s->lookahead >= MIN_MATCH) { INSERT_STRING(s, s->strstart, hash_head); } /* Find the longest match, discarding those <= prev_length. * At this point we have always match_length < MIN_MATCH */ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ #ifdef FASTEST if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) || (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { s->match_length = longest_match_fast (s, hash_head); } #else if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { s->match_length = longest_match (s, hash_head); } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { s->match_length = longest_match_fast (s, hash_head); } #endif /* longest_match() or longest_match_fast() sets match_start */ } if (s->match_length >= MIN_MATCH) { check_match(s, s->strstart, s->match_start, s->match_length); _tr_tally_dist(s, s->strstart - s->match_start, s->match_length - MIN_MATCH, bflush); s->lookahead -= s->match_length; /* Insert new strings in the hash table only if the match length * is not too large. This saves time but degrades compression. */ #ifndef FASTEST if (s->match_length <= s->max_insert_length && s->lookahead >= MIN_MATCH) { s->match_length--; /* string at strstart already in table */ do { s->strstart++; INSERT_STRING(s, s->strstart, hash_head); /* strstart never exceeds WSIZE-MAX_MATCH, so there are * always MIN_MATCH bytes ahead. */ } while (--s->match_length != 0); s->strstart++; } else #endif { s->strstart += s->match_length; s->match_length = 0; s->ins_h = s->window[s->strstart]; UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not * matter since it will be recomputed at next deflate call. */ } } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); _tr_tally_lit (s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } if (bflush) FLUSH_BLOCK(s, 0); } FLUSH_BLOCK(s, flush == Z_FINISH); return flush == Z_FINISH ? finish_done : block_done; } #ifndef FASTEST /* =========================================================================== * Same as above, but achieves better compression. We use a lazy * evaluation for matches: a match is finally adopted only if there is * no better match at the next window position. */ local block_state deflate_slow(s, flush) deflate_state *s; int flush; { IPos hash_head = NIL; /* head of hash chain */ int bflush; /* set if current block must be flushed */ /* Process the input block. */ for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes * for the next match, plus MIN_MATCH bytes to insert the * string following the next match. */ if (s->lookahead < MIN_LOOKAHEAD) { fill_window(s); if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } /* Insert the string window[strstart .. strstart+2] in the * dictionary, and set hash_head to the head of the hash chain: */ if (s->lookahead >= MIN_MATCH) { INSERT_STRING(s, s->strstart, hash_head); } /* Find the longest match, discarding those <= prev_length. */ s->prev_length = s->match_length, s->prev_match = s->match_start; s->match_length = MIN_MATCH-1; if (hash_head != NIL && s->prev_length < s->max_lazy_match && s->strstart - hash_head <= MAX_DIST(s)) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { s->match_length = longest_match (s, hash_head); } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { s->match_length = longest_match_fast (s, hash_head); } /* longest_match() or longest_match_fast() sets match_start */ if (s->match_length <= 5 && (s->strategy == Z_FILTERED #if TOO_FAR <= 32767 || (s->match_length == MIN_MATCH && s->strstart - s->match_start > TOO_FAR) #endif )) { /* If prev_match is also MIN_MATCH, match_start is garbage * but we will ignore the current match anyway. */ s->match_length = MIN_MATCH-1; } } /* If there was a match at the previous step and the current * match is not better, output the previous match: */ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; /* Do not insert strings in hash table beyond this. */ check_match(s, s->strstart-1, s->prev_match, s->prev_length); _tr_tally_dist(s, s->strstart -1 - s->prev_match, s->prev_length - MIN_MATCH, bflush); /* Insert in hash table all strings up to the end of the match. * strstart-1 and strstart are already inserted. If there is not * enough lookahead, the last two strings are not inserted in * the hash table. */ s->lookahead -= s->prev_length-1; s->prev_length -= 2; do { if (++s->strstart <= max_insert) { INSERT_STRING(s, s->strstart, hash_head); } } while (--s->prev_length != 0); s->match_available = 0; s->match_length = MIN_MATCH-1; s->strstart++; if (bflush) FLUSH_BLOCK(s, 0); } else if (s->match_available) { /* If there was no match at the previous position, output a * single literal. If there was a match but the current match * is longer, truncate the previous match to a single literal. */ Tracevv((stderr,"%c", s->window[s->strstart-1])); _tr_tally_lit(s, s->window[s->strstart-1], bflush); if (bflush) { FLUSH_BLOCK_ONLY(s, 0); } s->strstart++; s->lookahead--; if (s->strm->avail_out == 0) return need_more; } else { /* There is no previous match to compare with, wait for * the next step to decide. */ s->match_available = 1; s->strstart++; s->lookahead--; } } Assert (flush != Z_NO_FLUSH, "no flush?"); if (s->match_available) { Tracevv((stderr,"%c", s->window[s->strstart-1])); _tr_tally_lit(s, s->window[s->strstart-1], bflush); s->match_available = 0; } FLUSH_BLOCK(s, flush == Z_FINISH); return flush == Z_FINISH ? finish_done : block_done; } #endif /* FASTEST */ #if 0 /* =========================================================================== * For Z_RLE, simply look for runs of bytes, generate matches only of distance * one. Do not maintain a hash table. (It will be regenerated if this run of * deflate switches away from Z_RLE.) */ local block_state deflate_rle(s, flush) deflate_state *s; int flush; { int bflush; /* set if current block must be flushed */ uInt run; /* length of run */ uInt max; /* maximum length of run */ uInt prev; /* byte at distance one to match */ Bytef *scan; /* scan for end of run */ for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes * for the longest encodable run. */ if (s->lookahead < MAX_MATCH) { fill_window(s); if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } /* See how many times the previous byte repeats */ run = 0; if (s->strstart > 0) { /* if there is a previous byte, that is */ max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH; scan = s->window + s->strstart - 1; prev = *scan++; do { if (*scan++ != prev) break; } while (++run < max); } /* Emit match if have run of MIN_MATCH or longer, else emit literal */ if (run >= MIN_MATCH) { check_match(s, s->strstart, s->strstart - 1, run); _tr_tally_dist(s, 1, run - MIN_MATCH, bflush); s->lookahead -= run; s->strstart += run; } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); _tr_tally_lit (s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } if (bflush) FLUSH_BLOCK(s, 0); } FLUSH_BLOCK(s, flush == Z_FINISH); return flush == Z_FINISH ? finish_done : block_done; } #endif ================================================ FILE: unity_decoder/libil2cpp/external/zlib/deflate.h ================================================ /* deflate.h -- internal compression state * Copyright (C) 1995-2005 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* @(#) $Id$ */ #ifndef DEFLATE_H #define DEFLATE_H #include "zutil.h" /* define NO_GZIP when compiling if you want to disable gzip header and trailer creation by deflate(). NO_GZIP would be used to avoid linking in the crc code when it is not needed. For shared libraries, gzip encoding should be left enabled. */ #ifndef NO_GZIP # define GZIP #endif /* =========================================================================== * Internal compression state. */ #define LENGTH_CODES 29 /* number of length codes, not counting the special END_BLOCK code */ #define LITERALS 256 /* number of literal bytes 0..255 */ #define L_CODES (LITERALS+1+LENGTH_CODES) /* number of Literal or Length codes, including the END_BLOCK code */ #define D_CODES 30 /* number of distance codes */ #define BL_CODES 19 /* number of codes used to transfer the bit lengths */ #define HEAP_SIZE (2*L_CODES+1) /* maximum heap size */ #define MAX_BITS 15 /* All codes must not exceed MAX_BITS bits */ #define INIT_STATE 42 #define EXTRA_STATE 69 #define NAME_STATE 73 #define COMMENT_STATE 91 #define HCRC_STATE 103 #define BUSY_STATE 113 #define FINISH_STATE 666 /* Stream status */ /* Data structure describing a single value and its code string. */ typedef struct ct_data_s { union { ush freq; /* frequency count */ ush code; /* bit string */ } fc; union { ush dad; /* father node in Huffman tree */ ush len; /* length of bit string */ } dl; } FAR ct_data; #define Freq fc.freq #define Code fc.code #define Dad dl.dad #define Len dl.len typedef struct static_tree_desc_s static_tree_desc; typedef struct tree_desc_s { ct_data *dyn_tree; /* the dynamic tree */ int max_code; /* largest code with non zero frequency */ static_tree_desc *stat_desc; /* the corresponding static tree */ } FAR tree_desc; typedef ush Pos; typedef Pos FAR Posf; typedef unsigned IPos; /* A Pos is an index in the character window. We use short instead of int to * save space in the various tables. IPos is used only for parameter passing. */ typedef struct internal_state { z_streamp strm; /* pointer back to this zlib stream */ int status; /* as the name implies */ Bytef *pending_buf; /* output still pending */ ulg pending_buf_size; /* size of pending_buf */ Bytef *pending_out; /* next pending byte to output to the stream */ uInt pending; /* nb of bytes in the pending buffer */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ gz_headerp gzhead; /* gzip header information to write */ uInt gzindex; /* where in extra, name, or comment */ Byte method; /* STORED (for zip only) or DEFLATED */ int last_flush; /* value of flush param for previous deflate call */ /* used by deflate.c: */ uInt w_size; /* LZ77 window size (32K by default) */ uInt w_bits; /* log2(w_size) (8..16) */ uInt w_mask; /* w_size - 1 */ Bytef *window; /* Sliding window. Input bytes are read into the second half of the window, * and move to the first half later to keep a dictionary of at least wSize * bytes. With this organization, matches are limited to a distance of * wSize-MAX_MATCH bytes, but this ensures that IO is always * performed with a length multiple of the block size. Also, it limits * the window size to 64K, which is quite useful on MSDOS. * To do: use the user input buffer as sliding window. */ ulg window_size; /* Actual size of window: 2*wSize, except when the user input buffer * is directly used as sliding window. */ Posf *prev; /* Link to older string with same hash index. To limit the size of this * array to 64K, this link is maintained only for the last 32K strings. * An index in this array is thus a window index modulo 32K. */ Posf *head; /* Heads of the hash chains or NIL. */ uInt ins_h; /* hash index of string to be inserted */ uInt hash_size; /* number of elements in hash table */ uInt hash_bits; /* log2(hash_size) */ uInt hash_mask; /* hash_size-1 */ uInt hash_shift; /* Number of bits by which ins_h must be shifted at each input * step. It must be such that after MIN_MATCH steps, the oldest * byte no longer takes part in the hash key, that is: * hash_shift * MIN_MATCH >= hash_bits */ long block_start; /* Window position at the beginning of the current output block. Gets * negative when the window is moved backwards. */ uInt match_length; /* length of best match */ IPos prev_match; /* previous match */ int match_available; /* set if previous match exists */ uInt strstart; /* start of string to insert */ uInt match_start; /* start of matching string */ uInt lookahead; /* number of valid bytes ahead in window */ uInt prev_length; /* Length of the best match at previous step. Matches not greater than this * are discarded. This is used in the lazy match evaluation. */ uInt max_chain_length; /* To speed up deflation, hash chains are never searched beyond this * length. A higher limit improves compression ratio but degrades the * speed. */ uInt max_lazy_match; /* Attempt to find a better match only when the current match is strictly * smaller than this value. This mechanism is used only for compression * levels >= 4. */ # define max_insert_length max_lazy_match /* Insert new strings in the hash table only if the match length is not * greater than this length. This saves time but degrades compression. * max_insert_length is used only for compression levels <= 3. */ int level; /* compression level (1..9) */ int strategy; /* favor or force Huffman coding*/ uInt good_match; /* Use a faster search when the previous match is longer than this */ int nice_match; /* Stop searching when current match exceeds this */ /* used by trees.c: */ /* Didn't use ct_data typedef below to supress compiler warning */ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ struct tree_desc_s l_desc; /* desc. for literal tree */ struct tree_desc_s d_desc; /* desc. for distance tree */ struct tree_desc_s bl_desc; /* desc. for bit length tree */ ush bl_count[MAX_BITS+1]; /* number of codes at each bit length for an optimal tree */ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ int heap_len; /* number of elements in the heap */ int heap_max; /* element of largest frequency */ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. * The same heap array is used to build all trees. */ uch depth[2*L_CODES+1]; /* Depth of each subtree used as tie breaker for trees of equal frequency */ uchf *l_buf; /* buffer for literals or lengths */ uInt lit_bufsize; /* Size of match buffer for literals/lengths. There are 4 reasons for * limiting lit_bufsize to 64K: * - frequencies can be kept in 16 bit counters * - if compression is not successful for the first block, all input * data is still in the window so we can still emit a stored block even * when input comes from standard input. (This can also be done for * all blocks if lit_bufsize is not greater than 32K.) * - if compression is not successful for a file smaller than 64K, we can * even emit a stored file instead of a stored block (saving 5 bytes). * This is applicable only for zip (not gzip or zlib). * - creating new Huffman trees less frequently may not provide fast * adaptation to changes in the input data statistics. (Take for * example a binary file with poorly compressible code followed by * a highly compressible string table.) Smaller buffer sizes give * fast adaptation but have of course the overhead of transmitting * trees more frequently. * - I can't count above 4 */ uInt last_lit; /* running index in l_buf */ ushf *d_buf; /* Buffer for distances. To simplify the code, d_buf and l_buf have * the same number of elements. To use different lengths, an extra flag * array would be necessary. */ ulg opt_len; /* bit length of current block with optimal trees */ ulg static_len; /* bit length of current block with static trees */ uInt matches; /* number of string matches in current block */ int last_eob_len; /* bit length of EOB code for last block */ #ifdef DEBUG ulg compressed_len; /* total bit length of compressed file mod 2^32 */ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ #endif ush bi_buf; /* Output buffer. bits are inserted starting at the bottom (least * significant bits). */ int bi_valid; /* Number of valid bits in bi_buf. All bits above the last valid bit * are always zero. */ } FAR deflate_state; /* Output a byte on the stream. * IN assertion: there is enough room in pending_buf. */ #define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) /* Minimum amount of lookahead, except at the end of the input file. * See deflate.c for comments about the MIN_MATCH+1. */ #define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) /* In order to simplify the code, particularly on 16 bit machines, match * distances are limited to MAX_DIST instead of WSIZE. */ /* in trees.c */ void _tr_init OF((deflate_state *s)); int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, int eof)); void _tr_align OF((deflate_state *s)); void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, int eof)); #define d_code(dist) \ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) /* Mapping from a distance to a distance code. dist is the distance - 1 and * must not have side effects. _dist_code[256] and _dist_code[257] are never * used. */ #ifndef DEBUG /* Inline versions of _tr_tally for speed: */ #if defined(GEN_TREES_H) || !defined(STDC) extern uch _length_code[]; extern uch _dist_code[]; #else extern const uch _length_code[]; extern const uch _dist_code[]; #endif # define _tr_tally_lit(s, c, flush) \ { uch cc = (c); \ s->d_buf[s->last_lit] = 0; \ s->l_buf[s->last_lit++] = cc; \ s->dyn_ltree[cc].Freq++; \ flush = (s->last_lit == s->lit_bufsize-1); \ } # define _tr_tally_dist(s, distance, length, flush) \ { uch len = (length); \ ush dist = (distance); \ s->d_buf[s->last_lit] = dist; \ s->l_buf[s->last_lit++] = len; \ dist--; \ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ s->dyn_dtree[d_code(dist)].Freq++; \ flush = (s->last_lit == s->lit_bufsize-1); \ } #else # define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) # define _tr_tally_dist(s, distance, length, flush) \ flush = _tr_tally(s, distance, length) #endif #endif /* DEFLATE_H */ ================================================ FILE: unity_decoder/libil2cpp/external/zlib/gzio.c ================================================ #ifdef MONO_DOES_NOT_NEED_THIS /* gzio.c -- IO on .gz files * Copyright (C) 1995-2006 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h * * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. */ /* @(#) $Id$ */ #ifdef _LARGEFILE64_SOURCE # ifndef _LARGEFILE_SOURCE # define _LARGEFILE_SOURCE # endif # ifdef _FILE_OFFSET_BITS # undef _FILE_OFFSET_BITS # endif #endif #include "zutil.h" #include #ifdef NO_DEFLATE /* for compatibility with old definition */ # define NO_GZCOMPRESS #endif #ifndef NO_DUMMY_DECL struct internal_state {int dummy;}; /* for buggy compilers */ #endif #ifndef Z_BUFSIZE # ifdef MAXSEG_64K # define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ # else # define Z_BUFSIZE 16384 # endif #endif #ifndef Z_PRINTF_BUFSIZE # define Z_PRINTF_BUFSIZE 4096 #endif #ifdef __MVS__ # pragma map (fdopen , "\174\174FDOPEN") FILE *fdopen(int, const char *); #endif #ifndef STDC extern voidp malloc OF((uInt size)); extern void free OF((voidpf ptr)); #endif #ifdef NO_FSEEKO # define FSEEK fseek # define FTELL ftell #else # define FSEEK fseeko # define FTELL ftello #endif #define ALLOC(size) malloc(size) #define TRYFREE(p) {if (p) free(p);} static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ /* gzip flag byte */ #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ #define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ #define ORIG_NAME 0x08 /* bit 3 set: original file name present */ #define COMMENT 0x10 /* bit 4 set: file comment present */ #define RESERVED 0xE0 /* bits 5..7: reserved */ typedef struct gz_stream { z_stream stream; int z_err; /* error code for last stream operation */ int z_eof; /* set if end of input file */ FILE *file; /* .gz file */ Byte *inbuf; /* input buffer */ Byte *outbuf; /* output buffer */ uLong crc; /* crc32 of uncompressed data */ char *msg; /* error message */ char *path; /* path name for debugging only */ int transparent; /* 1 if input file is not a .gz file */ char mode; /* 'w' or 'r' */ #ifdef _LARGEFILE64_SOURCE off64_t start; /* start of compressed data in file (header skipped) */ off64_t in; /* bytes into deflate or inflate */ off64_t out; /* bytes out of deflate or inflate */ #else z_off_t start; /* start of compressed data in file (header skipped) */ z_off_t in; /* bytes into deflate or inflate */ z_off_t out; /* bytes out of deflate or inflate */ #endif int back; /* one character push-back */ int last; /* true if push-back is last character */ } gz_stream; local gzFile gz_open OF((const char *path, const char *mode, int fd, int use64)); #ifdef _LARGEFILE64_SOURCE local off64_t gz_seek OF((gzFile file, off64_t offset, int whence, int use64)); #else local z_off_t gz_seek OF((gzFile file, z_off_t offset, int whence, int use64)); #endif local int do_flush OF((gzFile file, int flush)); local int get_byte OF((gz_stream *s)); local void check_header OF((gz_stream *s)); local int destroy OF((gz_stream *s)); local void putLong OF((FILE *file, uLong x)); local uLong getLong OF((gz_stream *s)); /* =========================================================================== Opens a gzip (.gz) file for reading or writing. The mode parameter is as in fopen ("rb" or "wb"). The file is given either by file descriptor or path name (if fd == -1). gz_open returns NULL if the file could not be opened or if there was insufficient memory to allocate the (de)compression state; errno can be checked to distinguish the two cases (if errno is zero, the zlib error is Z_MEM_ERROR). */ local gzFile gz_open (path, mode, fd, use64) const char *path; const char *mode; int fd; int use64; { int err; int level = Z_DEFAULT_COMPRESSION; /* compression level */ int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ char *p = (char*)mode; gz_stream *s; char fmode[80]; /* copy of mode, without the compression level */ char *m = fmode; if (!path || !mode) return Z_NULL; s = (gz_stream *)ALLOC(sizeof(gz_stream)); if (!s) return Z_NULL; s->stream.zalloc = (alloc_func)0; s->stream.zfree = (free_func)0; s->stream.opaque = (voidpf)0; s->stream.next_in = s->inbuf = Z_NULL; s->stream.next_out = s->outbuf = Z_NULL; s->stream.avail_in = s->stream.avail_out = 0; s->file = NULL; s->z_err = Z_OK; s->z_eof = 0; s->in = 0; s->out = 0; s->back = EOF; s->crc = crc32(0L, Z_NULL, 0); s->msg = NULL; s->transparent = 0; s->path = (char*)ALLOC(strlen(path)+1); if (s->path == NULL) { return destroy(s), (gzFile)Z_NULL; } strcpy(s->path, path); /* do this early for debugging */ s->mode = '\0'; do { if (*p == 'r') s->mode = 'r'; if (*p == 'w' || *p == 'a') s->mode = 'w'; if (*p >= '0' && *p <= '9') { level = *p - '0'; } else if (*p == 'f') { strategy = Z_FILTERED; } else if (*p == 'h') { strategy = Z_HUFFMAN_ONLY; } else if (*p == 'R') { strategy = Z_RLE; } else { *m++ = *p; /* copy the mode */ } } while (*p++ && m != fmode + sizeof(fmode)); if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; if (s->mode == 'w') { #ifdef NO_GZCOMPRESS err = Z_STREAM_ERROR; #else err = deflateInit2(&(s->stream), level, Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); /* windowBits is passed < 0 to suppress zlib header */ s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); #endif if (err != Z_OK || s->outbuf == Z_NULL) { return destroy(s), (gzFile)Z_NULL; } } else { s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); err = inflateInit2(&(s->stream), -MAX_WBITS); /* windowBits is passed < 0 to tell that there is no zlib header */ if (err != Z_OK || s->inbuf == Z_NULL) { return destroy(s), (gzFile)Z_NULL; } } s->stream.avail_out = Z_BUFSIZE; errno = 0; s->file = fd < 0 ? (use64 ? F_OPEN64(path, fmode) : F_OPEN(path, fmode)) : (FILE*)fdopen(fd, fmode); if (s->file == NULL) { return destroy(s), (gzFile)Z_NULL; } if (s->mode == 'w') { /* Write a very simple .gz header: */ fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, level == 9 ? 2 : (strategy >= Z_HUFFMAN_ONLY || (level != Z_DEFAULT_COMPRESSION && level < 2) ? 4 : 0) /*xflags*/, OS_CODE); s->start = 10L; /* We use 10L instead of ftell(s->file) to because ftell causes an * fflush on some systems. This version of the library doesn't use * start anyway in write mode, so this initialization is not * necessary. */ } else { check_header(s); /* skip the .gz header */ s->start = FTELL(s->file) - s->stream.avail_in; } return (gzFile)s; } /* =========================================================================== Opens a gzip (.gz) file for reading or writing. */ gzFile ZEXPORT gzopen (path, mode) const char *path; const char *mode; { return gz_open (path, mode, -1, 0); } /* =========================================================================== Opens a gzip (.gz) file for reading or writing for 64-bit offsets */ gzFile ZEXPORT gzopen64 (path, mode) const char *path; const char *mode; { return gz_open (path, mode, -1, 1); } /* =========================================================================== Associate a gzFile with the file descriptor fd. fd is not dup'ed here to mimic the behavio(u)r of fdopen. */ gzFile ZEXPORT gzdopen (fd, mode) int fd; const char *mode; { char name[46]; /* allow for up to 128-bit integers */ if (fd < 0) return (gzFile)Z_NULL; sprintf(name, "", fd); /* for debugging */ return gz_open (name, mode, fd, 0); } /* =========================================================================== * Update the compression level and strategy */ int ZEXPORT gzsetparams (file, level, strategy) gzFile file; int level; int strategy; { gz_stream *s = (gz_stream*)file; if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; /* Make room to allow flushing */ if (s->stream.avail_out == 0) { s->stream.next_out = s->outbuf; if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { s->z_err = Z_ERRNO; } s->stream.avail_out = Z_BUFSIZE; } return deflateParams (&(s->stream), level, strategy); } /* =========================================================================== Read a byte from a gz_stream; update next_in and avail_in. Return EOF for end of file. IN assertion: the stream s has been successfully opened for reading. */ local int get_byte(s) gz_stream *s; { if (s->z_eof) return EOF; if (s->stream.avail_in == 0) { errno = 0; s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); if (s->stream.avail_in == 0) { s->z_eof = 1; if (ferror(s->file)) s->z_err = Z_ERRNO; return EOF; } s->stream.next_in = s->inbuf; } s->stream.avail_in--; return *(s->stream.next_in)++; } /* =========================================================================== Check the gzip header of a gz_stream opened for reading. Set the stream mode to transparent if the gzip magic header is not present; set s->err to Z_DATA_ERROR if the magic header is present but the rest of the header is incorrect. IN assertion: the stream s has already been created successfully; s->stream.avail_in is zero for the first time, but may be non-zero for concatenated .gz files. */ local void check_header(s) gz_stream *s; { int method; /* method byte */ int flags; /* flags byte */ uInt len; int c; /* Assure two bytes in the buffer so we can peek ahead -- handle case where first byte of header is at the end of the buffer after the last gzip segment */ len = s->stream.avail_in; if (len < 2) { if (len) s->inbuf[0] = s->stream.next_in[0]; errno = 0; len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); if (len == 0) s->z_eof = 1; if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; s->stream.avail_in += len; s->stream.next_in = s->inbuf; if (s->stream.avail_in < 2) { s->transparent = s->stream.avail_in; return; } } /* Peek ahead to check the gzip magic header */ if (s->stream.next_in[0] != gz_magic[0] || s->stream.next_in[1] != gz_magic[1]) { s->transparent = 1; return; } s->stream.avail_in -= 2; s->stream.next_in += 2; /* Check the rest of the gzip header */ method = get_byte(s); flags = get_byte(s); if (method != Z_DEFLATED || (flags & RESERVED) != 0) { s->z_err = Z_DATA_ERROR; return; } /* Discard time, xflags and OS code: */ for (len = 0; len < 6; len++) (void)get_byte(s); if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ len = (uInt)get_byte(s); len += ((uInt)get_byte(s))<<8; /* len is garbage if EOF but the loop below will quit anyway */ while (len-- != 0 && get_byte(s) != EOF) ; } if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ while ((c = get_byte(s)) != 0 && c != EOF) ; } if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ while ((c = get_byte(s)) != 0 && c != EOF) ; } if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ for (len = 0; len < 2; len++) (void)get_byte(s); } s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; } /* =========================================================================== * Cleanup then free the given gz_stream. Return a zlib error code. Try freeing in the reverse order of allocations. */ local int destroy (s) gz_stream *s; { int err = Z_OK; if (!s) return Z_STREAM_ERROR; TRYFREE(s->msg); if (s->stream.state != NULL) { if (s->mode == 'w') { #ifdef NO_GZCOMPRESS err = Z_STREAM_ERROR; #else err = deflateEnd(&(s->stream)); #endif } else if (s->mode == 'r') { err = inflateEnd(&(s->stream)); } } if (s->file != NULL && fclose(s->file)) { #ifdef ESPIPE if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ #endif err = Z_ERRNO; } if (s->z_err < 0) err = s->z_err; TRYFREE(s->inbuf); TRYFREE(s->outbuf); TRYFREE(s->path); TRYFREE(s); return err; } /* =========================================================================== Reads the given number of uncompressed bytes from the compressed file. gzread returns the number of bytes actually read (0 for end of file). */ int ZEXPORT gzread (file, buf, len) gzFile file; voidp buf; unsigned len; { gz_stream *s = (gz_stream*)file; Bytef *start = (Bytef*)buf; /* starting point for crc computation */ Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; if (s->z_err == Z_STREAM_END) return 0; /* EOF */ next_out = (Byte*)buf; s->stream.next_out = (Bytef*)buf; s->stream.avail_out = len; if (s->stream.avail_out && s->back != EOF) { *next_out++ = s->back; s->stream.next_out++; s->stream.avail_out--; s->back = EOF; s->out++; start++; if (s->last) { s->z_err = Z_STREAM_END; return 1; } } while (s->stream.avail_out != 0) { if (s->transparent) { /* Copy first the lookahead bytes: */ uInt n = s->stream.avail_in; if (n > s->stream.avail_out) n = s->stream.avail_out; if (n > 0) { zmemcpy(s->stream.next_out, s->stream.next_in, n); next_out += n; s->stream.next_out = next_out; s->stream.next_in += n; s->stream.avail_out -= n; s->stream.avail_in -= n; } if (s->stream.avail_out > 0 && !feof(s->file)) { s->stream.avail_out -= (uInt)fread(next_out, 1, s->stream.avail_out, s->file); } len -= s->stream.avail_out; s->in += len; s->out += len; if (len == 0) s->z_eof = 1; return (int)len; } if (s->stream.avail_in == 0 && !s->z_eof) { errno = 0; s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); if (s->stream.avail_in == 0) { s->z_eof = 1; if (ferror(s->file)) { s->z_err = Z_ERRNO; break; } } s->stream.next_in = s->inbuf; } s->in += s->stream.avail_in; s->out += s->stream.avail_out; s->z_err = inflate(&(s->stream), Z_NO_FLUSH); s->in -= s->stream.avail_in; s->out -= s->stream.avail_out; if (s->z_err == Z_STREAM_END) { /* Check CRC and original size */ s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); start = s->stream.next_out; if (getLong(s) != s->crc) { s->z_err = Z_DATA_ERROR; } else { (void)getLong(s); /* The uncompressed length returned by above getlong() may be * different from s->out in case of concatenated .gz files. * Check for such files: */ check_header(s); if (s->z_err == Z_OK) { inflateReset(&(s->stream)); s->crc = crc32(0L, Z_NULL, 0); } } } if (s->z_err != Z_OK || s->z_eof) break; } s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); if (len == s->stream.avail_out && (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)) return -1; return (int)(len - s->stream.avail_out); } /* =========================================================================== Reads one byte from the compressed file. gzgetc returns this byte or -1 in case of end of file or error. */ int ZEXPORT gzgetc(file) gzFile file; { unsigned char c; return gzread(file, &c, 1) == 1 ? c : -1; } /* =========================================================================== Push one byte back onto the stream. */ int ZEXPORT gzungetc(c, file) int c; gzFile file; { gz_stream *s = (gz_stream*)file; if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; s->back = c; s->out--; s->last = (s->z_err == Z_STREAM_END); if (s->last) s->z_err = Z_OK; s->z_eof = 0; return c; } /* =========================================================================== Reads bytes from the compressed file until len-1 characters are read, or a newline character is read and transferred to buf, or an end-of-file condition is encountered. The string is then terminated with a null character. gzgets returns buf, or Z_NULL in case of error. The current implementation is not optimized at all. */ char * ZEXPORT gzgets(file, buf, len) gzFile file; char *buf; int len; { char *b = buf; if (buf == Z_NULL || len <= 0) return Z_NULL; while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; *buf = '\0'; return b == buf && len > 0 ? Z_NULL : b; } #ifndef NO_GZCOMPRESS /* =========================================================================== Writes the given number of uncompressed bytes into the compressed file. gzwrite returns the number of bytes actually written (0 in case of error). */ int ZEXPORT gzwrite (file, buf, len) gzFile file; voidpc buf; unsigned len; { gz_stream *s = (gz_stream*)file; if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; s->stream.next_in = (Bytef*)buf; s->stream.avail_in = len; while (s->stream.avail_in != 0) { if (s->stream.avail_out == 0) { s->stream.next_out = s->outbuf; if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { s->z_err = Z_ERRNO; break; } s->stream.avail_out = Z_BUFSIZE; } s->in += s->stream.avail_in; s->out += s->stream.avail_out; s->z_err = deflate(&(s->stream), Z_NO_FLUSH); s->in -= s->stream.avail_in; s->out -= s->stream.avail_out; if (s->z_err != Z_OK) break; } s->crc = crc32(s->crc, (const Bytef *)buf, len); return (int)(len - s->stream.avail_in); } /* =========================================================================== Converts, formats, and writes the args to the compressed file under control of the format string, as in fprintf. gzprintf returns the number of uncompressed bytes actually written (0 in case of error). */ #ifdef STDC #include int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) { char buf[Z_PRINTF_BUFSIZE]; va_list va; int len; buf[sizeof(buf) - 1] = 0; va_start(va, format); #ifdef NO_vsnprintf # ifdef HAS_vsprintf_void (void)vsprintf(buf, format, va); va_end(va); for (len = 0; len < sizeof(buf); len++) if (buf[len] == 0) break; # else len = vsprintf(buf, format, va); va_end(va); # endif #else # ifdef HAS_vsnprintf_void (void)vsnprintf(buf, sizeof(buf), format, va); va_end(va); len = strlen(buf); # else len = vsnprintf(buf, sizeof(buf), format, va); va_end(va); # endif #endif if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0) return 0; return gzwrite(file, buf, (unsigned)len); } #else /* not ANSI C */ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) gzFile file; const char *format; int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; { char buf[Z_PRINTF_BUFSIZE]; int len; buf[sizeof(buf) - 1] = 0; #ifdef NO_snprintf # ifdef HAS_sprintf_void sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); for (len = 0; len < sizeof(buf); len++) if (buf[len] == 0) break; # else len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); # endif #else # ifdef HAS_snprintf_void snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); len = strlen(buf); # else len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); # endif #endif if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) return 0; return gzwrite(file, buf, len); } #endif /* =========================================================================== Writes c, converted to an unsigned char, into the compressed file. gzputc returns the value that was written, or -1 in case of error. */ int ZEXPORT gzputc(file, c) gzFile file; int c; { unsigned char cc = (unsigned char) c; /* required for big endian systems */ return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; } /* =========================================================================== Writes the given null-terminated string to the compressed file, excluding the terminating null character. gzputs returns the number of characters written, or -1 in case of error. */ int ZEXPORT gzputs(file, s) gzFile file; const char *s; { return gzwrite(file, (char*)s, (unsigned)strlen(s)); } /* =========================================================================== Flushes all pending output into the compressed file. The parameter flush is as in the deflate() function. */ local int do_flush (file, flush) gzFile file; int flush; { uInt len; int done = 0; gz_stream *s = (gz_stream*)file; if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; s->stream.avail_in = 0; /* should be zero already anyway */ for (;;) { len = Z_BUFSIZE - s->stream.avail_out; if (len != 0) { if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { s->z_err = Z_ERRNO; return Z_ERRNO; } s->stream.next_out = s->outbuf; s->stream.avail_out = Z_BUFSIZE; } if (done) break; s->out += s->stream.avail_out; s->z_err = deflate(&(s->stream), flush); s->out -= s->stream.avail_out; /* Ignore the second of two consecutive flushes: */ if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; /* deflate has finished flushing only when it hasn't used up * all the available space in the output buffer: */ done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; } return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; } int ZEXPORT gzflush (file, flush) gzFile file; int flush; { gz_stream *s = (gz_stream*)file; int err = do_flush (file, flush); if (err) return err; fflush(s->file); return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; } #endif /* NO_GZCOMPRESS */ /* =========================================================================== Sets the starting position for the next gzread or gzwrite on the given compressed file. The offset represents a number of bytes in the gzseek returns the resulting offset location as measured in bytes from the beginning of the uncompressed stream, or -1 in case of error. SEEK_END is not implemented, returns error. In this version of the library, gzseek can be extremely slow. */ #ifdef _LARGEFILE64_SOURCE local off64_t gz_seek (file, offset, whence, use64) gzFile file; off64_t offset; #else local z_off_t gz_seek (file, offset, whence, use64) gzFile file; z_off_t offset; #endif int whence; int use64; { gz_stream *s = (gz_stream*)file; if (s == NULL || whence == SEEK_END || s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { return -1L; } if (s->mode == 'w') { #ifdef NO_GZCOMPRESS return -1L; #else if (whence == SEEK_SET) { offset -= s->in; } if (offset < 0) return -1L; /* At this point, offset is the number of zero bytes to write. */ if (s->inbuf == Z_NULL) { s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ if (s->inbuf == Z_NULL) return -1L; zmemzero(s->inbuf, Z_BUFSIZE); } while (offset > 0) { uInt size = Z_BUFSIZE; if (offset < Z_BUFSIZE) size = (uInt)offset; size = gzwrite(file, s->inbuf, size); if (size == 0) return -1L; offset -= size; } return s->in; #endif } /* Rest of function is for reading only */ /* compute absolute position */ if (whence == SEEK_CUR) { offset += s->out; } if (offset < 0) return -1L; if (s->transparent) { /* map to fseek */ s->back = EOF; s->stream.avail_in = 0; s->stream.next_in = s->inbuf; #ifdef _LARGEFILE64_SOURCE if ((use64 ? fseeko64(s->file, offset, SEEK_SET) : FSEEK(s->file, offset, SEEK_SET)) < 0) return -1L; #else if (FSEEK(s->file, offset, SEEK_SET) < 0) return -1L; #endif s->in = s->out = offset; return offset; } /* For a negative seek, rewind and use positive seek */ if (offset >= s->out) { offset -= s->out; } else if (gzrewind(file) < 0) { return -1L; } /* offset is now the number of bytes to skip. */ if (offset != 0 && s->outbuf == Z_NULL) { s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); if (s->outbuf == Z_NULL) return -1L; } if (offset && s->back != EOF) { s->back = EOF; s->out++; offset--; if (s->last) s->z_err = Z_STREAM_END; } while (offset > 0) { int size = Z_BUFSIZE; if (offset < Z_BUFSIZE) size = (int)offset; size = gzread(file, s->outbuf, (uInt)size); if (size <= 0) return -1L; offset -= size; } return s->out; } /* =========================================================================== Define external functions gzseek() and gzseek64() using local gz_seek(). */ z_off_t ZEXPORT gzseek (file, offset, whence) gzFile file; z_off_t offset; int whence; { return (z_off_t)gz_seek(file, offset, whence, 0); } #ifdef _LARGEFILE64_SOURCE off64_t ZEXPORT gzseek64 (file, offset, whence) gzFile file; off64_t offset; int whence; { return gz_seek(file, offset, whence, 1); } #else z_off_t ZEXPORT gzseek64 (file, offset, whence) gzFile file; z_off_t offset; int whence; { return gz_seek(file, offset, whence, 0); } #endif /* =========================================================================== Rewinds input file. */ int ZEXPORT gzrewind (file) gzFile file; { gz_stream *s = (gz_stream*)file; if (s == NULL || s->mode != 'r') return -1; s->z_err = Z_OK; s->z_eof = 0; s->back = EOF; s->stream.avail_in = 0; s->stream.next_in = s->inbuf; s->crc = crc32(0L, Z_NULL, 0); if (!s->transparent) (void)inflateReset(&s->stream); s->in = 0; s->out = 0; return FSEEK(s->file, s->start, SEEK_SET); } /* =========================================================================== Returns the starting position for the next gzread or gzwrite on the given compressed file. This position represents a number of bytes in the uncompressed data stream. */ z_off_t ZEXPORT gztell (file) gzFile file; { return gzseek(file, 0L, SEEK_CUR); } /* =========================================================================== 64-bit version */ #ifdef _LARGEFILE64_SOURCE off64_t ZEXPORT gztell64 (file) #else z_off_t ZEXPORT gztell64 (file) #endif gzFile file; { return gzseek64(file, 0L, SEEK_CUR); } /* =========================================================================== Returns 1 when EOF has previously been detected reading the given input stream, otherwise zero. */ int ZEXPORT gzeof (file) gzFile file; { gz_stream *s = (gz_stream*)file; /* With concatenated compressed files that can have embedded * crc trailers, z_eof is no longer the only/best indicator of EOF * on a gz_stream. Handle end-of-stream error explicitly here. */ if (s == NULL || s->mode != 'r') return 0; if (s->z_eof) return 1; return s->z_err == Z_STREAM_END; } /* =========================================================================== Returns 1 if reading and doing so transparently, otherwise zero. */ int ZEXPORT gzdirect (file) gzFile file; { gz_stream *s = (gz_stream*)file; if (s == NULL || s->mode != 'r') return 0; return s->transparent; } /* =========================================================================== Outputs a long in LSB order to the given file */ local void putLong (file, x) FILE *file; uLong x; { int n; for (n = 0; n < 4; n++) { fputc((int)(x & 0xff), file); x >>= 8; } } /* =========================================================================== Reads a long in LSB order from the given gz_stream. Sets z_err in case of error. */ local uLong getLong (s) gz_stream *s; { uLong x = (uLong)get_byte(s); int c; x += ((uLong)get_byte(s))<<8; x += ((uLong)get_byte(s))<<16; c = get_byte(s); if (c == EOF) s->z_err = Z_DATA_ERROR; x += ((uLong)c)<<24; return x; } /* =========================================================================== Flushes all pending output if necessary, closes the compressed file and deallocates all the (de)compression state. */ int ZEXPORT gzclose (file) gzFile file; { gz_stream *s = (gz_stream*)file; if (s == NULL) return Z_STREAM_ERROR; if (s->mode == 'w') { #ifdef NO_GZCOMPRESS return Z_STREAM_ERROR; #else if (do_flush (file, Z_FINISH) != Z_OK) return destroy((gz_stream*)file); putLong (s->file, s->crc); putLong (s->file, (uLong)(s->in & 0xffffffff)); #endif } return destroy((gz_stream*)file); } #if defined(STDC) && !defined(_WIN32_WCE) # define zstrerror(errnum) strerror(errnum) #else # define zstrerror(errnum) "" #endif /* =========================================================================== Returns the error message for the last error which occurred on the given compressed file. errnum is set to zlib error number. If an error occurred in the file system and not in the compression library, errnum is set to Z_ERRNO and the application may consult errno to get the exact error code. */ const char * ZEXPORT gzerror (file, errnum) gzFile file; int *errnum; { char *m; gz_stream *s = (gz_stream*)file; if (s == NULL) { *errnum = Z_STREAM_ERROR; return (const char*)ERR_MSG(Z_STREAM_ERROR); } *errnum = s->z_err; if (*errnum == Z_OK) return (const char*)""; m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); TRYFREE(s->msg); s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR); strcpy(s->msg, s->path); strcat(s->msg, ": "); strcat(s->msg, m); return (const char*)s->msg; } /* =========================================================================== Clear the error and end-of-file flags, and do the same for the real file. */ void ZEXPORT gzclearerr (file) gzFile file; { gz_stream *s = (gz_stream*)file; if (s == NULL) return; if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; s->z_eof = 0; clearerr(s->file); } #endif ================================================ FILE: unity_decoder/libil2cpp/external/zlib/infback.c ================================================ /* infback.c -- inflate using a call-back interface * Copyright (C) 1995-2006 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* This code is largely copied from inflate.c. Normally either infback.o or inflate.o would be linked into an application--not both. The interface with inffast.c is retained so that optimized assembler-coded versions of inflate_fast() can be used with either inflate.c or infback.c. */ #include "zutil.h" #include "inftrees.h" #include "inflate.h" #include "inffast.h" /* function prototypes */ local void fixedtables OF((struct inflate_state FAR *state)); /* strm provides memory allocation functions in zalloc and zfree, or Z_NULL to use the library memory allocation functions. windowBits is in the range 8..15, and window is a user-supplied window and output buffer that is 2**windowBits bytes. */ int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) z_streamp strm; int windowBits; unsigned char FAR *window; const char *version; int stream_size; { struct inflate_state FAR *state; if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || stream_size != (int)(sizeof(z_stream))) return Z_VERSION_ERROR; if (strm == Z_NULL || window == Z_NULL || windowBits < 8 || windowBits > 15) return Z_STREAM_ERROR; strm->msg = Z_NULL; /* in case we return an error */ if (strm->zalloc == (alloc_func)0) { strm->zalloc = zcalloc; strm->opaque = (voidpf)0; } if (strm->zfree == (free_func)0) strm->zfree = zcfree; state = (struct inflate_state FAR *)ZALLOC(strm, 1, sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); strm->state = (struct internal_state FAR *)state; state->dmax = 32768U; state->wbits = windowBits; state->wsize = 1U << windowBits; state->window = window; state->write = 0; state->whave = 0; return Z_OK; } /* Return state with length and distance decoding tables and index sizes set to fixed code decoding. Normally this returns fixed tables from inffixed.h. If BUILDFIXED is defined, then instead this routine builds the tables the first time it's called, and returns those tables the first time and thereafter. This reduces the size of the code by about 2K bytes, in exchange for a little execution time. However, BUILDFIXED should not be used for threaded applications, since the rewriting of the tables and virgin may not be thread-safe. */ local void fixedtables(state) struct inflate_state FAR *state; { #ifdef BUILDFIXED static int virgin = 1; static code *lenfix, *distfix; static code fixed[544]; /* build fixed huffman tables if first call (may not be thread safe) */ if (virgin) { unsigned sym, bits; static code *next; /* literal/length table */ sym = 0; while (sym < 144) state->lens[sym++] = 8; while (sym < 256) state->lens[sym++] = 9; while (sym < 280) state->lens[sym++] = 7; while (sym < 288) state->lens[sym++] = 8; next = fixed; lenfix = next; bits = 9; inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); /* distance table */ sym = 0; while (sym < 32) state->lens[sym++] = 5; distfix = next; bits = 5; inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); /* do this just once */ virgin = 0; } #else /* !BUILDFIXED */ # include "inffixed.h" #endif /* BUILDFIXED */ state->lencode = lenfix; state->lenbits = 9; state->distcode = distfix; state->distbits = 5; } /* Macros for inflateBack(): */ /* Load returned state from inflate_fast() */ #define LOAD() \ do { \ put = strm->next_out; \ left = strm->avail_out; \ next = strm->next_in; \ have = strm->avail_in; \ hold = state->hold; \ bits = state->bits; \ } while (0) /* Set state from registers for inflate_fast() */ #define RESTORE() \ do { \ strm->next_out = put; \ strm->avail_out = left; \ strm->next_in = next; \ strm->avail_in = have; \ state->hold = hold; \ state->bits = bits; \ } while (0) /* Clear the input bit accumulator */ #define INITBITS() \ do { \ hold = 0; \ bits = 0; \ } while (0) /* Assure that some input is available. If input is requested, but denied, then return a Z_BUF_ERROR from inflateBack(). */ #define PULL() \ do { \ if (have == 0) { \ have = in(in_desc, &next); \ if (have == 0) { \ next = Z_NULL; \ ret = Z_BUF_ERROR; \ goto inf_leave; \ } \ } \ } while (0) /* Get a byte of input into the bit accumulator, or return from inflateBack() with an error if there is no input available. */ #define PULLBYTE() \ do { \ PULL(); \ have--; \ hold += (unsigned long)(*next++) << bits; \ bits += 8; \ } while (0) /* Assure that there are at least n bits in the bit accumulator. If there is not enough available input to do that, then return from inflateBack() with an error. */ #define NEEDBITS(n) \ do { \ while (bits < (unsigned)(n)) \ PULLBYTE(); \ } while (0) /* Return the low n bits of the bit accumulator (n < 16) */ #define BITS(n) \ ((unsigned)hold & ((1U << (n)) - 1)) /* Remove n bits from the bit accumulator */ #define DROPBITS(n) \ do { \ hold >>= (n); \ bits -= (unsigned)(n); \ } while (0) /* Remove zero to seven bits as needed to go to a byte boundary */ #define BYTEBITS() \ do { \ hold >>= bits & 7; \ bits -= bits & 7; \ } while (0) /* Assure that some output space is available, by writing out the window if it's full. If the write fails, return from inflateBack() with a Z_BUF_ERROR. */ #define ROOM() \ do { \ if (left == 0) { \ put = state->window; \ left = state->wsize; \ state->whave = left; \ if (out(out_desc, put, left)) { \ ret = Z_BUF_ERROR; \ goto inf_leave; \ } \ } \ } while (0) /* strm provides the memory allocation functions and window buffer on input, and provides information on the unused input on return. For Z_DATA_ERROR returns, strm will also provide an error message. in() and out() are the call-back input and output functions. When inflateBack() needs more input, it calls in(). When inflateBack() has filled the window with output, or when it completes with data in the window, it calls out() to write out the data. The application must not change the provided input until in() is called again or inflateBack() returns. The application must not change the window/output buffer until inflateBack() returns. in() and out() are called with a descriptor parameter provided in the inflateBack() call. This parameter can be a structure that provides the information required to do the read or write, as well as accumulated information on the input and output such as totals and check values. in() should return zero on failure. out() should return non-zero on failure. If either in() or out() fails, than inflateBack() returns a Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it was in() or out() that caused in the error. Otherwise, inflateBack() returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format error, or Z_MEM_ERROR if it could not allocate memory for the state. inflateBack() can also return Z_STREAM_ERROR if the input parameters are not correct, i.e. strm is Z_NULL or the state was not initialized. */ int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) z_streamp strm; in_func in; void FAR *in_desc; out_func out; void FAR *out_desc; { struct inflate_state FAR *state; unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ unsigned bits; /* bits in bit buffer */ unsigned copy; /* number of stored or match bytes to copy */ unsigned char FAR *from; /* where to copy match bytes from */ code here; /* current decoding table entry */ code last; /* parent table entry */ unsigned len; /* length to copy for repeats, bits to drop */ int ret; /* return code */ static const unsigned short order[19] = /* permutation of code lengths */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; /* Check that the strm exists and that the state was initialized */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; /* Reset the state */ strm->msg = Z_NULL; state->mode = TYPE; state->last = 0; state->whave = 0; next = strm->next_in; have = next != Z_NULL ? strm->avail_in : 0; hold = 0; bits = 0; put = state->window; left = state->wsize; /* Inflate until end of block marked as last */ for (;;) switch (state->mode) { case TYPE: /* determine and dispatch block type */ if (state->last) { BYTEBITS(); state->mode = DONE; break; } NEEDBITS(3); state->last = BITS(1); DROPBITS(1); switch (BITS(2)) { case 0: /* stored block */ Tracev((stderr, "inflate: stored block%s\n", state->last ? " (last)" : "")); state->mode = STORED; break; case 1: /* fixed block */ fixedtables(state); Tracev((stderr, "inflate: fixed codes block%s\n", state->last ? " (last)" : "")); state->mode = LEN; /* decode codes */ break; case 2: /* dynamic block */ Tracev((stderr, "inflate: dynamic codes block%s\n", state->last ? " (last)" : "")); state->mode = TABLE; break; case 3: strm->msg = (char *)"invalid block type"; state->mode = BAD; } DROPBITS(2); break; case STORED: /* get and verify stored block length */ BYTEBITS(); /* go to byte boundary */ NEEDBITS(32); if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { strm->msg = (char *)"invalid stored block lengths"; state->mode = BAD; break; } state->length = (unsigned)hold & 0xffff; Tracev((stderr, "inflate: stored length %u\n", state->length)); INITBITS(); /* copy stored block from input to output */ while (state->length != 0) { copy = state->length; PULL(); ROOM(); if (copy > have) copy = have; if (copy > left) copy = left; zmemcpy(put, next, copy); have -= copy; next += copy; left -= copy; put += copy; state->length -= copy; } Tracev((stderr, "inflate: stored end\n")); state->mode = TYPE; break; case TABLE: /* get dynamic table entries descriptor */ NEEDBITS(14); state->nlen = BITS(5) + 257; DROPBITS(5); state->ndist = BITS(5) + 1; DROPBITS(5); state->ncode = BITS(4) + 4; DROPBITS(4); #ifndef PKZIP_BUG_WORKAROUND if (state->nlen > 286 || state->ndist > 30) { strm->msg = (char *)"too many length or distance symbols"; state->mode = BAD; break; } #endif Tracev((stderr, "inflate: table sizes ok\n")); /* get code length code lengths (not a typo) */ state->have = 0; while (state->have < state->ncode) { NEEDBITS(3); state->lens[order[state->have++]] = (unsigned short)BITS(3); DROPBITS(3); } while (state->have < 19) state->lens[order[state->have++]] = 0; state->next = state->codes; state->lencode = (code const FAR *)(state->next); state->lenbits = 7; ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); if (ret) { strm->msg = (char *)"invalid code lengths set"; state->mode = BAD; break; } Tracev((stderr, "inflate: code lengths ok\n")); /* get length and distance code code lengths */ state->have = 0; while (state->have < state->nlen + state->ndist) { for (;;) { here = state->lencode[BITS(state->lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.val < 16) { NEEDBITS(here.bits); DROPBITS(here.bits); state->lens[state->have++] = here.val; } else { if (here.val == 16) { NEEDBITS(here.bits + 2); DROPBITS(here.bits); if (state->have == 0) { strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } len = (unsigned)(state->lens[state->have - 1]); copy = 3 + BITS(2); DROPBITS(2); } else if (here.val == 17) { NEEDBITS(here.bits + 3); DROPBITS(here.bits); len = 0; copy = 3 + BITS(3); DROPBITS(3); } else { NEEDBITS(here.bits + 7); DROPBITS(here.bits); len = 0; copy = 11 + BITS(7); DROPBITS(7); } if (state->have + copy > state->nlen + state->ndist) { strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } while (copy--) state->lens[state->have++] = (unsigned short)len; } } /* handle error breaks in while */ if (state->mode == BAD) break; /* build code tables */ state->next = state->codes; state->lencode = (code const FAR *)(state->next); state->lenbits = 9; ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); if (ret) { strm->msg = (char *)"invalid literal/lengths set"; state->mode = BAD; break; } state->distcode = (code const FAR *)(state->next); state->distbits = 6; ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); if (ret) { strm->msg = (char *)"invalid distances set"; state->mode = BAD; break; } Tracev((stderr, "inflate: codes ok\n")); state->mode = LEN; case LEN: /* use inflate_fast() if we have enough input and output */ if (have >= 6 && left >= 258) { RESTORE(); if (state->whave < state->wsize) state->whave = state->wsize - left; inflate_fast(strm, state->wsize); LOAD(); break; } /* get a literal, length, or end-of-block code */ for (;;) { here = state->lencode[BITS(state->lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.op && (here.op & 0xf0) == 0) { last = here; for (;;) { here = state->lencode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); } DROPBITS(here.bits); state->length = (unsigned)here.val; /* process literal */ if (here.op == 0) { Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here.val)); ROOM(); *put++ = (unsigned char)(state->length); left--; state->mode = LEN; break; } /* process end of block */ if (here.op & 32) { Tracevv((stderr, "inflate: end of block\n")); state->mode = TYPE; break; } /* invalid code */ if (here.op & 64) { strm->msg = (char *)"invalid literal/length code"; state->mode = BAD; break; } /* length code -- get extra bits, if any */ state->extra = (unsigned)(here.op) & 15; if (state->extra != 0) { NEEDBITS(state->extra); state->length += BITS(state->extra); DROPBITS(state->extra); } Tracevv((stderr, "inflate: length %u\n", state->length)); /* get distance code */ for (;;) { here = state->distcode[BITS(state->distbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if ((here.op & 0xf0) == 0) { last = here; for (;;) { here = state->distcode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); } DROPBITS(here.bits); if (here.op & 64) { strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } state->offset = (unsigned)here.val; /* get distance extra bits, if any */ state->extra = (unsigned)(here.op) & 15; if (state->extra != 0) { NEEDBITS(state->extra); state->offset += BITS(state->extra); DROPBITS(state->extra); } if (state->offset > state->wsize - (state->whave < state->wsize ? left : 0)) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } Tracevv((stderr, "inflate: distance %u\n", state->offset)); /* copy match from window to output */ do { ROOM(); copy = state->wsize - state->offset; if (copy < left) { from = put + copy; copy = left - copy; } else { from = put - state->offset; copy = left; } if (copy > state->length) copy = state->length; state->length -= copy; left -= copy; do { *put++ = *from++; } while (--copy); } while (state->length != 0); break; case DONE: /* inflate stream terminated properly -- write leftover output */ ret = Z_STREAM_END; if (left < state->wsize) { if (out(out_desc, state->window, state->wsize - left)) ret = Z_BUF_ERROR; } goto inf_leave; case BAD: ret = Z_DATA_ERROR; goto inf_leave; default: /* can't happen, but makes compilers happy */ ret = Z_STREAM_ERROR; goto inf_leave; } /* Return unused input */ inf_leave: strm->next_in = next; strm->avail_in = have; return ret; } int ZEXPORT inflateBackEnd(strm) z_streamp strm; { if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) return Z_STREAM_ERROR; ZFREE(strm, strm->state); strm->state = Z_NULL; Tracev((stderr, "inflate: end\n")); return Z_OK; } ================================================ FILE: unity_decoder/libil2cpp/external/zlib/inffast.c ================================================ /* inffast.c -- fast decoding * Copyright (C) 1995-2006 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zutil.h" #include "inftrees.h" #include "inflate.h" #include "inffast.h" #ifndef ASMINF /* Allow machine dependent optimization for post-increment or pre-increment. Based on testing to date, Pre-increment preferred for: - PowerPC G3 (Adler) - MIPS R5000 (Randers-Pehrson) Post-increment preferred for: - none No measurable difference: - Pentium III (Anderson) - M68060 (Nikl) */ #ifdef POSTINC # define OFF 0 # define PUP(a) *(a)++ #else # define OFF 1 # define PUP(a) *++(a) #endif /* Decode literal, length, and distance codes and write out the resulting literal and match bytes until either not enough input or output is available, an end-of-block is encountered, or a data error is encountered. When large enough input and output buffers are supplied to inflate(), for example, a 16K input buffer and a 64K output buffer, more than 95% of the inflate execution time is spent in this routine. Entry assumptions: state->mode == LEN strm->avail_in >= 6 strm->avail_out >= 258 start >= strm->avail_out state->bits < 8 On return, state->mode is one of: LEN -- ran out of enough output space or enough available input TYPE -- reached end of block code, inflate() to interpret next block BAD -- error in block data Notes: - The maximum input bits used by a length/distance pair is 15 bits for the length code, 5 bits for the length extra, 15 bits for the distance code, and 13 bits for the distance extra. This totals 48 bits, or six bytes. Therefore if strm->avail_in >= 6, then there is enough input to avoid checking for available input while decoding. - The maximum bytes that a single length/distance pair can output is 258 bytes, which is the maximum length that can be coded. inflate_fast() requires strm->avail_out >= 258 for each loop to avoid checking for output space. */ void inflate_fast(strm, start) z_streamp strm; unsigned start; /* inflate()'s starting value for strm->avail_out */ { struct inflate_state FAR *state; unsigned char FAR *in; /* local strm->next_in */ unsigned char FAR *last; /* while in < last, enough input available */ unsigned char FAR *out; /* local strm->next_out */ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ unsigned char FAR *end; /* while out < end, enough space available */ #ifdef INFLATE_STRICT unsigned dmax; /* maximum distance from zlib header */ #endif unsigned wsize; /* window size or zero if not using window */ unsigned whave; /* valid bytes in the window */ unsigned write; /* window write index */ unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ unsigned long hold; /* local strm->hold */ unsigned bits; /* local strm->bits */ code const FAR *lcode; /* local strm->lencode */ code const FAR *dcode; /* local strm->distcode */ unsigned lmask; /* mask for first level of length codes */ unsigned dmask; /* mask for first level of distance codes */ code here; /* retrieved table entry */ unsigned op; /* code bits, operation, extra bits, or */ /* window position, window bytes to copy */ unsigned len; /* match length, unused bytes */ unsigned dist; /* match distance */ unsigned char FAR *from; /* where to copy match from */ /* copy state to local variables */ state = (struct inflate_state FAR *)strm->state; in = strm->next_in - OFF; last = in + (strm->avail_in - 5); out = strm->next_out - OFF; beg = out - (start - strm->avail_out); end = out + (strm->avail_out - 257); #ifdef INFLATE_STRICT dmax = state->dmax; #endif wsize = state->wsize; whave = state->whave; write = state->write; window = state->window; hold = state->hold; bits = state->bits; lcode = state->lencode; dcode = state->distcode; lmask = (1U << state->lenbits) - 1; dmask = (1U << state->distbits) - 1; /* decode literals and length/distances until end-of-block or not enough input data or output space */ do { if (bits < 15) { hold += (unsigned long)(PUP(in)) << bits; bits += 8; hold += (unsigned long)(PUP(in)) << bits; bits += 8; } here = lcode[hold & lmask]; dolen: op = (unsigned)(here.bits); hold >>= op; bits -= op; op = (unsigned)(here.op); if (op == 0) { /* literal */ Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here.val)); PUP(out) = (unsigned char)(here.val); } else if (op & 16) { /* length base */ len = (unsigned)(here.val); op &= 15; /* number of extra bits */ if (op) { if (bits < op) { hold += (unsigned long)(PUP(in)) << bits; bits += 8; } len += (unsigned)hold & ((1U << op) - 1); hold >>= op; bits -= op; } Tracevv((stderr, "inflate: length %u\n", len)); if (bits < 15) { hold += (unsigned long)(PUP(in)) << bits; bits += 8; hold += (unsigned long)(PUP(in)) << bits; bits += 8; } here = dcode[hold & dmask]; dodist: op = (unsigned)(here.bits); hold >>= op; bits -= op; op = (unsigned)(here.op); if (op & 16) { /* distance base */ dist = (unsigned)(here.val); op &= 15; /* number of extra bits */ if (bits < op) { hold += (unsigned long)(PUP(in)) << bits; bits += 8; if (bits < op) { hold += (unsigned long)(PUP(in)) << bits; bits += 8; } } dist += (unsigned)hold & ((1U << op) - 1); #ifdef INFLATE_STRICT if (dist > dmax) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #endif hold >>= op; bits -= op; Tracevv((stderr, "inflate: distance %u\n", dist)); op = (unsigned)(out - beg); /* max distance in output */ if (dist > op) { /* see if copy from window */ op = dist - op; /* distance back in window */ if (op > whave) { if (state->sane) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR if (len <= op - whave) { do { PUP(out) = 0; } while (--len); continue; } len -= op - whave; do { PUP(out) = 0; } while (--op > whave); if (op == 0) { from = out - dist; do { PUP(out) = PUP(from); } while (--len); continue; } #endif } from = window - OFF; if (write == 0) { /* very common case */ from += wsize - op; if (op < len) { /* some from window */ len -= op; do { PUP(out) = PUP(from); } while (--op); from = out - dist; /* rest from output */ } } else if (write < op) { /* wrap around window */ from += wsize + write - op; op -= write; if (op < len) { /* some from end of window */ len -= op; do { PUP(out) = PUP(from); } while (--op); from = window - OFF; if (write < len) { /* some from start of window */ op = write; len -= op; do { PUP(out) = PUP(from); } while (--op); from = out - dist; /* rest from output */ } } } else { /* contiguous in window */ from += write - op; if (op < len) { /* some from window */ len -= op; do { PUP(out) = PUP(from); } while (--op); from = out - dist; /* rest from output */ } } while (len > 2) { PUP(out) = PUP(from); PUP(out) = PUP(from); PUP(out) = PUP(from); len -= 3; } if (len) { PUP(out) = PUP(from); if (len > 1) PUP(out) = PUP(from); } } else { from = out - dist; /* copy direct from output */ do { /* minimum length is three */ PUP(out) = PUP(from); PUP(out) = PUP(from); PUP(out) = PUP(from); len -= 3; } while (len > 2); if (len) { PUP(out) = PUP(from); if (len > 1) PUP(out) = PUP(from); } } } else if ((op & 64) == 0) { /* 2nd level distance code */ here = dcode[here.val + (hold & ((1U << op) - 1))]; goto dodist; } else { strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } } else if ((op & 64) == 0) { /* 2nd level length code */ here = lcode[here.val + (hold & ((1U << op) - 1))]; goto dolen; } else if (op & 32) { /* end-of-block */ Tracevv((stderr, "inflate: end of block\n")); state->mode = TYPE; break; } else { strm->msg = (char *)"invalid literal/length code"; state->mode = BAD; break; } } while (in < last && out < end); /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ len = bits >> 3; in -= len; bits -= len << 3; hold &= (1U << bits) - 1; /* update state and return */ strm->next_in = in + OFF; strm->next_out = out + OFF; strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); strm->avail_out = (unsigned)(out < end ? 257 + (end - out) : 257 - (out - end)); state->hold = hold; state->bits = bits; return; } /* inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): - Using bit fields for code structure - Different op definition to avoid & for extra bits (do & for table bits) - Three separate decoding do-loops for direct, window, and write == 0 - Special case for distance > 1 copies to do overlapped load and store copy - Explicit branch predictions (based on measured branch probabilities) - Deferring match copy and interspersed it with decoding subsequent codes - Swapping literal/length else - Swapping window/direct else - Larger unrolled copy loops (three is about right) - Moving len -= 3 statement into middle of loop */ #endif /* !ASMINF */ ================================================ FILE: unity_decoder/libil2cpp/external/zlib/inffast.h ================================================ /* inffast.h -- header to use inffast.c * Copyright (C) 1995-2003 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ void inflate_fast OF((z_streamp strm, unsigned start)); ================================================ FILE: unity_decoder/libil2cpp/external/zlib/inffixed.h ================================================ /* inffixed.h -- table for decoding fixed codes * Generated automatically by makefixed(). */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ static const code lenfix[512] = { {96, 7, 0}, {0, 8, 80}, {0, 8, 16}, {20, 8, 115}, {18, 7, 31}, {0, 8, 112}, {0, 8, 48}, {0, 9, 192}, {16, 7, 10}, {0, 8, 96}, {0, 8, 32}, {0, 9, 160}, {0, 8, 0}, {0, 8, 128}, {0, 8, 64}, {0, 9, 224}, {16, 7, 6}, {0, 8, 88}, {0, 8, 24}, {0, 9, 144}, {19, 7, 59}, {0, 8, 120}, {0, 8, 56}, {0, 9, 208}, {17, 7, 17}, {0, 8, 104}, {0, 8, 40}, {0, 9, 176}, {0, 8, 8}, {0, 8, 136}, {0, 8, 72}, {0, 9, 240}, {16, 7, 4}, {0, 8, 84}, {0, 8, 20}, {21, 8, 227}, {19, 7, 43}, {0, 8, 116}, {0, 8, 52}, {0, 9, 200}, {17, 7, 13}, {0, 8, 100}, {0, 8, 36}, {0, 9, 168}, {0, 8, 4}, {0, 8, 132}, {0, 8, 68}, {0, 9, 232}, {16, 7, 8}, {0, 8, 92}, {0, 8, 28}, {0, 9, 152}, {20, 7, 83}, {0, 8, 124}, {0, 8, 60}, {0, 9, 216}, {18, 7, 23}, {0, 8, 108}, {0, 8, 44}, {0, 9, 184}, {0, 8, 12}, {0, 8, 140}, {0, 8, 76}, {0, 9, 248}, {16, 7, 3}, {0, 8, 82}, {0, 8, 18}, {21, 8, 163}, {19, 7, 35}, {0, 8, 114}, {0, 8, 50}, {0, 9, 196}, {17, 7, 11}, {0, 8, 98}, {0, 8, 34}, {0, 9, 164}, {0, 8, 2}, {0, 8, 130}, {0, 8, 66}, {0, 9, 228}, {16, 7, 7}, {0, 8, 90}, {0, 8, 26}, {0, 9, 148}, {20, 7, 67}, {0, 8, 122}, {0, 8, 58}, {0, 9, 212}, {18, 7, 19}, {0, 8, 106}, {0, 8, 42}, {0, 9, 180}, {0, 8, 10}, {0, 8, 138}, {0, 8, 74}, {0, 9, 244}, {16, 7, 5}, {0, 8, 86}, {0, 8, 22}, {64, 8, 0}, {19, 7, 51}, {0, 8, 118}, {0, 8, 54}, {0, 9, 204}, {17, 7, 15}, {0, 8, 102}, {0, 8, 38}, {0, 9, 172}, {0, 8, 6}, {0, 8, 134}, {0, 8, 70}, {0, 9, 236}, {16, 7, 9}, {0, 8, 94}, {0, 8, 30}, {0, 9, 156}, {20, 7, 99}, {0, 8, 126}, {0, 8, 62}, {0, 9, 220}, {18, 7, 27}, {0, 8, 110}, {0, 8, 46}, {0, 9, 188}, {0, 8, 14}, {0, 8, 142}, {0, 8, 78}, {0, 9, 252}, {96, 7, 0}, {0, 8, 81}, {0, 8, 17}, {21, 8, 131}, {18, 7, 31}, {0, 8, 113}, {0, 8, 49}, {0, 9, 194}, {16, 7, 10}, {0, 8, 97}, {0, 8, 33}, {0, 9, 162}, {0, 8, 1}, {0, 8, 129}, {0, 8, 65}, {0, 9, 226}, {16, 7, 6}, {0, 8, 89}, {0, 8, 25}, {0, 9, 146}, {19, 7, 59}, {0, 8, 121}, {0, 8, 57}, {0, 9, 210}, {17, 7, 17}, {0, 8, 105}, {0, 8, 41}, {0, 9, 178}, {0, 8, 9}, {0, 8, 137}, {0, 8, 73}, {0, 9, 242}, {16, 7, 4}, {0, 8, 85}, {0, 8, 21}, {16, 8, 258}, {19, 7, 43}, {0, 8, 117}, {0, 8, 53}, {0, 9, 202}, {17, 7, 13}, {0, 8, 101}, {0, 8, 37}, {0, 9, 170}, {0, 8, 5}, {0, 8, 133}, {0, 8, 69}, {0, 9, 234}, {16, 7, 8}, {0, 8, 93}, {0, 8, 29}, {0, 9, 154}, {20, 7, 83}, {0, 8, 125}, {0, 8, 61}, {0, 9, 218}, {18, 7, 23}, {0, 8, 109}, {0, 8, 45}, {0, 9, 186}, {0, 8, 13}, {0, 8, 141}, {0, 8, 77}, {0, 9, 250}, {16, 7, 3}, {0, 8, 83}, {0, 8, 19}, {21, 8, 195}, {19, 7, 35}, {0, 8, 115}, {0, 8, 51}, {0, 9, 198}, {17, 7, 11}, {0, 8, 99}, {0, 8, 35}, {0, 9, 166}, {0, 8, 3}, {0, 8, 131}, {0, 8, 67}, {0, 9, 230}, {16, 7, 7}, {0, 8, 91}, {0, 8, 27}, {0, 9, 150}, {20, 7, 67}, {0, 8, 123}, {0, 8, 59}, {0, 9, 214}, {18, 7, 19}, {0, 8, 107}, {0, 8, 43}, {0, 9, 182}, {0, 8, 11}, {0, 8, 139}, {0, 8, 75}, {0, 9, 246}, {16, 7, 5}, {0, 8, 87}, {0, 8, 23}, {64, 8, 0}, {19, 7, 51}, {0, 8, 119}, {0, 8, 55}, {0, 9, 206}, {17, 7, 15}, {0, 8, 103}, {0, 8, 39}, {0, 9, 174}, {0, 8, 7}, {0, 8, 135}, {0, 8, 71}, {0, 9, 238}, {16, 7, 9}, {0, 8, 95}, {0, 8, 31}, {0, 9, 158}, {20, 7, 99}, {0, 8, 127}, {0, 8, 63}, {0, 9, 222}, {18, 7, 27}, {0, 8, 111}, {0, 8, 47}, {0, 9, 190}, {0, 8, 15}, {0, 8, 143}, {0, 8, 79}, {0, 9, 254}, {96, 7, 0}, {0, 8, 80}, {0, 8, 16}, {20, 8, 115}, {18, 7, 31}, {0, 8, 112}, {0, 8, 48}, {0, 9, 193}, {16, 7, 10}, {0, 8, 96}, {0, 8, 32}, {0, 9, 161}, {0, 8, 0}, {0, 8, 128}, {0, 8, 64}, {0, 9, 225}, {16, 7, 6}, {0, 8, 88}, {0, 8, 24}, {0, 9, 145}, {19, 7, 59}, {0, 8, 120}, {0, 8, 56}, {0, 9, 209}, {17, 7, 17}, {0, 8, 104}, {0, 8, 40}, {0, 9, 177}, {0, 8, 8}, {0, 8, 136}, {0, 8, 72}, {0, 9, 241}, {16, 7, 4}, {0, 8, 84}, {0, 8, 20}, {21, 8, 227}, {19, 7, 43}, {0, 8, 116}, {0, 8, 52}, {0, 9, 201}, {17, 7, 13}, {0, 8, 100}, {0, 8, 36}, {0, 9, 169}, {0, 8, 4}, {0, 8, 132}, {0, 8, 68}, {0, 9, 233}, {16, 7, 8}, {0, 8, 92}, {0, 8, 28}, {0, 9, 153}, {20, 7, 83}, {0, 8, 124}, {0, 8, 60}, {0, 9, 217}, {18, 7, 23}, {0, 8, 108}, {0, 8, 44}, {0, 9, 185}, {0, 8, 12}, {0, 8, 140}, {0, 8, 76}, {0, 9, 249}, {16, 7, 3}, {0, 8, 82}, {0, 8, 18}, {21, 8, 163}, {19, 7, 35}, {0, 8, 114}, {0, 8, 50}, {0, 9, 197}, {17, 7, 11}, {0, 8, 98}, {0, 8, 34}, {0, 9, 165}, {0, 8, 2}, {0, 8, 130}, {0, 8, 66}, {0, 9, 229}, {16, 7, 7}, {0, 8, 90}, {0, 8, 26}, {0, 9, 149}, {20, 7, 67}, {0, 8, 122}, {0, 8, 58}, {0, 9, 213}, {18, 7, 19}, {0, 8, 106}, {0, 8, 42}, {0, 9, 181}, {0, 8, 10}, {0, 8, 138}, {0, 8, 74}, {0, 9, 245}, {16, 7, 5}, {0, 8, 86}, {0, 8, 22}, {64, 8, 0}, {19, 7, 51}, {0, 8, 118}, {0, 8, 54}, {0, 9, 205}, {17, 7, 15}, {0, 8, 102}, {0, 8, 38}, {0, 9, 173}, {0, 8, 6}, {0, 8, 134}, {0, 8, 70}, {0, 9, 237}, {16, 7, 9}, {0, 8, 94}, {0, 8, 30}, {0, 9, 157}, {20, 7, 99}, {0, 8, 126}, {0, 8, 62}, {0, 9, 221}, {18, 7, 27}, {0, 8, 110}, {0, 8, 46}, {0, 9, 189}, {0, 8, 14}, {0, 8, 142}, {0, 8, 78}, {0, 9, 253}, {96, 7, 0}, {0, 8, 81}, {0, 8, 17}, {21, 8, 131}, {18, 7, 31}, {0, 8, 113}, {0, 8, 49}, {0, 9, 195}, {16, 7, 10}, {0, 8, 97}, {0, 8, 33}, {0, 9, 163}, {0, 8, 1}, {0, 8, 129}, {0, 8, 65}, {0, 9, 227}, {16, 7, 6}, {0, 8, 89}, {0, 8, 25}, {0, 9, 147}, {19, 7, 59}, {0, 8, 121}, {0, 8, 57}, {0, 9, 211}, {17, 7, 17}, {0, 8, 105}, {0, 8, 41}, {0, 9, 179}, {0, 8, 9}, {0, 8, 137}, {0, 8, 73}, {0, 9, 243}, {16, 7, 4}, {0, 8, 85}, {0, 8, 21}, {16, 8, 258}, {19, 7, 43}, {0, 8, 117}, {0, 8, 53}, {0, 9, 203}, {17, 7, 13}, {0, 8, 101}, {0, 8, 37}, {0, 9, 171}, {0, 8, 5}, {0, 8, 133}, {0, 8, 69}, {0, 9, 235}, {16, 7, 8}, {0, 8, 93}, {0, 8, 29}, {0, 9, 155}, {20, 7, 83}, {0, 8, 125}, {0, 8, 61}, {0, 9, 219}, {18, 7, 23}, {0, 8, 109}, {0, 8, 45}, {0, 9, 187}, {0, 8, 13}, {0, 8, 141}, {0, 8, 77}, {0, 9, 251}, {16, 7, 3}, {0, 8, 83}, {0, 8, 19}, {21, 8, 195}, {19, 7, 35}, {0, 8, 115}, {0, 8, 51}, {0, 9, 199}, {17, 7, 11}, {0, 8, 99}, {0, 8, 35}, {0, 9, 167}, {0, 8, 3}, {0, 8, 131}, {0, 8, 67}, {0, 9, 231}, {16, 7, 7}, {0, 8, 91}, {0, 8, 27}, {0, 9, 151}, {20, 7, 67}, {0, 8, 123}, {0, 8, 59}, {0, 9, 215}, {18, 7, 19}, {0, 8, 107}, {0, 8, 43}, {0, 9, 183}, {0, 8, 11}, {0, 8, 139}, {0, 8, 75}, {0, 9, 247}, {16, 7, 5}, {0, 8, 87}, {0, 8, 23}, {64, 8, 0}, {19, 7, 51}, {0, 8, 119}, {0, 8, 55}, {0, 9, 207}, {17, 7, 15}, {0, 8, 103}, {0, 8, 39}, {0, 9, 175}, {0, 8, 7}, {0, 8, 135}, {0, 8, 71}, {0, 9, 239}, {16, 7, 9}, {0, 8, 95}, {0, 8, 31}, {0, 9, 159}, {20, 7, 99}, {0, 8, 127}, {0, 8, 63}, {0, 9, 223}, {18, 7, 27}, {0, 8, 111}, {0, 8, 47}, {0, 9, 191}, {0, 8, 15}, {0, 8, 143}, {0, 8, 79}, {0, 9, 255} }; static const code distfix[32] = { {16, 5, 1}, {23, 5, 257}, {19, 5, 17}, {27, 5, 4097}, {17, 5, 5}, {25, 5, 1025}, {21, 5, 65}, {29, 5, 16385}, {16, 5, 3}, {24, 5, 513}, {20, 5, 33}, {28, 5, 8193}, {18, 5, 9}, {26, 5, 2049}, {22, 5, 129}, {64, 5, 0}, {16, 5, 2}, {23, 5, 385}, {19, 5, 25}, {27, 5, 6145}, {17, 5, 7}, {25, 5, 1537}, {21, 5, 97}, {29, 5, 24577}, {16, 5, 4}, {24, 5, 769}, {20, 5, 49}, {28, 5, 12289}, {18, 5, 13}, {26, 5, 3073}, {22, 5, 193}, {64, 5, 0} }; ================================================ FILE: unity_decoder/libil2cpp/external/zlib/inflate.c ================================================ /* inflate.c -- zlib decompression * Copyright (C) 1995-2006 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* * Change history: * * 1.2.beta0 24 Nov 2002 * - First version -- complete rewrite of inflate to simplify code, avoid * creation of window when not needed, minimize use of window when it is * needed, make inffast.c even faster, implement gzip decoding, and to * improve code readability and style over the previous zlib inflate code * * 1.2.beta1 25 Nov 2002 * - Use pointers for available input and output checking in inffast.c * - Remove input and output counters in inffast.c * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 * - Remove unnecessary second byte pull from length extra in inffast.c * - Unroll direct copy to three copies per loop in inffast.c * * 1.2.beta2 4 Dec 2002 * - Change external routine names to reduce potential conflicts * - Correct filename to inffixed.h for fixed tables in inflate.c * - Make hbuf[] unsigned char to match parameter type in inflate.c * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) * to avoid negation problem on Alphas (64 bit) in inflate.c * * 1.2.beta3 22 Dec 2002 * - Add comments on state->bits assertion in inffast.c * - Add comments on op field in inftrees.h * - Fix bug in reuse of allocated window after inflateReset() * - Remove bit fields--back to byte structure for speed * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths * - Change post-increments to pre-increments in inflate_fast(), PPC biased? * - Add compile time option, POSTINC, to use post-increments instead (Intel?) * - Make MATCH copy in inflate() much faster for when inflate_fast() not used * - Use local copies of stream next and avail values, as well as local bit * buffer and bit count in inflate()--for speed when inflate_fast() not used * * 1.2.beta4 1 Jan 2003 * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings * - Move a comment on output buffer sizes from inffast.c to inflate.c * - Add comments in inffast.c to introduce the inflate_fast() routine * - Rearrange window copies in inflate_fast() for speed and simplification * - Unroll last copy for window match in inflate_fast() * - Use local copies of window variables in inflate_fast() for speed * - Pull out common write == 0 case for speed in inflate_fast() * - Make op and len in inflate_fast() unsigned for consistency * - Add FAR to lcode and dcode declarations in inflate_fast() * - Simplified bad distance check in inflate_fast() * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new * source file infback.c to provide a call-back interface to inflate for * programs like gzip and unzip -- uses window as output buffer to avoid * window copying * * 1.2.beta5 1 Jan 2003 * - Improved inflateBack() interface to allow the caller to provide initial * input in strm. * - Fixed stored blocks bug in inflateBack() * * 1.2.beta6 4 Jan 2003 * - Added comments in inffast.c on effectiveness of POSTINC * - Typecasting all around to reduce compiler warnings * - Changed loops from while (1) or do {} while (1) to for (;;), again to * make compilers happy * - Changed type of window in inflateBackInit() to unsigned char * * * 1.2.beta7 27 Jan 2003 * - Changed many types to unsigned or unsigned short to avoid warnings * - Added inflateCopy() function * * 1.2.0 9 Mar 2003 * - Changed inflateBack() interface to provide separate opaque descriptors * for the in() and out() functions * - Changed inflateBack() argument and in_func typedef to swap the length * and buffer address return values for the input function * - Check next_in and next_out for Z_NULL on entry to inflate() * * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. */ #include "zutil.h" #include "inftrees.h" #include "inflate.h" #include "inffast.h" #ifdef MAKEFIXED # ifndef BUILDFIXED # define BUILDFIXED # endif #endif /* function prototypes */ local void fixedtables OF((struct inflate_state FAR *state)); local int updatewindow OF((z_streamp strm, unsigned out)); #ifdef BUILDFIXED void makefixed OF((void)); #endif local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, unsigned len)); int ZEXPORT inflateReset(strm) z_streamp strm; { struct inflate_state FAR *state; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; strm->total_in = strm->total_out = state->total = 0; strm->msg = Z_NULL; strm->adler = 1; /* to support ill-conceived Java test suite */ state->mode = HEAD; state->last = 0; state->havedict = 0; state->dmax = 32768U; state->head = Z_NULL; state->wsize = 0; state->whave = 0; state->write = 0; state->hold = 0; state->bits = 0; state->lencode = state->distcode = state->next = state->codes; state->sane = 1; Tracev((stderr, "inflate: reset\n")); return Z_OK; } int ZEXPORT inflatePrime(strm, bits, value) z_streamp strm; int bits; int value; { struct inflate_state FAR *state; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; value &= (1L << bits) - 1; state->hold += value << state->bits; state->bits += bits; return Z_OK; } int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) z_streamp strm; int windowBits; const char *version; int stream_size; { struct inflate_state FAR *state; if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || stream_size != (int)(sizeof(z_stream))) return Z_VERSION_ERROR; if (strm == Z_NULL) return Z_STREAM_ERROR; strm->msg = Z_NULL; /* in case we return an error */ if (strm->zalloc == (alloc_func)0) { strm->zalloc = zcalloc; strm->opaque = (voidpf)0; } if (strm->zfree == (free_func)0) strm->zfree = zcfree; state = (struct inflate_state FAR *) ZALLOC(strm, 1, sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); strm->state = (struct internal_state FAR *)state; if (windowBits < 0) { state->wrap = 0; windowBits = -windowBits; } else { state->wrap = (windowBits >> 4) + 1; #ifdef GUNZIP if (windowBits < 48) windowBits &= 15; #endif } if (windowBits < 8 || windowBits > 15) { ZFREE(strm, state); strm->state = Z_NULL; return Z_STREAM_ERROR; } state->wbits = (unsigned)windowBits; state->window = Z_NULL; return inflateReset(strm); } int ZEXPORT inflateInit_(strm, version, stream_size) z_streamp strm; const char *version; int stream_size; { return inflateInit2_(strm, DEF_WBITS, version, stream_size); } /* Return state with length and distance decoding tables and index sizes set to fixed code decoding. Normally this returns fixed tables from inffixed.h. If BUILDFIXED is defined, then instead this routine builds the tables the first time it's called, and returns those tables the first time and thereafter. This reduces the size of the code by about 2K bytes, in exchange for a little execution time. However, BUILDFIXED should not be used for threaded applications, since the rewriting of the tables and virgin may not be thread-safe. */ local void fixedtables(state) struct inflate_state FAR *state; { #ifdef BUILDFIXED static int virgin = 1; static code *lenfix, *distfix; static code fixed[544]; /* build fixed huffman tables if first call (may not be thread safe) */ if (virgin) { unsigned sym, bits; static code *next; /* literal/length table */ sym = 0; while (sym < 144) state->lens[sym++] = 8; while (sym < 256) state->lens[sym++] = 9; while (sym < 280) state->lens[sym++] = 7; while (sym < 288) state->lens[sym++] = 8; next = fixed; lenfix = next; bits = 9; inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); /* distance table */ sym = 0; while (sym < 32) state->lens[sym++] = 5; distfix = next; bits = 5; inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); /* do this just once */ virgin = 0; } #else /* !BUILDFIXED */ # include "inffixed.h" #endif /* BUILDFIXED */ state->lencode = lenfix; state->lenbits = 9; state->distcode = distfix; state->distbits = 5; } #ifdef MAKEFIXED #include /* Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also defines BUILDFIXED, so the tables are built on the fly. makefixed() writes those tables to stdout, which would be piped to inffixed.h. A small program can simply call makefixed to do this: void makefixed(void); int main(void) { makefixed(); return 0; } Then that can be linked with zlib built with MAKEFIXED defined and run: a.out > inffixed.h */ void makefixed() { unsigned low, size; struct inflate_state state; fixedtables(&state); puts(" /* inffixed.h -- table for decoding fixed codes"); puts(" * Generated automatically by makefixed()."); puts(" */"); puts(""); puts(" /* WARNING: this file should *not* be used by applications."); puts(" It is part of the implementation of this library and is"); puts(" subject to change. Applications should only use zlib.h."); puts(" */"); puts(""); size = 1U << 9; printf(" static const code lenfix[%u] = {", size); low = 0; for (;;) { if ((low % 7) == 0) printf("\n "); printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, state.lencode[low].val); if (++low == size) break; putchar(','); } puts("\n };"); size = 1U << 5; printf("\n static const code distfix[%u] = {", size); low = 0; for (;;) { if ((low % 6) == 0) printf("\n "); printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, state.distcode[low].val); if (++low == size) break; putchar(','); } puts("\n };"); } #endif /* MAKEFIXED */ /* Update the window with the last wsize (normally 32K) bytes written before returning. If window does not exist yet, create it. This is only called when a window is already in use, or when output has been written during this inflate call, but the end of the deflate stream has not been reached yet. It is also called to create a window for dictionary data when a dictionary is loaded. Providing output buffers larger than 32K to inflate() should provide a speed advantage, since only the last 32K of output is copied to the sliding window upon return from inflate(), and since all distances after the first 32K of output will fall in the output data, making match copies simpler and faster. The advantage may be dependent on the size of the processor's data caches. */ local int updatewindow(strm, out) z_streamp strm; unsigned out; { struct inflate_state FAR *state; unsigned copy, dist; state = (struct inflate_state FAR *)strm->state; /* if it hasn't been done already, allocate space for the window */ if (state->window == Z_NULL) { state->window = (unsigned char FAR *) ZALLOC(strm, 1U << state->wbits, sizeof(unsigned char)); if (state->window == Z_NULL) return 1; } /* if window not in use yet, initialize */ if (state->wsize == 0) { state->wsize = 1U << state->wbits; state->write = 0; state->whave = 0; } /* copy state->wsize or less output bytes into the circular window */ copy = out - strm->avail_out; if (copy >= state->wsize) { zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); state->write = 0; state->whave = state->wsize; } else { dist = state->wsize - state->write; if (dist > copy) dist = copy; zmemcpy(state->window + state->write, strm->next_out - copy, dist); copy -= dist; if (copy) { zmemcpy(state->window, strm->next_out - copy, copy); state->write = copy; state->whave = state->wsize; } else { state->write += dist; if (state->write == state->wsize) state->write = 0; if (state->whave < state->wsize) state->whave += dist; } } return 0; } /* Macros for inflate(): */ /* check function to use adler32() for zlib or crc32() for gzip */ #ifdef GUNZIP # define UPDATE(check, buf, len) \ (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) #else # define UPDATE(check, buf, len) adler32(check, buf, len) #endif /* check macros for header crc */ #ifdef GUNZIP # define CRC2(check, word) \ do { \ hbuf[0] = (unsigned char)(word); \ hbuf[1] = (unsigned char)((word) >> 8); \ check = crc32(check, hbuf, 2); \ } while (0) # define CRC4(check, word) \ do { \ hbuf[0] = (unsigned char)(word); \ hbuf[1] = (unsigned char)((word) >> 8); \ hbuf[2] = (unsigned char)((word) >> 16); \ hbuf[3] = (unsigned char)((word) >> 24); \ check = crc32(check, hbuf, 4); \ } while (0) #endif /* Load registers with state in inflate() for speed */ #define LOAD() \ do { \ put = strm->next_out; \ left = strm->avail_out; \ next = strm->next_in; \ have = strm->avail_in; \ hold = state->hold; \ bits = state->bits; \ } while (0) /* Restore state from registers in inflate() */ #define RESTORE() \ do { \ strm->next_out = put; \ strm->avail_out = left; \ strm->next_in = next; \ strm->avail_in = have; \ state->hold = hold; \ state->bits = bits; \ } while (0) /* Clear the input bit accumulator */ #define INITBITS() \ do { \ hold = 0; \ bits = 0; \ } while (0) /* Get a byte of input into the bit accumulator, or return from inflate() if there is no input available. */ #define PULLBYTE() \ do { \ if (have == 0) goto inf_leave; \ have--; \ hold += (unsigned long)(*next++) << bits; \ bits += 8; \ } while (0) /* Assure that there are at least n bits in the bit accumulator. If there is not enough available input to do that, then return from inflate(). */ #define NEEDBITS(n) \ do { \ while (bits < (unsigned)(n)) \ PULLBYTE(); \ } while (0) /* Return the low n bits of the bit accumulator (n < 16) */ #define BITS(n) \ ((unsigned)hold & ((1U << (n)) - 1)) /* Remove n bits from the bit accumulator */ #define DROPBITS(n) \ do { \ hold >>= (n); \ bits -= (unsigned)(n); \ } while (0) /* Remove zero to seven bits as needed to go to a byte boundary */ #define BYTEBITS() \ do { \ hold >>= bits & 7; \ bits -= bits & 7; \ } while (0) /* Reverse the bytes in a 32-bit value */ #define REVERSE(q) \ ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) /* inflate() uses a state machine to process as much input data and generate as much output data as possible before returning. The state machine is structured roughly as follows: for (;;) switch (state) { ... case STATEn: if (not enough input data or output space to make progress) return; ... make progress ... state = STATEm; break; ... } so when inflate() is called again, the same case is attempted again, and if the appropriate resources are provided, the machine proceeds to the next state. The NEEDBITS() macro is usually the way the state evaluates whether it can proceed or should return. NEEDBITS() does the return if the requested bits are not available. The typical use of the BITS macros is: NEEDBITS(n); ... do something with BITS(n) ... DROPBITS(n); where NEEDBITS(n) either returns from inflate() if there isn't enough input left to load n bits into the accumulator, or it continues. BITS(n) gives the low n bits in the accumulator. When done, DROPBITS(n) drops the low n bits off the accumulator. INITBITS() clears the accumulator and sets the number of available bits to zero. BYTEBITS() discards just enough bits to put the accumulator on a byte boundary. After BYTEBITS() and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return if there is no input available. The decoding of variable length codes uses PULLBYTE() directly in order to pull just enough bytes to decode the next code, and no more. Some states loop until they get enough input, making sure that enough state information is maintained to continue the loop where it left off if NEEDBITS() returns in the loop. For example, want, need, and keep would all have to actually be part of the saved state in case NEEDBITS() returns: case STATEw: while (want < need) { NEEDBITS(n); keep[want++] = BITS(n); DROPBITS(n); } state = STATEx; case STATEx: As shown above, if the next state is also the next case, then the break is omitted. A state may also return if there is not enough output space available to complete that state. Those states are copying stored data, writing a literal byte, and copying a matching string. When returning, a "goto inf_leave" is used to update the total counters, update the check value, and determine whether any progress has been made during that inflate() call in order to return the proper return code. Progress is defined as a change in either strm->avail_in or strm->avail_out. When there is a window, goto inf_leave will update the window with the last output written. If a goto inf_leave occurs in the middle of decompression and there is no window currently, goto inf_leave will create one and copy output to the window for the next call of inflate(). In this implementation, the flush parameter of inflate() only affects the return code (per zlib.h). inflate() always writes as much as possible to strm->next_out, given the space available and the provided input--the effect documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers the allocation of and copying into a sliding window until necessary, which provides the effect documented in zlib.h for Z_FINISH when the entire input stream available. So the only thing the flush parameter actually does is: when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it will return Z_BUF_ERROR if it has not reached the end of the stream. */ int ZEXPORT inflate(strm, flush) z_streamp strm; int flush; { struct inflate_state FAR *state; unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ unsigned bits; /* bits in bit buffer */ unsigned in, out; /* save starting available input and output */ unsigned copy; /* number of stored or match bytes to copy */ unsigned char FAR *from; /* where to copy match bytes from */ code here; /* current decoding table entry */ code last; /* parent table entry */ unsigned len; /* length to copy for repeats, bits to drop */ int ret; /* return code */ #ifdef GUNZIP unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ #endif static const unsigned short order[19] = /* permutation of code lengths */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || (strm->next_in == Z_NULL && strm->avail_in != 0)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ LOAD(); in = have; out = left; ret = Z_OK; for (;;) switch (state->mode) { case HEAD: if (state->wrap == 0) { state->mode = TYPEDO; break; } NEEDBITS(16); #ifdef GUNZIP if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ state->check = crc32(0L, Z_NULL, 0); CRC2(state->check, hold); INITBITS(); state->mode = FLAGS; break; } state->flags = 0; /* expect zlib header */ if (state->head != Z_NULL) state->head->done = -1; if (!(state->wrap & 1) || /* check if zlib header allowed */ #else if ( #endif ((BITS(8) << 8) + (hold >> 8)) % 31) { strm->msg = (char *)"incorrect header check"; state->mode = BAD; break; } if (BITS(4) != Z_DEFLATED) { strm->msg = (char *)"unknown compression method"; state->mode = BAD; break; } DROPBITS(4); len = BITS(4) + 8; if (len > state->wbits) { strm->msg = (char *)"invalid window size"; state->mode = BAD; break; } state->dmax = 1U << len; Tracev((stderr, "inflate: zlib header ok\n")); strm->adler = state->check = adler32(0L, Z_NULL, 0); state->mode = hold & 0x200 ? DICTID : TYPE; INITBITS(); break; #ifdef GUNZIP case FLAGS: NEEDBITS(16); state->flags = (int)(hold); if ((state->flags & 0xff) != Z_DEFLATED) { strm->msg = (char *)"unknown compression method"; state->mode = BAD; break; } if (state->flags & 0xe000) { strm->msg = (char *)"unknown header flags set"; state->mode = BAD; break; } if (state->head != Z_NULL) state->head->text = (int)((hold >> 8) & 1); if (state->flags & 0x0200) CRC2(state->check, hold); INITBITS(); state->mode = TIME; case TIME: NEEDBITS(32); if (state->head != Z_NULL) state->head->time = hold; if (state->flags & 0x0200) CRC4(state->check, hold); INITBITS(); state->mode = OS; case OS: NEEDBITS(16); if (state->head != Z_NULL) { state->head->xflags = (int)(hold & 0xff); state->head->os = (int)(hold >> 8); } if (state->flags & 0x0200) CRC2(state->check, hold); INITBITS(); state->mode = EXLEN; case EXLEN: if (state->flags & 0x0400) { NEEDBITS(16); state->length = (unsigned)(hold); if (state->head != Z_NULL) state->head->extra_len = (unsigned)hold; if (state->flags & 0x0200) CRC2(state->check, hold); INITBITS(); } else if (state->head != Z_NULL) state->head->extra = Z_NULL; state->mode = EXTRA; case EXTRA: if (state->flags & 0x0400) { copy = state->length; if (copy > have) copy = have; if (copy) { if (state->head != Z_NULL && state->head->extra != Z_NULL) { len = state->head->extra_len - state->length; zmemcpy(state->head->extra + len, next, len + copy > state->head->extra_max ? state->head->extra_max - len : copy); } if (state->flags & 0x0200) state->check = crc32(state->check, next, copy); have -= copy; next += copy; state->length -= copy; } if (state->length) goto inf_leave; } state->length = 0; state->mode = NAME; case NAME: if (state->flags & 0x0800) { if (have == 0) goto inf_leave; copy = 0; do { len = (unsigned)(next[copy++]); if (state->head != Z_NULL && state->head->name != Z_NULL && state->length < state->head->name_max) state->head->name[state->length++] = len; } while (len && copy < have); if (state->flags & 0x0200) state->check = crc32(state->check, next, copy); have -= copy; next += copy; if (len) goto inf_leave; } else if (state->head != Z_NULL) state->head->name = Z_NULL; state->length = 0; state->mode = COMMENT; case COMMENT: if (state->flags & 0x1000) { if (have == 0) goto inf_leave; copy = 0; do { len = (unsigned)(next[copy++]); if (state->head != Z_NULL && state->head->comment != Z_NULL && state->length < state->head->comm_max) state->head->comment[state->length++] = len; } while (len && copy < have); if (state->flags & 0x0200) state->check = crc32(state->check, next, copy); have -= copy; next += copy; if (len) goto inf_leave; } else if (state->head != Z_NULL) state->head->comment = Z_NULL; state->mode = HCRC; case HCRC: if (state->flags & 0x0200) { NEEDBITS(16); if (hold != (state->check & 0xffff)) { strm->msg = (char *)"header crc mismatch"; state->mode = BAD; break; } INITBITS(); } if (state->head != Z_NULL) { state->head->hcrc = (int)((state->flags >> 9) & 1); state->head->done = 1; } strm->adler = state->check = crc32(0L, Z_NULL, 0); state->mode = TYPE; break; #endif case DICTID: NEEDBITS(32); strm->adler = state->check = REVERSE(hold); INITBITS(); state->mode = DICT; case DICT: if (state->havedict == 0) { RESTORE(); return Z_NEED_DICT; } strm->adler = state->check = adler32(0L, Z_NULL, 0); state->mode = TYPE; case TYPE: if (flush == Z_BLOCK) goto inf_leave; case TYPEDO: if (state->last) { BYTEBITS(); state->mode = CHECK; break; } NEEDBITS(3); state->last = BITS(1); DROPBITS(1); switch (BITS(2)) { case 0: /* stored block */ Tracev((stderr, "inflate: stored block%s\n", state->last ? " (last)" : "")); state->mode = STORED; break; case 1: /* fixed block */ fixedtables(state); Tracev((stderr, "inflate: fixed codes block%s\n", state->last ? " (last)" : "")); state->mode = LEN; /* decode codes */ break; case 2: /* dynamic block */ Tracev((stderr, "inflate: dynamic codes block%s\n", state->last ? " (last)" : "")); state->mode = TABLE; break; case 3: strm->msg = (char *)"invalid block type"; state->mode = BAD; } DROPBITS(2); break; case STORED: BYTEBITS(); /* go to byte boundary */ NEEDBITS(32); if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { strm->msg = (char *)"invalid stored block lengths"; state->mode = BAD; break; } state->length = (unsigned)hold & 0xffff; Tracev((stderr, "inflate: stored length %u\n", state->length)); INITBITS(); state->mode = COPY; case COPY: copy = state->length; if (copy) { if (copy > have) copy = have; if (copy > left) copy = left; if (copy == 0) goto inf_leave; zmemcpy(put, next, copy); have -= copy; next += copy; left -= copy; put += copy; state->length -= copy; break; } Tracev((stderr, "inflate: stored end\n")); state->mode = TYPE; break; case TABLE: NEEDBITS(14); state->nlen = BITS(5) + 257; DROPBITS(5); state->ndist = BITS(5) + 1; DROPBITS(5); state->ncode = BITS(4) + 4; DROPBITS(4); #ifndef PKZIP_BUG_WORKAROUND if (state->nlen > 286 || state->ndist > 30) { strm->msg = (char *)"too many length or distance symbols"; state->mode = BAD; break; } #endif Tracev((stderr, "inflate: table sizes ok\n")); state->have = 0; state->mode = LENLENS; case LENLENS: while (state->have < state->ncode) { NEEDBITS(3); state->lens[order[state->have++]] = (unsigned short)BITS(3); DROPBITS(3); } while (state->have < 19) state->lens[order[state->have++]] = 0; state->next = state->codes; state->lencode = (code const FAR *)(state->next); state->lenbits = 7; ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); if (ret) { strm->msg = (char *)"invalid code lengths set"; state->mode = BAD; break; } Tracev((stderr, "inflate: code lengths ok\n")); state->have = 0; state->mode = CODELENS; case CODELENS: while (state->have < state->nlen + state->ndist) { for (;;) { here = state->lencode[BITS(state->lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.val < 16) { NEEDBITS(here.bits); DROPBITS(here.bits); state->lens[state->have++] = here.val; } else { if (here.val == 16) { NEEDBITS(here.bits + 2); DROPBITS(here.bits); if (state->have == 0) { strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } len = state->lens[state->have - 1]; copy = 3 + BITS(2); DROPBITS(2); } else if (here.val == 17) { NEEDBITS(here.bits + 3); DROPBITS(here.bits); len = 0; copy = 3 + BITS(3); DROPBITS(3); } else { NEEDBITS(here.bits + 7); DROPBITS(here.bits); len = 0; copy = 11 + BITS(7); DROPBITS(7); } if (state->have + copy > state->nlen + state->ndist) { strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } while (copy--) state->lens[state->have++] = (unsigned short)len; } } /* handle error breaks in while */ if (state->mode == BAD) break; /* build code tables */ state->next = state->codes; state->lencode = (code const FAR *)(state->next); state->lenbits = 9; ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); if (ret) { strm->msg = (char *)"invalid literal/lengths set"; state->mode = BAD; break; } state->distcode = (code const FAR *)(state->next); state->distbits = 6; ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); if (ret) { strm->msg = (char *)"invalid distances set"; state->mode = BAD; break; } Tracev((stderr, "inflate: codes ok\n")); state->mode = LEN; case LEN: if (have >= 6 && left >= 258) { RESTORE(); inflate_fast(strm, out); LOAD(); break; } for (;;) { here = state->lencode[BITS(state->lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.op && (here.op & 0xf0) == 0) { last = here; for (;;) { here = state->lencode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); } DROPBITS(here.bits); state->length = (unsigned)here.val; if ((int)(here.op) == 0) { Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here.val)); state->mode = LIT; break; } if (here.op & 32) { Tracevv((stderr, "inflate: end of block\n")); state->mode = TYPE; break; } if (here.op & 64) { strm->msg = (char *)"invalid literal/length code"; state->mode = BAD; break; } state->extra = (unsigned)(here.op) & 15; state->mode = LENEXT; case LENEXT: if (state->extra) { NEEDBITS(state->extra); state->length += BITS(state->extra); DROPBITS(state->extra); } Tracevv((stderr, "inflate: length %u\n", state->length)); state->mode = DIST; case DIST: for (;;) { here = state->distcode[BITS(state->distbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if ((here.op & 0xf0) == 0) { last = here; for (;;) { here = state->distcode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); } DROPBITS(here.bits); if (here.op & 64) { strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } state->offset = (unsigned)here.val; state->extra = (unsigned)(here.op) & 15; state->mode = DISTEXT; case DISTEXT: if (state->extra) { NEEDBITS(state->extra); state->offset += BITS(state->extra); DROPBITS(state->extra); } #ifdef INFLATE_STRICT if (state->offset > state->dmax) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #endif Tracevv((stderr, "inflate: distance %u\n", state->offset)); state->mode = MATCH; case MATCH: if (left == 0) goto inf_leave; copy = out - left; if (state->offset > copy) { /* copy from window */ copy = state->offset - copy; if (copy > state->whave) { if (state->sane) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR Trace((stderr, "inflate.c too far\n")); copy -= state->whave; if (copy > state->length) copy = state->length; if (copy > left) copy = left; left -= copy; state->length -= copy; do { *put++ = 0; } while (--copy); if (state->length == 0) state->mode = LEN; break; #endif } if (copy > state->write) { copy -= state->write; from = state->window + (state->wsize - copy); } else from = state->window + (state->write - copy); if (copy > state->length) copy = state->length; } else { /* copy from output */ from = put - state->offset; copy = state->length; } if (copy > left) copy = left; left -= copy; state->length -= copy; do { *put++ = *from++; } while (--copy); if (state->length == 0) state->mode = LEN; break; case LIT: if (left == 0) goto inf_leave; *put++ = (unsigned char)(state->length); left--; state->mode = LEN; break; case CHECK: if (state->wrap) { NEEDBITS(32); out -= left; strm->total_out += out; state->total += out; if (out) strm->adler = state->check = UPDATE(state->check, put - out, out); out = left; if (( #ifdef GUNZIP state->flags ? hold : #endif REVERSE(hold)) != state->check) { strm->msg = (char *)"incorrect data check"; state->mode = BAD; break; } INITBITS(); Tracev((stderr, "inflate: check matches trailer\n")); } #ifdef GUNZIP state->mode = LENGTH; case LENGTH: if (state->wrap && state->flags) { NEEDBITS(32); if (hold != (state->total & 0xffffffffUL)) { strm->msg = (char *)"incorrect length check"; state->mode = BAD; break; } INITBITS(); Tracev((stderr, "inflate: length matches trailer\n")); } #endif state->mode = DONE; case DONE: ret = Z_STREAM_END; goto inf_leave; case BAD: ret = Z_DATA_ERROR; goto inf_leave; case MEM: return Z_MEM_ERROR; case SYNC: default: return Z_STREAM_ERROR; } /* Return from inflate(), updating the total counts and the check value. If there was no progress during the inflate() call, return a buffer error. Call updatewindow() to create and/or update the window state. Note: a memory error from inflate() is non-recoverable. */ inf_leave: RESTORE(); if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) if (updatewindow(strm, out)) { state->mode = MEM; return Z_MEM_ERROR; } in -= strm->avail_in; out -= strm->avail_out; strm->total_in += in; strm->total_out += out; state->total += out; if (state->wrap && out) strm->adler = state->check = UPDATE(state->check, strm->next_out - out, out); strm->data_type = state->bits + (state->last ? 64 : 0) + (state->mode == TYPE ? 128 : 0); if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) ret = Z_BUF_ERROR; return ret; } int ZEXPORT inflateEnd(strm) z_streamp strm; { struct inflate_state FAR *state; if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->window != Z_NULL) ZFREE(strm, state->window); ZFREE(strm, strm->state); strm->state = Z_NULL; Tracev((stderr, "inflate: end\n")); return Z_OK; } int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) z_streamp strm; const Bytef *dictionary; uInt dictLength; { struct inflate_state FAR *state; unsigned long id; /* check state */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->wrap != 0 && state->mode != DICT) return Z_STREAM_ERROR; /* check for correct dictionary id */ if (state->mode == DICT) { id = adler32(0L, Z_NULL, 0); id = adler32(id, dictionary, dictLength); if (id != state->check) return Z_DATA_ERROR; } /* copy dictionary to window */ if (updatewindow(strm, strm->avail_out)) { state->mode = MEM; return Z_MEM_ERROR; } if (dictLength > state->wsize) { zmemcpy(state->window, dictionary + dictLength - state->wsize, state->wsize); state->whave = state->wsize; } else { zmemcpy(state->window + state->wsize - dictLength, dictionary, dictLength); state->whave = dictLength; } state->havedict = 1; Tracev((stderr, "inflate: dictionary set\n")); return Z_OK; } int ZEXPORT inflateGetHeader(strm, head) z_streamp strm; gz_headerp head; { struct inflate_state FAR *state; /* check state */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; /* save header structure */ state->head = head; head->done = 0; return Z_OK; } /* Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found or when out of input. When called, *have is the number of pattern bytes found in order so far, in 0..3. On return *have is updated to the new state. If on return *have equals four, then the pattern was found and the return value is how many bytes were read including the last byte of the pattern. If *have is less than four, then the pattern has not been found yet and the return value is len. In the latter case, syncsearch() can be called again with more data and the *have state. *have is initialized to zero for the first call. */ local unsigned syncsearch(have, buf, len) unsigned FAR *have; unsigned char FAR *buf; unsigned len; { unsigned got; unsigned next; got = *have; next = 0; while (next < len && got < 4) { if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) got++; else if (buf[next]) got = 0; else got = 4 - got; next++; } *have = got; return next; } int ZEXPORT inflateSync(strm) z_streamp strm; { unsigned len; /* number of bytes to look at or looked at */ unsigned long in, out; /* temporary to save total_in and total_out */ unsigned char buf[4]; /* to restore bit buffer to byte string */ struct inflate_state FAR *state; /* check parameters */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; /* if first time, start search in bit buffer */ if (state->mode != SYNC) { state->mode = SYNC; state->hold <<= state->bits & 7; state->bits -= state->bits & 7; len = 0; while (state->bits >= 8) { buf[len++] = (unsigned char)(state->hold); state->hold >>= 8; state->bits -= 8; } state->have = 0; syncsearch(&(state->have), buf, len); } /* search available input */ len = syncsearch(&(state->have), strm->next_in, strm->avail_in); strm->avail_in -= len; strm->next_in += len; strm->total_in += len; /* return no joy or set up to restart inflate() on a new block */ if (state->have != 4) return Z_DATA_ERROR; in = strm->total_in; out = strm->total_out; inflateReset(strm); strm->total_in = in; strm->total_out = out; state->mode = TYPE; return Z_OK; } /* Returns true if inflate is currently at the end of a block generated by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored block. When decompressing, PPP checks that at the end of input packet, inflate is waiting for these length bytes. */ int ZEXPORT inflateSyncPoint(strm) z_streamp strm; { struct inflate_state FAR *state; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; return state->mode == STORED && state->bits == 0; } int ZEXPORT inflateCopy(dest, source) z_streamp dest; z_streamp source; { struct inflate_state FAR *state; struct inflate_state FAR *copy; unsigned char FAR *window; unsigned wsize; /* check input */ if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)source->state; /* allocate space */ copy = (struct inflate_state FAR *) ZALLOC(source, 1, sizeof(struct inflate_state)); if (copy == Z_NULL) return Z_MEM_ERROR; window = Z_NULL; if (state->window != Z_NULL) { window = (unsigned char FAR *) ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); if (window == Z_NULL) { ZFREE(source, copy); return Z_MEM_ERROR; } } /* copy state */ zmemcpy(dest, source, sizeof(z_stream)); zmemcpy(copy, state, sizeof(struct inflate_state)); if (state->lencode >= state->codes && state->lencode <= state->codes + ENOUGH - 1) { copy->lencode = copy->codes + (state->lencode - state->codes); copy->distcode = copy->codes + (state->distcode - state->codes); } copy->next = copy->codes + (state->next - state->codes); if (window != Z_NULL) { wsize = 1U << state->wbits; zmemcpy(window, state->window, wsize); } copy->window = window; dest->state = (struct internal_state FAR *)copy; return Z_OK; } int ZEXPORT inflateUndermine(strm, subvert) z_streamp strm; int subvert; { struct inflate_state FAR *state; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR state->sane = !subvert; return Z_OK; #else state->sane = 1; return Z_DATA_ERROR; #endif } ================================================ FILE: unity_decoder/libil2cpp/external/zlib/inflate.h ================================================ /* inflate.h -- internal inflate state definition * Copyright (C) 1995-2006 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* define NO_GZIP when compiling if you want to disable gzip header and trailer decoding by inflate(). NO_GZIP would be used to avoid linking in the crc code when it is not needed. For shared libraries, gzip decoding should be left enabled. */ #ifndef NO_GZIP # define GUNZIP #endif /* Possible inflate modes between inflate() calls */ typedef enum { HEAD, /* i: waiting for magic header */ FLAGS, /* i: waiting for method and flags (gzip) */ TIME, /* i: waiting for modification time (gzip) */ OS, /* i: waiting for extra flags and operating system (gzip) */ EXLEN, /* i: waiting for extra length (gzip) */ EXTRA, /* i: waiting for extra bytes (gzip) */ NAME, /* i: waiting for end of file name (gzip) */ COMMENT, /* i: waiting for end of comment (gzip) */ HCRC, /* i: waiting for header crc (gzip) */ DICTID, /* i: waiting for dictionary check value */ DICT, /* waiting for inflateSetDictionary() call */ TYPE, /* i: waiting for type bits, including last-flag bit */ TYPEDO, /* i: same, but skip check to exit inflate on new block */ STORED, /* i: waiting for stored size (length and complement) */ COPY, /* i/o: waiting for input or output to copy stored block */ TABLE, /* i: waiting for dynamic block table lengths */ LENLENS, /* i: waiting for code length code lengths */ CODELENS, /* i: waiting for length/lit and distance code lengths */ LEN, /* i: waiting for length/lit code */ LENEXT, /* i: waiting for length extra bits */ DIST, /* i: waiting for distance code */ DISTEXT, /* i: waiting for distance extra bits */ MATCH, /* o: waiting for output space to copy string */ LIT, /* o: waiting for output space to write literal */ CHECK, /* i: waiting for 32-bit check value */ LENGTH, /* i: waiting for 32-bit length (gzip) */ DONE, /* finished check, done -- remain here until reset */ BAD, /* got a data error -- remain here until reset */ MEM, /* got an inflate() memory error -- remain here until reset */ SYNC /* looking for synchronization bytes to restart inflate() */ } inflate_mode; /* State transitions between above modes - (most modes can go to the BAD or MEM mode -- not shown for clarity) Process header: HEAD -> (gzip) or (zlib) (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME NAME -> COMMENT -> HCRC -> TYPE (zlib) -> DICTID or TYPE DICTID -> DICT -> TYPE Read deflate blocks: TYPE -> STORED or TABLE or LEN or CHECK STORED -> COPY -> TYPE TABLE -> LENLENS -> CODELENS -> LEN Read deflate codes: LEN -> LENEXT or LIT or TYPE LENEXT -> DIST -> DISTEXT -> MATCH -> LEN LIT -> LEN Process trailer: CHECK -> LENGTH -> DONE */ /* state maintained between inflate() calls. Approximately 10K bytes. */ struct inflate_state { inflate_mode mode; /* current inflate mode */ int last; /* true if processing last block */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ int havedict; /* true if dictionary provided */ int flags; /* gzip header method and flags (0 if zlib) */ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ unsigned long check; /* protected copy of check value */ unsigned long total; /* protected copy of output count */ gz_headerp head; /* where to save gzip header information */ /* sliding window */ unsigned wbits; /* log base 2 of requested window size */ unsigned wsize; /* window size or zero if not using window */ unsigned whave; /* valid bytes in the window */ unsigned write; /* window write index */ unsigned char FAR *window; /* allocated sliding window, if needed */ /* bit accumulator */ unsigned long hold; /* input bit accumulator */ unsigned bits; /* number of bits in "in" */ /* for string and stored block copying */ unsigned length; /* literal or length of data to copy */ unsigned offset; /* distance back to copy string from */ /* for table and code decoding */ unsigned extra; /* extra bits needed */ /* fixed and dynamic code tables */ code const FAR *lencode; /* starting table for length/literal codes */ code const FAR *distcode; /* starting table for distance codes */ unsigned lenbits; /* index bits for lencode */ unsigned distbits; /* index bits for distcode */ /* dynamic table building */ unsigned ncode; /* number of code length code lengths */ unsigned nlen; /* number of length code lengths */ unsigned ndist; /* number of distance code lengths */ unsigned have; /* number of code lengths in lens[] */ code FAR *next; /* next available space in codes[] */ unsigned short lens[320]; /* temporary storage for code lengths */ unsigned short work[288]; /* work area for code table building */ code codes[ENOUGH]; /* space for code tables */ int sane; /* if false, allow invalid distance too far */ }; ================================================ FILE: unity_decoder/libil2cpp/external/zlib/inftrees.c ================================================ /* inftrees.c -- generate Huffman trees for efficient decoding * Copyright (C) 1995-2006 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zutil.h" #include "inftrees.h" #define MAXBITS 15 const char inflate_copyright[] = " inflate 1.2.3.3 Copyright 1995-2006 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot include such an acknowledgment, I would appreciate that you keep this copyright string in the executable of your product. */ /* Build a set of tables to decode the provided canonical Huffman code. The code lengths are lens[0..codes-1]. The result starts at *table, whose indices are 0..2^bits-1. work is a writable array of at least lens shorts, which is used as a work area. type is the type of code to be generated, CODES, LENS, or DISTS. On return, zero is success, -1 is an invalid code, and +1 means that ENOUGH isn't enough. table on return points to the next available entry's address. bits is the requested root table index bits, and on return it is the actual root table index bits. It will differ if the request is greater than the longest code or if it is less than the shortest code. */ int inflate_table(type, lens, codes, table, bits, work) codetype type; unsigned short FAR *lens; unsigned codes; code FAR * FAR *table; unsigned FAR *bits; unsigned short FAR *work; { unsigned len; /* a code's length in bits */ unsigned sym; /* index of code symbols */ unsigned min, max; /* minimum and maximum code lengths */ unsigned root; /* number of index bits for root table */ unsigned curr; /* number of index bits for current table */ unsigned drop; /* code bits to drop for sub-table */ int left; /* number of prefix codes available */ unsigned used; /* code entries in table used */ unsigned huff; /* Huffman code */ unsigned incr; /* for incrementing code, index */ unsigned fill; /* index for replicating entries */ unsigned low; /* low bits for current root entry */ unsigned mask; /* mask for low root bits */ code here; /* table entry for duplication */ code FAR *next; /* next available space in table */ const unsigned short FAR *base; /* base value table to use */ const unsigned short FAR *extra; /* extra bits table to use */ int end; /* use base and extra for symbol > end */ unsigned short count[MAXBITS+1]; /* number of codes of each length */ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ static const unsigned short lbase[31] = { /* Length codes 257..285 base */ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 203}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0}; static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 64, 64}; /* Process a set of code lengths to create a canonical Huffman code. The code lengths are lens[0..codes-1]. Each length corresponds to the symbols 0..codes-1. The Huffman code is generated by first sorting the symbols by length from short to long, and retaining the symbol order for codes with equal lengths. Then the code starts with all zero bits for the first code of the shortest length, and the codes are integer increments for the same length, and zeros are appended as the length increases. For the deflate format, these bits are stored backwards from their more natural integer increment ordering, and so when the decoding tables are built in the large loop below, the integer codes are incremented backwards. This routine assumes, but does not check, that all of the entries in lens[] are in the range 0..MAXBITS. The caller must assure this. 1..MAXBITS is interpreted as that code length. zero means that that symbol does not occur in this code. The codes are sorted by computing a count of codes for each length, creating from that a table of starting indices for each length in the sorted table, and then entering the symbols in order in the sorted table. The sorted table is work[], with that space being provided by the caller. The length counts are used for other purposes as well, i.e. finding the minimum and maximum length codes, determining if there are any codes at all, checking for a valid set of lengths, and looking ahead at length counts to determine sub-table sizes when building the decoding tables. */ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ for (len = 0; len <= MAXBITS; len++) count[len] = 0; for (sym = 0; sym < codes; sym++) count[lens[sym]]++; /* bound code lengths, force root to be within code lengths */ root = *bits; for (max = MAXBITS; max >= 1; max--) if (count[max] != 0) break; if (root > max) root = max; if (max == 0) { /* no symbols to code at all */ here.op = (unsigned char)64; /* invalid code marker */ here.bits = (unsigned char)1; here.val = (unsigned short)0; *(*table)++ = here; /* make a table to force an error */ *(*table)++ = here; *bits = 1; return 0; /* no symbols, but wait for decoding to report error */ } for (min = 1; min <= MAXBITS; min++) if (count[min] != 0) break; if (root < min) root = min; /* check for an over-subscribed or incomplete set of lengths */ left = 1; for (len = 1; len <= MAXBITS; len++) { left <<= 1; left -= count[len]; if (left < 0) return -1; /* over-subscribed */ } if (left > 0 && (type == CODES || max != 1)) return -1; /* incomplete set */ /* generate offsets into symbol table for each length for sorting */ offs[1] = 0; for (len = 1; len < MAXBITS; len++) offs[len + 1] = offs[len] + count[len]; /* sort symbols by length, by symbol order within each length */ for (sym = 0; sym < codes; sym++) if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; /* Create and fill in decoding tables. In this loop, the table being filled is at next and has curr index bits. The code being used is huff with length len. That code is converted to an index by dropping drop bits off of the bottom. For codes where len is less than drop + curr, those top drop + curr - len bits are incremented through all values to fill the table with replicated entries. root is the number of index bits for the root table. When len exceeds root, sub-tables are created pointed to by the root entry with an index of the low root bits of huff. This is saved in low to check for when a new sub-table should be started. drop is zero when the root table is being filled, and drop is root when sub-tables are being filled. When a new sub-table is needed, it is necessary to look ahead in the code lengths to determine what size sub-table is needed. The length counts are used for this, and so count[] is decremented as codes are entered in the tables. used keeps track of how many table entries have been allocated from the provided *table space. It is checked when a LENS table is being made against the space in *table, ENOUGH, minus the maximum space needed by the worst case distance code, MAXD. This should never happen, but the sufficiency of ENOUGH has not been proven exhaustively, hence the check. This assumes that when type == LENS, bits == 9. sym increments through all symbols, and the loop terminates when all codes of length max, i.e. all codes, have been processed. This routine permits incomplete codes, so another loop after this one fills in the rest of the decoding tables with invalid code markers. */ /* set up for code type */ switch (type) { case CODES: base = extra = work; /* dummy value--not used */ end = 19; break; case LENS: base = lbase; base -= 257; extra = lext; extra -= 257; end = 256; break; default: /* DISTS */ base = dbase; extra = dext; end = -1; } /* initialize state for loop */ huff = 0; /* starting code */ sym = 0; /* starting code symbol */ len = min; /* starting code length */ next = *table; /* current table to fill in */ curr = root; /* current table index bits */ drop = 0; /* current bits to drop from code for index */ low = (unsigned)(-1); /* trigger new sub-table when len > root */ used = 1U << root; /* use root table entries */ mask = used - 1; /* mask for comparing low */ /* check available table space */ if (type == LENS && used >= ENOUGH - MAXD) return 1; /* process all codes and make table entries */ for (;;) { /* create table entry */ here.bits = (unsigned char)(len - drop); if ((int)(work[sym]) < end) { here.op = (unsigned char)0; here.val = work[sym]; } else if ((int)(work[sym]) > end) { here.op = (unsigned char)(extra[work[sym]]); here.val = base[work[sym]]; } else { here.op = (unsigned char)(32 + 64); /* end of block */ here.val = 0; } /* replicate for those indices with low len bits equal to huff */ incr = 1U << (len - drop); fill = 1U << curr; min = fill; /* save offset to next table */ do { fill -= incr; next[(huff >> drop) + fill] = here; } while (fill != 0); /* backwards increment the len-bit code huff */ incr = 1U << (len - 1); while (huff & incr) incr >>= 1; if (incr != 0) { huff &= incr - 1; huff += incr; } else huff = 0; /* go to next symbol, update count, len */ sym++; if (--(count[len]) == 0) { if (len == max) break; len = lens[work[sym]]; } /* create new sub-table if needed */ if (len > root && (huff & mask) != low) { /* if first time, transition to sub-tables */ if (drop == 0) drop = root; /* increment past last table */ next += min; /* here min is 1 << curr */ /* determine length of next table */ curr = len - drop; left = (int)(1 << curr); while (curr + drop < max) { left -= count[curr + drop]; if (left <= 0) break; curr++; left <<= 1; } /* check for enough space */ used += 1U << curr; if (type == LENS && used >= ENOUGH - MAXD) return 1; /* point entry in root table to sub-table */ low = huff & mask; (*table)[low].op = (unsigned char)curr; (*table)[low].bits = (unsigned char)root; (*table)[low].val = (unsigned short)(next - *table); } } /* Fill in rest of table for incomplete codes. This loop is similar to the loop above in incrementing huff for table indices. It is assumed that len is equal to curr + drop, so there is no loop needed to increment through high index bits. When the current sub-table is filled, the loop drops back to the root table to fill in any remaining entries there. */ here.op = (unsigned char)64; /* invalid code marker */ here.bits = (unsigned char)(len - drop); here.val = (unsigned short)0; while (huff != 0) { /* when done with sub-table, drop back to root table */ if (drop != 0 && (huff & mask) != low) { drop = 0; len = root; next = *table; here.bits = (unsigned char)len; } /* put invalid code marker in table */ next[huff >> drop] = here; /* backwards increment the len-bit code huff */ incr = 1U << (len - 1); while (huff & incr) incr >>= 1; if (incr != 0) { huff &= incr - 1; huff += incr; } else huff = 0; } /* set return parameters */ *table += used; *bits = root; return 0; } ================================================ FILE: unity_decoder/libil2cpp/external/zlib/inftrees.h ================================================ /* inftrees.h -- header to use inftrees.c * Copyright (C) 1995-2005 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* Structure for decoding tables. Each entry provides either the information needed to do the operation requested by the code that indexed that table entry, or it provides a pointer to another table that indexes more bits of the code. op indicates whether the entry is a pointer to another table, a literal, a length or distance, an end-of-block, or an invalid code. For a table pointer, the low four bits of op is the number of index bits of that table. For a length or distance, the low four bits of op is the number of extra bits to get after the code. bits is the number of bits in this code or part of the code to drop off of the bit buffer. val is the actual byte to output in the case of a literal, the base length or distance, or the offset from the current table to the next table. Each entry is four bytes. */ typedef struct { unsigned char op; /* operation, extra bits, table bits */ unsigned char bits; /* bits in this part of the code */ unsigned short val; /* offset in table or code value */ } code; /* op values as set by inflate_table(): 00000000 - literal 0000tttt - table link, tttt != 0 is the number of table index bits 0001eeee - length or distance, eeee is the number of extra bits 01100000 - end of block 01000000 - invalid code */ /* Maximum size of dynamic tree. The maximum found in a long but non- exhaustive search was 1444 code structures (852 for length/literals and 592 for distances, the latter actually the result of an exhaustive search). The true maximum is not known, but the value below is more than safe. */ #define ENOUGH 2048 #define MAXD 592 /* Type of code to build for inftable() */ typedef enum { CODES, LENS, DISTS } codetype; extern int inflate_table OF((codetype type, unsigned short FAR *lens, unsigned codes, code FAR * FAR *table, unsigned FAR *bits, unsigned short FAR *work)); ================================================ FILE: unity_decoder/libil2cpp/external/zlib/trees.c ================================================ /* trees.c -- output deflated data using Huffman coding * Copyright (C) 1995-2006 Jean-loup Gailly * detect_data_type() function provided freely by Cosmin Truta, 2006 * For conditions of distribution and use, see copyright notice in zlib.h */ /* * ALGORITHM * * The "deflation" process uses several Huffman trees. The more * common source values are represented by shorter bit sequences. * * Each code tree is stored in a compressed form which is itself * a Huffman encoding of the lengths of all the code strings (in * ascending order by source values). The actual code strings are * reconstructed from the lengths in the inflate process, as described * in the deflate specification. * * REFERENCES * * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc * * Storer, James A. * Data Compression: Methods and Theory, pp. 49-50. * Computer Science Press, 1988. ISBN 0-7167-8156-5. * * Sedgewick, R. * Algorithms, p290. * Addison-Wesley, 1983. ISBN 0-201-06672-6. */ /* @(#) $Id$ */ /* #define GEN_TREES_H */ #include "deflate.h" #ifdef DEBUG # include #endif /* =========================================================================== * Constants */ #define MAX_BL_BITS 7 /* Bit length codes must not exceed MAX_BL_BITS bits */ #define END_BLOCK 256 /* end of block literal code */ #define REP_3_6 16 /* repeat previous bit length 3-6 times (2 bits of repeat count) */ #define REPZ_3_10 17 /* repeat a zero length 3-10 times (3 bits of repeat count) */ #define REPZ_11_138 18 /* repeat a zero length 11-138 times (7 bits of repeat count) */ local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; local const int extra_dbits[D_CODES] /* extra bits for each distance code */ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; local const uch bl_order[BL_CODES] = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; /* The lengths of the bit length codes are sent in order of decreasing * probability, to avoid transmitting the lengths for unused bit length codes. */ #define Buf_size (8 * 2*sizeof(char)) /* Number of bits used within bi_buf. (bi_buf might be implemented on * more than 16 bits on some systems.) */ /* =========================================================================== * Local data. These are initialized only once. */ #define DIST_CODE_LEN 512 /* see definition of array dist_code below */ #if defined(GEN_TREES_H) || !defined(STDC) /* non ANSI compilers may not accept trees.h */ local ct_data static_ltree[L_CODES+2]; /* The static literal tree. Since the bit lengths are imposed, there is no * need for the L_CODES extra codes used during heap construction. However * The codes 286 and 287 are needed to build a canonical tree (see _tr_init * below). */ local ct_data static_dtree[D_CODES]; /* The static distance tree. (Actually a trivial tree since all codes use * 5 bits.) */ uch _dist_code[DIST_CODE_LEN]; /* Distance codes. The first 256 values correspond to the distances * 3 .. 258, the last 256 values correspond to the top 8 bits of * the 15 bit distances. */ uch _length_code[MAX_MATCH-MIN_MATCH+1]; /* length code for each normalized match length (0 == MIN_MATCH) */ local int base_length[LENGTH_CODES]; /* First normalized length for each code (0 = MIN_MATCH) */ local int base_dist[D_CODES]; /* First normalized distance for each code (0 = distance of 1) */ #else # include "trees.h" #endif /* GEN_TREES_H */ struct static_tree_desc_s { const ct_data *static_tree; /* static tree or NULL */ const intf *extra_bits; /* extra bits for each code or NULL */ int extra_base; /* base index for extra_bits */ int elems; /* max number of elements in the tree */ int max_length; /* max bit length for the codes */ }; local static_tree_desc static_l_desc = {static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; local static_tree_desc static_d_desc = {static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; local static_tree_desc static_bl_desc = {(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; /* =========================================================================== * Local (static) routines in this file. */ local void tr_static_init OF((void)); local void init_block OF((deflate_state *s)); local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); local void build_tree OF((deflate_state *s, tree_desc *desc)); local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); local int build_bl_tree OF((deflate_state *s)); local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, int blcodes)); local void compress_block OF((deflate_state *s, ct_data *ltree, ct_data *dtree)); local int detect_data_type OF((deflate_state *s)); local unsigned bi_reverse OF((unsigned value, int length)); local void bi_windup OF((deflate_state *s)); local void bi_flush OF((deflate_state *s)); local void copy_block OF((deflate_state *s, charf *buf, unsigned len, int header)); #ifdef GEN_TREES_H local void gen_trees_header OF((void)); #endif #ifndef DEBUG # define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) /* Send a code of the given tree. c and tree must not have side effects */ #else /* DEBUG */ # define send_code(s, c, tree) \ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ send_bits(s, tree[c].Code, tree[c].Len); } #endif /* =========================================================================== * Output a short LSB first on the stream. * IN assertion: there is enough room in pendingBuf. */ #define put_short(s, w) { \ put_byte(s, (uch)((w) & 0xff)); \ put_byte(s, (uch)((ush)(w) >> 8)); \ } /* =========================================================================== * Send a value on a given number of bits. * IN assertion: length <= 16 and value fits in length bits. */ #ifdef DEBUG local void send_bits OF((deflate_state *s, int value, int length)); local void send_bits(s, value, length) deflate_state *s; int value; /* value to send */ int length; /* number of bits */ { Tracevv((stderr," l %2d v %4x ", length, value)); Assert(length > 0 && length <= 15, "invalid length"); s->bits_sent += (ulg)length; /* If not enough room in bi_buf, use (valid) bits from bi_buf and * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) * unused bits in value. */ if (s->bi_valid > (int)Buf_size - length) { s->bi_buf |= (value << s->bi_valid); put_short(s, s->bi_buf); s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); s->bi_valid += length - Buf_size; } else { s->bi_buf |= value << s->bi_valid; s->bi_valid += length; } } #else /* !DEBUG */ #define send_bits(s, value, length) \ { int len = length;\ if (s->bi_valid > (int)Buf_size - len) {\ int val = value;\ s->bi_buf |= (val << s->bi_valid);\ put_short(s, s->bi_buf);\ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ s->bi_valid += len - Buf_size;\ } else {\ s->bi_buf |= (value) << s->bi_valid;\ s->bi_valid += len;\ }\ } #endif /* DEBUG */ /* the arguments must not have side effects */ /* =========================================================================== * Initialize the various 'constant' tables. */ local void tr_static_init() { #if defined(GEN_TREES_H) || !defined(STDC) static int static_init_done = 0; int n; /* iterates over tree elements */ int bits; /* bit counter */ int length; /* length value */ int code; /* code value */ int dist; /* distance index */ ush bl_count[MAX_BITS+1]; /* number of codes at each bit length for an optimal tree */ if (static_init_done) return; /* For some embedded targets, global variables are not initialized: */ #ifdef NO_INIT_GLOBAL_POINTERS static_l_desc.static_tree = static_ltree; static_l_desc.extra_bits = extra_lbits; static_d_desc.static_tree = static_dtree; static_d_desc.extra_bits = extra_dbits; static_bl_desc.extra_bits = extra_blbits; #endif /* Initialize the mapping length (0..255) -> length code (0..28) */ length = 0; for (code = 0; code < LENGTH_CODES-1; code++) { base_length[code] = length; for (n = 0; n < (1< dist code (0..29) */ dist = 0; for (code = 0 ; code < 16; code++) { base_dist[code] = dist; for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ for ( ; code < D_CODES; code++) { base_dist[code] = dist << 7; for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { _dist_code[256 + dist++] = (uch)code; } } Assert (dist == 256, "tr_static_init: 256+dist != 512"); /* Construct the codes of the static literal tree */ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; n = 0; while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; /* Codes 286 and 287 do not exist, but we must include them in the * tree construction to get a canonical Huffman tree (longest code * all ones) */ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); /* The static distance tree is trivial: */ for (n = 0; n < D_CODES; n++) { static_dtree[n].Len = 5; static_dtree[n].Code = bi_reverse((unsigned)n, 5); } static_init_done = 1; # ifdef GEN_TREES_H gen_trees_header(); # endif #endif /* defined(GEN_TREES_H) || !defined(STDC) */ } /* =========================================================================== * Genererate the file trees.h describing the static trees. */ #ifdef GEN_TREES_H # ifndef DEBUG # include # endif # define SEPARATOR(i, last, width) \ ((i) == (last)? "\n};\n\n" : \ ((i) % (width) == (width)-1 ? ",\n" : ", ")) void gen_trees_header() { FILE *header = fopen("trees.h", "w"); int i; Assert (header != NULL, "Can't open trees.h"); fprintf(header, "/* header created automatically with -DGEN_TREES_H */\n\n"); fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); for (i = 0; i < L_CODES+2; i++) { fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); } fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); for (i = 0; i < D_CODES; i++) { fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); } fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); for (i = 0; i < DIST_CODE_LEN; i++) { fprintf(header, "%2u%s", _dist_code[i], SEPARATOR(i, DIST_CODE_LEN-1, 20)); } fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { fprintf(header, "%2u%s", _length_code[i], SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); } fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); for (i = 0; i < LENGTH_CODES; i++) { fprintf(header, "%1u%s", base_length[i], SEPARATOR(i, LENGTH_CODES-1, 20)); } fprintf(header, "local const int base_dist[D_CODES] = {\n"); for (i = 0; i < D_CODES; i++) { fprintf(header, "%5u%s", base_dist[i], SEPARATOR(i, D_CODES-1, 10)); } fclose(header); } #endif /* GEN_TREES_H */ /* =========================================================================== * Initialize the tree data structures for a new zlib stream. */ void _tr_init(s) deflate_state *s; { tr_static_init(); s->l_desc.dyn_tree = s->dyn_ltree; s->l_desc.stat_desc = &static_l_desc; s->d_desc.dyn_tree = s->dyn_dtree; s->d_desc.stat_desc = &static_d_desc; s->bl_desc.dyn_tree = s->bl_tree; s->bl_desc.stat_desc = &static_bl_desc; s->bi_buf = 0; s->bi_valid = 0; s->last_eob_len = 8; /* enough lookahead for inflate */ #ifdef DEBUG s->compressed_len = 0L; s->bits_sent = 0L; #endif /* Initialize the first block of the first file: */ init_block(s); } /* =========================================================================== * Initialize a new block. */ local void init_block(s) deflate_state *s; { int n; /* iterates over tree elements */ /* Initialize the trees. */ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; s->dyn_ltree[END_BLOCK].Freq = 1; s->opt_len = s->static_len = 0L; s->last_lit = s->matches = 0; } #define SMALLEST 1 /* Index within the heap array of least frequent node in the Huffman tree */ /* =========================================================================== * Remove the smallest element from the heap and recreate the heap with * one less element. Updates heap and heap_len. */ #define pqremove(s, tree, top) \ {\ top = s->heap[SMALLEST]; \ s->heap[SMALLEST] = s->heap[s->heap_len--]; \ pqdownheap(s, tree, SMALLEST); \ } /* =========================================================================== * Compares to subtrees, using the tree depth as tie breaker when * the subtrees have equal frequency. This minimizes the worst case length. */ #define smaller(tree, n, m, depth) \ (tree[n].Freq < tree[m].Freq || \ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) /* =========================================================================== * Restore the heap property by moving down the tree starting at node k, * exchanging a node with the smallest of its two sons if necessary, stopping * when the heap property is re-established (each father smaller than its * two sons). */ local void pqdownheap(s, tree, k) deflate_state *s; ct_data *tree; /* the tree to restore */ int k; /* node to move down */ { int v = s->heap[k]; int j = k << 1; /* left son of k */ while (j <= s->heap_len) { /* Set j to the smallest of the two sons: */ if (j < s->heap_len && smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { j++; } /* Exit if v is smaller than both sons */ if (smaller(tree, v, s->heap[j], s->depth)) break; /* Exchange v with the smallest son */ s->heap[k] = s->heap[j]; k = j; /* And continue down the tree, setting j to the left son of k */ j <<= 1; } s->heap[k] = v; } /* =========================================================================== * Compute the optimal bit lengths for a tree and update the total bit length * for the current block. * IN assertion: the fields freq and dad are set, heap[heap_max] and * above are the tree nodes sorted by increasing frequency. * OUT assertions: the field len is set to the optimal bit length, the * array bl_count contains the frequencies for each bit length. * The length opt_len is updated; static_len is also updated if stree is * not null. */ local void gen_bitlen(s, desc) deflate_state *s; tree_desc *desc; /* the tree descriptor */ { ct_data *tree = desc->dyn_tree; int max_code = desc->max_code; const ct_data *stree = desc->stat_desc->static_tree; const intf *extra = desc->stat_desc->extra_bits; int base = desc->stat_desc->extra_base; int max_length = desc->stat_desc->max_length; int h; /* heap index */ int n, m; /* iterate over the tree elements */ int bits; /* bit length */ int xbits; /* extra bits */ ush f; /* frequency */ int overflow = 0; /* number of elements with bit length too large */ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; /* In a first pass, compute the optimal bit lengths (which may * overflow in the case of the bit length tree). */ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ for (h = s->heap_max+1; h < HEAP_SIZE; h++) { n = s->heap[h]; bits = tree[tree[n].Dad].Len + 1; if (bits > max_length) bits = max_length, overflow++; tree[n].Len = (ush)bits; /* We overwrite tree[n].Dad which is no longer needed */ if (n > max_code) continue; /* not a leaf node */ s->bl_count[bits]++; xbits = 0; if (n >= base) xbits = extra[n-base]; f = tree[n].Freq; s->opt_len += (ulg)f * (bits + xbits); if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); } if (overflow == 0) return; Trace((stderr,"\nbit length overflow\n")); /* This happens for example on obj2 and pic of the Calgary corpus */ /* Find the first bit length which could increase: */ do { bits = max_length-1; while (s->bl_count[bits] == 0) bits--; s->bl_count[bits]--; /* move one leaf down the tree */ s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ s->bl_count[max_length]--; /* The brother of the overflow item also moves one step up, * but this does not affect bl_count[max_length] */ overflow -= 2; } while (overflow > 0); /* Now recompute all bit lengths, scanning in increasing frequency. * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all * lengths instead of fixing only the wrong ones. This idea is taken * from 'ar' written by Haruhiko Okumura.) */ for (bits = max_length; bits != 0; bits--) { n = s->bl_count[bits]; while (n != 0) { m = s->heap[--h]; if (m > max_code) continue; if ((unsigned) tree[m].Len != (unsigned) bits) { Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); s->opt_len += ((long)bits - (long)tree[m].Len) *(long)tree[m].Freq; tree[m].Len = (ush)bits; } n--; } } } /* =========================================================================== * Generate the codes for a given tree and bit counts (which need not be * optimal). * IN assertion: the array bl_count contains the bit length statistics for * the given tree and the field len is set for all tree elements. * OUT assertion: the field code is set for all tree elements of non * zero code length. */ local void gen_codes (tree, max_code, bl_count) ct_data *tree; /* the tree to decorate */ int max_code; /* largest code with non zero frequency */ ushf *bl_count; /* number of codes at each bit length */ { ush next_code[MAX_BITS+1]; /* next code value for each bit length */ ush code = 0; /* running code value */ int bits; /* bit index */ int n; /* code index */ /* The distribution counts are first used to generate the code values * without bit reversal. */ for (bits = 1; bits <= MAX_BITS; bits++) { next_code[bits] = code = (code + bl_count[bits-1]) << 1; } /* Check that the bit counts in bl_count are consistent. The last code * must be all ones. */ Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; const ct_data *stree = desc->stat_desc->static_tree; int elems = desc->stat_desc->elems; int n, m; /* iterate over heap elements */ int max_code = -1; /* largest code with non zero frequency */ int node; /* new node being created */ /* Construct the initial heap, with least frequent element in * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. * heap[0] is not used. */ s->heap_len = 0, s->heap_max = HEAP_SIZE; for (n = 0; n < elems; n++) { if (tree[n].Freq != 0) { s->heap[++(s->heap_len)] = max_code = n; s->depth[n] = 0; } else { tree[n].Len = 0; } } /* The pkzip format requires that at least one distance code exists, * and that at least one bit should be sent even if there is only one * possible code. So to avoid special checks later on we force at least * two codes of non zero frequency. */ while (s->heap_len < 2) { node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); tree[node].Freq = 1; s->depth[node] = 0; s->opt_len--; if (stree) s->static_len -= stree[node].Len; /* node is 0 or 1 so it does not have extra bits */ } desc->max_code = max_code; /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, * establish sub-heaps of increasing lengths: */ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); /* Construct the Huffman tree by repeatedly combining the least two * frequent nodes. */ node = elems; /* next internal node of the tree */ do { pqremove(s, tree, n); /* n = node of least frequency */ m = s->heap[SMALLEST]; /* m = node of next least frequency */ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ s->heap[--(s->heap_max)] = m; /* Create a new node father of n and m */ tree[node].Freq = tree[n].Freq + tree[m].Freq; s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? s->depth[n] : s->depth[m]) + 1); tree[n].Dad = tree[m].Dad = (ush)node; #ifdef DUMP_BL_TREE if (tree == s->bl_tree) { fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); } #endif /* and insert the new node in the heap */ s->heap[SMALLEST] = node++; pqdownheap(s, tree, SMALLEST); } while (s->heap_len >= 2); s->heap[--(s->heap_max)] = s->heap[SMALLEST]; /* At this point, the fields freq and dad are set. We can now * generate the bit lengths. */ gen_bitlen(s, (tree_desc *)desc); /* The field len is now set, we can generate the bit codes */ gen_codes ((ct_data *)tree, max_code, s->bl_count); } /* =========================================================================== * Scan a literal or distance tree to determine the frequencies of the codes * in the bit length tree. */ local void scan_tree (s, tree, max_code) deflate_state *s; ct_data *tree; /* the tree to be scanned */ int max_code; /* and its largest code of non zero frequency */ { int n; /* iterates over all tree elements */ int prevlen = -1; /* last emitted length */ int curlen; /* length of current code */ int nextlen = tree[0].Len; /* length of next code */ int count = 0; /* repeat count of the current code */ int max_count = 7; /* max repeat count */ int min_count = 4; /* min repeat count */ if (nextlen == 0) max_count = 138, min_count = 3; tree[max_code+1].Len = (ush)0xffff; /* guard */ for (n = 0; n <= max_code; n++) { curlen = nextlen; nextlen = tree[n+1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { s->bl_tree[curlen].Freq += count; } else if (curlen != 0) { if (curlen != prevlen) s->bl_tree[curlen].Freq++; s->bl_tree[REP_3_6].Freq++; } else if (count <= 10) { s->bl_tree[REPZ_3_10].Freq++; } else { s->bl_tree[REPZ_11_138].Freq++; } count = 0; prevlen = curlen; if (nextlen == 0) { max_count = 138, min_count = 3; } else if (curlen == nextlen) { max_count = 6, min_count = 3; } else { max_count = 7, min_count = 4; } } } /* =========================================================================== * Send a literal or distance tree in compressed form, using the codes in * bl_tree. */ local void send_tree (s, tree, max_code) deflate_state *s; ct_data *tree; /* the tree to be scanned */ int max_code; /* and its largest code of non zero frequency */ { int n; /* iterates over all tree elements */ int prevlen = -1; /* last emitted length */ int curlen; /* length of current code */ int nextlen = tree[0].Len; /* length of next code */ int count = 0; /* repeat count of the current code */ int max_count = 7; /* max repeat count */ int min_count = 4; /* min repeat count */ /* tree[max_code+1].Len = -1; */ /* guard already set */ if (nextlen == 0) max_count = 138, min_count = 3; for (n = 0; n <= max_code; n++) { curlen = nextlen; nextlen = tree[n+1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { do { send_code(s, curlen, s->bl_tree); } while (--count != 0); } else if (curlen != 0) { if (curlen != prevlen) { send_code(s, curlen, s->bl_tree); count--; } Assert(count >= 3 && count <= 6, " 3_6?"); send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); } else if (count <= 10) { send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); } else { send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); } count = 0; prevlen = curlen; if (nextlen == 0) { max_count = 138, min_count = 3; } else if (curlen == nextlen) { max_count = 6, min_count = 3; } else { max_count = 7, min_count = 4; } } } /* =========================================================================== * Construct the Huffman tree for the bit lengths and return the index in * bl_order of the last bit length code to send. */ local int build_bl_tree(s) deflate_state *s; { int max_blindex; /* index of last bit length code of non zero freq */ /* Determine the bit length frequencies for literal and distance trees */ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); /* Build the bit length tree: */ build_tree(s, (tree_desc *)(&(s->bl_desc))); /* opt_len now includes the length of the tree representations, except * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. */ /* Determine the number of bit length codes to send. The pkzip format * requires that at least 4 bit length codes be sent. (appnote.txt says * 3 but the actual value used is 4.) */ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; } /* Update opt_len to include the bit length tree and counts */ s->opt_len += 3*(max_blindex+1) + 5+5+4; Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", s->opt_len, s->static_len)); return max_blindex; } /* =========================================================================== * Send the header for a block using dynamic Huffman trees: the counts, the * lengths of the bit length codes, the literal tree and the distance tree. * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. */ local void send_all_trees(s, lcodes, dcodes, blcodes) deflate_state *s; int lcodes, dcodes, blcodes; /* number of codes for each tree */ { int rank; /* index in bl_order */ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, "too many codes"); Tracev((stderr, "\nbl counts: ")); send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ send_bits(s, dcodes-1, 5); send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ for (rank = 0; rank < blcodes; rank++) { Tracev((stderr, "\nbl code %2d ", bl_order[rank])); send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); } Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); } /* =========================================================================== * Send a stored block */ void _tr_stored_block(s, buf, stored_len, eof) deflate_state *s; charf *buf; /* input block */ ulg stored_len; /* length of input block */ int eof; /* true if this is the last block for a file */ { send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ #ifdef DEBUG s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; s->compressed_len += (stored_len + 4) << 3; #endif copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ } /* =========================================================================== * Send one empty static block to give enough lookahead for inflate. * This takes 10 bits, of which 7 may remain in the bit buffer. * The current inflate code requires 9 bits of lookahead. If the * last two codes for the previous block (real code plus EOB) were coded * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode * the last real code. In this case we send two empty static blocks instead * of one. (There are no problems if the previous block is stored or fixed.) * To simplify the code, we assume the worst case of last real code encoded * on one bit only. */ void _tr_align(s) deflate_state *s; { send_bits(s, STATIC_TREES<<1, 3); send_code(s, END_BLOCK, static_ltree); #ifdef DEBUG s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ #endif bi_flush(s); /* Of the 10 bits for the empty block, we have already sent * (10 - bi_valid) bits. The lookahead for the last real code (before * the EOB of the previous block) was thus at least one plus the length * of the EOB plus what we have just sent of the empty static block. */ if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { send_bits(s, STATIC_TREES<<1, 3); send_code(s, END_BLOCK, static_ltree); #ifdef DEBUG s->compressed_len += 10L; #endif bi_flush(s); } s->last_eob_len = 7; } /* =========================================================================== * Determine the best encoding for the current block: dynamic trees, static * trees or store, and output the encoded block to the zip file. */ void _tr_flush_block(s, buf, stored_len, eof) deflate_state *s; charf *buf; /* input block, or NULL if too old */ ulg stored_len; /* length of input block */ int eof; /* true if this is the last block for a file */ { ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ int max_blindex = 0; /* index of last bit length code of non zero freq */ /* Build the Huffman trees unless a stored block is forced */ if (s->level > 0) { /* Check if the file is binary or text */ if (s->strm->data_type == Z_UNKNOWN) s->strm->data_type = detect_data_type(s); /* Construct the literal and distance trees */ build_tree(s, (tree_desc *)(&(s->l_desc))); Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, s->static_len)); build_tree(s, (tree_desc *)(&(s->d_desc))); Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, s->static_len)); /* At this point, opt_len and static_len are the total bit lengths of * the compressed block data, excluding the tree representations. */ /* Build the bit length tree for the above two trees, and get the index * in bl_order of the last bit length code to send. */ max_blindex = build_bl_tree(s); /* Determine the best encoding. Compute the block lengths in bytes. */ opt_lenb = (s->opt_len+3+7)>>3; static_lenb = (s->static_len+3+7)>>3; Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, s->last_lit)); if (static_lenb <= opt_lenb) opt_lenb = static_lenb; } else { Assert(buf != (char*)0, "lost buf"); opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ } #ifdef FORCE_STORED if (buf != (char*)0) { /* force stored block */ #else if (stored_len+4 <= opt_lenb && buf != (char*)0) { /* 4: two words for the lengths */ #endif /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. * Otherwise we can't have processed more than WSIZE input bytes since * the last block flush, because compression would have been * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to * transform a block into a stored block. */ _tr_stored_block(s, buf, stored_len, eof); #ifdef FORCE_STATIC } else if (static_lenb >= 0) { /* force static trees */ #else } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { #endif send_bits(s, (STATIC_TREES<<1)+eof, 3); compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); #ifdef DEBUG s->compressed_len += 3 + s->static_len; #endif } else { send_bits(s, (DYN_TREES<<1)+eof, 3); send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, max_blindex+1); compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); #ifdef DEBUG s->compressed_len += 3 + s->opt_len; #endif } Assert (s->compressed_len == s->bits_sent, "bad compressed size"); /* The above check is made mod 2^32, for files larger than 512 MB * and uLong implemented on 32 bits. */ init_block(s); if (eof) { bi_windup(s); #ifdef DEBUG s->compressed_len += 7; /* align on byte boundary */ #endif } Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, s->compressed_len-7*eof)); } /* =========================================================================== * Save the match info and tally the frequency counts. Return true if * the current block must be flushed. */ int _tr_tally (s, dist, lc) deflate_state *s; unsigned dist; /* distance of matched string */ unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ { s->d_buf[s->last_lit] = (ush)dist; s->l_buf[s->last_lit++] = (uch)lc; if (dist == 0) { /* lc is the unmatched char */ s->dyn_ltree[lc].Freq++; } else { s->matches++; /* Here, lc is the match length - MIN_MATCH */ dist--; /* dist = match distance - 1 */ Assert((ush)dist < (ush)MAX_DIST(s) && (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; s->dyn_dtree[d_code(dist)].Freq++; } #ifdef TRUNCATE_BLOCK /* Try to guess if it is profitable to stop the current block here */ if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { /* Compute an upper bound for the compressed length */ ulg out_length = (ulg)s->last_lit*8L; ulg in_length = (ulg)((long)s->strstart - s->block_start); int dcode; for (dcode = 0; dcode < D_CODES; dcode++) { out_length += (ulg)s->dyn_dtree[dcode].Freq * (5L+extra_dbits[dcode]); } out_length >>= 3; Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", s->last_lit, in_length, out_length, 100L - out_length*100L/in_length)); if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; } #endif return (s->last_lit == s->lit_bufsize-1); /* We avoid equality with lit_bufsize because of wraparound at 64K * on 16 bit machines and because stored blocks are restricted to * 64K-1 bytes. */ } /* =========================================================================== * Send the block data compressed using the given Huffman trees */ local void compress_block(s, ltree, dtree) deflate_state *s; ct_data *ltree; /* literal tree */ ct_data *dtree; /* distance tree */ { unsigned dist; /* distance of matched string */ int lc; /* match length or unmatched char (if dist == 0) */ unsigned lx = 0; /* running index in l_buf */ unsigned code; /* the code to send */ int extra; /* number of extra bits to send */ if (s->last_lit != 0) do { dist = s->d_buf[lx]; lc = s->l_buf[lx++]; if (dist == 0) { send_code(s, lc, ltree); /* send a literal byte */ Tracecv(isgraph(lc), (stderr," '%c' ", lc)); } else { /* Here, lc is the match length - MIN_MATCH */ code = _length_code[lc]; send_code(s, code+LITERALS+1, ltree); /* send the length code */ extra = extra_lbits[code]; if (extra != 0) { lc -= base_length[code]; send_bits(s, lc, extra); /* send the extra length bits */ } dist--; /* dist is now the match distance - 1 */ code = d_code(dist); Assert (code < D_CODES, "bad d_code"); send_code(s, code, dtree); /* send the distance code */ extra = extra_dbits[code]; if (extra != 0) { dist -= base_dist[code]; send_bits(s, dist, extra); /* send the extra distance bits */ } } /* literal or match pair ? */ /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, "pendingBuf overflow"); } while (lx < s->last_lit); send_code(s, END_BLOCK, ltree); s->last_eob_len = ltree[END_BLOCK].Len; } /* =========================================================================== * Check if the data type is TEXT or BINARY, using the following algorithm: * - TEXT if the two conditions below are satisfied: * a) There are no non-portable control characters belonging to the * "black list" (0..6, 14..25, 28..31). * b) There is at least one printable character belonging to the * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). * - BINARY otherwise. * - The following partially-portable control characters form a * "gray list" that is ignored in this detection algorithm: * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). * IN assertion: the fields Freq of dyn_ltree are set. */ local int detect_data_type(s) deflate_state *s; { /* black_mask is the bit mask of black-listed bytes * set bits 0..6, 14..25, and 28..31 * 0xf3ffc07f = binary 11110011111111111100000001111111 */ unsigned long black_mask = 0xf3ffc07fUL; int n; /* Check for non-textual ("black-listed") bytes. */ for (n = 0; n <= 31; n++, black_mask >>= 1) if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) return Z_BINARY; /* Check for textual ("white-listed") bytes. */ if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 || s->dyn_ltree[13].Freq != 0) return Z_TEXT; for (n = 32; n < LITERALS; n++) if (s->dyn_ltree[n].Freq != 0) return Z_TEXT; /* There are no "black-listed" or "white-listed" bytes: * this stream either is empty or has tolerated ("gray-listed") bytes only. */ return Z_BINARY; } /* =========================================================================== * Reverse the first len bits of a code, using straightforward code (a faster * method would use a table) * IN assertion: 1 <= len <= 15 */ local unsigned bi_reverse(code, len) unsigned code; /* the value to invert */ int len; /* its bit length */ { register unsigned res = 0; do { res |= code & 1; code >>= 1, res <<= 1; } while (--len > 0); return res >> 1; } /* =========================================================================== * Flush the bit buffer, keeping at most 7 bits in it. */ local void bi_flush(s) deflate_state *s; { if (s->bi_valid == 16) { put_short(s, s->bi_buf); s->bi_buf = 0; s->bi_valid = 0; } else if (s->bi_valid >= 8) { put_byte(s, (Byte)s->bi_buf); s->bi_buf >>= 8; s->bi_valid -= 8; } } /* =========================================================================== * Flush the bit buffer and align the output on a byte boundary */ local void bi_windup(s) deflate_state *s; { if (s->bi_valid > 8) { put_short(s, s->bi_buf); } else if (s->bi_valid > 0) { put_byte(s, (Byte)s->bi_buf); } s->bi_buf = 0; s->bi_valid = 0; #ifdef DEBUG s->bits_sent = (s->bits_sent+7) & ~7; #endif } /* =========================================================================== * Copy a stored block, storing first the length and its * one's complement if requested. */ local void copy_block(s, buf, len, header) deflate_state *s; charf *buf; /* the input data */ unsigned len; /* its length */ int header; /* true if block header must be written */ { bi_windup(s); /* align on byte boundary */ s->last_eob_len = 8; /* enough lookahead for inflate */ if (header) { put_short(s, (ush)len); put_short(s, (ush)~len); #ifdef DEBUG s->bits_sent += 2*16; #endif } #ifdef DEBUG s->bits_sent += (ulg)len<<3; #endif while (len--) { put_byte(s, *buf++); } } ================================================ FILE: unity_decoder/libil2cpp/external/zlib/trees.h ================================================ /* header created automatically with -DGEN_TREES_H */ local const ct_data static_ltree[L_CODES + 2] = { {{ 12}, { 8}}, {{140}, { 8}}, {{ 76}, { 8}}, {{204}, { 8}}, {{ 44}, { 8}}, {{172}, { 8}}, {{108}, { 8}}, {{236}, { 8}}, {{ 28}, { 8}}, {{156}, { 8}}, {{ 92}, { 8}}, {{220}, { 8}}, {{ 60}, { 8}}, {{188}, { 8}}, {{124}, { 8}}, {{252}, { 8}}, {{ 2}, { 8}}, {{130}, { 8}}, {{ 66}, { 8}}, {{194}, { 8}}, {{ 34}, { 8}}, {{162}, { 8}}, {{ 98}, { 8}}, {{226}, { 8}}, {{ 18}, { 8}}, {{146}, { 8}}, {{ 82}, { 8}}, {{210}, { 8}}, {{ 50}, { 8}}, {{178}, { 8}}, {{114}, { 8}}, {{242}, { 8}}, {{ 10}, { 8}}, {{138}, { 8}}, {{ 74}, { 8}}, {{202}, { 8}}, {{ 42}, { 8}}, {{170}, { 8}}, {{106}, { 8}}, {{234}, { 8}}, {{ 26}, { 8}}, {{154}, { 8}}, {{ 90}, { 8}}, {{218}, { 8}}, {{ 58}, { 8}}, {{186}, { 8}}, {{122}, { 8}}, {{250}, { 8}}, {{ 6}, { 8}}, {{134}, { 8}}, {{ 70}, { 8}}, {{198}, { 8}}, {{ 38}, { 8}}, {{166}, { 8}}, {{102}, { 8}}, {{230}, { 8}}, {{ 22}, { 8}}, {{150}, { 8}}, {{ 86}, { 8}}, {{214}, { 8}}, {{ 54}, { 8}}, {{182}, { 8}}, {{118}, { 8}}, {{246}, { 8}}, {{ 14}, { 8}}, {{142}, { 8}}, {{ 78}, { 8}}, {{206}, { 8}}, {{ 46}, { 8}}, {{174}, { 8}}, {{110}, { 8}}, {{238}, { 8}}, {{ 30}, { 8}}, {{158}, { 8}}, {{ 94}, { 8}}, {{222}, { 8}}, {{ 62}, { 8}}, {{190}, { 8}}, {{126}, { 8}}, {{254}, { 8}}, {{ 1}, { 8}}, {{129}, { 8}}, {{ 65}, { 8}}, {{193}, { 8}}, {{ 33}, { 8}}, {{161}, { 8}}, {{ 97}, { 8}}, {{225}, { 8}}, {{ 17}, { 8}}, {{145}, { 8}}, {{ 81}, { 8}}, {{209}, { 8}}, {{ 49}, { 8}}, {{177}, { 8}}, {{113}, { 8}}, {{241}, { 8}}, {{ 9}, { 8}}, {{137}, { 8}}, {{ 73}, { 8}}, {{201}, { 8}}, {{ 41}, { 8}}, {{169}, { 8}}, {{105}, { 8}}, {{233}, { 8}}, {{ 25}, { 8}}, {{153}, { 8}}, {{ 89}, { 8}}, {{217}, { 8}}, {{ 57}, { 8}}, {{185}, { 8}}, {{121}, { 8}}, {{249}, { 8}}, {{ 5}, { 8}}, {{133}, { 8}}, {{ 69}, { 8}}, {{197}, { 8}}, {{ 37}, { 8}}, {{165}, { 8}}, {{101}, { 8}}, {{229}, { 8}}, {{ 21}, { 8}}, {{149}, { 8}}, {{ 85}, { 8}}, {{213}, { 8}}, {{ 53}, { 8}}, {{181}, { 8}}, {{117}, { 8}}, {{245}, { 8}}, {{ 13}, { 8}}, {{141}, { 8}}, {{ 77}, { 8}}, {{205}, { 8}}, {{ 45}, { 8}}, {{173}, { 8}}, {{109}, { 8}}, {{237}, { 8}}, {{ 29}, { 8}}, {{157}, { 8}}, {{ 93}, { 8}}, {{221}, { 8}}, {{ 61}, { 8}}, {{189}, { 8}}, {{125}, { 8}}, {{253}, { 8}}, {{ 19}, { 9}}, {{275}, { 9}}, {{147}, { 9}}, {{403}, { 9}}, {{ 83}, { 9}}, {{339}, { 9}}, {{211}, { 9}}, {{467}, { 9}}, {{ 51}, { 9}}, {{307}, { 9}}, {{179}, { 9}}, {{435}, { 9}}, {{115}, { 9}}, {{371}, { 9}}, {{243}, { 9}}, {{499}, { 9}}, {{ 11}, { 9}}, {{267}, { 9}}, {{139}, { 9}}, {{395}, { 9}}, {{ 75}, { 9}}, {{331}, { 9}}, {{203}, { 9}}, {{459}, { 9}}, {{ 43}, { 9}}, {{299}, { 9}}, {{171}, { 9}}, {{427}, { 9}}, {{107}, { 9}}, {{363}, { 9}}, {{235}, { 9}}, {{491}, { 9}}, {{ 27}, { 9}}, {{283}, { 9}}, {{155}, { 9}}, {{411}, { 9}}, {{ 91}, { 9}}, {{347}, { 9}}, {{219}, { 9}}, {{475}, { 9}}, {{ 59}, { 9}}, {{315}, { 9}}, {{187}, { 9}}, {{443}, { 9}}, {{123}, { 9}}, {{379}, { 9}}, {{251}, { 9}}, {{507}, { 9}}, {{ 7}, { 9}}, {{263}, { 9}}, {{135}, { 9}}, {{391}, { 9}}, {{ 71}, { 9}}, {{327}, { 9}}, {{199}, { 9}}, {{455}, { 9}}, {{ 39}, { 9}}, {{295}, { 9}}, {{167}, { 9}}, {{423}, { 9}}, {{103}, { 9}}, {{359}, { 9}}, {{231}, { 9}}, {{487}, { 9}}, {{ 23}, { 9}}, {{279}, { 9}}, {{151}, { 9}}, {{407}, { 9}}, {{ 87}, { 9}}, {{343}, { 9}}, {{215}, { 9}}, {{471}, { 9}}, {{ 55}, { 9}}, {{311}, { 9}}, {{183}, { 9}}, {{439}, { 9}}, {{119}, { 9}}, {{375}, { 9}}, {{247}, { 9}}, {{503}, { 9}}, {{ 15}, { 9}}, {{271}, { 9}}, {{143}, { 9}}, {{399}, { 9}}, {{ 79}, { 9}}, {{335}, { 9}}, {{207}, { 9}}, {{463}, { 9}}, {{ 47}, { 9}}, {{303}, { 9}}, {{175}, { 9}}, {{431}, { 9}}, {{111}, { 9}}, {{367}, { 9}}, {{239}, { 9}}, {{495}, { 9}}, {{ 31}, { 9}}, {{287}, { 9}}, {{159}, { 9}}, {{415}, { 9}}, {{ 95}, { 9}}, {{351}, { 9}}, {{223}, { 9}}, {{479}, { 9}}, {{ 63}, { 9}}, {{319}, { 9}}, {{191}, { 9}}, {{447}, { 9}}, {{127}, { 9}}, {{383}, { 9}}, {{255}, { 9}}, {{511}, { 9}}, {{ 0}, { 7}}, {{ 64}, { 7}}, {{ 32}, { 7}}, {{ 96}, { 7}}, {{ 16}, { 7}}, {{ 80}, { 7}}, {{ 48}, { 7}}, {{112}, { 7}}, {{ 8}, { 7}}, {{ 72}, { 7}}, {{ 40}, { 7}}, {{104}, { 7}}, {{ 24}, { 7}}, {{ 88}, { 7}}, {{ 56}, { 7}}, {{120}, { 7}}, {{ 4}, { 7}}, {{ 68}, { 7}}, {{ 36}, { 7}}, {{100}, { 7}}, {{ 20}, { 7}}, {{ 84}, { 7}}, {{ 52}, { 7}}, {{116}, { 7}}, {{ 3}, { 8}}, {{131}, { 8}}, {{ 67}, { 8}}, {{195}, { 8}}, {{ 35}, { 8}}, {{163}, { 8}}, {{ 99}, { 8}}, {{227}, { 8}} }; local const ct_data static_dtree[D_CODES] = { {{ 0}, { 5}}, {{16}, { 5}}, {{ 8}, { 5}}, {{24}, { 5}}, {{ 4}, { 5}}, {{20}, { 5}}, {{12}, { 5}}, {{28}, { 5}}, {{ 2}, { 5}}, {{18}, { 5}}, {{10}, { 5}}, {{26}, { 5}}, {{ 6}, { 5}}, {{22}, { 5}}, {{14}, { 5}}, {{30}, { 5}}, {{ 1}, { 5}}, {{17}, { 5}}, {{ 9}, { 5}}, {{25}, { 5}}, {{ 5}, { 5}}, {{21}, { 5}}, {{13}, { 5}}, {{29}, { 5}}, {{ 3}, { 5}}, {{19}, { 5}}, {{11}, { 5}}, {{27}, { 5}}, {{ 7}, { 5}}, {{23}, { 5}} }; const uch _dist_code[DIST_CODE_LEN] = { 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 }; const uch _length_code[MAX_MATCH - MIN_MATCH + 1] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 }; local const int base_length[LENGTH_CODES] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0 }; local const int base_dist[D_CODES] = { 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 }; ================================================ FILE: unity_decoder/libil2cpp/external/zlib/uncompr.c ================================================ /* uncompr.c -- decompress a memory buffer * Copyright (C) 1995-2003 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #define ZLIB_INTERNAL #include "zlib.h" /* =========================================================================== Decompresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be large enough to hold the entire uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and transmitted to the decompressor by some mechanism outside the scope of this compression library.) Upon exit, destLen is the actual size of the compressed buffer. This function can be used to decompress a whole file at once if the input file is mmap'ed. uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, or Z_DATA_ERROR if the input data was corrupted. */ int ZEXPORT uncompress (dest, destLen, source, sourceLen) Bytef *dest; uLongf *destLen; const Bytef *source; uLong sourceLen; { z_stream stream; int err; stream.next_in = (Bytef*)source; stream.avail_in = (uInt)sourceLen; /* Check for source > 64K on 16-bit machine: */ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; stream.next_out = dest; stream.avail_out = (uInt)*destLen; if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; err = inflateInit(&stream); if (err != Z_OK) return err; err = inflate(&stream, Z_FINISH); if (err != Z_STREAM_END) { inflateEnd(&stream); if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) return Z_DATA_ERROR; return err; } *destLen = stream.total_out; err = inflateEnd(&stream); return err; } ================================================ FILE: unity_decoder/libil2cpp/external/zlib/zconf.h ================================================ /* zconf.h -- configuration of the zlib compression library * Copyright (C) 1995-2006 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #ifndef ZCONF_H #define ZCONF_H /* * If you *really* need a unique prefix for all types and library functions, * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. * Even better than compiling with -DZ_PREFIX would be to use configure to set * this permanently in zconf.h using "./configure --zprefix". */ #define Z_PREFIX 1 #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ /* all linked symbols */ # define _dist_code il2cpp_z__dist_code # define _length_code il2cpp_z__length_code # define _tr_align il2cpp_z__tr_align # define _tr_flush_block il2cpp_z__tr_flush_block # define _tr_init il2cpp_z__tr_init # define _tr_stored_block il2cpp_z__tr_stored_block # define _tr_tally il2cpp_z__tr_tally # define adler32 il2cpp_z_adler32 # define adler32_combine il2cpp_z_adler32_combine # define adler32_combine64 il2cpp_z_adler32_combine64 # define compress il2cpp_z_compress # define compress2 il2cpp_z_compress2 # define compressBound il2cpp_z_compressBound # define crc32 il2cpp_z_crc32 # define crc32_combine il2cpp_z_crc32_combine # define crc32_combine64 il2cpp_z_crc32_combine64 # define deflate il2cpp_z_deflate # define deflateBound il2cpp_z_deflateBound # define deflateCopy il2cpp_z_deflateCopy # define deflateEnd il2cpp_z_deflateEnd # define deflateInit2_ il2cpp_z_deflateInit2_ # define deflateInit_ il2cpp_z_deflateInit_ # define deflateParams il2cpp_z_deflateParams # define deflatePrime il2cpp_z_deflatePrime # define deflateReset il2cpp_z_deflateReset # define deflateSetDictionary il2cpp_z_deflateSetDictionary # define deflateSetHeader il2cpp_z_deflateSetHeader # define deflateTune il2cpp_z_deflateTune # define deflate_copyright il2cpp_z_deflate_copyright # define get_crc_table il2cpp_z_get_crc_table # define gzclearerr il2cpp_z_gzclearerr # define gzclose il2cpp_z_gzclose # define gzdirect il2cpp_z_gzdirect # define gzdopen il2cpp_z_gzdopen # define gzeof il2cpp_z_gzeof # define gzerror il2cpp_z_gzerror # define gzflush il2cpp_z_gzflush # define gzgetc il2cpp_z_gzgetc # define gzgets il2cpp_z_gzgets # define gzopen il2cpp_z_gzopen # define gzprintf il2cpp_z_gzprintf # define gzputc il2cpp_z_gzputc # define gzputs il2cpp_z_gzputs # define gzread il2cpp_z_gzread # define gzrewind il2cpp_z_gzrewind # define gzseek il2cpp_z_gzseek # define gzsetparams il2cpp_z_gzsetparams # define gztell il2cpp_z_gztell # define gzungetc il2cpp_z_gzungetc # define gzwrite il2cpp_z_gzwrite # define inflate il2cpp_z_inflate # define inflateBack il2cpp_z_inflateBack # define inflateBackEnd il2cpp_z_inflateBackEnd # define inflateBackInit_ il2cpp_z_inflateBackInit_ # define inflateCopy il2cpp_z_inflateCopy # define inflateEnd il2cpp_z_inflateEnd # define inflateGetHeader il2cpp_z_inflateGetHeader # define inflateInit2_ il2cpp_z_inflateInit2_ # define inflateInit_ il2cpp_z_inflateInit_ # define inflatePrime il2cpp_z_inflatePrime # define inflateReset il2cpp_z_inflateReset # define inflateSetDictionary il2cpp_z_inflateSetDictionary # define inflateSync il2cpp_z_inflateSync # define inflateSyncPoint il2cpp_z_inflateSyncPoint # define inflateUndermine il2cpp_z_inflateUndermine # define inflate_copyright il2cpp_z_inflate_copyright # define inflate_fast il2cpp_z_inflate_fast # define inflate_table il2cpp_z_inflate_table # define uncompress il2cpp_z_uncompress # define zError il2cpp_z_zError # define z_errmsg il2cpp_z_z_errmsg # define zcalloc il2cpp_z_zcalloc # define zcfree il2cpp_z_zcfree # define zlibCompileFlags il2cpp_z_zlibCompileFlags # define zlibVersion il2cpp_z_zlibVersion /* all zlib typedefs in zlib.h and zconf.h */ # define Byte il2cpp_z_Byte # define Bytef il2cpp_z_Bytef # define alloc_func il2cpp_z_alloc_func # define charf il2cpp_z_charf # define free_func il2cpp_z_free_func # define gzFile il2cpp_z_gzFile # define gz_header il2cpp_z_gz_header # define gz_headerp il2cpp_z_gz_headerp # define in_func il2cpp_z_in_func # define intf il2cpp_z_intf # define out_func il2cpp_z_out_func # define uInt il2cpp_z_uInt # define uIntf il2cpp_z_uIntf # define uLong il2cpp_z_uLong # define uLongf il2cpp_z_uLongf # define voidp il2cpp_z_voidp # define voidp il2cpp_z_voidp # define voidpc il2cpp_z_voidpc # define voidpc il2cpp_z_voidpc # define voidpf il2cpp_z_voidpf # define voidpf il2cpp_z_voidpf # define z_stream il2cpp_z_z_stream # define z_streamp il2cpp_z_z_streamp /* all zlib structs in zlib.h and zconf.h */ # define gz_header_s il2cpp_z_gz_header_s # define internal_state il2cpp_z_internal_state # define z_stream_s il2cpp_z_z_stream_s #endif #if defined(__MSDOS__) && !defined(MSDOS) # define MSDOS #endif #if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) # define OS2 #endif #if defined(_WINDOWS) && !defined(WINDOWS) # define WINDOWS #endif #if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) # ifndef WIN32 # define WIN32 # endif #endif #if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) # if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) # ifndef SYS16BIT # define SYS16BIT # endif # endif #endif /* * Compile with -DMAXSEG_64K if the alloc function cannot allocate more * than 64k bytes at a time (needed on systems with 16-bit int). */ #ifdef SYS16BIT # define MAXSEG_64K #endif #ifdef MSDOS # define UNALIGNED_OK #endif #ifdef __STDC_VERSION__ # ifndef STDC # define STDC # endif # if __STDC_VERSION__ >= 199901L # ifndef STDC99 # define STDC99 # endif # endif #endif #if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) # define STDC #endif #if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) # define STDC #endif #if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) # define STDC #endif #if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) # define STDC #endif #if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ # define STDC #endif #ifndef STDC # ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ # define const /* note: need a more gentle solution here */ # endif #endif /* Some Mac compilers merge all .h files incorrectly: */ #if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) # define NO_DUMMY_DECL #endif /* Maximum value for memLevel in deflateInit2 */ #ifndef MAX_MEM_LEVEL # ifdef MAXSEG_64K # define MAX_MEM_LEVEL 8 # else # define MAX_MEM_LEVEL 9 # endif #endif /* Maximum value for windowBits in deflateInit2 and inflateInit2. * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files * created by gzip. (Files created by minigzip can still be extracted by * gzip.) */ #ifndef MAX_WBITS # define MAX_WBITS 15 /* 32K LZ77 window */ #endif /* The memory requirements for deflate are (in bytes): (1 << (windowBits+2)) + (1 << (memLevel+9)) that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) plus a few kilobytes for small objects. For example, if you want to reduce the default memory requirements from 256K to 128K, compile with make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" Of course this will generally degrade compression (there's no free lunch). The memory requirements for inflate are (in bytes) 1 << windowBits that is, 32K for windowBits=15 (default value) plus a few kilobytes for small objects. */ /* Type declarations */ #ifndef OF /* function prototypes */ # ifdef STDC # define OF(args) args # else # define OF(args) () # endif #endif /* The following definitions for FAR are needed only for MSDOS mixed * model programming (small or medium model with some far allocations). * This was tested only with MSC; for other MSDOS compilers you may have * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, * just define FAR to be empty. */ #ifdef SYS16BIT # if defined(M_I86SM) || defined(M_I86MM) /* MSC small or medium model */ # define SMALL_MEDIUM # ifdef _MSC_VER # define FAR _far # else # define FAR far # endif # endif # if (defined(__SMALL__) || defined(__MEDIUM__)) /* Turbo C small or medium model */ # define SMALL_MEDIUM # ifdef __BORLANDC__ # define FAR _far # else # define FAR far # endif # endif #endif #if defined(WINDOWS) || defined(WIN32) /* If building or using zlib as a DLL, define ZLIB_DLL. * This is not mandatory, but it offers a little performance increase. */ # ifdef ZLIB_DLL # if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) # ifdef ZLIB_INTERNAL # define ZEXTERN extern __declspec(dllexport) # else # define ZEXTERN extern __declspec(dllimport) # endif # endif # endif /* ZLIB_DLL */ /* If building or using zlib with the WINAPI/WINAPIV calling convention, * define ZLIB_WINAPI. * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. */ # ifdef ZLIB_WINAPI # ifdef FAR # undef FAR # endif # include /* No need for _export, use ZLIB.DEF instead. */ /* For complete Windows compatibility, use WINAPI, not __stdcall. */ # define ZEXPORT WINAPI # ifdef WIN32 # define ZEXPORTVA WINAPIV # else # define ZEXPORTVA FAR CDECL # endif # endif #endif #if defined (__BEOS__) # ifdef ZLIB_DLL # ifdef ZLIB_INTERNAL # define ZEXPORT __declspec(dllexport) # define ZEXPORTVA __declspec(dllexport) # else # define ZEXPORT __declspec(dllimport) # define ZEXPORTVA __declspec(dllimport) # endif # endif #endif #ifdef HAVE_VISIBILITY_PRAGMA # define ZEXTERN __attribute__((visibility ("default"))) extern #endif #ifndef ZEXTERN # define ZEXTERN extern #endif #ifndef ZEXPORT # define ZEXPORT #endif #ifndef ZEXPORTVA # define ZEXPORTVA #endif #ifndef FAR # define FAR #endif #if !defined(__MACTYPES__) typedef unsigned char Byte; /* 8 bits */ #endif typedef unsigned int uInt; /* 16 bits or more */ typedef unsigned long uLong; /* 32 bits or more */ #ifdef SMALL_MEDIUM /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ # define Bytef Byte FAR #else typedef Byte FAR Bytef; #endif typedef char FAR charf; typedef int FAR intf; typedef uInt FAR uIntf; typedef uLong FAR uLongf; #ifdef STDC typedef void const *voidpc; typedef void FAR *voidpf; typedef void *voidp; #else typedef Byte const *voidpc; typedef Byte FAR *voidpf; typedef Byte *voidp; #endif /* not needed * This is created by zlib's configure script to define off_t #include "zlibdefs.h" */ #ifndef SEEK_SET # define SEEK_SET 0 /* Seek from beginning of file. */ # define SEEK_CUR 1 /* Seek from current position. */ # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ #endif #ifndef z_off_t # define z_off_t long #endif #if defined(__OS400__) # define NO_vsnprintf #endif #if defined(__MVS__) # define NO_vsnprintf #endif /* MVS linker does not support external names larger than 8 bytes */ #if defined(__MVS__) # pragma map(deflateInit_,"DEIN") # pragma map(deflateInit2_,"DEIN2") # pragma map(deflateEnd,"DEEND") # pragma map(deflateBound,"DEBND") # pragma map(inflateInit_,"ININ") # pragma map(inflateInit2_,"ININ2") # pragma map(inflateEnd,"INEND") # pragma map(inflateSync,"INSY") # pragma map(inflateSetDictionary,"INSEDI") # pragma map(compressBound,"CMBND") # pragma map(inflate_table,"INTABL") # pragma map(inflate_fast,"INFA") # pragma map(inflate_copyright,"INCOPY") #endif #ifdef WINDOWS #define NO_FSEEKO 1 #define NO_vsnprintf 1 #endif #endif /* ZCONF_H */ ================================================ FILE: unity_decoder/libil2cpp/external/zlib/zlib.h ================================================ /* zlib.h -- interface of the 'zlib' general purpose compression library version 1.2.3.3, October 2nd, 2006 Copyright (C) 1995-2006 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). */ #ifndef ZLIB_H #define ZLIB_H #include "zconf.h" #ifdef __cplusplus extern "C" { #endif #define ZLIB_VERSION "1.2.3.3" #define ZLIB_VERNUM 0x1233 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 #define ZLIB_VER_REVISION 3 /* The 'zlib' compression library provides in-memory compression and decompression functions, including integrity checks of the uncompressed data. This version of the library supports only one compression method (deflation) but other algorithms will be added later and will have the same stream interface. Compression can be done in a single step if the buffers are large enough (for example if an input file is mmap'ed), or can be done by repeated calls of the compression function. In the latter case, the application must provide more input and/or consume the output (providing more output space) before each call. The compressed data format used by default by the in-memory functions is the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped around a deflate stream, which is itself documented in RFC 1951. The library also supports reading and writing files in gzip (.gz) format with an interface similar to that of stdio using the functions that start with "gz". The gzip format is different from the zlib format. gzip is a gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. This library can optionally read and write gzip streams in memory as well. The zlib format was designed to be compact and fast for use in memory and on communications channels. The gzip format was designed for single- file compression on file systems, has a larger header than zlib to maintain directory information, and uses a different, slower check method than zlib. The library does not install any signal handler. The decoder checks the consistency of the compressed data, so the library should never crash even in case of corrupted input. */ typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); typedef void (*free_func) OF((voidpf opaque, voidpf address)); struct internal_state; typedef struct z_stream_s { Bytef *next_in; /* next input byte */ uInt avail_in; /* number of bytes available at next_in */ uLong total_in; /* total nb of input bytes read so far */ Bytef *next_out; /* next output byte should be put there */ uInt avail_out; /* remaining free space at next_out */ uLong total_out; /* total nb of bytes output so far */ char *msg; /* last error message, NULL if no error */ struct internal_state FAR *state; /* not visible by applications */ alloc_func zalloc; /* used to allocate the internal state */ free_func zfree; /* used to free the internal state */ voidpf opaque; /* private data object passed to zalloc and zfree */ int data_type; /* best guess about the data type: binary or text */ uLong adler; /* adler32 value of the uncompressed data */ uLong reserved; /* reserved for future use */ } z_stream; typedef z_stream FAR *z_streamp; /* gzip header information passed to and from zlib routines. See RFC 1952 for more details on the meanings of these fields. */ typedef struct gz_header_s { int text; /* true if compressed data believed to be text */ uLong time; /* modification time */ int xflags; /* extra flags (not used when writing a gzip file) */ int os; /* operating system */ Bytef *extra; /* pointer to extra field or Z_NULL if none */ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ uInt extra_max; /* space at extra (only when reading header) */ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ uInt name_max; /* space at name (only when reading header) */ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ uInt comm_max; /* space at comment (only when reading header) */ int hcrc; /* true if there was or will be a header crc */ int done; /* true when done reading gzip header (not used when writing a gzip file) */ } gz_header; typedef gz_header FAR *gz_headerp; /* The application must update next_in and avail_in when avail_in has dropped to zero. It must update next_out and avail_out when avail_out has dropped to zero. The application must initialize zalloc, zfree and opaque before calling the init function. All other fields are set by the compression library and must not be updated by the application. The opaque value provided by the application will be passed as the first parameter for calls of zalloc and zfree. This can be useful for custom memory management. The compression library attaches no meaning to the opaque value. zalloc must return Z_NULL if there is not enough memory for the object. If zlib is used in a multi-threaded application, zalloc and zfree must be thread safe. On 16-bit systems, the functions zalloc and zfree must be able to allocate exactly 65536 bytes, but will not be required to allocate more than this if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers returned by zalloc for objects of exactly 65536 bytes *must* have their offset normalized to zero. The default allocation function provided by this library ensures this (see zutil.c). To reduce memory requirements and avoid any allocation of 64K objects, at the expense of compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). The fields total_in and total_out can be used for statistics or progress reports. After compression, total_in holds the total size of the uncompressed data and may be saved for use in the decompressor (particularly if the decompressor wants to decompress everything in a single step). */ /* constants */ #define Z_NO_FLUSH 0 #define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ #define Z_SYNC_FLUSH 2 #define Z_FULL_FLUSH 3 #define Z_FINISH 4 #define Z_BLOCK 5 /* Allowed flush values; see deflate() and inflate() below for details */ #define Z_OK 0 #define Z_STREAM_END 1 #define Z_NEED_DICT 2 #define Z_ERRNO (-1) #define Z_STREAM_ERROR (-2) #define Z_DATA_ERROR (-3) #define Z_MEM_ERROR (-4) #define Z_BUF_ERROR (-5) #define Z_VERSION_ERROR (-6) /* Return codes for the compression/decompression functions. Negative * values are errors, positive values are used for special but normal events. */ #define Z_NO_COMPRESSION 0 #define Z_BEST_SPEED 1 #define Z_BEST_COMPRESSION 9 #define Z_DEFAULT_COMPRESSION (-1) /* compression levels */ #define Z_FILTERED 1 #define Z_HUFFMAN_ONLY 2 #define Z_RLE 3 #define Z_FIXED 4 #define Z_DEFAULT_STRATEGY 0 /* compression strategy; see deflateInit2() below for details */ #define Z_BINARY 0 #define Z_TEXT 1 #define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ #define Z_UNKNOWN 2 /* Possible values of the data_type field (though see inflate()) */ #define Z_DEFLATED 8 /* The deflate compression method (the only one supported in this version) */ #define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ #define zlib_version zlibVersion() /* for compatibility with versions < 1.0.2 */ /* basic functions */ ZEXTERN const char * ZEXPORT zlibVersion OF((void)); /* The application can compare zlibVersion and ZLIB_VERSION for consistency. If the first character differs, the library code actually used is not compatible with the zlib.h header file used by the application. This check is automatically made by deflateInit and inflateInit. */ /* ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); Initializes the internal stream state for compression. The fields zalloc, zfree and opaque must be initialized before by the caller. If zalloc and zfree are set to Z_NULL, deflateInit updates them to use default allocation functions. The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression at all (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION requests a default compromise between speed and compression (currently equivalent to level 6). deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if level is not a valid compression level, Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible with the version assumed by the caller (ZLIB_VERSION). msg is set to null if there is no error message. deflateInit does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); /* deflate compresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush. The detailed semantics are as follows. deflate performs one or both of the following actions: - Compress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), next_in and avail_in are updated and processing will resume at this point for the next call of deflate(). - Provide more output starting at next_out and update next_out and avail_out accordingly. This action is forced if the parameter flush is non zero. Forcing flush frequently degrades the compression ratio, so this parameter should be set only when necessary (in interactive applications). Some output may be provided even if flush is not set. Before the call of deflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating avail_in or avail_out accordingly; avail_out should never be zero before the call. The application can consume the compressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to decide how much data to accumualte before producing output, in order to maximize compression. If the parameter flush is set to Z_SYNC_FLUSH, all pending output is flushed to the output buffer and the output is aligned on a byte boundary, so that the decompressor can get all input data available so far. (In particular avail_in is zero after the call if enough output space has been provided before the call.) Flushing may degrade compression for some compression algorithms and so it should be used only when necessary. If flush is set to Z_FULL_FLUSH, all output is flushed as with Z_SYNC_FLUSH, and the compression state is reset so that decompression can restart from this point if previous compressed data has been damaged or if random access is desired. Using Z_FULL_FLUSH too often can seriously degrade compression. If deflate returns with avail_out == 0, this function must be called again with the same value of the flush parameter and more output space (updated avail_out), until the flush is complete (deflate returns with non-zero avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that avail_out is greater than six to avoid repeated flush markers due to avail_out == 0 on return. If the parameter flush is set to Z_FINISH, pending input is processed, pending output is flushed and deflate returns with Z_STREAM_END if there was enough output space; if deflate returns with Z_OK, this function must be called again with Z_FINISH and more output space (updated avail_out) but no more input data, until it returns with Z_STREAM_END or an error. After deflate has returned Z_STREAM_END, the only possible operations on the stream are deflateReset or deflateEnd. Z_FINISH can be used immediately after deflateInit if all the compression is to be done in a single step. In this case, avail_out must be at least the value returned by deflateBound (see below). If deflate does not return Z_STREAM_END, then it must be called again as described above. deflate() sets strm->adler to the adler32 checksum of all input read so far (that is, total_in bytes). deflate() may update strm->data_type if it can make a good guess about the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered binary. This field is only for information purposes and does not affect the compression algorithm in any manner. deflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if all input has been consumed and all output has been produced (only when flush is set to Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and deflate() can be called again with more input and more output space to continue compressing. */ ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state was inconsistent, Z_DATA_ERROR if the stream was freed prematurely (some input or output was discarded). In the error case, msg may be set but then points to a static string (which must not be deallocated). */ /* ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); Initializes the internal stream state for decompression. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. If next_in is not Z_NULL and avail_in is large enough (the exact value depends on the compression method), inflateInit determines the compression method from the zlib header and allocates all data structures accordingly; otherwise the allocation will be deferred to the first call of inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to use default allocation functions. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if there is no error message. inflateInit does not perform any decompression apart from possibly reading the zlib header if present: actual decompression will be done by inflate(). (So next_in and avail_in may be modified, but next_out and avail_out are unused and unchanged.) The current implementation of inflateInit() does not process any header information -- that is deferred until inflate() is called. */ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); /* inflate decompresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush. The detailed semantics are as follows. inflate performs one or both of the following actions: - Decompress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), next_in is updated and processing will resume at this point for the next call of inflate(). - Provide more output starting at next_out and update next_out and avail_out accordingly. inflate() provides as much output as possible, until there is no more input data or no more space in the output buffer (see below about the flush parameter). Before the call of inflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating the next_* and avail_* values accordingly. The application can consume the uncompressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of inflate(). If inflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much output as possible to the output buffer. Z_BLOCK requests that inflate() stop if and when it gets to the next deflate block boundary. When decoding the zlib or gzip format, this will cause inflate() to return immediately after the header and before the first block. When doing a raw inflate, inflate() will go ahead and process the first block, and will return when it gets to the end of that block, or when it runs out of data. The Z_BLOCK option assists in appending to or combining deflate streams. Also to assist in this, on return inflate() will set strm->data_type to the number of unused bits in the last byte taken from strm->next_in, plus 64 if inflate() is currently decoding the last block in the deflate stream, plus 128 if inflate() returned immediately after decoding an end-of-block code or decoding the complete header up to just before the first byte of the deflate stream. The end-of-block will not be indicated until all of the uncompressed data from that block has been written to strm->next_out. The number of unused bits may in general be greater than seven, except when bit 7 of data_type is set, in which case the number of unused bits will be less than eight. inflate() should normally be called until it returns Z_STREAM_END or an error. However if all decompression is to be performed in a single step (a single call of inflate), the parameter flush should be set to Z_FINISH. In this case all pending input is processed and all pending output is flushed; avail_out must be large enough to hold all the uncompressed data. (The size of the uncompressed data may have been saved by the compressor for this purpose.) The next operation on this stream must be inflateEnd to deallocate the decompression state. The use of Z_FINISH is never required, but can be used to inform inflate that a faster approach may be used for the single inflate() call. In this implementation, inflate() always flushes as much output as possible to the output buffer, and always uses the faster approach on the first call. So the only effect of the flush parameter in this implementation is on the return value of inflate(), as noted below, or when it returns early because Z_BLOCK is used. If a preset dictionary is needed after this call (see inflateSetDictionary below), inflate sets strm->adler to the adler32 checksum of the dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise it sets strm->adler to the adler32 checksum of all output produced so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described below. At the end of the stream, inflate() checks that its computed adler32 checksum is equal to that saved by the compressor and returns Z_STREAM_END only if the checksum is correct. inflate() will decompress and check either zlib-wrapped or gzip-wrapped deflate data. The header type is detected automatically. Any information contained in the gzip header is not retained, so applications that need that information should instead use raw inflate, see inflateInit2() below, or inflateBack() and perform their own processing of the gzip header and trailer. inflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if the end of the compressed data has been reached and all uncompressed output has been produced, Z_NEED_DICT if a preset dictionary is needed at this point, Z_DATA_ERROR if the input data was corrupted (input stream not conforming to the zlib format or incorrect check value), Z_STREAM_ERROR if the stream structure was inconsistent (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no progress is possible or if there was not enough room in the output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and inflate() can be called again with more input and more output space to continue decompressing. If Z_DATA_ERROR is returned, the application may then call inflateSync() to look for a good compression block if a partial recovery of the data is desired. */ ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state was inconsistent. In the error case, msg may be set but then points to a static string (which must not be deallocated). */ /* Advanced functions */ /* The following functions are needed only in some special applications. */ /* ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy)); This is another version of deflateInit with more compression options. The fields next_in, zalloc, zfree and opaque must be initialized before by the caller. The method parameter is the compression method. It must be Z_DEFLATED in this version of the library. The windowBits parameter is the base two logarithm of the window size (the size of the history buffer). It should be in the range 8..15 for this version of the library. Larger values of this parameter result in better compression at the expense of memory usage. The default value is 15 if deflateInit is used instead. windowBits can also be -8..-15 for raw deflate. In this case, -windowBits determines the window size. deflate() will then generate raw deflate data with no zlib header or trailer, and will not compute an adler32 check value. windowBits can also be greater than 15 for optional gzip encoding. Add 16 to windowBits to write a simple gzip header and trailer around the compressed data instead of a zlib wrapper. The gzip header will have no file name, no extra data, no comment, no modification time (set to zero), no header crc, and the operating system will be set to 255 (unknown). If a gzip stream is being written, strm->adler is a crc32 instead of an adler32. The memLevel parameter specifies how much memory should be allocated for the internal compression state. memLevel=1 uses minimum memory but is slow and reduces compression ratio; memLevel=9 uses maximum memory for optimal speed. The default value is 8. See zconf.h for total memory usage as a function of windowBits and memLevel. The strategy parameter is used to tune the compression algorithm. Use the value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no string match), or Z_RLE to limit match distances to one (run-length encoding). Filtered data consists mostly of small values with a somewhat random distribution. In this case, the compression algorithm is tuned to compress them better. The effect of Z_FILTERED is to force more Huffman coding and less string matching; it is somewhat intermediate between Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy parameter only affects the compression ratio but not the correctness of the compressed output even if it is not set appropriately. Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler decoder for special applications. deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid method). msg is set to null if there is no error message. deflateInit2 does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, const Bytef *dictionary, uInt dictLength)); /* Initializes the compression dictionary from the given byte sequence without producing any compressed output. This function must be called immediately after deflateInit, deflateInit2 or deflateReset, before any call of deflate. The compressor and decompressor must use exactly the same dictionary (see inflateSetDictionary). The dictionary should consist of strings (byte sequences) that are likely to be encountered later in the data to be compressed, with the most commonly used strings preferably put towards the end of the dictionary. Using a dictionary is most useful when the data to be compressed is short and can be predicted with good accuracy; the data can then be compressed better than with the default empty dictionary. Depending on the size of the compression data structures selected by deflateInit or deflateInit2, a part of the dictionary may in effect be discarded, for example if the dictionary is larger than the window size in deflate or deflate2. Thus the strings most likely to be useful should be put at the end of the dictionary, not at the front. In addition, the current implementation of deflate will use at most the window size minus 262 bytes of the provided dictionary. Upon return of this function, strm->adler is set to the adler32 value of the dictionary; the decompressor may later use this value to determine which dictionary has been used by the compressor. (The adler32 value applies to the whole dictionary even if only a subset of the dictionary is actually used by the compressor.) If a raw deflate was requested, then the adler32 value is not computed and strm->adler is not set. deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a parameter is invalid (such as NULL dictionary) or the stream state is inconsistent (for example if deflate has already been called for this stream or if the compression method is bsort). deflateSetDictionary does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, z_streamp source)); /* Sets the destination stream as a complete copy of the source stream. This function can be useful when several compression strategies will be tried, for example when there are several ways of pre-processing the input data with a filter. The streams that will be discarded should then be freed by calling deflateEnd. Note that deflateCopy duplicates the internal compression state which can be quite large, so this strategy is slow and can consume lots of memory. deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc being NULL). msg is left unchanged in both source and destination. */ ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); /* This function is equivalent to deflateEnd followed by deflateInit, but does not free and reallocate all the internal compression state. The stream will keep the same compression level and any other attributes that may have been set by deflateInit2. deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being NULL). */ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, int level, int strategy)); /* Dynamically update the compression level and compression strategy. The interpretation of level and strategy is as in deflateInit2. This can be used to switch between compression and straight copy of the input data, or to switch to a different kind of input data requiring a different strategy. If the compression level is changed, the input available so far is compressed with the old level (and may be flushed); the new level will take effect only at the next call of deflate(). Before the call of deflateParams, the stream state must be set as for a call of deflate(), since the currently available input may have to be compressed and flushed. In particular, strm->avail_out must be non-zero. deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if strm->avail_out was zero. */ ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, int good_length, int max_lazy, int nice_length, int max_chain)); /* Fine tune deflate's internal compression parameters. This should only be used by someone who understands the algorithm used by zlib's deflate for searching for the best matching string, and even then only by the most fanatic optimizer trying to squeeze out the last compressed bit for their specific input data. Read the deflate.c source code for the meaning of the max_lazy, good_length, nice_length, and max_chain parameters. deflateTune() can be called after deflateInit() or deflateInit2(), and returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. */ ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, uLong sourceLen)); /* deflateBound() returns an upper bound on the compressed size after deflation of sourceLen bytes. It must be called after deflateInit() or deflateInit2(), and after deflateSetHeader(), if used. This would be used to allocate an output buffer for deflation in a single pass, and so would be called before deflate(). */ ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, int bits, int value)); /* deflatePrime() inserts bits in the deflate output stream. The intent is that this function is used to start off the deflate output with the bits leftover from a previous deflate stream when appending to it. As such, this function can only be used for raw deflate, and must be used before the first deflate() call after a deflateInit2() or deflateReset(). bits must be less than or equal to 16, and that many of the least significant bits of value will be inserted in the output. deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, gz_headerp head)); /* deflateSetHeader() provides gzip header information for when a gzip stream is requested by deflateInit2(). deflateSetHeader() may be called after deflateInit2() or deflateReset() and before the first call of deflate(). The text, time, os, extra field, name, and comment information in the provided gz_header structure are written to the gzip header (xflag is ignored -- the extra flags are set according to the compression level). The caller must assure that, if not Z_NULL, name and comment are terminated with a zero byte, and that if extra is not Z_NULL, that extra_len bytes are available there. If hcrc is true, a gzip header crc is included. Note that the current versions of the command-line version of gzip (up through version 1.3.x) do not support header crc's, and will report that it is a "multi-part gzip file" and give up. If deflateSetHeader is not used, the default gzip header has text false, the time set to zero, and os set to 255, with no extra, name, or comment fields. The gzip header is returned to the default state by deflateReset(). deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ /* ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, int windowBits)); This is another version of inflateInit with an extra parameter. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. The windowBits parameter is the base two logarithm of the maximum window size (the size of the history buffer). It should be in the range 8..15 for this version of the library. The default value is 15 if inflateInit is used instead. windowBits must be greater than or equal to the windowBits value provided to deflateInit2() while compressing, or it must be equal to 15 if deflateInit2() was not used. If a compressed stream with a larger window size is given as input, inflate() will return with the error code Z_DATA_ERROR instead of trying to allocate a larger window. windowBits can also be -8..-15 for raw inflate. In this case, -windowBits determines the window size. inflate() will then process raw deflate data, not looking for a zlib or gzip header, not generating a check value, and not looking for any check values for comparison at the end of the stream. This is for use with other formats that use the deflate compressed data format such as zip. Those formats provide their own check values. If a custom format is developed using the raw deflate format for compressed data, it is recommended that a check value such as an adler32 or a crc32 be applied to the uncompressed data as is done in the zlib, gzip, and zip formats. For most applications, the zlib format should be used as is. Note that comments above on the use in deflateInit2() applies to the magnitude of windowBits. windowBits can also be greater than 15 for optional gzip decoding. Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection, or add 16 to decode only the gzip format (the zlib format will return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a crc32 instead of an adler32. inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if there is no error message. inflateInit2 does not perform any decompression apart from possibly reading the zlib header if present: actual decompression will be done by inflate(). (So next_in and avail_in may be modified, but next_out and avail_out are unused and unchanged.) The current implementation of inflateInit2() does not process any header information -- that is deferred until inflate() is called. */ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, const Bytef *dictionary, uInt dictLength)); /* Initializes the decompression dictionary from the given uncompressed byte sequence. This function must be called immediately after a call of inflate, if that call returned Z_NEED_DICT. The dictionary chosen by the compressor can be determined from the adler32 value returned by that call of inflate. The compressor and decompressor must use exactly the same dictionary (see deflateSetDictionary). For raw inflate, this function can be called immediately after inflateInit2() or inflateReset() and before any call of inflate() to set the dictionary. The application must insure that the dictionary that was used for compression is provided. inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a parameter is invalid (such as NULL dictionary) or the stream state is inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the expected one (incorrect adler32 value). inflateSetDictionary does not perform any decompression: this will be done by subsequent calls of inflate(). */ ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); /* Skips invalid compressed data until a full flush point (see above the description of deflate with Z_FULL_FLUSH) can be found, or until all available input is skipped. No output is provided. inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the success case, the application may save the current current value of total_in which indicates where valid compressed data was found. In the error case, the application may repeatedly call inflateSync, providing more input each time, until success or end of the input data. */ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, z_streamp source)); /* Sets the destination stream as a complete copy of the source stream. This function can be useful when randomly accessing a large stream. The first pass through the stream can periodically record the inflate state, allowing restarting inflate at those points when randomly accessing the stream. inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc being NULL). msg is left unchanged in both source and destination. */ ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); /* This function is equivalent to inflateEnd followed by inflateInit, but does not free and reallocate all the internal decompression state. The stream will keep attributes that may have been set by inflateInit2. inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being NULL). */ ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, int bits, int value)); /* This function inserts bits in the inflate input stream. The intent is that this function is used to start inflating at a bit position in the middle of a byte. The provided bits will be used before any bytes are used from next_in. This function should only be used with raw inflate, and should be used before the first inflate() call after inflateInit2() or inflateReset(). bits must be less than or equal to 16, and that many of the least significant bits of value will be inserted in the input. inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, gz_headerp head)); /* inflateGetHeader() requests that gzip header information be stored in the provided gz_header structure. inflateGetHeader() may be called after inflateInit2() or inflateReset(), and before the first call of inflate(). As inflate() processes the gzip stream, head->done is zero until the header is completed, at which time head->done is set to one. If a zlib stream is being decoded, then head->done is set to -1 to indicate that there will be no gzip header information forthcoming. Note that Z_BLOCK can be used to force inflate() to return immediately after header processing is complete and before any actual data is decompressed. The text, time, xflags, and os fields are filled in with the gzip header contents. hcrc is set to true if there is a header CRC. (The header CRC was valid if done is set to one.) If extra is not Z_NULL, then extra_max contains the maximum number of bytes to write to extra. Once done is true, extra_len contains the actual extra field length, and extra contains the extra field, or that field truncated if extra_max is less than extra_len. If name is not Z_NULL, then up to name_max characters are written there, terminated with a zero unless the length is greater than name_max. If comment is not Z_NULL, then up to comm_max characters are written there, terminated with a zero unless the length is greater than comm_max. When any of extra, name, or comment are not Z_NULL and the respective field is not present in the header, then that field is set to Z_NULL to signal its absence. This allows the use of deflateSetHeader() with the returned structure to duplicate the header. However if those fields are set to allocated memory, then the application will need to save those pointers elsewhere so that they can be eventually freed. If inflateGetHeader is not used, then the header information is simply discarded. The header is always checked for validity, including the header CRC if present. inflateReset() will reset the process to discard the header information. The application would need to call inflateGetHeader() again to retrieve the header from the next gzip stream. inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ /* ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, unsigned char FAR *window)); Initialize the internal stream state for decompression using inflateBack() calls. The fields zalloc, zfree and opaque in strm must be initialized before the call. If zalloc and zfree are Z_NULL, then the default library- derived memory allocation routines are used. windowBits is the base two logarithm of the window size, in the range 8..15. window is a caller supplied buffer of that size. Except for special applications where it is assured that deflate was used with small window sizes, windowBits must be 15 and a 32K byte window must be supplied to be able to decompress general deflate streams. See inflateBack() for the usage of these routines. inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of the paramaters are invalid, Z_MEM_ERROR if the internal state could not be allocated, or Z_VERSION_ERROR if the version of the library does not match the version of the header file. */ typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, in_func in, void FAR *in_desc, out_func out, void FAR *out_desc)); /* inflateBack() does a raw inflate with a single call using a call-back interface for input and output. This is more efficient than inflate() for file i/o applications in that it avoids copying between the output and the sliding window by simply making the window itself the output buffer. This function trusts the application to not change the output buffer passed by the output function, at least until inflateBack() returns. inflateBackInit() must be called first to allocate the internal state and to initialize the state with the user-provided window buffer. inflateBack() may then be used multiple times to inflate a complete, raw deflate stream with each call. inflateBackEnd() is then called to free the allocated state. A raw deflate stream is one with no zlib or gzip header or trailer. This routine would normally be used in a utility that reads zip or gzip files and writes out uncompressed files. The utility would decode the header and process the trailer on its own, hence this routine expects only the raw deflate stream to decompress. This is different from the normal behavior of inflate(), which expects either a zlib or gzip header and trailer around the deflate stream. inflateBack() uses two subroutines supplied by the caller that are then called by inflateBack() for input and output. inflateBack() calls those routines until it reads a complete deflate stream and writes out all of the uncompressed data, or until it encounters an error. The function's parameters and return types are defined above in the in_func and out_func typedefs. inflateBack() will call in(in_desc, &buf) which should return the number of bytes of provided input, and a pointer to that input in buf. If there is no input available, in() must return zero--buf is ignored in that case--and inflateBack() will return a buffer error. inflateBack() will call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() should return zero on success, or non-zero on failure. If out() returns non-zero, inflateBack() will return with an error. Neither in() nor out() are permitted to change the contents of the window provided to inflateBackInit(), which is also the buffer that out() uses to write from. The length written by out() will be at most the window size. Any non-zero amount of input may be provided by in(). For convenience, inflateBack() can be provided input on the first call by setting strm->next_in and strm->avail_in. If that input is exhausted, then in() will be called. Therefore strm->next_in must be initialized before calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in must also be initialized, and then if strm->avail_in is not zero, input will initially be taken from strm->next_in[0 .. strm->avail_in - 1]. The in_desc and out_desc parameters of inflateBack() is passed as the first parameter of in() and out() respectively when they are called. These descriptors can be optionally used to pass any information that the caller- supplied in() and out() functions need to do their job. On return, inflateBack() will set strm->next_in and strm->avail_in to pass back any unused input that was provided by the last in() call. The return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR if in() or out() returned an error, Z_DATA_ERROR if there was a format error in the deflate stream (in which case strm->msg is set to indicate the nature of the error), or Z_STREAM_ERROR if the stream was not properly initialized. In the case of Z_BUF_ERROR, an input or output error can be distinguished using strm->next_in which will be Z_NULL only if in() returned an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to out() returning non-zero. (in() will always be called before out(), so strm->next_in is assured to be defined if out() returns non-zero.) Note that inflateBack() cannot return Z_OK. */ ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); /* All memory allocated by inflateBackInit() is freed. inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream state was inconsistent. */ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); /* Return flags indicating compile-time options. Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: 1.0: size of uInt 3.2: size of uLong 5.4: size of voidpf (pointer) 7.6: size of z_off_t Compiler, assembler, and debug options: 8: DEBUG 9: ASMV or ASMINF -- use ASM code 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention 11: 0 (reserved) One-time table building (smaller code, but not thread-safe if true): 12: BUILDFIXED -- build static block decoding tables when needed 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed 14,15: 0 (reserved) Library content (indicates missing functionality): 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking deflate code when not needed) 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect and decode gzip streams (to avoid linking crc code) 18-19: 0 (reserved) Operation variations (changes in library functionality): 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate 21: FASTEST -- deflate algorithm with only one, lowest compression level 22,23: 0 (reserved) The sprintf variant used by gzprintf (zero is best): 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! 26: 0 = returns value, 1 = void -- 1 means inferred string length returned Remainder: 27-31: 0 (reserved) */ /* utility functions */ /* The following utility functions are implemented on top of the basic stream-oriented functions. To simplify the interface, some default options are assumed (compression level and memory usage, standard memory allocation functions). The source code of these utility functions can easily be modified if you need special options. */ ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)); /* Compresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the compressed buffer. This function can be used to compress a whole file at once if the input file is mmap'ed. compress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer. */ ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level)); /* Compresses the source buffer into the destination buffer. The level parameter has the same meaning as in deflateInit. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the compressed buffer. compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); /* compressBound() returns an upper bound on the compressed size after compress() or compress2() on sourceLen bytes. It would be used before a compress() or compress2() call to allocate the destination buffer. */ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)); /* Decompresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be large enough to hold the entire uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and transmitted to the decompressor by some mechanism outside the scope of this compression library.) Upon exit, destLen is the actual size of the compressed buffer. This function can be used to decompress a whole file at once if the input file is mmap'ed. uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. */ typedef voidp gzFile; /* ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); Opens a gzip (.gz) file for reading or writing. The mode parameter is as in fopen ("rb" or "wb") but can also include a compression level ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman only compression as in "wb1h", or 'R' for run-length encoding as in "wb1R". (See the description of deflateInit2 for more information about the strategy parameter.) gzopen can be used to read a file which is not in gzip format; in this case gzread will directly read from the file without decompression. gzopen returns NULL if the file could not be opened or if there was insufficient memory to allocate the (de)compression state; errno can be checked to distinguish the two cases (if errno is zero, the zlib error is Z_MEM_ERROR). */ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); /* gzdopen() associates a gzFile with the file descriptor fd. File descriptors are obtained from calls like open, dup, creat, pipe or fileno (in the file has been previously opened with fopen). The mode parameter is as in gzopen. The next call of gzclose on the returned gzFile will also close the file descriptor fd, just like fclose(fdopen(fd), mode) closes the file descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). gzdopen returns NULL if there was insufficient memory to allocate the (de)compression state. */ ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); /* Dynamically update the compression level or strategy. See the description of deflateInit2 for the meaning of these parameters. gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not opened for writing. */ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); /* Reads the given number of uncompressed bytes from the compressed file. If the input file was not in gzip format, gzread copies the given number of bytes into the buffer. gzread returns the number of uncompressed bytes actually read (0 for end of file, -1 for error). */ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len)); /* Writes the given number of uncompressed bytes into the compressed file. gzwrite returns the number of uncompressed bytes actually written (0 in case of error). */ ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); /* Converts, formats, and writes the args to the compressed file under control of the format string, as in fprintf. gzprintf returns the number of uncompressed bytes actually written (0 in case of error). The number of uncompressed bytes written is limited to 4095. The caller should assure that this limit is not exceeded. If it is exceeded, then gzprintf() will return return an error (0) with nothing written. In this case, there may also be a buffer overflow with unpredictable consequences, which is possible only if zlib was compiled with the insecure functions sprintf() or vsprintf() because the secure snprintf() or vsnprintf() functions were not available. */ ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); /* Writes the given null-terminated string to the compressed file, excluding the terminating null character. gzputs returns the number of characters written, or -1 in case of error. */ ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); /* Reads bytes from the compressed file until len-1 characters are read, or a newline character is read and transferred to buf, or an end-of-file condition is encountered. The string is then terminated with a null character. gzgets returns buf, or Z_NULL in case of error. */ ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); /* Writes c, converted to an unsigned char, into the compressed file. gzputc returns the value that was written, or -1 in case of error. */ ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); /* Reads one byte from the compressed file. gzgetc returns this byte or -1 in case of end of file or error. */ ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); /* Push one character back onto the stream to be read again later. Only one character of push-back is allowed. gzungetc() returns the character pushed, or -1 on failure. gzungetc() will fail if a character has been pushed but not read yet, or if c is -1. The pushed character will be discarded if the stream is repositioned with gzseek() or gzrewind(). */ ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); /* Flushes all pending output into the compressed file. The parameter flush is as in the deflate() function. The return value is the zlib error number (see function gzerror below). gzflush returns Z_OK if the flush parameter is Z_FINISH and all output could be flushed. gzflush should be called only when strictly necessary because it can degrade compression. */ /* ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, z_off_t offset, int whence)); Sets the starting position for the next gzread or gzwrite on the given compressed file. The offset represents a number of bytes in the uncompressed data stream. The whence parameter is defined as in lseek(2); the value SEEK_END is not supported. If the file is opened for reading, this function is emulated but can be extremely slow. If the file is opened for writing, only forward seeks are supported; gzseek then compresses a sequence of zeroes up to the new starting position. gzseek returns the resulting offset location as measured in bytes from the beginning of the uncompressed stream, or -1 in case of error, in particular if the file is opened for writing and the new starting position would be before the current position. */ ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); /* Rewinds the given file. This function is supported only for reading. gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) */ /* ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); Returns the starting position for the next gzread or gzwrite on the given compressed file. This position represents a number of bytes in the uncompressed data stream. gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) */ ZEXTERN int ZEXPORT gzeof OF((gzFile file)); /* Returns 1 when EOF has previously been detected reading the given input stream, otherwise zero. */ ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); /* Returns 1 if file is being read directly without decompression, otherwise zero. */ ZEXTERN int ZEXPORT gzclose OF((gzFile file)); /* Flushes all pending output if necessary, closes the compressed file and deallocates all the (de)compression state. The return value is the zlib error number. Note that once file is close, you cannot call gzerror with file, since its structures have been deallocated. */ ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); /* Returns the error message for the last error which occurred on the given compressed file. errnum is set to zlib error number. If an error occurred in the file system and not in the compression library, errnum is set to Z_ERRNO and the application may consult errno to get the exact error code. The application must not modify the returned string and future calls to this function may invalidate the returned string. */ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); /* Clears the error and end-of-file flags for file. This is analogous to the clearerr() function in stdio. This is useful for continuing to read a gzip file that is being written concurrently. */ /* checksum functions */ /* These functions are not related to compression but are exported anyway because they might be useful in applications using the compression library. */ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); /* Update a running Adler-32 checksum with the bytes buf[0..len-1] and return the updated checksum. If buf is NULL, this function returns the required initial value for the checksum. An Adler-32 checksum is almost as reliable as a CRC32 but can be computed much faster. Usage example: uLong adler = adler32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { adler = adler32(adler, buffer, length); } if (adler != original_adler) error(); */ /* ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, z_off_t len2)); Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. */ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); /* Update a running CRC-32 with the bytes buf[0..len-1] and return the updated CRC-32. If buf is NULL, this function returns the required initial value for the for the crc. Pre- and post-conditioning (one's complement) is performed within this function so it shouldn't be done by the application. Usage example: uLong crc = crc32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { crc = crc32(crc, buffer, length); } if (crc != original_crc) error(); */ /* ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); Combine two CRC-32 check values into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, CRC-32 check values were calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and len2. */ /* various hacks, don't look :) */ /* deflateInit and inflateInit are macros to allow checking the zlib version * and the compiler's view of z_stream: */ ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, const char *version, int stream_size)); ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, const char *version, int stream_size)); ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy, const char *version, int stream_size)); ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, const char *version, int stream_size)); ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, unsigned char FAR *window, const char *version, int stream_size)); #define deflateInit(strm, level) \ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) #define inflateInit(strm) \ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) #define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ (strategy), ZLIB_VERSION, sizeof(z_stream)) #define inflateInit2(strm, windowBits) \ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) #define inflateBackInit(strm, windowBits, window) \ inflateBackInit_((strm), (windowBits), (window), \ ZLIB_VERSION, sizeof(z_stream)) #ifdef _LARGEFILE64_SOURCE ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); ZEXTERN off64_t ZEXPORT gzseek64 OF((gzFile, off64_t, int)); ZEXTERN off64_t ZEXPORT gztell64 OF((gzFile)); ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, off64_t)); ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, off64_t)); #endif /* Mono: disable this. We don't use it and makes compilation fail #if _FILE_OFFSET_BITS == 64 # define gzopen gzopen64 # define gzseek gzseek64 # define gztell gztell64 # define adler32_combine adler32_combine64 # define crc32_combine crc32_combine64 #else */ ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); /*#endif*/ #if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) struct internal_state {int dummy;}; /* hack for buggy compilers */ #endif ZEXTERN const char * ZEXPORT zError OF((int)); ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); #ifdef __cplusplus } #endif #endif /* ZLIB_H */ ================================================ FILE: unity_decoder/libil2cpp/external/zlib/zutil.c ================================================ /* zutil.c -- target dependent utility functions for the compression library * Copyright (C) 1995-2005 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #include "zutil.h" #ifndef NO_DUMMY_DECL struct internal_state {int dummy;}; /* for buggy compilers */ #endif const char * const z_errmsg[10] = { "need dictionary", /* Z_NEED_DICT 2 */ "stream end", /* Z_STREAM_END 1 */ "", /* Z_OK 0 */ "file error", /* Z_ERRNO (-1) */ "stream error", /* Z_STREAM_ERROR (-2) */ "data error", /* Z_DATA_ERROR (-3) */ "insufficient memory", /* Z_MEM_ERROR (-4) */ "buffer error", /* Z_BUF_ERROR (-5) */ "incompatible version",/* Z_VERSION_ERROR (-6) */ ""}; const char * ZEXPORT zlibVersion() { return ZLIB_VERSION; } uLong ZEXPORT zlibCompileFlags() { uLong flags; flags = 0; switch (sizeof(uInt)) { case 2: break; case 4: flags += 1; break; case 8: flags += 2; break; default: flags += 3; } switch (sizeof(uLong)) { case 2: break; case 4: flags += 1 << 2; break; case 8: flags += 2 << 2; break; default: flags += 3 << 2; } switch (sizeof(voidpf)) { case 2: break; case 4: flags += 1 << 4; break; case 8: flags += 2 << 4; break; default: flags += 3 << 4; } switch (sizeof(z_off_t)) { case 2: break; case 4: flags += 1 << 6; break; case 8: flags += 2 << 6; break; default: flags += 3 << 6; } #ifdef DEBUG flags += 1 << 8; #endif #if defined(ASMV) || defined(ASMINF) flags += 1 << 9; #endif #ifdef ZLIB_WINAPI flags += 1 << 10; #endif #ifdef BUILDFIXED flags += 1 << 12; #endif #ifdef DYNAMIC_CRC_TABLE flags += 1 << 13; #endif #ifdef NO_GZCOMPRESS flags += 1L << 16; #endif #ifdef NO_GZIP flags += 1L << 17; #endif #ifdef PKZIP_BUG_WORKAROUND flags += 1L << 20; #endif #ifdef FASTEST flags += 1L << 21; #endif #ifdef STDC # ifdef NO_vsnprintf flags += 1L << 25; # ifdef HAS_vsprintf_void flags += 1L << 26; # endif # else # ifdef HAS_vsnprintf_void flags += 1L << 26; # endif # endif #else flags += 1L << 24; # ifdef NO_snprintf flags += 1L << 25; # ifdef HAS_sprintf_void flags += 1L << 26; # endif # else # ifdef HAS_snprintf_void flags += 1L << 26; # endif # endif #endif return flags; } #ifdef DEBUG # ifndef verbose # define verbose 0 # endif int z_verbose = verbose; void z_error (m) char *m; { fprintf(stderr, "%s\n", m); exit(1); } #endif /* exported to allow conversion of error code to string for compress() and * uncompress() */ const char * ZEXPORT zError(err) int err; { return ERR_MSG(err); } #if defined(_WIN32_WCE) /* The Microsoft C Run-Time Library for Windows CE doesn't have * errno. We define it as a global variable to simplify porting. * Its value is always 0 and should not be used. */ int errno = 0; #endif #ifndef HAVE_MEMCPY void zmemcpy(dest, source, len) Bytef* dest; const Bytef* source; uInt len; { if (len == 0) return; do { *dest++ = *source++; /* ??? to be unrolled */ } while (--len != 0); } int zmemcmp(s1, s2, len) const Bytef* s1; const Bytef* s2; uInt len; { uInt j; for (j = 0; j < len; j++) { if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; } return 0; } void zmemzero(dest, len) Bytef* dest; uInt len; { if (len == 0) return; do { *dest++ = 0; /* ??? to be unrolled */ } while (--len != 0); } #endif #ifdef SYS16BIT #ifdef __TURBOC__ /* Turbo C in 16-bit mode */ # define MY_ZCALLOC /* Turbo C malloc() does not allow dynamic allocation of 64K bytes * and farmalloc(64K) returns a pointer with an offset of 8, so we * must fix the pointer. Warning: the pointer must be put back to its * original form in order to free it, use zcfree(). */ #define MAX_PTR 10 /* 10*64K = 640K */ local int next_ptr = 0; typedef struct ptr_table_s { voidpf org_ptr; voidpf new_ptr; } ptr_table; local ptr_table table[MAX_PTR]; /* This table is used to remember the original form of pointers * to large buffers (64K). Such pointers are normalized with a zero offset. * Since MSDOS is not a preemptive multitasking OS, this table is not * protected from concurrent access. This hack doesn't work anyway on * a protected system like OS/2. Use Microsoft C instead. */ voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) { voidpf buf = opaque; /* just to make some compilers happy */ ulg bsize = (ulg)items*size; /* If we allocate less than 65520 bytes, we assume that farmalloc * will return a usable pointer which doesn't have to be normalized. */ if (bsize < 65520L) { buf = farmalloc(bsize); if (*(ush*)&buf != 0) return buf; } else { buf = farmalloc(bsize + 16L); } if (buf == NULL || next_ptr >= MAX_PTR) return NULL; table[next_ptr].org_ptr = buf; /* Normalize the pointer to seg:0 */ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; *(ush*)&buf = 0; table[next_ptr++].new_ptr = buf; return buf; } void zcfree (voidpf opaque, voidpf ptr) { int n; if (*(ush*)&ptr != 0) { /* object < 64K */ farfree(ptr); return; } /* Find the original pointer */ for (n = 0; n < next_ptr; n++) { if (ptr != table[n].new_ptr) continue; farfree(table[n].org_ptr); while (++n < next_ptr) { table[n-1] = table[n]; } next_ptr--; return; } ptr = opaque; /* just to make some compilers happy */ Assert(0, "zcfree: ptr not found"); } #endif /* __TURBOC__ */ #ifdef M_I86 /* Microsoft C in 16-bit mode */ # define MY_ZCALLOC #if (!defined(_MSC_VER) || (_MSC_VER <= 600)) # define _halloc halloc # define _hfree hfree #endif voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) { if (opaque) opaque = 0; /* to make compiler happy */ return _halloc((long)items, size); } void zcfree (voidpf opaque, voidpf ptr) { if (opaque) opaque = 0; /* to make compiler happy */ _hfree(ptr); } #endif /* M_I86 */ #endif /* SYS16BIT */ #ifndef MY_ZCALLOC /* Any system without a special alloc function */ #ifndef STDC extern voidp malloc OF((uInt size)); extern voidp calloc OF((uInt items, uInt size)); extern void free OF((voidpf ptr)); #endif voidpf zcalloc (opaque, items, size) voidpf opaque; unsigned items; unsigned size; { if (opaque) items += size - size; /* make compiler happy */ return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : (voidpf)calloc(items, size); } void zcfree (opaque, ptr) voidpf opaque; voidpf ptr; { free(ptr); if (opaque) return; /* make compiler happy */ } #endif /* MY_ZCALLOC */ ================================================ FILE: unity_decoder/libil2cpp/external/zlib/zutil.h ================================================ /* zutil.h -- internal interface and configuration of the compression library * Copyright (C) 1995-2006 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* @(#) $Id$ */ #ifndef ZUTIL_H #define ZUTIL_H #define ZLIB_INTERNAL #include "zlib.h" #ifdef STDC # ifndef _WIN32_WCE # include # endif # include # include #endif #if defined(NO_ERRNO_H) || defined(_WIN32_WCE) # ifdef _WIN32_WCE /* The Microsoft C Run-Time Library for Windows CE doesn't have * errno. We define it as a global variable to simplify porting. * Its value is always 0 and should not be used. We rename it to * avoid conflict with other libraries that use the same workaround. */ # define errno z_errno # endif extern int errno; #else # include #endif #ifndef local # define local static #endif /* compile with -Dlocal if your debugger can't find static symbols */ typedef unsigned char uch; typedef uch FAR uchf; typedef unsigned short ush; typedef ush FAR ushf; typedef unsigned long ulg; extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ /* (size given to avoid silly warnings with Visual C++) */ #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] #define ERR_RETURN(strm,err) \ return (strm->msg = (char*)ERR_MSG(err), (err)) /* To be used only when the state is known to be valid */ /* common constants */ #ifndef DEF_WBITS # define DEF_WBITS MAX_WBITS #endif /* default windowBits for decompression. MAX_WBITS is for compression only */ #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 #else # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif /* default memLevel */ #define STORED_BLOCK 0 #define STATIC_TREES 1 #define DYN_TREES 2 /* The three kinds of block type */ #define MIN_MATCH 3 #define MAX_MATCH 258 /* The minimum and maximum match lengths */ #define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ /* target dependencies */ #if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) # define OS_CODE 0x00 # if defined(__TURBOC__) || defined(__BORLANDC__) # if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) /* Allow compilation with ANSI keywords only enabled */ void _Cdecl farfree( void *block ); void *_Cdecl farmalloc( unsigned long nbytes ); # else # include # endif # else /* MSC or DJGPP */ # include # endif #endif #ifdef AMIGA # define OS_CODE 0x01 #endif #if defined(VAXC) || defined(VMS) # define OS_CODE 0x02 # define F_OPEN(name, mode) \ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") #endif #if defined(ATARI) || defined(atarist) # define OS_CODE 0x05 #endif #ifdef OS2 # define OS_CODE 0x06 # ifdef M_I86 #include # endif #endif #if defined(MACOS) || defined(TARGET_OS_MAC) # define OS_CODE 0x07 # if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os # include /* for fdopen */ # else # ifndef fdopen # define fdopen(fd,mode) NULL /* No fdopen() */ # endif # endif #endif #ifdef TOPS20 # define OS_CODE 0x0a #endif #ifdef WIN32 # ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ # define OS_CODE 0x0b # endif #endif #ifdef __50SERIES /* Prime/PRIMOS */ # define OS_CODE 0x0f #endif #if defined(_BEOS_) || defined(RISCOS) # define fdopen(fd,mode) NULL /* No fdopen() */ #endif #if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX # if defined(_WIN32_WCE) # define fdopen(fd,mode) NULL /* No fdopen() */ # ifndef _PTRDIFF_T_DEFINED typedef int ptrdiff_t; # define _PTRDIFF_T_DEFINED # endif # else # define fdopen(fd,type) _fdopen(fd,type) # endif #endif #if defined(__BORLANDC__) #pragma warn -8004 #pragma warn -8008 #pragma warn -8066 #endif /* common defaults */ #ifndef OS_CODE # define OS_CODE 0x03 /* assume Unix */ #endif #ifndef F_OPEN # define F_OPEN(name, mode) fopen((name), (mode)) #endif #ifdef _LARGEFILE64_SOURCE # define F_OPEN64(name, mode) fopen64((name), (mode)) #else # define F_OPEN64(name, mode) fopen((name), (mode)) #endif /* functions */ #if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) # ifndef HAVE_VSNPRINTF # define HAVE_VSNPRINTF # endif #endif #if defined (_MSC_VER) && (_MSC_VER > 1800) # define HAVE_VSNPRINTF #endif #if defined(__CYGWIN__) # ifndef HAVE_VSNPRINTF # define HAVE_VSNPRINTF # endif #endif #ifndef HAVE_VSNPRINTF # ifdef MSDOS /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), but for now we just assume it doesn't. */ # define NO_vsnprintf # endif # ifdef __TURBOC__ # define NO_vsnprintf # endif # ifdef WIN32 /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ # if !defined(vsnprintf) && !defined(NO_vsnprintf) # define vsnprintf _vsnprintf # endif # endif # ifdef __SASC # define NO_vsnprintf # endif #endif #ifdef VMS # define NO_vsnprintf #endif #if defined(pyr) # define NO_MEMCPY #endif #if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) /* Use our own functions for small and medium model with MSC <= 5.0. * You may have to use the same strategy for Borland C (untested). * The __SC__ check is for Symantec. */ # define NO_MEMCPY #endif #if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) # define HAVE_MEMCPY #endif #ifdef HAVE_MEMCPY # ifdef SMALL_MEDIUM /* MSDOS small or medium model */ # define zmemcpy _fmemcpy # define zmemcmp _fmemcmp # define zmemzero(dest, len) _fmemset(dest, 0, len) # else # define zmemcpy memcpy # define zmemcmp memcmp # define zmemzero(dest, len) memset(dest, 0, len) # endif #else extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); extern void zmemzero OF((Bytef* dest, uInt len)); #endif #if Z_PREFIX # define z_verbose il2cpp_z__verbose # define z_error il2cpp_z__error #endif /* Diagnostic functions */ #ifdef DEBUG # include extern int z_verbose; extern void z_error OF((char *m)); # define Assert(cond,msg) {if(!(cond)) z_error(msg);} # define Trace(x) {if (z_verbose>=0) fprintf x ;} # define Tracev(x) {if (z_verbose>0) fprintf x ;} # define Tracevv(x) {if (z_verbose>1) fprintf x ;} # define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} # define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} #else # define Assert(cond,msg) # define Trace(x) # define Tracev(x) # define Tracevv(x) # define Tracec(c,x) # define Tracecv(c,x) #endif voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); void zcfree OF((voidpf opaque, voidpf ptr)); #define ZALLOC(strm, items, size) \ (*((strm)->zalloc))((strm)->opaque, (items), (size)) #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} #endif /* ZUTIL_H */ ================================================ FILE: unity_decoder/libil2cpp/externals/MonoPosixHelper.cpp ================================================ #include "MonoPosixHelper.h" #include #include #include "external/zlib/zlib.h" #define BUFFER_SIZE 4096 #define ARGUMENT_ERROR -10 #define IO_ERROR -11 #if NET_4_0 typedef int32_t (*read_write_func)(intptr_t buffer, int32_t length, intptr_t gchandle); #else typedef int32_t (STDCALL * read_write_func)(intptr_t buffer, int32_t length, intptr_t gchandle); #endif struct ZStream { z_stream *stream; uint8_t *buffer; read_write_func func; void *gchandle; uint8_t compress; uint8_t eof; }; static int32_t write_to_managed(ZStream *stream) { int32_t n; z_stream *zs; zs = stream->stream; if (zs->avail_out != BUFFER_SIZE) { intptr_t buffer_ptr = reinterpret_cast(stream->buffer); intptr_t gchandle_ptr = reinterpret_cast(stream->gchandle); n = stream->func(buffer_ptr, BUFFER_SIZE - zs->avail_out, gchandle_ptr); zs->next_out = stream->buffer; zs->avail_out = BUFFER_SIZE; if (n < 0) return IO_ERROR; } return 0; } static int32_t flush_internal(ZStream *stream, bool is_final) { int32_t status; if (!stream->compress) return 0; if (!is_final) { status = deflate(stream->stream, Z_PARTIAL_FLUSH); if (status != Z_OK && status != Z_STREAM_END) return status; } return write_to_managed(stream); } static void *z_alloc(void *opaque, uint32_t nitems, uint32_t item_size) { return calloc(nitems, item_size); } static void z_free(void *opaque, void *ptr) { free(ptr); } intptr_t CreateZStream(int32_t compress, uint8_t gzip, Il2CppMethodPointer func_ptr, intptr_t gchandle) { z_stream *z; int32_t retval; ZStream *result; intptr_t result_ptr = 0; read_write_func func = (read_write_func)func_ptr; if (func == NULL) return result_ptr; #if !defined(ZLIB_VERNUM) || (ZLIB_VERNUM < 0x1204) // Older versions of zlib do not support raw deflate or gzip return NULL; #endif z = (z_stream*)calloc(1, sizeof(z_stream)); if (compress) { retval = deflateInit2(z, Z_DEFAULT_COMPRESSION, Z_DEFLATED, gzip ? 31 : -15, 8, Z_DEFAULT_STRATEGY); } else { retval = inflateInit2(z, gzip ? 31 : -15); } if (retval != Z_OK) { free(z); return result_ptr; } z->zalloc = z_alloc; z->zfree = z_free; result = (ZStream*)calloc(1, sizeof(ZStream)); result->stream = z; result->func = func; result->gchandle = reinterpret_cast(gchandle); result->compress = compress; result->buffer = (uint8_t*)malloc(BUFFER_SIZE * sizeof(uint8_t)); result_ptr = reinterpret_cast(result); return result_ptr; } int32_t CloseZStream(intptr_t zstream) { int32_t status; int32_t flush_status; ZStream *stream = reinterpret_cast(zstream); if (stream == NULL) return ARGUMENT_ERROR; status = 0; if (stream->compress) { if (stream->stream->total_in > 0) { do { status = deflate(stream->stream, Z_FINISH); flush_status = flush_internal(stream, true); } while (status == Z_OK); /* We want Z_STREAM_END or error here here */ if (status == Z_STREAM_END) status = flush_status; } deflateEnd(stream->stream); } else { inflateEnd(stream->stream); } free(stream->buffer); free(stream->stream); memset(stream, 0, sizeof(ZStream)); free(stream); return status; } int32_t Flush(intptr_t zstream) { ZStream *stream = (ZStream*)zstream; return flush_internal(stream, false); } int32_t ReadZStream(intptr_t zstream, intptr_t zbuffer, int32_t length) { int32_t n; int32_t status; z_stream *zs; ZStream *stream = (ZStream*)zstream; uint8_t *buffer = (uint8_t*)zbuffer; if (stream == NULL || buffer == NULL || length < 0) return ARGUMENT_ERROR; if (stream->eof) return 0; zs = stream->stream; zs->next_out = buffer; zs->avail_out = length; while (zs->avail_out > 0) { if (zs->avail_in == 0) { intptr_t buffer_ptr = reinterpret_cast(stream->buffer); intptr_t gchandle_ptr = reinterpret_cast(stream->gchandle); n = stream->func(buffer_ptr, BUFFER_SIZE, gchandle_ptr); if (n <= 0) { stream->eof = 1; break; } zs->next_in = stream->buffer; zs->avail_in = n; } status = inflate(stream->stream, Z_SYNC_FLUSH); if (status == Z_STREAM_END) { stream->eof = 1; break; } else if (status != Z_OK) { return status; } } return length - zs->avail_out; } int32_t WriteZStream(intptr_t zstream, intptr_t zbuffer, int32_t length) { int32_t n; int32_t status; z_stream *zs; ZStream *stream = (ZStream*)zstream; uint8_t *buffer = (uint8_t*)zbuffer; if (stream == NULL || buffer == NULL || length < 0) return ARGUMENT_ERROR; if (stream->eof) return IO_ERROR; zs = stream->stream; zs->next_in = buffer; zs->avail_in = length; while (zs->avail_in > 0) { if (zs->avail_out == 0) { zs->next_out = stream->buffer; zs->avail_out = BUFFER_SIZE; } status = deflate(stream->stream, Z_NO_FLUSH); if (status != Z_OK && status != Z_STREAM_END) return status; if (zs->avail_out == 0) { n = write_to_managed(stream); if (n < 0) return n; } } return length; } ================================================ FILE: unity_decoder/libil2cpp/externals/MonoPosixHelper.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" extern "C" { struct ZStream; IL2CPP_EXPORT intptr_t CreateZStream(int32_t compress, uint8_t gzip, Il2CppMethodPointer func, intptr_t gchandle); IL2CPP_EXPORT int32_t CloseZStream(intptr_t zstream); IL2CPP_EXPORT int32_t Flush(intptr_t zstream); IL2CPP_EXPORT int32_t ReadZStream(intptr_t zstream, intptr_t buffer, int32_t length); IL2CPP_EXPORT int32_t WriteZStream(intptr_t zstream, intptr_t buffer, int32_t length); } ================================================ FILE: unity_decoder/libil2cpp/gc/Allocator.h ================================================ #pragma once #include "GarbageCollector.h" namespace il2cpp { namespace gc { template class Allocator { public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T* pointer; typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; typedef T value_type; typedef Allocator allocator_type; Allocator() {} Allocator(const Allocator&) {} pointer allocate(size_type n, const void * = 0) { T* t = (T*)GarbageCollector::AllocateFixed(n * sizeof(T), 0); return t; } void deallocate(void* p, size_type) { if (p) { GarbageCollector::FreeFixed(p); } } pointer address(reference x) const { return &x; } const_pointer address(const_reference x) const { return &x; } Allocator& operator=(const Allocator&) { return *this; } void construct(pointer p, const T& val) { new((T*)p)T(val); } void destroy(pointer p) { p->~T(); } size_type max_size() const { return size_t(-1); } template struct rebind { typedef Allocator other; }; template Allocator(const Allocator&) {} template Allocator& operator=(const Allocator&) { return *this; } }; } } ================================================ FILE: unity_decoder/libil2cpp/gc/AppendOnlyGCHashMap.h ================================================ #pragma once #include "utils/Il2CppHashMap.h" #include "utils/NonCopyable.h" #include "GarbageCollector.h" namespace il2cpp { namespace gc { template > class AppendOnlyGCHashMap : public il2cpp::utils::NonCopyable { typedef Il2CppHashMap hash_map_type; typedef typename Il2CppHashMap::const_iterator ConstIterator; public: typedef typename hash_map_type::key_type key_type; typedef T data_type; typedef typename hash_map_type::size_type size_type; typedef typename hash_map_type::hasher hasher; typedef typename hash_map_type::key_equal key_equal; AppendOnlyGCHashMap() : m_Data(NULL), m_Size(0) { } ~AppendOnlyGCHashMap() { if (m_Data) il2cpp::gc::GarbageCollector::FreeFixed(m_Data); } bool Contains(const Key& k) { return m_Map.find(k) != m_Map.end(); } // Returns true if value was added. False if it already existed bool Add(const Key& k, T value) { if (m_Map.find(k) != m_Map.end()) return false; if (m_Size == 0) { m_Size = 8; m_Data = (T*)il2cpp::gc::GarbageCollector::AllocateFixed(m_Size * sizeof(T), NULL); assert(m_Data); } else if (m_Map.size() == m_Size) { size_t newSize = 2 * m_Size; T* newData = (T*)il2cpp::gc::GarbageCollector::AllocateFixed(newSize * sizeof(T), NULL); MemCpyData memCpyData = { newData, m_Data, m_Size * sizeof(T) }; // perform memcpy with GC lock held so GC doesn't see torn pointer values.I think this is less of an issue with Boehm than other GCs, but being safe. il2cpp::gc::GarbageCollector::CallWithAllocLockHeld(&CopyValues, &memCpyData); il2cpp::gc::GarbageCollector::FreeFixed(m_Data); m_Size = newSize; m_Data = newData; assert(m_Data); } size_t index = m_Map.size(); m_Map.insert(std::make_pair(k, index)); m_Data[index] = value; assert(m_Map.size() <= m_Size); return true; } bool TryGetValue(const Key& k, T* value) { ConstIterator iter = m_Map.find(k); if (iter == m_Map.end()) return false; size_t index = iter->second; assert(index <= m_Map.size()); *value = m_Data[index]; return true; } private: struct MemCpyData { void* dst; const void* src; size_t size; }; static void* CopyValues(void* arg) { MemCpyData* thisPtr = (MemCpyData*)arg; memcpy(thisPtr->dst, thisPtr->src, thisPtr->size); return NULL; } Il2CppHashMap m_Map; T* m_Data; size_t m_Size; }; } } ================================================ FILE: unity_decoder/libil2cpp/gc/BoehmGC.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_GC_BOEHM #include #include "gc_wrapper.h" #include "GarbageCollector.h" #include "vm/Profiler.h" static bool s_GCInitialized = false; #if IL2CPP_ENABLE_DEFERRED_GC static bool s_PendingGC = false; #endif #if IL2CPP_ENABLE_PROFILER using il2cpp::vm::Profiler; static void on_gc_event(GCEventType eventType); static void on_heap_resize(GC_word newSize); #endif void il2cpp::gc::GarbageCollector::Initialize() { if (s_GCInitialized) return; // This tells the GC that we are not scanning dynamic library data segments and that // the GC tracked data structures need ot be manually pushed and marked. // Call this before GC_INIT since the initialization logic uses this value. GC_set_no_dls(1); #if IL2CPP_ENABLE_PROFILER GC_set_on_event(&on_gc_event); GC_set_on_heap_resize(&on_heap_resize); #endif GC_INIT(); #if defined(GC_THREADS) GC_set_finalize_on_demand(1); GC_set_finalizer_notifier(&il2cpp::gc::GarbageCollector::NotifyFinalizers); // We need to call this if we want to manually register threads, i.e. GC_register_my_thread GC_allow_register_threads(); #endif #ifdef GC_GCJ_SUPPORT GC_init_gcj_malloc(0, NULL); #endif s_GCInitialized = true; } void il2cpp::gc::GarbageCollector::UninitializeGC() { GC_deinit(); } int32_t il2cpp::gc::GarbageCollector::GetCollectionCount(int32_t generation) { return (int32_t)GC_get_gc_no(); } int32_t il2cpp::gc::GarbageCollector::GetMaxGeneration() { return 0; } void il2cpp::gc::GarbageCollector::Collect(int maxGeneration) { #if IL2CPP_ENABLE_DEFERRED_GC if (GC_is_disabled()) s_PendingGC = true; #endif GC_gcollect(); } int32_t il2cpp::gc::GarbageCollector::CollectALittle() { #if IL2CPP_ENABLE_DEFERRED_GC if (s_PendingGC) { s_PendingGC = false; GC_gcollect(); return 0; // no more work to do } else { return GC_collect_a_little(); } #else return GC_collect_a_little(); #endif } int64_t il2cpp::gc::GarbageCollector::GetUsedHeapSize(void) { return GC_get_heap_size() - GC_get_free_bytes(); } int64_t il2cpp::gc::GarbageCollector::GetAllocatedHeapSize(void) { return GC_get_heap_size(); } void il2cpp::gc::GarbageCollector::Disable() { GC_disable(); } void il2cpp::gc::GarbageCollector::Enable() { GC_enable(); } bool il2cpp::gc::GarbageCollector::RegisterThread(void *baseptr) { #if defined(GC_THREADS) struct GC_stack_base sb; int res; res = GC_get_stack_base(&sb); if (res != GC_SUCCESS) { sb.mem_base = baseptr; #ifdef __ia64__ /* Can't determine the register stack bounds */ IL2CPP_ASSERT(false && "mono_gc_register_thread failed ()."); #endif } res = GC_register_my_thread(&sb); if ((res != GC_SUCCESS) && (res != GC_DUPLICATE)) { IL2CPP_ASSERT(false && "GC_register_my_thread () failed."); return false; } #endif return true; } bool il2cpp::gc::GarbageCollector::UnregisterThread() { #if defined(GC_THREADS) int res; res = GC_unregister_my_thread(); if (res != GC_SUCCESS) IL2CPP_ASSERT(false && "GC_unregister_my_thread () failed."); return res == GC_SUCCESS; #else return true; #endif } il2cpp::gc::GarbageCollector::FinalizerCallback il2cpp::gc::GarbageCollector::RegisterFinalizerWithCallback(Il2CppObject* obj, FinalizerCallback callback) { FinalizerCallback oldCallback; void* oldData; GC_REGISTER_FINALIZER_NO_ORDER((char*)obj, callback, NULL, &oldCallback, &oldData); IL2CPP_ASSERT(oldData == NULL); return oldCallback; } void il2cpp::gc::GarbageCollector::AddWeakLink(void **link_addr, Il2CppObject *obj, bool track) { /* libgc requires that we use HIDE_POINTER... */ *link_addr = (void*)GC_HIDE_POINTER(obj); // need this since our strings are not real objects if (GC_is_heap_ptr(obj)) GC_GENERAL_REGISTER_DISAPPEARING_LINK(link_addr, obj); } void il2cpp::gc::GarbageCollector::RemoveWeakLink(void **link_addr) { Il2CppObject* obj = GarbageCollector::GetWeakLink(link_addr); if (GC_is_heap_ptr(obj)) GC_unregister_disappearing_link(link_addr); *link_addr = NULL; } static void* RevealLink(void* link_addr) { void **link_a = (void**)link_addr; return GC_REVEAL_POINTER(*link_a); } Il2CppObject* il2cpp::gc::GarbageCollector::GetWeakLink(void **link_addr) { Il2CppObject *obj = (Il2CppObject*)GC_call_with_alloc_lock(RevealLink, link_addr); if (obj == (Il2CppObject*)-1) return NULL; return obj; } void* il2cpp::gc::GarbageCollector::MakeDescriptorForObject(size_t *bitmap, int numbits) { #ifdef GC_GCJ_SUPPORT /* It seems there are issues when the bitmap doesn't fit: play it safe */ if (numbits >= 30) return GC_NO_DESCRIPTOR; else return (void*)GC_make_descriptor((GC_bitmap)bitmap, numbits); #else return 0; #endif } void* il2cpp::gc::GarbageCollector::MakeDescriptorForString() { return GC_NO_DESCRIPTOR; } void* il2cpp::gc::GarbageCollector::MakeDescriptorForArray() { return GC_NO_DESCRIPTOR; } void il2cpp::gc::GarbageCollector::StopWorld() { GC_stop_world_external(); } void il2cpp::gc::GarbageCollector::StartWorld() { GC_start_world_external(); } void* il2cpp::gc::GarbageCollector::AllocateFixed(size_t size, void *descr) { // Note that we changed the implementation from mono. // In our case, we expect that // a) This memory will never be moved // b) This memory will be scanned for references // c) This memory will remain 'alive' until explicitly freed // GC_MALLOC_UNCOLLECTABLE fulfills all these requirements // It does not accept a descriptor, but there was only one // or two places in mono that pass a descriptor to this routine // and we can or will support those use cases in a different manner. IL2CPP_ASSERT(!descr); return GC_MALLOC_UNCOLLECTABLE(size); } void il2cpp::gc::GarbageCollector::FreeFixed(void* addr) { GC_FREE(addr); } int32_t il2cpp::gc::GarbageCollector::InvokeFinalizers() { return (int32_t)GC_invoke_finalizers(); } bool il2cpp::gc::GarbageCollector::HasPendingFinalizers() { return GC_should_invoke_finalizers() != 0; } #if IL2CPP_ENABLE_PROFILER void on_gc_event(GCEventType eventType) { Profiler::GCEvent((Il2CppGCEvent)eventType); } void on_heap_resize(GC_word newSize) { Profiler::GCHeapResize((int64_t)newSize); } #endif // IL2CPP_ENABLE_PROFILER void il2cpp::gc::GarbageCollector::ForEachHeapSection(void* user_data, HeapSectionCallback callback) { GC_foreach_heap_section(user_data, callback); } size_t il2cpp::gc::GarbageCollector::GetSectionCount() { return GC_get_heap_section_count(); } void* il2cpp::gc::GarbageCollector::CallWithAllocLockHeld(GCCallWithAllocLockCallback callback, void* user_data) { return GC_call_with_alloc_lock(callback, user_data); } #endif ================================================ FILE: unity_decoder/libil2cpp/gc/GCHandle.cpp ================================================ #include "il2cpp-config.h" #include "gc/GCHandle.h" #include "object-internals.h" #include "GarbageCollector.h" #include "os/Mutex.h" #include "utils/Memory.h" #include namespace il2cpp { namespace gc { typedef struct { uint32_t *bitmap; void* *entries; uint32_t size; uint8_t type; uint32_t slot_hint : 24;/* starting slot for search */ /* 2^16 appdomains should be enough for everyone (though I know I'll regret this in 20 years) */ /* we alloc this only for weak refs, since we can get the domain directly in the other cases */ uint16_t *domain_ids; } HandleData; /* weak and weak-track arrays will be allocated in malloc memory */ static HandleData gc_handles[] = { {NULL, NULL, 0, HANDLE_WEAK, 0}, {NULL, NULL, 0, HANDLE_WEAK_TRACK, 0}, {NULL, NULL, 0, HANDLE_NORMAL, 0}, {NULL, NULL, 0, HANDLE_PINNED, 0} }; static int find_first_unset(uint32_t bitmap) { int i; for (i = 0; i < 32; ++i) { if (!(bitmap & (1 << i))) return i; } return -1; } static os::FastMutex g_HandlesMutex; #define lock_handles(handles) g_HandlesMutex.Lock () #define unlock_handles(handles) g_HandlesMutex.Unlock () static uint32_t alloc_handle(HandleData *handles, Il2CppObject *obj, bool track) { uint32_t slot; int i; lock_handles(handles); if (!handles->size) { handles->size = 32; if (handles->type > HANDLE_WEAK_TRACK) { handles->entries = (void**)GarbageCollector::AllocateFixed(sizeof(void*) * handles->size, NULL); } else { handles->entries = (void**)IL2CPP_MALLOC_ZERO(sizeof(void*) * handles->size); handles->domain_ids = (uint16_t*)IL2CPP_MALLOC_ZERO(sizeof(uint16_t) * handles->size); } handles->bitmap = (uint32_t*)IL2CPP_MALLOC_ZERO(handles->size / 8); } i = -1; for (slot = handles->slot_hint; slot < handles->size / 32; ++slot) { if (handles->bitmap[slot] != 0xffffffff) { i = find_first_unset(handles->bitmap[slot]); handles->slot_hint = slot; break; } } if (i == -1 && handles->slot_hint != 0) { for (slot = 0; slot < handles->slot_hint; ++slot) { if (handles->bitmap[slot] != 0xffffffff) { i = find_first_unset(handles->bitmap[slot]); handles->slot_hint = slot; break; } } } if (i == -1) { uint32_t *new_bitmap; uint32_t new_size = handles->size * 2; /* always double: we memset to 0 based on this below */ /* resize and copy the bitmap */ new_bitmap = (uint32_t*)IL2CPP_MALLOC_ZERO(new_size / 8); memcpy(new_bitmap, handles->bitmap, handles->size / 8); IL2CPP_FREE(handles->bitmap); handles->bitmap = new_bitmap; /* resize and copy the entries */ if (handles->type > HANDLE_WEAK_TRACK) { void* *entries; entries = (void**)GarbageCollector::AllocateFixed(sizeof(void*) * new_size, NULL); memcpy(entries, handles->entries, sizeof(void*) * handles->size); void** previous_entries = handles->entries; handles->entries = entries; GarbageCollector::FreeFixed(previous_entries); } else { void* *entries; uint16_t *domain_ids; domain_ids = (uint16_t*)IL2CPP_MALLOC_ZERO(sizeof(uint16_t) * new_size); entries = (void**)IL2CPP_MALLOC(sizeof(void*) * new_size); /* we disable GC because we could lose some disappearing link updates */ GarbageCollector::Disable(); memcpy(entries, handles->entries, sizeof(void*) * handles->size); memset(entries + handles->size, 0, sizeof(void*) * handles->size); memcpy(domain_ids, handles->domain_ids, sizeof(uint16_t) * handles->size); for (i = 0; i < (int32_t)handles->size; ++i) { Il2CppObject *obj = GarbageCollector::GetWeakLink(&(handles->entries[i])); if (handles->entries[i]) GarbageCollector::RemoveWeakLink(&(handles->entries[i])); /*g_print ("reg/unreg entry %d of type %d at %p to object %p (%p), was: %p\n", i, handles->type, &(entries [i]), obj, entries [i], handles->entries [i]);*/ if (obj) { GarbageCollector::AddWeakLink(&(entries[i]), obj, track); } } IL2CPP_FREE(handles->entries); IL2CPP_FREE(handles->domain_ids); handles->entries = entries; handles->domain_ids = domain_ids; GarbageCollector::Enable(); } /* set i and slot to the next free position */ i = 0; slot = (handles->size + 1) / 32; handles->slot_hint = handles->size + 1; handles->size = new_size; } handles->bitmap[slot] |= 1 << i; slot = slot * 32 + i; handles->entries[slot] = obj; if (handles->type <= HANDLE_WEAK_TRACK) { if (obj) GarbageCollector::AddWeakLink(&(handles->entries[slot]), obj, track); } //mono_perfcounters->gc_num_handles++; unlock_handles(handles); /*g_print ("allocated entry %d of type %d to object %p (in slot: %p)\n", slot, handles->type, obj, handles->entries [slot]);*/ return (slot << 3) | (handles->type + 1); } uint32_t GCHandle::New(Il2CppObject *obj, bool pinned) { return alloc_handle(&gc_handles[pinned ? HANDLE_PINNED : HANDLE_NORMAL], obj, false); } uint32_t GCHandle::NewWeakref(Il2CppObject *obj, bool track_resurrection) { uint32_t handle = alloc_handle(&gc_handles[track_resurrection ? HANDLE_WEAK_TRACK : HANDLE_WEAK], obj, track_resurrection); #ifndef HAVE_SGEN_GC if (track_resurrection) NOT_IMPLEMENTED(GCHandle::NewWeakref); #endif return handle; } GCHandleType GCHandle::GetHandleType(uint32_t gchandle) { return static_cast((gchandle & 7) - 1); } static inline uint32_t GetHandleSlot(uint32_t gchandle) { return gchandle >> 3; } Il2CppObject* GCHandle::GetTarget(uint32_t gchandle) { uint32_t slot = GetHandleSlot(gchandle); uint32_t type = GetHandleType(gchandle); HandleData *handles = &gc_handles[type]; Il2CppObject *obj = NULL; if (type > 3) return NULL; lock_handles(handles); if (slot < handles->size && (handles->bitmap[slot / 32] & (1 << (slot % 32)))) { if (handles->type <= HANDLE_WEAK_TRACK) { obj = GarbageCollector::GetWeakLink(&handles->entries[slot]); } else { obj = (Il2CppObject*)handles->entries[slot]; } } else { /* print a warning? */ } unlock_handles(handles); /*g_print ("get target of entry %d of type %d: %p\n", slot, handles->type, obj);*/ return obj; } static void il2cpp_gchandle_set_target(uint32_t gchandle, Il2CppObject *obj) { uint32_t slot = GetHandleSlot(gchandle); uint32_t type = GCHandle::GetHandleType(gchandle); HandleData *handles = &gc_handles[type]; Il2CppObject *old_obj = NULL; if (type > 3) return; lock_handles(handles); if (slot < handles->size && (handles->bitmap[slot / 32] & (1 << (slot % 32)))) { if (handles->type <= HANDLE_WEAK_TRACK) { old_obj = (Il2CppObject*)handles->entries[slot]; if (handles->entries[slot]) GarbageCollector::RemoveWeakLink(&handles->entries[slot]); if (obj) GarbageCollector::AddWeakLink(&handles->entries[slot], obj, handles->type == HANDLE_WEAK_TRACK); } else { handles->entries[slot] = obj; } } else { /* print a warning? */ } unlock_handles(handles); #ifndef HAVE_SGEN_GC if (type == HANDLE_WEAK_TRACK) NOT_IMPLEMENTED(il2cpp_gchandle_set_target); #endif } void GCHandle::Free(uint32_t gchandle) { uint32_t slot = GetHandleSlot(gchandle); uint32_t type = GetHandleType(gchandle); HandleData *handles = &gc_handles[type]; if (type > 3) return; #ifndef HAVE_SGEN_GC if (type == HANDLE_WEAK_TRACK) NOT_IMPLEMENTED(GCHandle::Free); #endif lock_handles(handles); if (slot < handles->size && (handles->bitmap[slot / 32] & (1 << (slot % 32)))) { if (handles->type <= HANDLE_WEAK_TRACK) { if (handles->entries[slot]) GarbageCollector::RemoveWeakLink(&handles->entries[slot]); } else { handles->entries[slot] = NULL; } handles->bitmap[slot / 32] &= ~(1 << (slot % 32)); } else { /* print a warning? */ } //mono_perfcounters->gc_num_handles--; /*g_print ("freed entry %d of type %d\n", slot, handles->type);*/ unlock_handles(handles); } int32_t GCHandle::GetTargetHandle(Il2CppObject * obj, int32_t handle, int32_t type) { if (type == -1) { il2cpp_gchandle_set_target(handle, obj); /* the handle doesn't change */ return handle; } switch (type) { case HANDLE_WEAK: return NewWeakref(obj, false); case HANDLE_WEAK_TRACK: return NewWeakref(obj, true); case HANDLE_NORMAL: return New(obj, false); case HANDLE_PINNED: return New(obj, true); default: IL2CPP_ASSERT(0); } return 0; } void GCHandle::WalkStrongGCHandleTargets(WalkGCHandleTargetsCallback callback, void* context) { lock_handles(handles); const GCHandleType types[] = { HANDLE_NORMAL, HANDLE_PINNED }; for (int gcHandleTypeIndex = 0; gcHandleTypeIndex < 2; gcHandleTypeIndex++) { const HandleData& handles = gc_handles[types[gcHandleTypeIndex]]; for (uint32_t i = 0; i < handles.size; i++) { if (handles.entries[i] != NULL) callback(static_cast(handles.entries[i]), context); } } unlock_handles(handles); } } /* gc */ } /* il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/gc/GCHandle.h ================================================ #pragma once #include struct Il2CppObject; namespace il2cpp { namespace gc { enum GCHandleType { HANDLE_WEAK, HANDLE_WEAK_TRACK, HANDLE_NORMAL, HANDLE_PINNED }; class LIBIL2CPP_CODEGEN_API GCHandle { public: // external static uint32_t New(Il2CppObject *obj, bool pinned); static uint32_t NewWeakref(Il2CppObject *obj, bool track_resurrection); static Il2CppObject* GetTarget(uint32_t gchandle); static GCHandleType GetHandleType(uint32_t gcHandle); static void Free(uint32_t gchandle); public: //internal static int32_t GetTargetHandle(Il2CppObject * obj, int32_t handle, int32_t type); typedef void(*WalkGCHandleTargetsCallback)(Il2CppObject* obj, void* context); static void WalkStrongGCHandleTargets(WalkGCHandleTargetsCallback callback, void* context); }; } /* gc */ } /* il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/gc/GarbageCollector.cpp ================================================ #include "il2cpp-config.h" #include "object-internals.h" #include "il2cpp-vm-support.h" #include "GarbageCollector.h" #include "os/Event.h" #include "os/Mutex.h" #include "os/Semaphore.h" #include "os/Thread.h" #include "utils/Il2CppHashMap.h" #include "utils/HashUtils.h" #include "vm/CCW.h" #include "vm/Class.h" #include "vm/Domain.h" #include "vm/Exception.h" #include "vm/RCW.h" #include "vm/Runtime.h" #include "vm/Thread.h" using namespace il2cpp::os; using namespace il2cpp::vm; namespace il2cpp { namespace gc { // So COM Callable Wrapper can be created for any kind of managed object, // whether it has finalizer or not. If it doesn't then it's an easy case: // when creating the CCW, we just register our cleanup method to be the // finalizer method. In case it does, then we need to be able to invoke // both our CCW cleanup method, and the finalizer in question. // We could chain them by registering CCW cleanup method over the finalizer // method and storing the previous finalizer in CCW cache, but it would // screw us over if for example the object is IDisposable and then it // calls `GC.SuppressFinalize` from C# - instead of the finalizer getting // unregistered, our CCW cleanup method gets unregistered, and we now have // a dangling pointer to the managed heap in the CCW cache. Not pretty. // Instead, we made GarbageCollector::RegisterFinalizer and GarbageCollector::SuppressFinalizer // to be CCW cache aware. Now, any managed object goes into 1 of these categories: // // 1. Object has no finalizer and it is not in CCW cache. It gets garbage // collected and no cleanup is needed. // 2. Object has a finalizer and it is not in CCW cache. GarbageCollector::RunFinalizer // gets registered with the GC for such object. // 3. Object has no finalizer and it is in CCW cache. CleanupCCW is // registered with the GC for such object. Once it is called, it removes // the object from the CCW cache. // 4. Object has a finalizer and it is in CCW cache. CleanupCCW is // registered with the GC for such object. Once it is called, it removes // the object from the CCW cache and then calls its finalizer. // // To know whether we have case 3 or 4, we have the "hasFinalizer" field in // the CachedCCW object. // // When GarbageCollector::RegisterFinalizer or GarbageCollector::SuppressFinalizer // is called, we have managed objects fitting in two buckets: // // 1. Those that do not exist in CCW cache. Finalizer is normally registered with // the GC. // 2. Those that are in the CCW cache. In such case, GC won't know about the call, // but instead we'll find the object in the CCW cache and RegisterFinalizer will // set "hasFinalizer" field to true, while SuppressFinalizer will set it to false // // Any methods that interact with s_CCWCache have to lock s_CCWCacheMutex. struct CachedCCW { Il2CppIManagedObjectHolder* managedObjectHolder; bool hasFinalizer; }; typedef Il2CppHashMap > CCWCache; static FastMutex s_CCWCacheMutex; static CCWCache s_CCWCache; #if IL2CPP_SUPPORT_THREADS static bool s_StopFinalizer = false; static il2cpp::os::Thread* s_FinalizerThread; static Il2CppThread* s_FinalizerThreadObject; static Semaphore s_FinalizerSemaphore(0, 32767); static Event s_FinalizersThreadStartedEvent; static Event s_FinalizersCompletedEvent(true, false); static void FinalizerThread(void* arg) { s_FinalizerThreadObject = il2cpp::vm::Thread::Attach(Domain::GetCurrent()); s_FinalizerThread->SetName("GC Finalizer"); s_FinalizersThreadStartedEvent.Set(); while (!s_StopFinalizer) { s_FinalizerSemaphore.Wait(); GarbageCollector::InvokeFinalizers(); s_FinalizersCompletedEvent.Set(); } il2cpp::vm::Thread::Detach(s_FinalizerThreadObject); } bool GarbageCollector::IsFinalizerThread(Il2CppThread *thread) { return s_FinalizerThreadObject == thread; } #else bool GarbageCollector::IsFinalizerThread(Il2CppThread *thread) { return false; } #endif void GarbageCollector::InitializeFinalizer() { GarbageCollector::InvokeFinalizers(); #if IL2CPP_SUPPORT_THREADS s_FinalizerThread = new il2cpp::os::Thread; s_FinalizerThread->Run(&FinalizerThread, NULL); s_FinalizersThreadStartedEvent.Wait(); #endif } void GarbageCollector::UninitializeFinalizers() { #if IL2CPP_SUPPORT_THREADS s_StopFinalizer = true; NotifyFinalizers(); s_FinalizerThread->Join(); delete s_FinalizerThread; s_FinalizerThread = NULL; #endif } void GarbageCollector::NotifyFinalizers() { #if IL2CPP_SUPPORT_THREADS s_FinalizerSemaphore.Post(1, NULL); #endif } void GarbageCollector::RunFinalizer(void *obj, void *data) { NOT_IMPLEMENTED_NO_ASSERT(GarbageCollector::RunFinalizer, "Compare to mono implementation special cases"); Il2CppException *exc = NULL; Il2CppObject *o; const MethodInfo* finalizer = NULL; o = (Il2CppObject*)obj; finalizer = Class::GetFinalizer(o->klass); Runtime::Invoke(finalizer, o, NULL, &exc); if (exc) Runtime::UnhandledException(exc); } void GarbageCollector::RegisterFinalizerForNewObject(Il2CppObject* obj) { // Fast path // No need to check CCW cache since it's guaranteed to not be in it for a new object RegisterFinalizerWithCallback(obj, &GarbageCollector::RunFinalizer); } void GarbageCollector::RegisterFinalizer(Il2CppObject* obj) { // Slow path // Check in CCW cache first os::FastAutoLock lock(&s_CCWCacheMutex); CCWCache::iterator it = s_CCWCache.find(obj); if (it != s_CCWCache.end()) { it->second.hasFinalizer = true; } else { RegisterFinalizerWithCallback(obj, &GarbageCollector::RunFinalizer); } } void GarbageCollector::SuppressFinalizer(Il2CppObject* obj) { // Slow path // Check in CCW cache first os::FastAutoLock lock(&s_CCWCacheMutex); CCWCache::iterator it = s_CCWCache.find(obj); if (it != s_CCWCache.end()) { it->second.hasFinalizer = false; } else { RegisterFinalizerWithCallback(obj, NULL); } } void GarbageCollector::WaitForPendingFinalizers() { if (!GarbageCollector::HasPendingFinalizers()) return; #if IL2CPP_SUPPORT_THREADS /* Avoid deadlocks */ if (vm::Thread::Current() == s_FinalizerThreadObject) return; s_FinalizersCompletedEvent.Reset(); NotifyFinalizers(); s_FinalizersCompletedEvent.Wait(); #else GarbageCollector::InvokeFinalizers(); #endif } int32_t GarbageCollector::GetGeneration(void* addr) { return 0; } void GarbageCollector::AddMemoryPressure(int64_t value) { } static void CleanupCCW(void* obj, void* data) { bool hasFinalizer; // We have to destroy CCW before invoking the finalizer, because we cannot know whether the finalizer will revive the object // In cases it does revive it, it's also possible for it to hit CCW cache, and in that case we'd want to create a new CCW object // rather than returning the one that we're about to destroy here { os::FastAutoLock lock(&s_CCWCacheMutex); CCWCache::iterator it = s_CCWCache.find(static_cast(obj)); IL2CPP_ASSERT(it != s_CCWCache.end()); Il2CppIManagedObjectHolder* managedObjectHolder = it->second.managedObjectHolder; hasFinalizer = it->second.hasFinalizer; s_CCWCache.erase(it); managedObjectHolder->Destroy(); } if (hasFinalizer) GarbageCollector::RunFinalizer(obj, data); } // When creating COM Callable Wrappers for classes that project to other Windows Runtime classes // for instance, System.Uri to Windows.Foundation.Uri, we cannot actually create a wrapper against managed object // as the native side actually wants an instance of a real Windows.Foundation.Uri class. So do that, our createCCW // instead of creating a COM Callable Wrapper, will create an instance of that windows runtime class. In that case, // we do not (AND CANNOT!) put it into a CCW cache because it's not a CCW. static bool ShouldInsertIntoCCWCache(Il2CppObject* obj) { if (obj->klass == il2cpp_defaults.system_uri_class && il2cpp_defaults.windows_foundation_uri_class != NULL) return false; /* TODO - Add the rest of the class projections: System.Collections.Specialized.NotifyCollectionChangedEventArgs <-> Windows.UI.Xaml.Interop.NotifyCollectionChangedEventArgs System.ComponentModel.PropertyChangedEventArgs <-> Windows.UI.Xaml.Data.PropertyChangedEventArgs */ return true; } Il2CppIUnknown* GarbageCollector::GetOrCreateCCW(Il2CppObject* obj, const Il2CppGuid& iid) { if (obj == NULL) return NULL; // check for rcw object. COM interface can be extracted from it and there's no need to create ccw if (obj->klass->is_import_or_windows_runtime) return RCW::QueryInterface(static_cast(obj), iid); os::FastAutoLock lock(&s_CCWCacheMutex); CCWCache::iterator it = s_CCWCache.find(obj); Il2CppIUnknown* comCallableWrapper; if (it == s_CCWCache.end()) { comCallableWrapper = CCW::CreateCCW(obj); if (ShouldInsertIntoCCWCache(obj)) { #if IL2CPP_DEBUG // Assert that CCW::CreateCCW actually returns upcasted Il2CppIManagedObjectHolder Il2CppIManagedObjectHolder* managedObjectHolder = NULL; comCallableWrapper->QueryInterface(Il2CppIManagedObjectHolder::IID, reinterpret_cast(&managedObjectHolder)); IL2CPP_ASSERT(static_cast(comCallableWrapper) == static_cast(managedObjectHolder)); managedObjectHolder->Release(); #endif CachedCCW ccw = { static_cast(comCallableWrapper), RegisterFinalizerWithCallback(obj, &CleanupCCW) != NULL }; s_CCWCache.insert(std::make_pair(obj, ccw)); } } else { comCallableWrapper = it->second.managedObjectHolder; } Il2CppIUnknown* result; il2cpp_hresult_t hr = comCallableWrapper->QueryInterface(iid, reinterpret_cast(&result)); IL2CPP_VM_RAISE_IF_FAILED(hr, true); return result; } #if NET_4_0 void il2cpp::gc::GarbageCollector::SetSkipThread(bool skip) { } #endif } // namespace gc } // namespace il2cpp ================================================ FILE: unity_decoder/libil2cpp/gc/GarbageCollector.h ================================================ #pragma once struct Il2CppGuid; struct Il2CppIUnknown; struct Il2CppObject; struct Il2CppThread; namespace il2cpp { namespace gc { class GarbageCollector { public: static void Collect(int maxGeneration); static int32_t CollectALittle(); static int32_t GetCollectionCount(int32_t generation); static int64_t GetUsedHeapSize(); public: // internal typedef void (*FinalizerCallback)(void* object, void* client_data); // functions implemented in a GC agnostic manner static void InitializeFinalizer(); static bool IsFinalizerThread(Il2CppThread* thread); static int32_t GetGeneration(void* addr); static void UninitializeFinalizers(); static void UninitializeGC(); static void NotifyFinalizers(); static void RunFinalizer(void *obj, void *data); static void RegisterFinalizerForNewObject(Il2CppObject* obj); static void RegisterFinalizer(Il2CppObject* obj); static void SuppressFinalizer(Il2CppObject* obj); static void WaitForPendingFinalizers(); static int32_t GetMaxGeneration(); static void AddMemoryPressure(int64_t value); static Il2CppIUnknown* GetOrCreateCCW(Il2CppObject* obj, const Il2CppGuid& iid); // functions implemented in a GC specific manner static void Initialize(); static void Enable(); static void Disable(); static FinalizerCallback RegisterFinalizerWithCallback(Il2CppObject* obj, FinalizerCallback callback); static int64_t GetAllocatedHeapSize(); static void* MakeDescriptorForObject(size_t *bitmap, int numbits); static void* MakeDescriptorForString(); static void* MakeDescriptorForArray(); static void* AllocateFixed(size_t size, void *descr); static void FreeFixed(void* addr); static bool RegisterThread(void *baseptr); static bool UnregisterThread(); static bool HasPendingFinalizers(); static int32_t InvokeFinalizers(); static void AddWeakLink(void **link_addr, Il2CppObject *obj, bool track); static void RemoveWeakLink(void **link_addr); static Il2CppObject *GetWeakLink(void **link_addr); /* Used by liveness code */ static void StopWorld(); static void StartWorld(); typedef void (*HeapSectionCallback) (void* user_data, void* start, void* end); static void ForEachHeapSection(void* user_data, HeapSectionCallback callback); static size_t GetSectionCount(); typedef void* (*GCCallWithAllocLockCallback)(void* user_data); static void* CallWithAllocLockHeld(GCCallWithAllocLockCallback callback, void* user_data); #if NET_4_0 static void SetSkipThread(bool skip); #endif }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/gc/NullGC.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_GC_NULL struct Il2CppObject; #include #include "il2cpp-api.h" #include "GarbageCollector.h" #include "utils/Memory.h" void il2cpp::gc::GarbageCollector::Initialize() { } void il2cpp::gc::GarbageCollector::UninitializeGC() { } void* il2cpp::gc::GarbageCollector::AllocateFixed(size_t size, void *descr) { return IL2CPP_MALLOC_ZERO(size); } void* il2cpp::gc::GarbageCollector::MakeDescriptorForObject(size_t *bitmap, int numbits) { return NULL; } void* il2cpp::gc::GarbageCollector::MakeDescriptorForString() { return NULL; } void* il2cpp::gc::GarbageCollector::MakeDescriptorForArray() { return NULL; } void il2cpp::gc::GarbageCollector::StopWorld() { NOT_IMPLEMENTED(il2cpp::gc::GarbageCollector::StopWorld); } void il2cpp::gc::GarbageCollector::StartWorld() { NOT_IMPLEMENTED(il2cpp::gc::GarbageCollector::StartWorld); } void il2cpp::gc::GarbageCollector::RemoveWeakLink(void **link_addr) { *link_addr = NULL; } Il2CppObject* il2cpp::gc::GarbageCollector::GetWeakLink(void **link_addr) { return (Il2CppObject*)*link_addr; } void il2cpp::gc::GarbageCollector::AddWeakLink(void **link_addr, Il2CppObject *obj, bool track) { *link_addr = obj; } bool il2cpp::gc::GarbageCollector::RegisterThread(void *baseptr) { return true; } bool il2cpp::gc::GarbageCollector::UnregisterThread() { return true; } il2cpp::gc::GarbageCollector::FinalizerCallback il2cpp::gc::GarbageCollector::RegisterFinalizerWithCallback(Il2CppObject* obj, FinalizerCallback callback) { return NULL; } void il2cpp::gc::GarbageCollector::FreeFixed(void* addr) { IL2CPP_FREE(addr); } int32_t il2cpp::gc::GarbageCollector::InvokeFinalizers() { return 0; } bool il2cpp::gc::GarbageCollector::HasPendingFinalizers() { return false; } void il2cpp::gc::GarbageCollector::Collect(int maxGeneration) { } int32_t il2cpp::gc::GarbageCollector::CollectALittle() { return 0; } void il2cpp::gc::GarbageCollector::Enable() { } void il2cpp::gc::GarbageCollector::Disable() { } int64_t il2cpp::gc::GarbageCollector::GetUsedHeapSize(void) { return 0; } int64_t il2cpp::gc::GarbageCollector::GetAllocatedHeapSize(void) { return 0; } int32_t il2cpp::gc::GarbageCollector::GetMaxGeneration() { return 0; } int32_t il2cpp::gc::GarbageCollector::GetCollectionCount(int32_t generation) { return 0; } void il2cpp::gc::GarbageCollector::ForEachHeapSection(void* user_data, HeapSectionCallback callback) { } size_t il2cpp::gc::GarbageCollector::GetSectionCount() { return 0; } void* il2cpp::gc::GarbageCollector::CallWithAllocLockHeld(GCCallWithAllocLockCallback callback, void* user_data) { return callback(user_data); } #endif ================================================ FILE: unity_decoder/libil2cpp/gc/WriteBarrier.cpp ================================================ #include "il2cpp-config.h" #include "gc/WriteBarrier.h" namespace il2cpp { namespace gc { void WriteBarrier::GenericStore(void* ptr, Il2CppObject* value) { *(void**)ptr = value; } } /* gc */ } /* il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/gc/WriteBarrier.h ================================================ #pragma once struct Il2CppObject; namespace il2cpp { namespace gc { class WriteBarrier { public: static void GenericStore(void* ptr, Il2CppObject* value); }; } /* gc */ } /* il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/gc/gc_wrapper.h ================================================ #pragma once #include "il2cpp-config.h" #if IL2CPP_GC_BOEHM /* here is the defines we build Boehm with */ #define IGNORE_DYNAMIC_LOADING 1 #define GC_DONT_REGISTER_MAIN_STATIC_DATA 1 #if IL2CPP_HAS_GC_DESCRIPTORS #define GC_GCJ_SUPPORT 1 #endif #if IL2CPP_SUPPORT_THREADS #define GC_THREADS 1 #endif #if IL2CPP_TARGET_WINRT #define GC_NOT_DLL #endif #include "gc.h" #include "gc_typed.h" #include "gc_mark.h" #include "gc_gcj.h" #define GC_NO_DESCRIPTOR ((void*)(0 | GC_DS_LENGTH)) #else #define GC_NO_DESCRIPTOR ((void*)0) #endif ================================================ FILE: unity_decoder/libil2cpp/icallincludes.h ================================================ #include "icalls/mscorlib/Mono.Globalization.Unicode/Normalization.h" #include "icalls/mscorlib/Mono.Interop/ComInteropProxy.h" #include "icalls/mscorlib/Mono/Runtime.h" #include "icalls/mscorlib/Mono.Security.Cryptography/KeyPairPersistence.h" #include "icalls/mscorlib/System/__ComObject.h" #include "icalls/mscorlib/System/Activator.h" #include "icalls/mscorlib/System/AppDomain.h" #include "icalls/mscorlib/System/ArgIterator.h" #include "icalls/mscorlib/System/Array.h" #include "icalls/mscorlib/System/Buffer.h" #include "icalls/mscorlib/System/Char.h" #include "icalls/mscorlib/System/CLRConfig.h" #include "icalls/mscorlib/System/Convert.h" #include "icalls/mscorlib/System/ConsoleDriver.h" #include "icalls/mscorlib/System/CurrentSystemTimeZone.h" #include "icalls/mscorlib/System/DateTime.h" #include "icalls/mscorlib/System/Decimal.h" #include "icalls/mscorlib/System/Delegate.h" #include "icalls/mscorlib/System.Diagnostics/Assert.h" #include "icalls/mscorlib/System.Diagnostics/Debugger.h" #include "icalls/mscorlib/System.Diagnostics/StackFrame.h" #include "icalls/mscorlib/System.Diagnostics/StackTrace.h" #include "icalls/mscorlib/System/Double.h" #include "icalls/mscorlib/System/Enum.h" #include "icalls/mscorlib/System/Environment.h" #include "icalls/mscorlib/System/Exception.h" #include "icalls/mscorlib/System/GC.h" #include "icalls/mscorlib/System.Globalization/CalendarData.h" #include "icalls/mscorlib/System.Globalization/CompareInfo.h" #include "icalls/mscorlib/System.Globalization/CultureData.h" #include "icalls/mscorlib/System.Globalization/CultureInfo.h" #include "icalls/mscorlib/System.Globalization/RegionInfo.h" #include "icalls/mscorlib/System.IO/DriveInfo.h" #include "icalls/mscorlib/System.IO/MonoIO.h" #include "icalls/mscorlib/System.IO/Path.h" #include "icalls/mscorlib/System/Math.h" #include "icalls/mscorlib/System/MissingMemberException.h" #include "icalls/mscorlib/System/MonoCustomAttrs.h" #include "icalls/mscorlib/System/MonoEnumInfo.h" #include "icalls/mscorlib/System/MonoType.h" #include "icalls/mscorlib/System/Number.h" #include "icalls/mscorlib/System/NumberFormatter.h" #include "icalls/mscorlib/System/Object.h" #include "icalls/mscorlib/System.Reflection/Assembly.h" #include "icalls/mscorlib/System.Reflection/AssemblyName.h" #include "icalls/mscorlib/System.Reflection/CustomAttributeData.h" #include "icalls/mscorlib/System.Reflection.Emit/AssemblyBuilder.h" #include "icalls/mscorlib/System.Reflection.Emit/CustomAttributeBuilder.h" #include "icalls/mscorlib/System.Reflection.Emit/DerivedType.h" #include "icalls/mscorlib/System.Reflection.Emit/DynamicMethod.h" #include "icalls/mscorlib/System.Reflection.Emit/EnumBuilder.h" #include "icalls/mscorlib/System.Reflection.Emit/GenericTypeParameterBuilder.h" #include "icalls/mscorlib/System.Reflection.Emit/MethodBuilder.h" #include "icalls/mscorlib/System.Reflection.Emit/ModuleBuilder.h" #include "icalls/mscorlib/System.Reflection.Emit/SignatureHelper.h" #include "icalls/mscorlib/System.Reflection.Emit/SymbolType.h" #include "icalls/mscorlib/System.Reflection.Emit/TypeBuilder.h" #include "icalls/mscorlib/System.Reflection/FieldInfo.h" #include "icalls/mscorlib/System.Reflection/MemberInfo.h" #include "icalls/mscorlib/System.Reflection/MethodBase.h" #include "icalls/mscorlib/System.Reflection/Module.h" #include "icalls/mscorlib/System.Reflection/MonoCMethod.h" #include "icalls/mscorlib/System.Reflection/MonoEventInfo.h" #include "icalls/mscorlib/System.Reflection/MonoField.h" #include "icalls/mscorlib/System.Reflection/MonoGenericClass.h" #include "icalls/mscorlib/System.Reflection/MonoGenericCMethod.h" #include "icalls/mscorlib/System.Reflection/MonoGenericMethod.h" #include "icalls/mscorlib/System.Reflection/MonoMethod.h" #include "icalls/mscorlib/System.Reflection/MonoMethodInfo.h" #include "icalls/mscorlib/System.Reflection/MonoPropertyInfo.h" #include "icalls/mscorlib/System.Reflection/ParameterInfo.h" #include "icalls/mscorlib/System.Reflection/RtFieldInfo.h" #include "icalls/mscorlib/System.Runtime.CompilerServices/RuntimeHelpers.h" #include "icalls/mscorlib/System.Runtime.InteropServices/GCHandle.h" #include "icalls/mscorlib/System.Runtime.InteropServices/Marshal.h" #include "icalls/mscorlib/System.Runtime.InteropServices.WindowsRuntime/UnsafeNativeMethods.h" #include "icalls/mscorlib/System.Runtime.Remoting.Activation/ActivationServices.h" #include "icalls/mscorlib/System.Runtime.Remoting.Contexts/Context.h" #include "icalls/mscorlib/System.Runtime.Remoting.Messaging/AsyncResult.h" #include "icalls/mscorlib/System.Runtime.Remoting.Messaging/MonoMethodMessage.h" #include "icalls/mscorlib/System.Runtime.Remoting.Proxies/RealProxy.h" #include "icalls/mscorlib/System.Runtime.Remoting/RemotingServices.h" #include "icalls/mscorlib/System.Runtime.Versioning/VersioningHelper.h" #include "icalls/mscorlib/System/RuntimeFieldHandle.h" #include "icalls/mscorlib/System/RuntimeMethodHandle.h" #include "icalls/mscorlib/System/RuntimeTypeHandle.h" #include "icalls/mscorlib/System/RuntimeType.h" #include "icalls/mscorlib/System.Security.Cryptography/RNGCryptoServiceProvider.h" #include "icalls/mscorlib/System.Security.Policy/Evidence.h" #include "icalls/mscorlib/System.Security.Principal/WindowsIdentity.h" #include "icalls/mscorlib/System.Security.Principal/WindowsImpersonationContext.h" #include "icalls/mscorlib/System.Security.Principal/WindowsPrincipal.h" #include "icalls/mscorlib/System.Security/SecurityFrame.h" #include "icalls/mscorlib/System.Security/SecurityManager.h" #include "icalls/mscorlib/System/SizedReference.h" #include "icalls/mscorlib/System/String.h" #include "icalls/mscorlib/System.Text/Encoding.h" #include "icalls/mscorlib/System.Text/EncodingHelper.h" #include "icalls/mscorlib/System.Text/Normalization.h" #include "icalls/mscorlib/System.Threading/Interlocked.h" #include "icalls/mscorlib/System.Threading/InternalThread.h" #include "icalls/mscorlib/System.Threading/Monitor.h" #include "icalls/mscorlib/System.Threading/Mutex.h" #include "icalls/mscorlib/System.Threading/NativeEventCalls.h" #include "icalls/mscorlib/System.Threading/Timer.h" #include "icalls/mscorlib/System.Threading/Thread.h" #include "icalls/mscorlib/System.Threading/ThreadPool.h" #include "icalls/mscorlib/System.Threading/WaitHandle.h" #include "icalls/mscorlib/System/TimeSpan.h" #include "icalls/mscorlib/System/TimeZoneInfo.h" #include "icalls/mscorlib/System/Type.h" #include "icalls/mscorlib/System/TypedReference.h" #include "icalls/mscorlib/System/ValueType.h" #include "icalls/System/Microsoft.Win32/NativeMethods.h" #include "icalls/System/Mono.Net.Security/MonoTlsProviderFactory.h" #include "icalls/System.Configuration/System.Configuration/InternalConfigurationHost.h" #include "icalls/System.Core/System.IO.MemoryMappedFiles/MemoryMapImpl.h" #include "icalls/System/System.ComponentModel/Win32Exception.h" #include "icalls/System/System.Configuration/DefaultConfig.h" #include "icalls/System/System.Configuration/InternalConfigurationHost.h" #include "icalls/System/System.IO/FAMWatcher.h" #include "icalls/System/System.IO/FileSystemWatcher.h" #include "icalls/System/System.IO/InotifyWatcher.h" #include "icalls/System/System.IO/KqueueMonitor.h" #include "icalls/System/System/IOSelector.h" #include "icalls/System/System.Diagnostics/DefaultTraceListener.h" #include "icalls/System/System.Diagnostics/FileVersionInfo.h" #include "icalls/System/System.Diagnostics/PerformanceCounter.h" #include "icalls/System/System.Diagnostics/PerformanceCounterCategory.h" #include "icalls/System/System.Diagnostics/Process.h" #include "icalls/System/System.Diagnostics/Stopwatch.h" #include "icalls/System/System.Net/Dns.h" #include "icalls/System/System.Net.NetworkInformation/LinuxNetworkInterface.h" #include "icalls/System/System.Net.NetworkInformation/MacOsIPInterfaceProperties.h" #include "icalls/System/System.Net.Sockets/Socket.h" #include "icalls/System/System.Net.Sockets/SocketException.h" #include "icalls/System/System.Threading/Semaphore.h" #include "mono/ThreadPool/threadpool-ms.h" #include "mono/ThreadPool/threadpool-ms-io.h" #include "icalls/mscorlib/Mono/SafeStringMarshal.h" #include "icalls/mscorlib/Mono/RuntimeMarshal.h" #include "icalls/mscorlib/Mono/RuntimeGPtrArrayHandle.h" #include "icalls/mscorlib/Mono/RuntimeClassHandle.h" #include "icalls/mscorlib/System.Reflection/EventInfo.h" #include "icalls/mscorlib/System.Reflection/PropertyInfo.h" ================================================ FILE: unity_decoder/libil2cpp/icalls/System/Microsoft.Win32/NativeMethods.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "NativeMethods.h" #include "os/Win32/WindowsHeaders.h" #include "os/NativeMethods.h" #include "os/Process.h" namespace il2cpp { namespace icalls { namespace System { namespace Microsoft { namespace Win32 { bool NativeMethods::CloseProcess(Il2CppIntPtr handle) { return os::NativeMethods::CloseProcess((il2cpp::os::ProcessHandle*)handle.m_value); } bool NativeMethods::GetExitCodeProcess(Il2CppIntPtr processHandle, int32_t* exitCode) { return os::NativeMethods::GetExitCodeProcess((il2cpp::os::ProcessHandle*)processHandle.m_value, exitCode); } bool NativeMethods::GetProcessTimes(Il2CppIntPtr handle, int64_t* creation, int64_t* exit, int64_t* kernel, int64_t* user) { NOT_IMPLEMENTED_ICALL(NativeMethods::GetProcessTimes); IL2CPP_UNREACHABLE; return false; } bool NativeMethods::GetProcessWorkingSetSize(Il2CppIntPtr handle, Il2CppIntPtr* min, Il2CppIntPtr* max) { NOT_IMPLEMENTED_ICALL(NativeMethods::GetProcessWorkingSetSize); IL2CPP_UNREACHABLE; return false; } bool NativeMethods::SetPriorityClass(Il2CppIntPtr handle, int32_t priorityClass) { NOT_IMPLEMENTED_ICALL(NativeMethods::SetPriorityClass); IL2CPP_UNREACHABLE; return false; } bool NativeMethods::SetProcessWorkingSetSize(Il2CppIntPtr handle, Il2CppIntPtr min, Il2CppIntPtr max) { NOT_IMPLEMENTED_ICALL(NativeMethods::SetProcessWorkingSetSize); IL2CPP_UNREACHABLE; return false; } bool NativeMethods::TerminateProcess(Il2CppIntPtr processHandle, int32_t exitCode) { NOT_IMPLEMENTED_ICALL(NativeMethods::TerminateProcess); IL2CPP_UNREACHABLE; return false; } int32_t NativeMethods::GetCurrentProcessId() { return os::NativeMethods::GetCurrentProcessId(); } int32_t NativeMethods::GetPriorityClass(Il2CppIntPtr handle) { NOT_IMPLEMENTED_ICALL(NativeMethods::GetPriorityClass); IL2CPP_UNREACHABLE; return 0; } int32_t NativeMethods::WaitForInputIdle(Il2CppIntPtr handle, int32_t milliseconds) { NOT_IMPLEMENTED_ICALL(NativeMethods::WaitForInputIdle); IL2CPP_UNREACHABLE; return 0; } Il2CppIntPtr NativeMethods::GetCurrentProcess() { Il2CppIntPtr handle; handle.m_value = os::NativeMethods::GetCurrentProcess(); return handle; } } // namespace Win32 } // namespace Microsoft } // namespace System } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/System/Microsoft.Win32/NativeMethods.h ================================================ #pragma once #if NET_4_0 #include "object-internals.h" namespace il2cpp { namespace icalls { namespace System { namespace Microsoft { namespace Win32 { class LIBIL2CPP_CODEGEN_API NativeMethods { public: static bool CloseProcess(Il2CppIntPtr handle); static bool GetExitCodeProcess(Il2CppIntPtr processHandle, int32_t* exitCode); static bool GetProcessTimes(Il2CppIntPtr handle, int64_t* creation, int64_t* exit, int64_t* kernel, int64_t* user); static bool GetProcessWorkingSetSize(Il2CppIntPtr handle, Il2CppIntPtr* min, Il2CppIntPtr* max); static bool SetPriorityClass(Il2CppIntPtr handle, int32_t priorityClass); static bool SetProcessWorkingSetSize(Il2CppIntPtr handle, Il2CppIntPtr min, Il2CppIntPtr max); static bool TerminateProcess(Il2CppIntPtr processHandle, int32_t exitCode); static int32_t GetCurrentProcessId(); static int32_t GetPriorityClass(Il2CppIntPtr handle); static int32_t WaitForInputIdle(Il2CppIntPtr handle, int32_t milliseconds); static Il2CppIntPtr GetCurrentProcess(); }; } // namespace Win32 } // namespace Microsoft } // namespace System } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/System/Mono.Net.Security/MonoTlsProviderFactory.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "MonoTlsProviderFactory.h" namespace il2cpp { namespace icalls { namespace System { namespace Mono { namespace Net { namespace Security { bool MonoTlsProviderFactory::IsBtlsSupported() { NOT_IMPLEMENTED_ICALL(MonoTlsProviderFactory::IsBtlsSupported); IL2CPP_UNREACHABLE; } } // namespace Security } // namespace Net } // namespace Mono } // namespace System } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/System/Mono.Net.Security/MonoTlsProviderFactory.h ================================================ #pragma once #if NET_4_0 namespace il2cpp { namespace icalls { namespace System { namespace Mono { namespace Net { namespace Security { class LIBIL2CPP_CODEGEN_API MonoTlsProviderFactory { public: static bool IsBtlsSupported(); }; } // namespace Security } // namespace Net } // namespace Mono } // namespace System } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System/IOSelector.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "IOSelector.h" namespace il2cpp { namespace icalls { namespace System { namespace System { void IOSelector::Add(Il2CppIntPtr handle, Il2CppObject* job) { NOT_IMPLEMENTED_ICALL(IOSelector::Add); IL2CPP_UNREACHABLE; } void IOSelector::Remove(Il2CppIntPtr handle) { NOT_IMPLEMENTED_ICALL(IOSelector::Remove); IL2CPP_UNREACHABLE; } } // namespace System } // namespace System } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System/IOSelector.h ================================================ #pragma once #if NET_4_0 #include "object-internals.h" namespace il2cpp { namespace icalls { namespace System { namespace System { class LIBIL2CPP_CODEGEN_API IOSelector { public: static void Add(Il2CppIntPtr handle, Il2CppObject* job); static void Remove(Il2CppIntPtr handle); }; } // namespace System } // namespace System } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.ComponentModel/Win32Exception.cpp ================================================ #include "il2cpp-config.h" #include #include "icalls/System/System.ComponentModel/Win32Exception.h" #include "vm/String.h" #include "os/ErrorCodes.h" #include "os/Messages.h" #include "class-internals.h" #include "object-internals.h" #include "utils/StringUtils.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace ComponentModel { Il2CppString *Win32Exception::W32ErrorMessage(int32_t code) { std::string message = os::Messages::FromCode((os::ErrorCode)code); if (message.size() == 0) { // Note: this is a special case only for il2cpp. We might not want to keep // this in the future, but helps with debugging and testing for now. message = utils::StringUtils::Printf("Win32 Error message: %d (message string not found in the message table)", code); } return vm::String::New(message.c_str()); } } /* namespace ComponentModel */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.ComponentModel/Win32Exception.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppString; namespace il2cpp { namespace icalls { namespace System { namespace System { namespace ComponentModel { class LIBIL2CPP_CODEGEN_API Win32Exception { public: static Il2CppString *W32ErrorMessage(int32_t code); }; } /* namespace ComponentModel */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Configuration/DefaultConfig.cpp ================================================ #include "il2cpp-config.h" #include "icalls/System/System.Configuration/DefaultConfig.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Configuration { Il2CppString* DefaultConfig::get_bundled_machine_config() { NOT_IMPLEMENTED_ICALL(DefaultConfig::get_bundled_machine_config); return 0; } Il2CppString* DefaultConfig::get_machine_config_path() { NOT_IMPLEMENTED_ICALL(DefaultConfig::get_machine_config_path); return 0; } } /* namespace Configuration */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Configuration/DefaultConfig.h ================================================ #pragma once #include #include "object-internals.h" #include "il2cpp-config.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Configuration { class LIBIL2CPP_CODEGEN_API DefaultConfig { public: static Il2CppString* get_machine_config_path(); static Il2CppString* get_bundled_machine_config(); }; } /* namespace Configuration */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Configuration/InternalConfigurationHost.cpp ================================================ #include "il2cpp-config.h" #include "icalls/System/System.Configuration/InternalConfigurationHost.h" #include "vm/String.h" #include "vm/Exception.h" #include "vm/Runtime.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Configuration { Il2CppString* InternalConfigurationHost::get_bundled_machine_config() { const char *config_xml = vm::Runtime::GetBundledMachineConfig(); if (config_xml == 0) return NULL; return vm::String::NewWrapper(config_xml); } } /* namespace Configuration */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Configuration/InternalConfigurationHost.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppString; namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Configuration { class LIBIL2CPP_CODEGEN_API InternalConfigurationHost { public: static Il2CppString* get_bundled_machine_config(); }; } /* namespace Configuration */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Diagnostics/DefaultTraceListener.cpp ================================================ #include "il2cpp-config.h" #include "icalls/System/System.Diagnostics/DefaultTraceListener.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Diagnostics { void DefaultTraceListener::WriteWindowsDebugString(Il2CppString* message) { NOT_IMPLEMENTED_ICALL(DefaultTraceListener::WriteWindowsDebugString); } } /* namespace Diagnostics */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Diagnostics/DefaultTraceListener.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Diagnostics { class LIBIL2CPP_CODEGEN_API DefaultTraceListener { public: static void WriteWindowsDebugString(Il2CppString* message); }; } /* namespace Diagnostics */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Diagnostics/FileVersionInfo.cpp ================================================ #include "il2cpp-config.h" #include "icalls/System/System.Diagnostics/FileVersionInfo.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Diagnostics { void FileVersionInfo::GetVersionInfo_internal(void* /* System.Diagnostics.FileVersionInfo */ self, Il2CppString* fileName) { NOT_IMPLEMENTED_ICALL(FileVersionInfo::GetVersionInfo_internal); } } /* namespace Diagnostics */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Diagnostics/FileVersionInfo.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Diagnostics { class LIBIL2CPP_CODEGEN_API FileVersionInfo { public: static void GetVersionInfo_internal(void* /* System.Diagnostics.FileVersionInfo */ self, Il2CppString* fileName); }; } /* namespace Diagnostics */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Diagnostics/PerformanceCounter.cpp ================================================ #include "il2cpp-config.h" #include "icalls/System/System.Diagnostics/PerformanceCounter.h" #include "PerformanceCounterUtils.h" #include "os/Time.h" #include "utils/Memory.h" #include "utils/StringUtils.h" #include "vm/Exception.h" #include "vm-utils/VmStringUtils.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Diagnostics { static void fill_sample(Il2CppCounterSample *sample) { sample->timeStamp = os::Time::GetTicksMillisecondsMonotonic(); sample->timeStamp100nSec = sample->timeStamp; sample->counterTimeStamp = sample->timeStamp; sample->counterFrequency = 10000000; sample->systemFrequency = 10000000; // the real basevalue needs to be get from a different counter... sample->baseValue = 0; } static bool Il2CppMemoryCounter(ImplVtable *vtable, bool only_value, Il2CppCounterSample *sample) { int id = (int)(intptr_t)vtable->arg; if (!only_value) { fill_sample(sample); sample->baseValue = 1; } sample->counterType = predef_counters[predef_categories[CATEGORY_MONO_MEM].first_counter + id].type; switch (id) { case COUNTER_MEM_NUM_OBJECTS: sample->rawValue = il2cpp_runtime_stats.new_object_count; return true; } return false; } static void* Il2CppMemoryCounterImpl(Il2CppString* counter, Il2CppString* instance, int* type, bool* custom) { *custom = false; const CounterDesc *cdesc = get_counter_in_category(&predef_categories[CATEGORY_MONO_MEM], counter); if (cdesc) { *type = cdesc->type; return create_vtable((void*)(intptr_t)cdesc->id, Il2CppMemoryCounter, NULL); } return NULL; } Il2CppIntPtr PerformanceCounter::GetImpl(Il2CppString* category, Il2CppString* counter, Il2CppString* instance, Il2CppString* machine, int* type, bool* custom) { Il2CppIntPtr returnValue = {0}; const CategoryDesc *cdesc; if (!utils::VmStringUtils::CaseInsensitiveEquals(machine, ".")) return returnValue; cdesc = find_category(category); if (!cdesc) { return returnValue; } else { switch (cdesc->id) { case CATEGORY_MONO_MEM: returnValue.m_value = Il2CppMemoryCounterImpl(counter, instance, type, custom); } } return returnValue; } bool PerformanceCounter::GetSample(Il2CppIntPtr impl, bool only_value, Il2CppCounterSample* sample) { ImplVtable *vtable = (ImplVtable*)impl.m_value; if (vtable && vtable->sample) return vtable->sample(vtable, only_value, sample); return false; } int64_t PerformanceCounter::UpdateValue(Il2CppIntPtr impl, bool do_incr, int64_t value) { NOT_IMPLEMENTED_ICALL(PerformanceCounter::UpdateValue); return 0; } void PerformanceCounter::FreeData(Il2CppIntPtr impl) { ImplVtable* vtable = (ImplVtable*)impl.m_value; if (vtable && vtable->cleanup) vtable->cleanup(vtable); IL2CPP_FREE(vtable); } } /* namespace Diagnostics */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Diagnostics/PerformanceCounter.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Diagnostics { struct Il2CppCounterSample; class LIBIL2CPP_CODEGEN_API PerformanceCounter { public: static void FreeData(Il2CppIntPtr impl); static bool GetSample(Il2CppIntPtr impl, bool only_value, Il2CppCounterSample* sample); static int64_t UpdateValue(Il2CppIntPtr impl, bool do_incr, int64_t value); static Il2CppIntPtr GetImpl(Il2CppString* category, Il2CppString* counter, Il2CppString* instance, Il2CppString* machine, int* type, bool* custom); }; } /* namespace Diagnostics */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Diagnostics/PerformanceCounterCategory.cpp ================================================ #include "il2cpp-config.h" #include "icalls/System/System.Diagnostics/PerformanceCounterCategory.h" #include "PerformanceCounterUtils.h" #include "utils/StringUtils.h" #include "vm/Array.h" #include "vm/String.h" #include "vm/Exception.h" #include "vm-utils/VmStringUtils.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Diagnostics { bool PerformanceCounterCategory::CategoryDelete(Il2CppString* name) { NOT_SUPPORTED_IL2CPP(PerformanceCounterCategory::Create, "The IL2CPP scripting backend does not support the removal of custom performance counter categories."); return false; } Il2CppString* PerformanceCounterCategory::CategoryHelpInternal(Il2CppString* category, Il2CppString* machine) { if (!utils::VmStringUtils::CaseInsensitiveEquals(machine, ".")) return NULL; const CategoryDesc* cdesc = find_category(category); if (!cdesc) return NULL; return vm::String::New(cdesc->help); } bool PerformanceCounterCategory::CounterCategoryExists(Il2CppString* counter, Il2CppString* category, Il2CppString* machine) { if (!utils::VmStringUtils::CaseInsensitiveEquals(machine, ".")) return false; const CategoryDesc* cdesc = find_category(category); if (!cdesc) return false; /* counter is allowed to be null */ if (!counter) return true; if (get_counter_in_category(cdesc, counter)) return true; return false; } bool PerformanceCounterCategory::Create(Il2CppString* categoryName, Il2CppString* categoryHelp, PerformanceCounterCategoryType categoryType, Il2CppArray* items) { NOT_SUPPORTED_IL2CPP(PerformanceCounterCategory::Create, "The IL2CPP scripting backend does not support the creation of custom performance counter categories."); return false; } int32_t PerformanceCounterCategory::InstanceExistsInternal(Il2CppString* instance, Il2CppString* category, Il2CppString* machine) { return 0; } Il2CppArray* PerformanceCounterCategory::GetCategoryNames(Il2CppString* machine) { if (!utils::VmStringUtils::CaseInsensitiveEquals(machine, ".")) return vm::Array::New(il2cpp_defaults.string_class, 0); Il2CppArray* res = vm::Array::New(il2cpp_defaults.string_class, NUM_CATEGORIES); for (int i = 0; i < NUM_CATEGORIES; ++i) { const CategoryDesc *cdesc = &predef_categories[i]; il2cpp_array_setref(res, i, vm::String::New(cdesc->name)); } return res; } Il2CppArray* PerformanceCounterCategory::GetCounterNames(Il2CppString* category, Il2CppString* machine) { if (!utils::VmStringUtils::CaseInsensitiveEquals(machine, ".")) return vm::Array::New(il2cpp_defaults.string_class, 0); const CategoryDesc* cdesc = find_category(category); if (cdesc) { Il2CppArray* res = vm::Array::New(il2cpp_defaults.string_class, cdesc[1].first_counter - cdesc->first_counter); for (int i = cdesc->first_counter; i < cdesc[1].first_counter; ++i) { const CounterDesc *desc = &predef_counters[i]; il2cpp_array_setref(res, i - cdesc->first_counter, vm::String::New(desc->name)); } return res; } return vm::Array::New(il2cpp_defaults.string_class, 0); } Il2CppArray* PerformanceCounterCategory::GetInstanceNames(Il2CppString* category, Il2CppString* machine) { return vm::Array::New(il2cpp_defaults.string_class, 0); } } /* namespace Diagnostics */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Diagnostics/PerformanceCounterCategory.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Diagnostics { typedef int32_t PerformanceCounterCategoryType; class LIBIL2CPP_CODEGEN_API PerformanceCounterCategory { public: static Il2CppString* CategoryHelpInternal(Il2CppString* category, Il2CppString* machine); static bool CounterCategoryExists(Il2CppString* counter, Il2CppString* category, Il2CppString* machine); static bool Create(Il2CppString* categoryName, Il2CppString* categoryHelp, PerformanceCounterCategoryType categoryType, Il2CppArray* items); static Il2CppArray* GetCategoryNames(Il2CppString* machine); static Il2CppArray* GetCounterNames(Il2CppString* category, Il2CppString* machine); static Il2CppArray* GetInstanceNames(Il2CppString* category, Il2CppString* machine); static int32_t InstanceExistsInternal(Il2CppString* instance, Il2CppString* category, Il2CppString* machine); static bool CategoryDelete(Il2CppString* name); }; } /* namespace Diagnostics */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Diagnostics/PerformanceCounterUtils.cpp ================================================ #include "il2cpp-config.h" #include "PerformanceCounterUtils.h" #include "object-internals.h" #include "utils/Memory.h" #include "utils/StringUtils.h" #include "vm/String.h" #include "vm-utils/VmStringUtils.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Diagnostics { ImplVtable* create_vtable(void *arg, SampleFunc sample, UpdateFunc update) { ImplVtable* vtable = (ImplVtable*)IL2CPP_MALLOC_ZERO(sizeof(ImplVtable)); vtable->arg = arg; vtable->sample = sample; vtable->update = update; return vtable; } const CategoryDesc* find_category(Il2CppString *category) { for (int i = 0; i < NUM_CATEGORIES; ++i) { if (utils::VmStringUtils::CaseInsensitiveEquals(category, predef_categories[i].name)) return &predef_categories[i]; } return NULL; } const CounterDesc* get_counter_in_category(const CategoryDesc *desc, Il2CppString *counter) { const CounterDesc *cdesc = &predef_counters[desc->first_counter]; const CounterDesc *end = &predef_counters[desc[1].first_counter]; for (; cdesc < end; ++cdesc) { if (utils::VmStringUtils::CaseInsensitiveEquals(counter, cdesc->name)) return cdesc; } return NULL; } } /* namespace Diagnostics */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Diagnostics/PerformanceCounterUtils.h ================================================ #pragma once #include "class-internals.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Diagnostics { struct CategoryDesc { const char *name; const char *help; unsigned char id; signed int type : 2; unsigned int instance_type : 6; short first_counter; }; #define PERFCTR_CAT(id, name, help, type, inst, first_counter) CATEGORY_ ## id, #define PERFCTR_COUNTER(id, name, help, type, field) enum { #include "perfcounters-def.h" NUM_CATEGORIES }; #undef PERFCTR_CAT #undef PERFCTR_COUNTER #define PERFCTR_CAT(id, name, help, type, inst, first_counter) CATEGORY_START_ ## id = -1, #define PERFCTR_COUNTER(id, name, help, type, field) COUNTER_ ## id, /* each counter is assigned an id starting from 0 inside the category */ enum { #include "perfcounters-def.h" END_COUNTERS }; #undef PERFCTR_CAT #undef PERFCTR_COUNTER #define PERFCTR_CAT(id, name, help, type, inst, first_counter) #define PERFCTR_COUNTER(id, name, help, type, field) CCOUNTER_ ## id, /* this is used just to count the number of counters */ enum { #include "perfcounters-def.h" NUM_COUNTERS }; struct CounterDesc { const char *name; const char *help; short id; unsigned short offset; // offset inside Il2CppPerfCounters int type; }; enum { FTYPE_CATEGORY = 'C', FTYPE_DELETED = 'D', FTYPE_PREDEF_INSTANCE = 'P', // an instance of a predef counter FTYPE_INSTANCE = 'I', FTYPE_DIRTY = 'd', FTYPE_END = 0 }; struct SharedHeader { unsigned char ftype; unsigned char extra; unsigned short size; }; struct SharedCategory { SharedHeader header; unsigned short num_counters; unsigned short counters_data_size; int num_instances; /* variable length data follows */ char name[1]; // string name // string help // SharedCounter counters_info [num_counters] }; struct SharedInstance { SharedHeader header; size_t category_offset; /* variable length data follows */ char instance_name[1]; // string name }; struct SharedCounter { unsigned char type; uint8_t seq_num; /* variable length data follows */ char name[1]; // string name // string help }; struct CatSearch { Il2CppString *name; SharedCategory *cat; }; /* map of PerformanceCounterType.cs */ enum { NumberOfItemsHEX32 = 0x00000000, NumberOfItemsHEX64 = 0x00000100, NumberOfItems32 = 0x00010000, NumberOfItems64 = 0x00010100, CounterDelta32 = 0x00400400, CounterDelta64 = 0x00400500, SampleCounter = 0x00410400, CountPerTimeInterval32 = 0x00450400, CountPerTimeInterval64 = 0x00450500, RateOfCountsPerSecond32 = 0x10410400, RateOfCountsPerSecond64 = 0x10410500, RawFraction = 0x20020400, CounterTimer = 0x20410500, Timer100Ns = 0x20510500, SampleFraction = 0x20C20400, CounterTimerInverse = 0x21410500, Timer100NsInverse = 0x21510500, CounterMultiTimer = 0x22410500, CounterMultiTimer100Ns = 0x22510500, CounterMultiTimerInverse = 0x23410500, CounterMultiTimer100NsInverse = 0x23510500, AverageTimer32 = 0x30020400, ElapsedTime = 0x30240500, AverageCount64 = 0x40020500, SampleBase = 0x40030401, AverageBase = 0x40030402, RawBase = 0x40030403, CounterMultiBase = 0x42030500 }; /* maps a small integer type to the counter types above */ static const int simple_type_to_type[] = { NumberOfItemsHEX32, NumberOfItemsHEX64, NumberOfItems32, NumberOfItems64, CounterDelta32, CounterDelta64, SampleCounter, CountPerTimeInterval32, CountPerTimeInterval64, RateOfCountsPerSecond32, RateOfCountsPerSecond64, RawFraction, CounterTimer, Timer100Ns, SampleFraction, CounterTimerInverse, Timer100NsInverse, CounterMultiTimer, CounterMultiTimer100Ns, CounterMultiTimerInverse, CounterMultiTimer100NsInverse, AverageTimer32, ElapsedTime, AverageCount64, SampleBase, AverageBase, RawBase, CounterMultiBase }; enum { SingleInstance, MultiInstance, CatTypeUnknown = -1 }; enum { ProcessInstance, ThreadInstance, CPUInstance, MonoInstance, NetworkInterfaceInstance, CustomInstance }; /* map of CounterSample.cs */ struct Il2CppCounterSample { int64_t rawValue; int64_t baseValue; int64_t counterFrequency; int64_t systemFrequency; int64_t timeStamp; int64_t timeStamp100nSec; int64_t counterTimeStamp; int counterType; }; #undef PERFCTR_CAT #undef PERFCTR_COUNTER #define PERFCTR_CAT(id, name, help, type, inst, first_counter) {name, help, CATEGORY_ ## id, type, inst ## Instance, CCOUNTER_ ## first_counter}, #define PERFCTR_COUNTER(id, name, help, type, field) static const CategoryDesc predef_categories[] = { /* sample runtime counter */ #include "perfcounters-def.h" { NULL, NULL, NUM_CATEGORIES, -1, 0, NUM_COUNTERS } }; #undef PERFCTR_CAT #undef PERFCTR_COUNTER #define PERFCTR_CAT(id, name, help, type, inst, first_counter) #define PERFCTR_COUNTER(id, name, help, type, field) {name, help, COUNTER_ ## id, offsetof (Il2CppPerfCounters, field), type}, static const CounterDesc predef_counters[] = { #include "perfcounters-def.h" { NULL, NULL, -1, 0, 0 } }; /* * We have several different classes of counters: * *) system counters * *) runtime counters * *) remote counters * *) user-defined counters * *) windows counters (the implementation on windows will use this) * * To easily handle the differences we create a vtable for each class that contains the * function pointers with the actual implementation to access the counters. */ typedef struct _ImplVtable ImplVtable; typedef bool(*SampleFunc) (ImplVtable *vtable, bool only_value, Il2CppCounterSample* sample); typedef uint64_t(*UpdateFunc) (ImplVtable *vtable, bool do_incr, int64_t value); typedef void(*CleanupFunc) (ImplVtable *vtable); struct _ImplVtable { void *arg; SampleFunc sample; UpdateFunc update; CleanupFunc cleanup; }; struct CustomVTable { ImplVtable vtable; SharedInstance *instance_desc; SharedCounter *counter_desc; }; const CategoryDesc* find_category(Il2CppString *category); const CounterDesc* get_counter_in_category(const CategoryDesc *desc, Il2CppString *counter); ImplVtable* create_vtable(void *arg, SampleFunc sample, UpdateFunc update); } /* namespace Diagnostics */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Diagnostics/Process.cpp ================================================ #include "il2cpp-config.h" #include "icalls/System/System.Diagnostics/Process.h" #include "os/Process.h" #include "vm/Exception.h" #include "vm/String.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Diagnostics { int32_t Process::ExitCode_internal(Il2CppIntPtr handle) { NOT_IMPLEMENTED_ICALL(Process::ExitCode_internal); return 0; } int64_t Process::ExitTime_internal(Il2CppIntPtr handle) { NOT_IMPLEMENTED_ICALL(Process::ExitTime_internal); return 0; } bool Process::GetWorkingSet_internal(Il2CppIntPtr handle, int32_t* min, int32_t* max) { NOT_IMPLEMENTED_ICALL(Process::GetWorkingSet_internal); return false; } bool Process::SetWorkingSet_internal(Il2CppIntPtr handle, int32_t min, int32_t max, bool use_min) { NOT_IMPLEMENTED_ICALL(Process::SetWorkingSet_internal); return false; } Il2CppArray* Process::GetModules_internal(void* /* System.Diagnostics.Process */ self, Il2CppIntPtr handle) { NOT_IMPLEMENTED_ICALL(Process::GetModules_internal); return 0; } int64_t Process::GetProcessData(int32_t pid, int32_t data_type, int32_t* error) { NOT_IMPLEMENTED_ICALL(Process::GetProcessData); return 0; } int32_t Process::GetPriorityClass(Il2CppIntPtr handle, int32_t* error) { NOT_IMPLEMENTED_ICALL(Process::GetPriorityClass); return 0; } bool Process::SetPriorityClass(Il2CppIntPtr handle, int32_t priority, int32_t* error) { NOT_IMPLEMENTED_ICALL(Process::SetPriorityClass); return false; } int64_t Process::Times(Il2CppIntPtr handle, int32_t type) { NOT_IMPLEMENTED_ICALL(Process::Times); return 0; } Il2CppString* Process::ProcessName_internal(Il2CppIntPtr handle) { os::ProcessHandle *pHandle = (os::ProcessHandle*)handle.m_value; std::string name = os::Process::GetProcessName(pHandle); return il2cpp::vm::String::New(name.c_str()); } int64_t Process::StartTime_internal(Il2CppIntPtr handle) { NOT_IMPLEMENTED_ICALL(Process::StartTime_internal); return 0; } bool Process::Kill_internal(Il2CppIntPtr handle, int32_t signo) { NOT_IMPLEMENTED_ICALL(Process::Kill_internal); return false; } Il2CppIntPtr Process::GetProcess_internal(int32_t pid) { Il2CppIntPtr process; process.m_value = os::Process::GetProcess(pid); return process; } int32_t Process::GetPid_internal() { return os::Process::GetCurrentProcessId(); } Il2CppArray* Process::GetProcesses_internal() { NOT_IMPLEMENTED_ICALL(Process::GetProcesses_internal); return 0; } bool Process::ShellExecuteEx_internal(void* /* System.Diagnostics.ProcessStartInfo */ startInfo, ProcInfo* proc_info) { NOT_IMPLEMENTED_ICALL(Process::ShellExecuteEx_internal); return false; } bool Process::CreateProcess_internal(void* /* System.Diagnostics.ProcessStartInfo */ startInfo, Il2CppIntPtr _stdin, Il2CppIntPtr _stdout, Il2CppIntPtr _stderr, ProcInfo* proc_info) { NOT_IMPLEMENTED_ICALL(Process::CreateProcess_internal); return false; } bool Process::WaitForExit_internal(void* /* System.Diagnostics.Process */ self, Il2CppIntPtr handle, int32_t ms) { NOT_IMPLEMENTED_ICALL(Process::WaitForExit_internal); return false; } bool Process::WaitForInputIdle_internal(void* /* System.Diagnostics.Process */ self, Il2CppIntPtr handle, int32_t ms) { NOT_IMPLEMENTED_ICALL(Process::WaitForInputIdle_internal); return false; } void Process::Process_free_internal(void* /* System.Diagnostics.Process */ self, Il2CppIntPtr handle) { os::Process::FreeProcess((os::ProcessHandle*)handle.m_value); } } /* namespace Diagnostics */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Diagnostics/Process.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Diagnostics { struct ProcInfo; class LIBIL2CPP_CODEGEN_API Process { public: static Il2CppArray* GetProcesses_internal(); static int32_t GetPid_internal(); static bool CreateProcess_internal(void* /* System.Diagnostics.ProcessStartInfo */ startInfo, Il2CppIntPtr _stdin, Il2CppIntPtr _stdout, Il2CppIntPtr _stderr, ProcInfo* proc_info); static int64_t ExitTime_internal(Il2CppIntPtr handle); static Il2CppArray* GetModules_internal(void* /* System.Diagnostics.Process */ self, Il2CppIntPtr handle); static int32_t GetPriorityClass(Il2CppIntPtr handle, int32_t* error); static int64_t GetProcessData(int32_t pid, int32_t data_type, int32_t* error); static Il2CppIntPtr GetProcess_internal(int32_t pid); static bool GetWorkingSet_internal(Il2CppIntPtr handle, int32_t* min, int32_t* max); static bool Kill_internal(Il2CppIntPtr handle, int32_t signo); static Il2CppString* ProcessName_internal(Il2CppIntPtr handle); static void Process_free_internal(void* /* System.Diagnostics.Process */ self, Il2CppIntPtr handle); static bool SetPriorityClass(Il2CppIntPtr handle, int32_t priority, int32_t* error); static bool SetWorkingSet_internal(Il2CppIntPtr handle, int32_t min, int32_t max, bool use_min); static bool ShellExecuteEx_internal(void* /* System.Diagnostics.ProcessStartInfo */ startInfo, ProcInfo* proc_info); static int64_t StartTime_internal(Il2CppIntPtr handle); static int64_t Times(Il2CppIntPtr handle, int32_t type); static bool WaitForExit_internal(void* /* System.Diagnostics.Process */ self, Il2CppIntPtr handle, int32_t ms); static bool WaitForInputIdle_internal(void* /* System.Diagnostics.Process */ self, Il2CppIntPtr handle, int32_t ms); static int32_t ExitCode_internal(Il2CppIntPtr handle); }; } /* namespace Diagnostics */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Diagnostics/Stopwatch.cpp ================================================ #include "il2cpp-config.h" #include "icalls/System/System.Diagnostics/Stopwatch.h" #include "os/Time.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Diagnostics { int64_t Stopwatch::GetTimestamp() { return il2cpp::os::Time::GetTicks100NanosecondsMonotonic(); } } /* namespace Diagnostics */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Diagnostics/Stopwatch.h ================================================ #pragma once #include #include "il2cpp-config.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Diagnostics { class LIBIL2CPP_CODEGEN_API Stopwatch { public: static int64_t GetTimestamp(); }; } /* namespace Diagnostics */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Diagnostics/perfcounters-def.h ================================================ /* * Define the system and runtime performance counters. * Each category is defined with the macro: * PERFCTR_CAT(catid, name, help, type, instances, first_counter_id) * and after that follows the counters inside the category, defined by the macro: * PERFCTR_COUNTER(counter_id, name, help, type, field) * field is the field inside MonoPerfCounters per predefined counters. * Note we set it to unused for unrelated counters: it is unused * in those cases. */ //PERFCTR_CAT(CPU, "Processor", "", MultiInstance, CPU, CPU_USER_TIME) //PERFCTR_COUNTER(CPU_USER_TIME, "% User Time", "", Timer100Ns, unused) //PERFCTR_COUNTER(CPU_PRIV_TIME, "% Privileged Time", "", Timer100Ns, unused) //PERFCTR_COUNTER(CPU_INTR_TIME, "% Interrupt Time", "", Timer100Ns, unused) //PERFCTR_COUNTER(CPU_DCP_TIME, "% DCP Time", "", Timer100Ns, unused) //PERFCTR_COUNTER(CPU_PROC_TIME, "% Processor Time", "", Timer100NsInverse, unused) // //PERFCTR_CAT(PROC, "Process", "", MultiInstance, Process, PROC_USER_TIME) //PERFCTR_COUNTER(PROC_USER_TIME, "% User Time", "", Timer100Ns, unused) //PERFCTR_COUNTER(PROC_PRIV_TIME, "% Privileged Time", "", Timer100Ns, unused) //PERFCTR_COUNTER(PROC_PROC_TIME, "% Processor Time", "", Timer100Ns, unused) //PERFCTR_COUNTER(PROC_THREADS, "Thread Count", "", NumberOfItems64, unused) //PERFCTR_COUNTER(PROC_VBYTES, "Virtual Bytes", "", NumberOfItems64, unused) //PERFCTR_COUNTER(PROC_WSET, "Working Set", "", NumberOfItems64, unused) //PERFCTR_COUNTER(PROC_PBYTES, "Private Bytes", "", NumberOfItems64, unused) /* sample runtime counter */ PERFCTR_CAT(MONO_MEM, "Mono Memory", "", SingleInstance, Mono, MEM_NUM_OBJECTS) PERFCTR_COUNTER(MEM_NUM_OBJECTS, "Allocated Objects", "", NumberOfItems64, unused) //PERFCTR_COUNTER(MEM_PHYS_TOTAL, "Total Physical Memory", "Physical memory installed in the machine, in bytes", NumberOfItems64, unused) //PERFCTR_COUNTER(MEM_PHYS_AVAILABLE, "Available Physical Memory", "Physical memory available in the machine, in bytes", NumberOfItems64, unused) // //PERFCTR_CAT(ASPNET, "ASP.NET", "", MultiInstance, Mono, ASPNET_REQ_Q) //PERFCTR_COUNTER(ASPNET_REQ_Q, "Requests Queued", "", NumberOfItems64, aspnet_requests_queued) //PERFCTR_COUNTER(ASPNET_REQ_TOTAL, "Requests Total", "", NumberOfItems32, aspnet_requests) //PERFCTR_COUNTER(ASPNET_REQ_PSEC, "Requests/Sec", "", RateOfCountsPerSecond32, aspnet_requests) // //PERFCTR_CAT(JIT, ".NET CLR JIT", "", MultiInstance, Mono, JIT_BYTES) //PERFCTR_COUNTER(JIT_BYTES, "# of IL Bytes JITted", "", NumberOfItems32, jit_bytes) //PERFCTR_COUNTER(JIT_METHODS, "# of IL Methods JITted", "", NumberOfItems32, jit_methods) //PERFCTR_COUNTER(JIT_TIME, "% Time in JIT", "", RawFraction, jit_time) //PERFCTR_COUNTER(JIT_BYTES_PSEC, "IL Bytes Jitted/Sec", "", RateOfCountsPerSecond32, jit_bytes) //PERFCTR_COUNTER(JIT_FAILURES, "Standard Jit Failures", "", NumberOfItems32, jit_failures) // //PERFCTR_CAT(EXC, ".NET CLR Exceptions", "", MultiInstance, Mono, EXC_THROWN) //PERFCTR_COUNTER(EXC_THROWN, "# of Exceps Thrown", "", NumberOfItems32, exceptions_thrown) //PERFCTR_COUNTER(EXC_THROWN_PSEC, "# of Exceps Thrown/Sec", "", RateOfCountsPerSecond32, exceptions_thrown) //PERFCTR_COUNTER(EXC_FILTERS_PSEC, "# of Filters/Sec", "", RateOfCountsPerSecond32, exceptions_filters) //PERFCTR_COUNTER(EXC_FINALLYS_PSEC, "# of Finallys/Sec", "", RateOfCountsPerSecond32, exceptions_finallys) //PERFCTR_COUNTER(EXC_CATCH_DEPTH, "Throw to Catch Depth/Sec", "", NumberOfItems32, exceptions_depth) // //PERFCTR_CAT(GC, ".NET CLR Memory", "", MultiInstance, Mono, GC_GEN0) //PERFCTR_COUNTER(GC_GEN0, "# Gen 0 Collections", "", NumberOfItems32, gc_collections0) //PERFCTR_COUNTER(GC_GEN1, "# Gen 1 Collections", "", NumberOfItems32, gc_collections1) //PERFCTR_COUNTER(GC_GEN2, "# Gen 2 Collections", "", NumberOfItems32, gc_collections2) //PERFCTR_COUNTER(GC_PROM0, "Promoted Memory from Gen 0", "", NumberOfItems32, gc_promotions0) //PERFCTR_COUNTER(GC_PROM1, "Promoted Memory from Gen 1", "", NumberOfItems32, gc_promotions1) //PERFCTR_COUNTER(GC_PROM0SEC, "Gen 0 Promoted Bytes/Sec", "", RateOfCountsPerSecond32, gc_promotions0) //PERFCTR_COUNTER(GC_PROM1SEC, "Gen 1 Promoted Bytes/Sec", "", RateOfCountsPerSecond32, gc_promotions1) //PERFCTR_COUNTER(GC_PROMFIN, "Promoted Finalization-Memory from Gen 0", "", NumberOfItems32, gc_promotion_finalizers) //PERFCTR_COUNTER(GC_GEN0SIZE, "Gen 0 heap size", "", NumberOfItems32, gc_gen0size) //PERFCTR_COUNTER(GC_GEN1SIZE, "Gen 1 heap size", "", NumberOfItems32, gc_gen1size) //PERFCTR_COUNTER(GC_GEN2SIZE, "Gen 2 heap size", "", NumberOfItems32, gc_gen2size) //PERFCTR_COUNTER(GC_LOSIZE, "Large Object Heap size", "", NumberOfItems32, gc_lossize) //PERFCTR_COUNTER(GC_FINSURV, "Finalization Survivors", "", NumberOfItems32, gc_fin_survivors) //PERFCTR_COUNTER(GC_NHANDLES, "# GC Handles", "", NumberOfItems32, gc_num_handles) //PERFCTR_COUNTER(GC_BYTESSEC, "Allocated Bytes/sec", "", RateOfCountsPerSecond32, gc_allocated) //PERFCTR_COUNTER(GC_INDGC, "# Induced GC", "", NumberOfItems32, gc_induced) //PERFCTR_COUNTER(GC_PERCTIME, "% Time in GC", "", RawFraction, gc_time) //PERFCTR_COUNTER(GC_BYTES, "# Bytes in all Heaps", "", NumberOfItems32, gc_total_bytes) //PERFCTR_COUNTER(GC_COMMBYTES, "# Total committed Bytes", "", NumberOfItems32, gc_committed_bytes) //PERFCTR_COUNTER(GC_RESBYTES, "# Total reserved Bytes", "", NumberOfItems32, gc_reserved_bytes) //PERFCTR_COUNTER(GC_PINNED, "# of Pinned Objects", "", NumberOfItems32, gc_num_pinned) //PERFCTR_COUNTER(GC_SYNKB, "# of Sink Blocks in use", "", NumberOfItems32, gc_sync_blocks) // //PERFCTR_CAT(REMOTING, ".NET CLR Remoting", "", MultiInstance, Mono, REMOTING_CALLSEC) //PERFCTR_COUNTER(REMOTING_CALLSEC, "Remote Calls/sec", "", RateOfCountsPerSecond32, remoting_calls) //PERFCTR_COUNTER(REMOTING_CALLS, "Total Remote Calls", "", NumberOfItems32, remoting_calls) //PERFCTR_COUNTER(REMOTING_CHANNELS, "Channels", "", NumberOfItems32, remoting_channels) //PERFCTR_COUNTER(REMOTING_CPROXIES, "Context Proxies", "", NumberOfItems32, remoting_proxies) //PERFCTR_COUNTER(REMOTING_CBLOADED, "Context-Bound Classes Loaded", "", NumberOfItems32, remoting_classes) //PERFCTR_COUNTER(REMOTING_CBALLOCSEC, "Context-Bound Objects Alloc / sec", "", RateOfCountsPerSecond32, remoting_objects) //PERFCTR_COUNTER(REMOTING_CONTEXTS, "Contexts", "", NumberOfItems32, remoting_contexts) // //PERFCTR_CAT(LOADING, ".NET CLR Loading", "", MultiInstance, Mono, LOADING_CLASSES) //PERFCTR_COUNTER(LOADING_CLASSES, "Current Classes Loaded", "", NumberOfItems32, loader_classes) //PERFCTR_COUNTER(LOADING_TOTCLASSES, "Total Classes Loaded", "", NumberOfItems32, loader_total_classes) //PERFCTR_COUNTER(LOADING_CLASSESSEC, "Rate of Classes Loaded", "", RateOfCountsPerSecond32, loader_total_classes) //PERFCTR_COUNTER(LOADING_APPDOMAINS, "Current appdomains", "", NumberOfItems32, loader_appdomains) //PERFCTR_COUNTER(LOADING_TOTAPPDOMAINS, "Total Appdomains", "", NumberOfItems32, loader_total_appdomains) //PERFCTR_COUNTER(LOADING_APPDOMAINSEC, "Rate of appdomains", "", RateOfCountsPerSecond32, loader_total_appdomains) //PERFCTR_COUNTER(LOADING_ASSEMBLIES, "Current Assemblies", "", NumberOfItems32, loader_assemblies) //PERFCTR_COUNTER(LOADING_TOTASSEMBLIES, "Total Assemblies", "", NumberOfItems32, loader_total_assemblies) //PERFCTR_COUNTER(LOADING_ASSEMBLIESEC, "Rate of Assemblies", "", RateOfCountsPerSecond32, loader_total_assemblies) //PERFCTR_COUNTER(LOADING_FAILURES, "Total # of Load Failures", "", NumberOfItems32, loader_failures) //PERFCTR_COUNTER(LOADING_FAILURESSEC, "Rate of Load Failures", "", RateOfCountsPerSecond32, loader_failures) //PERFCTR_COUNTER(LOADING_BYTES, "Bytes in Loader Heap", "", NumberOfItems32, loader_bytes) //PERFCTR_COUNTER(LOADING_APPUNLOADED, "Total appdomains unloaded", "", NumberOfItems32, loader_appdomains_uloaded) //PERFCTR_COUNTER(LOADING_APPUNLOADEDSEC, "Rate of appdomains unloaded", "", RateOfCountsPerSecond32, loader_appdomains_uloaded) // //PERFCTR_CAT(THREAD, ".NET CLR LocksAndThreads", "", MultiInstance, Mono, THREAD_CONTENTIONS) //PERFCTR_COUNTER(THREAD_CONTENTIONS, "Total # of Contentions", "", NumberOfItems32, thread_contentions) //PERFCTR_COUNTER(THREAD_CONTENTIONSSEC, "Contention Rate / sec", "", RateOfCountsPerSecond32, thread_contentions) //PERFCTR_COUNTER(THREAD_QUEUELEN, "Current Queue Length", "", NumberOfItems32, thread_queue_len) //PERFCTR_COUNTER(THREAD_QUEUELENP, "Queue Length Peak", "", NumberOfItems32, thread_queue_max) //PERFCTR_COUNTER(THREAD_QUEUELENSEC, "Queue Length / sec", "", RateOfCountsPerSecond32, thread_queue_max) //PERFCTR_COUNTER(THREAD_NUMLOG, "# of current logical Threads", "", NumberOfItems32, thread_num_logical) //PERFCTR_COUNTER(THREAD_NUMPHYS, "# of current physical Threads", "", NumberOfItems32, thread_num_physical) //PERFCTR_COUNTER(THREAD_NUMREC, "# of current recognized threads", "", NumberOfItems32, thread_cur_recognized) //PERFCTR_COUNTER(THREAD_TOTREC, "# of total recognized threads", "", NumberOfItems32, thread_num_recognized) //PERFCTR_COUNTER(THREAD_TOTRECSEC, "rate of recognized threads / sec", "", RateOfCountsPerSecond32, thread_num_recognized) // //PERFCTR_CAT(INTEROP, ".NET CLR Interop", "", MultiInstance, Mono, INTEROP_NUMCCW) //PERFCTR_COUNTER(INTEROP_NUMCCW, "# of CCWs", "", NumberOfItems32, interop_num_ccw) //PERFCTR_COUNTER(INTEROP_STUBS, "# of Stubs", "", NumberOfItems32, interop_num_stubs) //PERFCTR_COUNTER(INTEROP_MARSH, "# of marshalling", "", NumberOfItems32, interop_num_marshals) // //PERFCTR_CAT(SECURITY, ".NET CLR Security", "", MultiInstance, Mono, SECURITY_CHECKS) //PERFCTR_COUNTER(SECURITY_CHECKS, "Total Runtime Checks", "", NumberOfItems32, security_num_checks) //PERFCTR_COUNTER(SECURITY_LCHECKS, "# Link Time Checks", "", NumberOfItems32, security_num_link_checks) //PERFCTR_COUNTER(SECURITY_PERCTIME, "% Time in RT checks", "", RawFraction, security_time) //PERFCTR_COUNTER(SECURITY_SWDEPTH, "Stack Walk Depth", "", NumberOfItems32, security_depth) // //PERFCTR_CAT(THREADPOOL, "Mono Threadpool", "", MultiInstance, Mono, THREADPOOL_WORKITEMS) //PERFCTR_COUNTER(THREADPOOL_WORKITEMS, "Work Items Added", "", NumberOfItems64, threadpool_workitems) //PERFCTR_COUNTER(THREADPOOL_WORKITEMS_PSEC, "Work Items Added/Sec", "", RateOfCountsPerSecond32, threadpool_workitems) //PERFCTR_COUNTER(THREADPOOL_IOWORKITEMS, "IO Work Items Added", "", NumberOfItems64, threadpool_ioworkitems) //PERFCTR_COUNTER(THREADPOOL_IOWORKITEMS_PSEC, "IO Work Items Added/Sec", "", RateOfCountsPerSecond32, threadpool_ioworkitems) //PERFCTR_COUNTER(THREADPOOL_THREADS, "# of Threads", "", NumberOfItems32, threadpool_threads) //PERFCTR_COUNTER(THREADPOOL_IOTHREADS, "# of IO Threads", "", NumberOfItems32, threadpool_iothreads) // //PERFCTR_CAT(NETWORK, "Network Interface", "", MultiInstance, NetworkInterface, NETWORK_BYTESRECSEC) //PERFCTR_COUNTER(NETWORK_BYTESRECSEC, "Bytes Received/sec", "", RateOfCountsPerSecond64, unused) //PERFCTR_COUNTER(NETWORK_BYTESSENTSEC, "Bytes Sent/sec", "", RateOfCountsPerSecond64, unused) //PERFCTR_COUNTER(NETWORK_BYTESTOTALSEC, "Bytes Total/sec", "", RateOfCountsPerSecond64, unused) ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.IO/FAMWatcher.cpp ================================================ #include "il2cpp-config.h" #include "icalls/System/System.IO/FAMWatcher.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace IO { int32_t FAMWatcher::InternalFAMNextEvent(FAMConnection* fc, Il2CppString** filename, int32_t* code, int32_t* reqnum) { NOT_IMPLEMENTED_ICALL(FAMWatcher::InternalFAMNextEvent); return 0; } } /* namespace IO */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.IO/FAMWatcher.h ================================================ #pragma once #include #include "object-internals.h" #include "il2cpp-config.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace System { namespace System { namespace IO { struct FAMConnection; class LIBIL2CPP_CODEGEN_API FAMWatcher { public: static int32_t InternalFAMNextEvent(FAMConnection* fc, Il2CppString** filename, int32_t* code, int32_t* reqnum); }; } /* namespace IO */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.IO/FileSystemWatcher.cpp ================================================ #include "il2cpp-config.h" #include "icalls/System/System.IO/FileSystemWatcher.h" #include "os/FileSystemWatcher.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace IO { int32_t FileSystemWatcher::InternalSupportsFSW() { return os::FileSystemWatcher::IsSupported(); } } /* namespace IO */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.IO/FileSystemWatcher.h ================================================ #pragma once #include #include "object-internals.h" #include "il2cpp-config.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace System { namespace System { namespace IO { class LIBIL2CPP_CODEGEN_API FileSystemWatcher { public: static int32_t InternalSupportsFSW(); }; } /* namespace IO */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.IO/InotifyWatcher.cpp ================================================ #include "il2cpp-config.h" #include "icalls/System/System.IO/InotifyWatcher.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace IO { Il2CppIntPtr InotifyWatcher::GetInotifyInstance() { NOT_IMPLEMENTED_ICALL(InotifyWatcher::GetInotifyInstance); return Il2CppIntPtr(); } int32_t InotifyWatcher::AddWatch(Il2CppIntPtr fd, Il2CppString* name, InotifyMask mask) { NOT_IMPLEMENTED_ICALL(InotifyWatcher::AddWatch); return 0; } Il2CppIntPtr InotifyWatcher::RemoveWatch(Il2CppIntPtr fd, int32_t wd) { NOT_IMPLEMENTED_ICALL(InotifyWatcher::RemoveWatch); return Il2CppIntPtr(); } } /* namespace IO */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.IO/InotifyWatcher.h ================================================ #pragma once #include #include "object-internals.h" #include "il2cpp-config.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace System { namespace System { namespace IO { typedef int32_t InotifyMask; class LIBIL2CPP_CODEGEN_API InotifyWatcher { public: static Il2CppIntPtr RemoveWatch(Il2CppIntPtr fd, int32_t wd); static int32_t AddWatch(Il2CppIntPtr fd, Il2CppString* name, InotifyMask mask); static Il2CppIntPtr GetInotifyInstance(); }; } /* namespace IO */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.IO/KqueueMonitor.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "KqueueMonitor.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace IO { int32_t KqueueMonitor::kevent_notimeout(int32_t* kq, Il2CppIntPtr ev, int32_t nchanges, Il2CppIntPtr evtlist, int32_t nevents) { NOT_IMPLEMENTED_ICALL(KqueueMonitor::kevent_notimeout); IL2CPP_UNREACHABLE; return 0; } } // namespace IO } // namespace System } // namespace System } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.IO/KqueueMonitor.h ================================================ #pragma once #if NET_4_0 #include "object-internals.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace IO { class LIBIL2CPP_CODEGEN_API KqueueMonitor { public: static int32_t kevent_notimeout(int32_t* kq, Il2CppIntPtr ev, int32_t nchanges, Il2CppIntPtr evtlist, int32_t nevents); }; } // namespace IO } // namespace System } // namespace System } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Net/Dns.cpp ================================================ #include "il2cpp-config.h" #include "icalls/System/System.Net/Dns.h" #include "class-internals.h" #include "object-internals.h" #include "vm/Array.h" #include "vm/String.h" #include "os/Socket.h" #include "os/WaitStatus.h" #include "utils/StringUtils.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Net { bool Dns::GetHostByAddr(Il2CppString* addr, Il2CppString** h_name, Il2CppArray** h_aliases, Il2CppArray** h_addr_list) { std::string name; std::vector aliases; std::vector addr_list; const std::string address = il2cpp::utils::StringUtils::Utf16ToUtf8(addr->chars); const os::WaitStatus result = os::Socket::GetHostByAddr(address, name, aliases, addr_list); *h_name = vm::String::New(name.c_str()); *h_aliases = vm::Array::New(il2cpp_defaults.string_class, (il2cpp_array_size_t)aliases.size()); *h_addr_list = vm::Array::New(il2cpp_defaults.string_class, (il2cpp_array_size_t)addr_list.size()); int32_t index = 0; std::vector::const_iterator it = aliases.begin(); while (it != aliases.end()) { il2cpp_array_setref(*h_aliases, index++, vm::String::New((*it).c_str())); ++it; } index = 0; it = addr_list.begin(); while (it != addr_list.end()) { il2cpp_array_setref(*h_addr_list, index++, vm::String::New((*it).c_str())); ++it; } return (result != os::kWaitStatusFailure); } bool Dns::GetHostByName(Il2CppString* host, Il2CppString** h_name, Il2CppArray** h_aliases, Il2CppArray** h_addr_list) { std::string name; std::vector aliases; std::vector addr_list; const std::string host_name = il2cpp::utils::StringUtils::Utf16ToUtf8(host->chars); const os::WaitStatus result = os::Socket::GetHostByName(host_name, name, aliases, addr_list); *h_name = vm::String::New(name.c_str()); *h_aliases = vm::Array::New(il2cpp_defaults.string_class, (il2cpp_array_size_t)aliases.size()); *h_addr_list = vm::Array::New(il2cpp_defaults.string_class, (il2cpp_array_size_t)addr_list.size()); int32_t index = 0; std::vector::const_iterator it = aliases.begin(); while (it != aliases.end()) { il2cpp_array_setref(*h_aliases, index++, vm::String::New((*it).c_str())); ++it; } index = 0; it = addr_list.begin(); while (it != addr_list.end()) { il2cpp_array_setref(*h_addr_list, index++, vm::String::New((*it).c_str())); ++it; } return (result != os::kWaitStatusFailure); } bool Dns::GetHostName(Il2CppString** name) { std::string host_name; *name = (os::Socket::GetHostName(host_name) != os::kWaitStatusFailure) ? vm::String::New(host_name.c_str()) : NULL; return *name != NULL; } } /* namespace Net */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Net/Dns.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppArray; struct Il2CppString; namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Net { class LIBIL2CPP_CODEGEN_API Dns { public: static bool GetHostByAddr(Il2CppString*, Il2CppString**, Il2CppArray**, Il2CppArray**); static bool GetHostByName(Il2CppString*, Il2CppString**, Il2CppArray**, Il2CppArray**); static bool GetHostName(Il2CppString**); }; } /* namespace Net */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Net.NetworkInformation/LinuxNetworkInterface.cpp ================================================ #if !NET_4_0 #include "il2cpp-config.h" #include "LinuxNetworkInterface.h" #include "external/xamarin-android/xamarin_getifaddrs.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Net { namespace NetworkInformation { int32_t LinuxNetworkInterface::GetInterfaceAddresses(Il2CppIntPtr* ifap) { return _monodroid_getifaddrs(reinterpret_cast<_monodroid_ifaddrs**>(&ifap->m_value)); } void LinuxNetworkInterface::FreeInterfaceAddresses(Il2CppIntPtr ifap) { _monodroid_freeifaddrs(static_cast<_monodroid_ifaddrs*>(ifap.m_value)); } void LinuxNetworkInterface::InitializeInterfaceAddresses() { _monodroid_getifaddrs_init(); } } // namespace NetworkInformation } // namespace Net } // namespace System } // namespace System } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Net.NetworkInformation/LinuxNetworkInterface.h ================================================ #pragma once #if !NET_4_0 #include "object-internals.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Net { namespace NetworkInformation { class LIBIL2CPP_CODEGEN_API LinuxNetworkInterface { public: static int32_t GetInterfaceAddresses(Il2CppIntPtr* ifap); static void FreeInterfaceAddresses(Il2CppIntPtr ifap); static void InitializeInterfaceAddresses(); }; } // namespace NetworkInformation } // namespace Net } // namespace System } // namespace System } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Net.NetworkInformation/MacOsIPInterfaceProperties.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "MacOsIPInterfaceProperties.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Net { namespace NetworkInformation { bool MacOsIPInterfaceProperties::ParseRouteInfo_internal(Il2CppString* iface, Il2CppArray** gw_addr_list) { NOT_IMPLEMENTED_ICALL(MacOsIPInterfaceProperties::ParseRouteInfo_internal); IL2CPP_UNREACHABLE; return false; } } // namespace NetworkInformation } // namespace Net } // namespace System } // namespace System } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Net.NetworkInformation/MacOsIPInterfaceProperties.h ================================================ #pragma once #if NET_4_0 namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Net { namespace NetworkInformation { class LIBIL2CPP_CODEGEN_API MacOsIPInterfaceProperties { public: static bool ParseRouteInfo_internal(Il2CppString* iface, Il2CppArray** gw_addr_list); }; } // namespace NetworkInformation } // namespace Net } // namespace System } // namespace System } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Net.Sockets/Socket.cpp ================================================ #include "il2cpp-config.h" #include "icalls/System/System.Net.Sockets/Socket.h" #include "class-internals.h" #include "os/Socket.h" #include "os/Mutex.h" #include "os/Thread.h" #include "utils/StringUtils.h" #include "vm/Array.h" #include "vm/Assembly.h" #include "vm/Class.h" #include "vm/Exception.h" #include "vm/Field.h" #include "vm/Object.h" #include "vm/String.h" #include "vm/Thread.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Net { namespace Sockets { static os::AddressFamily convert_address_family(AddressFamily family) { switch (family) { case kAddressFamilyUnknown: case kAddressFamilyImpLink: case kAddressFamilyPup: case kAddressFamilyChaos: case kAddressFamilyIso: case kAddressFamilyEcma: case kAddressFamilyDataKit: case kAddressFamilyCcitt: case kAddressFamilyDataLink: case kAddressFamilyLat: case kAddressFamilyHyperChannel: case kAddressFamilyNetBios: case kAddressFamilyVoiceView: case kAddressFamilyFireFox: case kAddressFamilyBanyan: case kAddressFamilyAtm: case kAddressFamilyCluster: case kAddressFamilyIeee12844: case kAddressFamilyNetworkDesigners: // Unsupported return os::kAddressFamilyError; case kAddressFamilyUnspecified: return os::kAddressFamilyUnspecified; case kAddressFamilyUnix: return os::kAddressFamilyUnix; case kAddressFamilyInterNetwork: return os::kAddressFamilyInterNetwork; case kAddressFamilyIpx: return os::kAddressFamilyIpx; case kAddressFamilySna: return os::kAddressFamilySna; case kAddressFamilyDecNet: return os::kAddressFamilyDecNet; case kAddressFamilyAppleTalk: return os::kAddressFamilyAppleTalk; case kAddressFamilyInterNetworkV6: return os::kAddressFamilyInterNetworkV6; case kAddressFamilyIrda: return os::kAddressFamilyIrda; default: return os::kAddressFamilyError; } return os::kAddressFamilyError; } static os::SocketType convert_socket_type(SocketType type) { switch (type) { case kSocketTypeStream: return os::kSocketTypeStream; case kSocketTypeDgram: return os::kSocketTypeDgram; case kSocketTypeRaw: return os::kSocketTypeRaw; case kSocketTypeRdm: return os::kSocketTypeRdm; case kSocketTypeSeqpacket: return os::kSocketTypeSeqpacket; default: return os::kSocketTypeError; } return os::kSocketTypeError; } static os::ProtocolType convert_socket_protocol(ProtocolType protocol) { switch (protocol) { case kProtocolTypeIP: case kProtocolTypeIPv6: case kProtocolTypeIcmp: case kProtocolTypeIgmp: case kProtocolTypeGgp: case kProtocolTypeTcp: case kProtocolTypePup: case kProtocolTypeUdp: case kProtocolTypeIdp: // In this case the enum values map exactly. return (os::ProtocolType)protocol; case kProtocolTypeND: case kProtocolTypeRaw: case kProtocolTypeIpx: case kProtocolTypeSpx: case kProtocolTypeSpxII: case kProtocolTypeUnknown: // Everything else in unsupported return os::kProtocolTypeUnknown; default: return os::kProtocolTypeUnknown; } return os::kProtocolTypeUnknown; } static AddressFamily convert_from_os_address_family(os::AddressFamily family) { switch (family) { case os::kAddressFamilyUnspecified: return kAddressFamilyUnspecified; case os::kAddressFamilyUnix: return kAddressFamilyUnix; case os::kAddressFamilyInterNetwork: return kAddressFamilyInterNetwork; // #ifdef AF_IPX case os::kAddressFamilyIpx: return kAddressFamilyIpx; // #endif case os::kAddressFamilySna: return kAddressFamilySna; case os::kAddressFamilyDecNet: return kAddressFamilyDecNet; case os::kAddressFamilyAppleTalk: return kAddressFamilyAppleTalk; // #ifdef AF_INET6 case os::kAddressFamilyInterNetworkV6: return kAddressFamilyInterNetworkV6; // #endif // #ifdef AF_IRDA case os::kAddressFamilyIrda: return kAddressFamilyIrda; // #endif default: break; } return kAddressFamilyUnknown; } static os::SocketFlags convert_socket_flags(SocketFlags flags) { return (os::SocketFlags)flags; } static Il2CppSocketAddress* end_point_info_to_socket_address(const os::EndPointInfo &info) { static Il2CppClass *System_Net_SocketAddress = NULL; Il2CppSocketAddress *socket_address = NULL; if (!System_Net_SocketAddress) { System_Net_SocketAddress = vm::Class::FromName( vm::Assembly::GetImage( vm::Assembly::Load("System.dll")), "System.Net", "SocketAddress"); } socket_address = (Il2CppSocketAddress*)vm::Object::New(System_Net_SocketAddress); const AddressFamily family = convert_from_os_address_family(info.family); if (info.family == os::kAddressFamilyInterNetwork) { #if NET_4_0 socket_address->m_Size = 8; #endif socket_address->data = vm::Array::New(il2cpp_defaults.byte_class, 8); const uint16_t port = info.data.inet.port; const uint32_t address = info.data.inet.address; il2cpp_array_set(socket_address->data, uint8_t, 0, (family >> 0) & 0xFF); il2cpp_array_set(socket_address->data, uint8_t, 1, (family >> 8) & 0xFF); il2cpp_array_set(socket_address->data, uint8_t, 2, (port >> 8) & 0xFF); il2cpp_array_set(socket_address->data, uint8_t, 3, (port >> 0) & 0xFF); il2cpp_array_set(socket_address->data, uint8_t, 4, (address >> 24) & 0xFF); il2cpp_array_set(socket_address->data, uint8_t, 5, (address >> 16) & 0xFF); il2cpp_array_set(socket_address->data, uint8_t, 6, (address >> 8) & 0xFF); il2cpp_array_set(socket_address->data, uint8_t, 7, (address >> 0) & 0xFF); } else if (info.family == os::kAddressFamilyUnix) { const int32_t path_len = (int32_t)strlen(info.data.path); #if NET_4_0 socket_address->m_Size = 3 + path_len; #endif socket_address->data = vm::Array::New(il2cpp_defaults.byte_class, 3 + path_len); il2cpp_array_set(socket_address->data, uint8_t, 0, (family >> 0) & 0xFF); il2cpp_array_set(socket_address->data, uint8_t, 1, (family >> 8) & 0xFF); for (int32_t i = 0; i <= path_len; i++) il2cpp_array_set(socket_address->data, uint8_t, i + 2, info.data.path[i]); il2cpp_array_set(socket_address->data, uint8_t, 2 + path_len, 0); } else if (info.family == os::kAddressFamilyInterNetworkV6) { #if NET_4_0 socket_address->m_Size = 28; #endif socket_address->data = vm::Array::New(il2cpp_defaults.byte_class, 28); il2cpp_array_set(socket_address->data, uint8_t, 0, (family >> 0) & 0xFF); il2cpp_array_set(socket_address->data, uint8_t, 1, (family >> 8) & 0xFF); // Note that we start at the 3rd byte in both the managed array, where the first // two bytes are the family, set just above this. We also start at the third byte // in the info.data.raw array, as the first two bytes are unused and garbage data. for (int i = 2; i < 28; ++i) il2cpp_array_set(socket_address->data, uint8_t, i, info.data.raw[i]); } else { // Not supported return NULL; } return socket_address; } static bool check_thread_status() { static os::FastMutex _mutex; os::FastAutoLock lock(&_mutex); Il2CppThread *current_thread = vm::Thread::Current(); const vm::ThreadState state = vm::Thread::GetState(current_thread); if (state & vm::kThreadStateAbortRequested) return false; if (state & vm::kThreadStateSuspendRequested) { IL2CPP_ASSERT(0 && "kThreadStateSuspendRequested not supported yet!"); return true; } if (state & vm::kThreadStateStopRequested) return false; if (current_thread->GetInternalThread()->interruption_requested) { IL2CPP_ASSERT(0 && "thread->interruption_requested not supported yet!"); return false; } return true; } /// Acquire os::SocketHandle in IntPtr "socket" for the current scope. #define AUTO_ACQUIRE_SOCKET \ os::SocketHandleWrapper socketHandle (os::PointerToSocketHandle (socket.m_value)) #define RETURN_IF_SOCKET_IS_INVALID(...) \ if (!socketHandle.IsValid ()) \ { \ *error = os::kErrorCodeInvalidHandle; \ return __VA_ARGS__; \ } Il2CppIntPtr Socket::Accept(Il2CppIntPtr socket, int32_t* error, bool blocking) { *error = 0; os::Socket *new_sock = NULL; AUTO_ACQUIRE_SOCKET; if (socketHandle.IsValid()) { const os::WaitStatus status = socketHandle->Accept(&new_sock); if (status == os::kWaitStatusFailure) *error = socketHandle->GetLastError(); } else { *error = os::kErrorCodeInvalidHandle; } Il2CppIntPtr ret; if (new_sock) ret.m_value = reinterpret_cast(static_cast(os::CreateSocketHandle(new_sock))); else ret.m_value = NULL; return ret; } int32_t Socket::Available(Il2CppIntPtr socket, int32_t *error) { *error = 0; AUTO_ACQUIRE_SOCKET; RETURN_IF_SOCKET_IS_INVALID(0); int32_t available = 0; const os::WaitStatus status = socketHandle->Available(&available); if (status == os::kWaitStatusFailure) { *error = socketHandle->GetLastError(); return 0; } return available; } void UnpackIPv6AddressFromBuffer(const uint8_t* buffer, int32_t length, uint16_t* port, uint8_t* address, uint32_t* scope) { if (length < 28) { vm::Exception::Raise(vm::Exception::GetSystemException()); return; } *port = ((buffer[2] << 8) | buffer[3]); for (int i = 0; i < ipv6AddressSize; i++) address[i] = buffer[i + 8]; *scope = (uint32_t)((buffer[27] << 24) + (buffer[26] << 16) + (buffer[25] << 8) + (buffer[24])); } void Socket::Bind(Il2CppIntPtr socket, Il2CppSocketAddress* socket_address, int32_t* error) { *error = 0; const int32_t length = socket_address->data->max_length; const uint8_t *buffer = (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress(socket_address->data); if (length < 2) { vm::Exception::Raise(vm::Exception::GetSystemException()); return; } const os::AddressFamily family = convert_address_family((AddressFamily)(buffer[0] | (buffer[1] << 8))); AUTO_ACQUIRE_SOCKET; RETURN_IF_SOCKET_IS_INVALID(); if (family == os::kAddressFamilyInterNetwork) { if (length < 8) { vm::Exception::Raise(vm::Exception::GetSystemException()); return; } const uint16_t port = ((buffer[2] << 8) | buffer[3]); const uint32_t address = ((buffer[4] << 24) | (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]); const os::WaitStatus status = socketHandle->Bind(address, port); if (status == os::kWaitStatusFailure) *error = socketHandle->GetLastError(); } else if (family == os::kAddressFamilyUnix) { if (length - 2 >= END_POINT_MAX_PATH_LEN) { vm::Exception::Raise(vm::Exception::GetSystemException()); return; } char path[END_POINT_MAX_PATH_LEN] = {0}; for (int32_t i = 0; i < (length - 2); ++i) { path[i] = (char)buffer[i + 2]; } const os::WaitStatus status = socketHandle->Bind(path); if (status == os::kWaitStatusFailure) *error = socketHandle->GetLastError(); } else if (family == os::kAddressFamilyInterNetworkV6) { uint16_t port; uint8_t address[ipv6AddressSize] = {0}; uint32_t scope; UnpackIPv6AddressFromBuffer(buffer, length, &port, address, &scope); const os::WaitStatus status = socketHandle->Bind(address, scope, port); if (status == os::kWaitStatusFailure) *error = socketHandle->GetLastError(); } else { *error = os::kWSAeafnosupport; return; } } void Socket::Blocking(Il2CppIntPtr socket, bool block, int32_t* error) { *error = 0; AUTO_ACQUIRE_SOCKET; RETURN_IF_SOCKET_IS_INVALID(); const os::WaitStatus status = socketHandle->SetBlocking(block); if (status == os::kWaitStatusFailure) *error = socketHandle->GetLastError(); } void Socket::Close(Il2CppIntPtr socket, int32_t* error) { *error = 0; // Socket::Close get invoked when running the finalizers; in case Socket_internal // didn't succeed, the socket.m_value has a NULL value and thus we don't need to do // anything here. if (os::PointerToSocketHandle(socket.m_value) == os::kInvalidSocketHandle) return; AUTO_ACQUIRE_SOCKET; RETURN_IF_SOCKET_IS_INVALID(); socket.m_value = (void*)os::kInvalidSocketHandle; socketHandle->Close(); // There is an implicit acquisition happening when we create the socket which we undo // now that we have closed the socket. os::ReleaseSocketHandle(socketHandle.GetHandle()); } void Socket::Connect(Il2CppIntPtr socket, Il2CppSocketAddress* socket_address, int32_t* error) { *error = 0; const int32_t length = socket_address->data->max_length; const uint8_t *buffer = (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress(socket_address->data); if (length < 2) { vm::Exception::Raise(vm::Exception::GetSystemException()); return; } const os::AddressFamily family = convert_address_family((AddressFamily)(buffer[0] | (buffer[1] << 8))); AUTO_ACQUIRE_SOCKET; RETURN_IF_SOCKET_IS_INVALID(); if (family == os::kAddressFamilyInterNetwork) { if (length < 8) { vm::Exception::Raise(vm::Exception::GetSystemException()); return; } const uint16_t port = ((buffer[2] << 8) | buffer[3]); const uint32_t address = ((buffer[4] << 24) | (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]); const os::WaitStatus status = socketHandle->Connect(address, port); if (status == os::kWaitStatusFailure) *error = socketHandle->GetLastError(); } else if (family == os::kAddressFamilyUnix) { if (length - 2 >= END_POINT_MAX_PATH_LEN) { vm::Exception::Raise(vm::Exception::GetSystemException()); return; } char path[END_POINT_MAX_PATH_LEN] = {0}; for (int32_t i = 0; i < (length - 2); ++i) { path[i] = (char)buffer[i + 2]; } const os::WaitStatus status = socketHandle->Connect(path); if (status == os::kWaitStatusFailure) *error = socketHandle->GetLastError(); } else if (family == os::kAddressFamilyInterNetworkV6) { uint16_t port; uint8_t address[ipv6AddressSize] = {0}; uint32_t scope; UnpackIPv6AddressFromBuffer(buffer, length, &port, address, &scope); const os::WaitStatus status = socketHandle->Connect(address, scope, port); if (status == os::kWaitStatusFailure) *error = socketHandle->GetLastError(); } else { *error = os::kWSAeafnosupport; return; } } void Socket::Disconnect(Il2CppIntPtr socket, bool reuse, int32_t *error) { *error = 0; AUTO_ACQUIRE_SOCKET; RETURN_IF_SOCKET_IS_INVALID(); const os::WaitStatus status = socketHandle->Disconnect(reuse); if (status == os::kWaitStatusFailure) *error = socketHandle->GetLastError(); } void Socket::GetSocketOptionArray(Il2CppIntPtr socket, SocketOptionLevel level, SocketOptionName name, Il2CppArray **byte_val, int32_t *error) { *error = 0; // Note: for now the options map one to one. const os::SocketOptionName system_name = (os::SocketOptionName)(name); const os::SocketOptionLevel system_level = (os::SocketOptionLevel)(level); int32_t length = (*byte_val)->max_length; uint8_t *buffer = (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress((*byte_val)); AUTO_ACQUIRE_SOCKET; RETURN_IF_SOCKET_IS_INVALID(); const os::WaitStatus status = socketHandle->GetSocketOption(system_level, system_name, buffer, &length); if (status == os::kWaitStatusFailure) *error = socketHandle->GetLastError(); } void Socket::GetSocketOptionObj(Il2CppIntPtr socket, SocketOptionLevel level, SocketOptionName name, Il2CppObject **obj_val, int32_t *error) { *error = 0; // Note: for now the options map one to one. const os::SocketOptionName system_name = (os::SocketOptionName)(name); const os::SocketOptionLevel system_level = (os::SocketOptionLevel)(level); AUTO_ACQUIRE_SOCKET; RETURN_IF_SOCKET_IS_INVALID(); int32_t first = 0; int32_t second = 0; const os::WaitStatus status = socketHandle->GetSocketOptionFull(system_level, system_name, &first, &second); if (status == os::kWaitStatusFailure) { *error = socketHandle->GetLastError(); return; } switch (name) { case kSocketOptionNameLinger: { static Il2CppClass *System_Net_Sockets_LingerOption = NULL; if (!System_Net_Sockets_LingerOption) { System_Net_Sockets_LingerOption = vm::Class::FromName( vm::Assembly::GetImage( vm::Assembly::Load("System.dll")), "System.Net.Sockets", "LingerOption"); } *obj_val = vm::Object::New(System_Net_Sockets_LingerOption); #if NET_4_0 const FieldInfo *enabled_field_info = vm::Class::GetFieldFromName(System_Net_Sockets_LingerOption, "enabled"); const FieldInfo *seconds_field_info = vm::Class::GetFieldFromName(System_Net_Sockets_LingerOption, "lingerTime"); #else const FieldInfo *enabled_field_info = vm::Class::GetFieldFromName(System_Net_Sockets_LingerOption, "enabled"); const FieldInfo *seconds_field_info = vm::Class::GetFieldFromName(System_Net_Sockets_LingerOption, "seconds"); #endif *((bool*)((char*)(*obj_val) + enabled_field_info->offset)) = (first ? 1 : 0); *((int32_t*)((char*)(*obj_val) + seconds_field_info->offset)) = second; } break; case kSocketOptionNameDontLinger: case kSocketOptionNameSendTimeout: case kSocketOptionNameReceiveTimeout: default: *obj_val = vm::Object::Box(il2cpp_defaults.int32_class, &first); break; } } void Socket::Listen(Il2CppIntPtr socket, int32_t backlog, int32_t *error) { *error = 0; AUTO_ACQUIRE_SOCKET; RETURN_IF_SOCKET_IS_INVALID(); const os::WaitStatus status = socketHandle->Listen(backlog); if (status == os::kWaitStatusFailure) *error = socketHandle->GetLastError(); } static os::PollFlags select_mode_to_poll_flags(SelectMode mode) { switch (mode) { case kSelectModeSelectRead: return os::kPollFlagsIn; case kSelectModeSelectWrite: return os::kPollFlagsOut; case kSelectModeSelectError: return os::kPollFlagsErr; } return os::kPollFlagsNone; } bool Socket::Poll(Il2CppIntPtr socket, SelectMode mode, int32_t timeout, int32_t *error) { *error = 0; os::PollRequest request; AUTO_ACQUIRE_SOCKET; RETURN_IF_SOCKET_IS_INVALID(false); request.fd = socketHandle.GetSocket()->GetDescriptor(); request.events = select_mode_to_poll_flags(mode); request.revents = os::kPollFlagsNone; if (request.events == os::kPollFlagsNone) { *error = os::kWSAefault; return false; } std::vector requests; requests.push_back(request); int32_t results = 0; const os::WaitStatus result = os::Socket::Poll(requests, timeout, &results, error); if (result == os::kWaitStatusFailure || results == 0) return false; return (requests[0].revents != os::kPollFlagsNone); } int32_t Socket::ReceiveArray(Il2CppIntPtr socket, Il2CppArray *buffers, SocketFlags flags, int32_t *error) { *error = 0; AUTO_ACQUIRE_SOCKET; RETURN_IF_SOCKET_IS_INVALID(0); const int32_t count = buffers->max_length; const os::SocketFlags c_flags = convert_socket_flags(flags); os::WSABuf *wsabufs = il2cpp_array_addr(buffers, os::WSABuf, 0); int32_t len = 0; const os::WaitStatus status = socketHandle->ReceiveArray(wsabufs, count, &len, c_flags); if (status == os::kWaitStatusFailure) { *error = socketHandle->GetLastError(); return 0; } return len; } int32_t Socket::Receive(Il2CppIntPtr socket, Il2CppArray *buffer, int32_t offset, int32_t count, SocketFlags flags, int32_t *error) { *error = 0; AUTO_ACQUIRE_SOCKET; RETURN_IF_SOCKET_IS_INVALID(0); const int32_t a_len = buffer->max_length; if (offset > a_len - count) return 0; const os::SocketFlags c_flags = convert_socket_flags(flags); const uint8_t *data = il2cpp_array_addr(buffer, uint8_t, offset); int32_t len = 0; const os::WaitStatus status = socketHandle->Receive(data, count, c_flags, &len); if (status == os::kWaitStatusFailure) *error = socketHandle->GetLastError(); return len; } int32_t Socket::RecvFrom(Il2CppIntPtr socket, Il2CppArray *buffer, int32_t offset, int32_t count, SocketFlags flags, Il2CppSocketAddress **socket_address, int32_t *error) { *error = 0; AUTO_ACQUIRE_SOCKET; RETURN_IF_SOCKET_IS_INVALID(0); const int32_t a_len = buffer->max_length; if (offset > a_len - count) return 0; const os::SocketFlags c_flags = convert_socket_flags(flags); const uint8_t *data = il2cpp_array_addr(buffer, uint8_t, offset); int32_t len = 0; const int32_t length = (*socket_address)->data->max_length; const uint8_t *socket_buffer = (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress((*socket_address)->data); if (length < 2) { vm::Exception::Raise(vm::Exception::GetSystemException()); return 0; } const os::AddressFamily family = convert_address_family((AddressFamily)(socket_buffer[0] | (socket_buffer[1] << 8))); os::EndPointInfo info; info.family = os::kAddressFamilyError; if (family == os::kAddressFamilyInterNetwork) { if (length < 8) { vm::Exception::Raise(vm::Exception::GetSystemException()); return 0; } const uint16_t port = ((socket_buffer[2] << 8) | socket_buffer[3]); const uint32_t address = ((socket_buffer[4] << 24) | (socket_buffer[5] << 16) | (socket_buffer[6] << 8) | socket_buffer[7]); const os::WaitStatus status = socketHandle->RecvFrom(address, port, data, count, c_flags, &len, info); if (status == os::kWaitStatusFailure) *error = socketHandle->GetLastError(); } else if (family == os::kAddressFamilyUnix) { if (length - 2 >= END_POINT_MAX_PATH_LEN) { vm::Exception::Raise(vm::Exception::GetSystemException()); return 0; } char path[END_POINT_MAX_PATH_LEN] = {0}; for (int32_t i = 0; i < (length - 2); ++i) { path[i] = (char)socket_buffer[i + 2]; } const os::WaitStatus status = socketHandle->RecvFrom(path, data, count, c_flags, &len, info); if (status == os::kWaitStatusFailure) *error = socketHandle->GetLastError(); } else if (family == os::kAddressFamilyInterNetworkV6) { uint16_t port; uint8_t address[ipv6AddressSize] = {0}; uint32_t scope; UnpackIPv6AddressFromBuffer(socket_buffer, length, &port, address, &scope); const os::WaitStatus status = socketHandle->RecvFrom(address, scope, port, data, count, c_flags, &len, info); if (status == os::kWaitStatusFailure) *error = socketHandle->GetLastError(); } else { *error = os::kWSAeafnosupport; return 0; } *socket_address = (info.family == os::kAddressFamilyError) ? NULL : end_point_info_to_socket_address(info); return len; } Il2CppSocketAddress* Socket::LocalEndPoint(Il2CppIntPtr socket, int32_t* error) { AUTO_ACQUIRE_SOCKET; RETURN_IF_SOCKET_IS_INVALID(NULL); os::EndPointInfo info; memset(&info, 0x00, sizeof(os::EndPointInfo)); const os::WaitStatus status = socketHandle->GetLocalEndPointInfo(info); if (status == os::kWaitStatusFailure) { *error = socketHandle->GetLastError(); return NULL; } Il2CppSocketAddress *socket_address = end_point_info_to_socket_address(info); if (socket_address == NULL) *error = os::kWSAeafnosupport; return socket_address; } Il2CppSocketAddress* Socket::RemoteEndPoint(Il2CppIntPtr socket, int32_t* error) { AUTO_ACQUIRE_SOCKET; RETURN_IF_SOCKET_IS_INVALID(NULL); os::EndPointInfo info; memset(&info, 0x00, sizeof(os::EndPointInfo)); const os::WaitStatus status = socketHandle->GetRemoteEndPointInfo(info); if (status == os::kWaitStatusFailure) { *error = socketHandle->GetLastError(); return NULL; } Il2CppSocketAddress *socket_address = end_point_info_to_socket_address(info); if (socket_address == NULL) *error = os::kWSAeafnosupport; return socket_address; } void Socket::Select(Il2CppArray **sockets, int32_t timeout, int32_t *error) { *error = 0; // Layout: READ, null, WRITE, null, ERROR, null const uint32_t input_sockets_count = (*sockets)->max_length; std::vector requests; std::vector socketHandles; requests.reserve(input_sockets_count - 3); int32_t mode = 0; for (uint32_t i = 0; i < input_sockets_count; ++i) { Il2CppObject *obj = il2cpp_array_get(*sockets, Il2CppObject*, i); if (obj == NULL) { if (++mode > 3) { // Something very bad happened here (ie: the input array was wrong) // so we gracefully terminate the method. *error = os::kWSAefault; return; } continue; } #if !NET_4_0 const FieldInfo *field_info = vm::Class::GetFieldFromName(obj->klass, "socket"); Il2CppIntPtr& intPtr = *((Il2CppIntPtr*)((char*)obj + field_info->offset)); #else FieldInfo *safe_handle_field_info = vm::Class::GetFieldFromName(obj->klass, "safe_handle"); const Il2CppObject* value = NULL; vm::Field::GetValue(obj, safe_handle_field_info, &value); const FieldInfo *handle_field_info = vm::Class::GetFieldFromName(value->klass, "handle"); Il2CppIntPtr& intPtr = *((Il2CppIntPtr*)((char*)value + handle_field_info->offset)); #endif // Acquire socket. socketHandles.push_back(os::SocketHandleWrapper()); os::SocketHandleWrapper& socketHandle = socketHandles.back(); socketHandle.Acquire(os::PointerToSocketHandle(intPtr.m_value)); os::PollRequest request; // May 'invalid socket' (-1); we want the error from Poll() in that case. request.fd = socketHandle.GetSocket() == NULL ? -1 : socketHandle.GetSocket()->GetDescriptor(); request.events = (mode == 0 ? os::kPollFlagsIn : (mode == 1 ? os::kPollFlagsOut : os::kPollFlagsErr)); request.revents = os::kPollFlagsNone; requests.push_back(request); } if (requests.size() == 0) return; int32_t results = 0; const os::WaitStatus result = os::Socket::Poll(requests, timeout, &results, error); if (result == os::kWaitStatusFailure) { *sockets = NULL; return; } Il2CppArray *new_sockets = vm::Array::New(((Il2CppObject*)(*sockets))->klass->element_class, results + 3); if (results > 0) { mode = 0; uint32_t request_index = 0; // This odd loop is due to the layout of the sockets input array: // Layout: READ, null, WRITE, null, ERROR, null // We need to iterate each request and iterate the sockets array, skipping // the null entries. We try to avoid an infinite loop here as well. uint32_t add_index = 0; while (request_index < requests.size()) { const uint32_t input_sockets_index = (request_index + mode); if (input_sockets_index > input_sockets_count - 1) break; // We have exhausted the input sockets array, so exit. Il2CppObject *obj = il2cpp_array_get(*sockets, Il2CppObject*, input_sockets_index); if (obj == NULL) { ++mode; continue; // Here is a null entry, skip it without updated the next request index. } os::PollRequest &request = requests[request_index]; if (request.revents != os::kPollFlagsNone) { switch (mode) { case 0: if (request.revents & (os::kPollFlagsIn | os::kPollFlagsErr)) { il2cpp_array_setref(new_sockets, (add_index + mode), obj); add_index++; } break; case 1: if (request.revents & (os::kPollFlagsOut | os::kPollFlagsErr)) { il2cpp_array_setref(new_sockets, (add_index + mode), obj); add_index++; } break; default: if (request.revents & os::kPollFlagsErr) { il2cpp_array_setref(new_sockets, (add_index + mode), obj); add_index++; } break; } } ++request_index; } } *sockets = new_sockets; } bool Socket::SendFile(Il2CppIntPtr socket, Il2CppString *filename, Il2CppArray *pre_buffer, Il2CppArray *post_buffer, TransmitFileOptions flags) { if (filename == NULL) return false; os::TransmitFileBuffers t_buffers = {0}; if (pre_buffer != NULL) { t_buffers.head = il2cpp_array_addr(pre_buffer, uint8_t, 0); t_buffers.head_length = pre_buffer->max_length; } if (post_buffer != NULL) { t_buffers.tail = il2cpp_array_addr(post_buffer, uint8_t, 0); t_buffers.tail_length = post_buffer->max_length; } AUTO_ACQUIRE_SOCKET; if (!socketHandle.IsValid()) return false; const Il2CppChar* ustr = utils::StringUtils::GetChars(filename); const std::string str = utils::StringUtils::Utf16ToUtf8(ustr); // Note: for now they map 1-1 const os::TransmitFileOptions o_flags = (os::TransmitFileOptions)flags; const os::WaitStatus status = socketHandle->SendFile(str.c_str(), &t_buffers, o_flags); if (status == os::kWaitStatusFailure) { // TODO: mono stores socketHandle->GetLastError into a threadlocal global variable // that can be retrieved later by other icalls. return false; } if ((flags & kTransmitFileOptionsDisconnect) == kTransmitFileOptionsDisconnect) socketHandle->Disconnect(true); return true; } int32_t Socket::SendTo(Il2CppIntPtr socket, Il2CppArray *buffer, int32_t offset, int32_t count, SocketFlags flags, Il2CppSocketAddress *socket_address, int32_t *error) { *error = 0; const int32_t a_len = buffer->max_length; if (offset > a_len - count) return 0; const os::SocketFlags c_flags = convert_socket_flags(flags); const uint8_t *data = il2cpp_array_addr(buffer, uint8_t, offset); int32_t len = 0; const int32_t length = socket_address->data->max_length; const uint8_t *socket_buffer = (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress(socket_address->data); if (length < 2) { vm::Exception::Raise(vm::Exception::GetSystemException()); return 0; } const os::AddressFamily family = convert_address_family((AddressFamily)(socket_buffer[0] | (socket_buffer[1] << 8))); AUTO_ACQUIRE_SOCKET; RETURN_IF_SOCKET_IS_INVALID(0); if (family == os::kAddressFamilyInterNetwork) { if (length < 8) { vm::Exception::Raise(vm::Exception::GetSystemException()); return 0; } const uint16_t port = ((socket_buffer[2] << 8) | socket_buffer[3]); const uint32_t address = ((socket_buffer[4] << 24) | (socket_buffer[5] << 16) | (socket_buffer[6] << 8) | socket_buffer[7]); const os::WaitStatus status = socketHandle->SendTo(address, port, data, count, c_flags, &len); if (status == os::kWaitStatusFailure) *error = socketHandle->GetLastError(); } else if (family == os::kAddressFamilyUnix) { if (length - 2 >= END_POINT_MAX_PATH_LEN) { vm::Exception::Raise(vm::Exception::GetSystemException()); return 0; } char path[END_POINT_MAX_PATH_LEN] = {0}; for (int32_t i = 0; i < (length - 2); ++i) { path[i] = (char)socket_buffer[i + 2]; } const os::WaitStatus status = socketHandle->SendTo(path, data, count, c_flags, &len); if (status == os::kWaitStatusFailure) *error = socketHandle->GetLastError(); } else if (family == os::kAddressFamilyInterNetworkV6) { uint16_t port; uint8_t address[ipv6AddressSize] = {0}; uint32_t scope; UnpackIPv6AddressFromBuffer(socket_buffer, length, &port, address, &scope); const os::WaitStatus status = socketHandle->SendTo(address, scope, port, data, count, c_flags, &len); if (status == os::kWaitStatusFailure) *error = socketHandle->GetLastError(); } else { *error = os::kWSAeafnosupport; return 0; } return len; } int32_t Socket::SendArray(Il2CppIntPtr socket, Il2CppArray *buffers, SocketFlags flags, int32_t *error) { *error = 0; const int32_t count = buffers->max_length; const os::SocketFlags c_flags = convert_socket_flags(flags); os::WSABuf *wsabufs = il2cpp_array_addr(buffers, os::WSABuf, 0); AUTO_ACQUIRE_SOCKET; RETURN_IF_SOCKET_IS_INVALID(0); int32_t sent = 0; const os::WaitStatus status = socketHandle->SendArray(wsabufs, count, &sent, c_flags); if (status == os::kWaitStatusFailure) { *error = socketHandle->GetLastError(); return 0; } return sent; } int32_t Socket::Send(Il2CppIntPtr socket, Il2CppArray *buffer, int32_t offset, int32_t count, SocketFlags flags, int32_t *error) { *error = 0; const int32_t a_len = buffer->max_length; if (offset > a_len - count) return 0; const os::SocketFlags c_flags = convert_socket_flags(flags); const uint8_t *data = il2cpp_array_addr(buffer, uint8_t, offset); AUTO_ACQUIRE_SOCKET; RETURN_IF_SOCKET_IS_INVALID(0); int32_t len = 0; const os::WaitStatus status = socketHandle->Send(data, count, c_flags, &len); if (status == os::kWaitStatusFailure) *error = socketHandle->GetLastError(); return len; } #if IL2CPP_SUPPORT_IPV6 static os::IPv6Address ipaddress_to_ipv6_addr(Il2CppObject *ipaddr) { FieldInfo* numbersFieldInfo = vm::Class::GetFieldFromName(ipaddr->klass, "m_Numbers"); IL2CPP_ASSERT(numbersFieldInfo); Il2CppArray* data = (Il2CppArray*)vm::Field::GetValueObject(numbersFieldInfo, ipaddr); os::IPv6Address ipv6; for (int i = 0; i < 8; i++) { uint16_t s = il2cpp_array_get(data, uint16_t, i); ipv6.addr[2 * i] = (s >> 8) & 0xff; ipv6.addr[2 * i + 1] = s & 0xff; } return ipv6; } static void GetAddressAndInterfaceFromObject(Il2CppObject* object, const char* groupField, const char* interfaceField, os::IPv6Address& ipv6, uint64_t& interfaceOffset) { FieldInfo* groupFieldInfo = vm::Class::GetFieldFromName(object->klass, groupField); IL2CPP_ASSERT(groupFieldInfo); Il2CppObject* address = vm::Field::GetValueObject(groupFieldInfo, object); if (address) ipv6 = ipaddress_to_ipv6_addr(address); FieldInfo* interfaceFieldInfo = vm::Class::GetFieldFromName(object->klass, interfaceField); IL2CPP_ASSERT(interfaceFieldInfo); vm::Field::GetValue(object, interfaceFieldInfo, &interfaceOffset); } #endif // IL2CPP_SUPPORT_IPV6 void Socket::SetSocketOption(Il2CppIntPtr socket, SocketOptionLevel level, SocketOptionName name, Il2CppObject *obj_val, Il2CppArray *byte_val, int32_t int_val, int32_t *error) { *error = 0; // Note: for now the options map one to one. const os::SocketOptionName system_name = (os::SocketOptionName)(name); const os::SocketOptionLevel system_level = (os::SocketOptionLevel)(level); AUTO_ACQUIRE_SOCKET; RETURN_IF_SOCKET_IS_INVALID(); os::WaitStatus status = os::kWaitStatusFailure; if (byte_val != NULL) { const int32_t length = byte_val->max_length; const uint8_t *buffer = (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress(byte_val); status = socketHandle->SetSocketOptionArray(system_level, system_name, buffer, length); } else if (obj_val != NULL) { switch (name) { case kSocketOptionNameLinger: { #if NET_4_0 const FieldInfo *enabled_field_info = vm::Class::GetFieldFromName(obj_val->klass, "enabled"); const FieldInfo *seconds_field_info = vm::Class::GetFieldFromName(obj_val->klass, "lingerTime"); #else const FieldInfo *enabled_field_info = vm::Class::GetFieldFromName(obj_val->klass, "enabled"); const FieldInfo *seconds_field_info = vm::Class::GetFieldFromName(obj_val->klass, "seconds"); #endif const bool enabled = *((bool*)((char*)obj_val + enabled_field_info->offset)); const int32_t seconds = *((int32_t*)((char*)obj_val + seconds_field_info->offset)); status = socketHandle->SetSocketOptionLinger(system_level, system_name, enabled, seconds); } break; case kSocketOptionNameAddMembership: case kSocketOptionNameDropMembership: { #if IL2CPP_SUPPORT_IPV6 if (system_level == (os::SocketOptionLevel)kSocketOptionLevelIPv6) { os::IPv6Address ipv6 = { { 0 } }; uint64_t interfaceOffset; #if NET_4_0 GetAddressAndInterfaceFromObject(obj_val, "m_Group", "m_Interface", ipv6, interfaceOffset); #else GetAddressAndInterfaceFromObject(obj_val, "group", "ifIndex", ipv6, interfaceOffset); #endif // NET_4_0 status = socketHandle->SetSocketOptionMembership(system_level, system_name, ipv6, interfaceOffset); } else if (system_level == (os::SocketOptionLevel)kSocketOptionLevelIP) #endif // IL2CPP_SUPPORT_IPV6 { FieldInfo *group_field_info = vm::Class::GetFieldFromName(obj_val->klass, "group"); #if NET_4_0 FieldInfo *local_field_info = vm::Class::GetFieldFromName(obj_val->klass, "localAddress"); #else FieldInfo *local_field_info = vm::Class::GetFieldFromName(obj_val->klass, "local"); #endif Il2CppObject* group_obj = vm::Field::GetValueObject(group_field_info, obj_val); Il2CppObject* local_obj = vm::Field::GetValueObject(local_field_info, obj_val); const FieldInfo *group_address_field_info = vm::Class::GetFieldFromName(group_obj->klass, "m_Address"); const FieldInfo *local_address_field_info = vm::Class::GetFieldFromName(local_obj->klass, "m_Address"); const uint32_t group_address = *((uint32_t*)(uint64_t*)((char*)group_obj + group_address_field_info->offset)); const uint32_t local_address = *((uint32_t*)(uint64_t*)((char*)local_obj + local_address_field_info->offset)); status = socketHandle->SetSocketOptionMembership(system_level, system_name, group_address, local_address); } } break; default: *error = os::kWSAeinval; return; // early out } } else status = socketHandle->SetSocketOption(system_level, system_name, int_val); if (status == os::kWaitStatusFailure) *error = socketHandle->GetLastError(); } void Socket::Shutdown(Il2CppIntPtr socket, SocketShutdown how, int32_t* error) { *error = 0; AUTO_ACQUIRE_SOCKET; RETURN_IF_SOCKET_IS_INVALID(); const os::WaitStatus status = socketHandle->Shutdown(how); if (status == os::kWaitStatusFailure) *error = socketHandle->GetLastError(); } Il2CppIntPtr Socket::Socket_internal(Il2CppObject *self, AddressFamily family, SocketType type, ProtocolType protocol, int32_t* error) { Il2CppIntPtr socket = { NULL }; *error = 0; os::AddressFamily n_family = convert_address_family(family); os::SocketType n_type = convert_socket_type(type); os::ProtocolType n_protocol = convert_socket_protocol(protocol); if (n_family == os::kAddressFamilyError) { *error = os::kWSAeafnosupport; return socket; } if (n_type == os::kSocketTypeError) { *error = os::kWSAesocktnosupport; return socket; } if (n_protocol == os::kProtocolTypeUnknown) { *error = os::kWSAeprotonosupport; return socket; } os::Socket *sock = new os::Socket(check_thread_status); const os::WaitStatus status = sock->Create(n_family, n_type, n_protocol); if (status == os::kWaitStatusFailure) { *error = sock->GetLastError(); // Okay to delete socket directly. We haven't created a handle yet. delete sock; return socket; } os::SocketHandle socketHandle = os::CreateSocketHandle(sock); socket.m_value = reinterpret_cast(static_cast(socketHandle)); return socket; } int32_t Socket::WSAIoctl(Il2CppIntPtr socket, int32_t code, Il2CppArray *input, Il2CppArray *output, int32_t *error) { *error = 0; AUTO_ACQUIRE_SOCKET; RETURN_IF_SOCKET_IS_INVALID(-1); if (code == 0x5421 /* FIONBIO */) { // Invalid command. Must use Socket.Blocking return -1; } const int32_t in_length = (input ? input->max_length : 0); const uint8_t *in_buffer = (input ? (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress(input) : NULL); const int32_t out_length = (output ? output->max_length : 0); uint8_t *out_buffer = (output ? (uint8_t*)il2cpp::vm::Array::GetFirstElementAddress(output) : NULL); int32_t output_bytes = 0; const os::WaitStatus status = socketHandle->Ioctl(code, in_buffer, in_length, out_buffer, out_length, &output_bytes); if (status == os::kWaitStatusFailure) { *error = socketHandle->GetLastError(); return -1; } return output_bytes; } #if NET_4_0 bool Socket::SendFile_internal(Il2CppIntPtr sock, Il2CppString* filename, Il2CppArray* pre_buffer, Il2CppArray* post_buffer, int32_t flags) { return SendFile(sock, filename, pre_buffer, post_buffer, static_cast(flags)); } bool Socket::SupportsPortReuse(ProtocolType proto) { NOT_IMPLEMENTED_ICALL(Socket::SupportsPortReuse); IL2CPP_UNREACHABLE; return false; } int32_t Socket::IOControl_internal(Il2CppIntPtr sock, int32_t ioctl_code, Il2CppArray* input, Il2CppArray* output, int32_t* error) { NOT_IMPLEMENTED_ICALL(Socket::IOControl_internal); IL2CPP_UNREACHABLE; return 0; } int32_t Socket::ReceiveFrom_internal(Il2CppIntPtr sock, Il2CppArray* buffer, int32_t offset, int32_t count, int32_t flags, Il2CppSocketAddress** sockaddr, int32_t* error) { return RecvFrom(sock, buffer, offset, count, static_cast(flags), sockaddr, error); } int32_t Socket::SendTo_internal(Il2CppIntPtr sock, Il2CppArray* buffer, int32_t offset, int32_t count, int32_t flags, Il2CppSocketAddress* sa, int32_t* error) { return SendTo(sock, buffer, offset, count, static_cast(flags), sa, error); } Il2CppSocketAddress* Socket::LocalEndPoint_internal(Il2CppIntPtr socket, int32_t family, int32_t* error) { // We should be able to ignore the family, as the socket should already have that information. return LocalEndPoint(socket, error); } Il2CppSocketAddress* Socket::RemoteEndPoint_internal(Il2CppIntPtr socket, int32_t family, int32_t* error) { // We should be able to ignore the family, as the socket should already have that information. return RemoteEndPoint(socket, error); } static void STDCALL abort_apc(void* param) { } void Socket::cancel_blocking_socket_operation(Il2CppObject* thread) { Il2CppThread* t = reinterpret_cast(thread); t->internal_thread->handle->QueueUserAPC(abort_apc, NULL); } void Socket::Connect_internal(Il2CppIntPtr sock, Il2CppSocketAddress* sa, int32_t* error) { Connect(sock, sa, error); } #endif } /* namespace Sockets */ } /* namespace Net */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Net.Sockets/Socket.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppArray; struct Il2CppObject; struct Il2CppString; namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Net { namespace Sockets { enum AddressFamily { kAddressFamilyUnknown = -1, kAddressFamilyUnspecified = 0, kAddressFamilyUnix = 1, kAddressFamilyInterNetwork = 2, kAddressFamilyImpLink = 3, kAddressFamilyPup = 4, kAddressFamilyChaos = 5, kAddressFamilyNS = 6, kAddressFamilyIpx = 6, kAddressFamilyIso = 7, kAddressFamilyOsi = 7, kAddressFamilyEcma = 8, kAddressFamilyDataKit = 9, kAddressFamilyCcitt = 10, kAddressFamilySna = 11, kAddressFamilyDecNet = 12, kAddressFamilyDataLink = 13, kAddressFamilyLat = 14, kAddressFamilyHyperChannel = 15, kAddressFamilyAppleTalk = 16, kAddressFamilyNetBios = 17, kAddressFamilyVoiceView = 18, kAddressFamilyFireFox = 19, kAddressFamilyBanyan = 21, kAddressFamilyAtm = 22, kAddressFamilyInterNetworkV6 = 23, kAddressFamilyCluster = 24, kAddressFamilyIeee12844 = 25, kAddressFamilyIrda = 26, kAddressFamilyNetworkDesigners = 28, kAddressFamilyMax = 29, }; enum SocketType { kSocketTypeUnknown = -1, kSocketTypeStream = 1, kSocketTypeDgram = 2, kSocketTypeRaw = 3, kSocketTypeRdm = 4, kSocketTypeSeqpacket = 5, }; enum ProtocolType { kProtocolTypeUnknown = -1, kProtocolTypeIP = 0, kProtocolTypeIcmp = 1, kProtocolTypeIgmp = 2, kProtocolTypeGgp = 3, kProtocolTypeTcp = 6, kProtocolTypePup = 12, kProtocolTypeUdp = 17, kProtocolTypeIdp = 22, kProtocolTypeND = 77, kProtocolTypeRaw = 255, kProtocolTypeUnspecified = 0, kProtocolTypeIpx = 1000, kProtocolTypeSpx = 1256, kProtocolTypeSpxII = 1257, // #if NET_1_1 kProtocolTypeIPv6 = 41, // #endif // #if NET_2_0 kProtocolTypeIPv4 = 4, kProtocolTypeIPv6RoutingHeader = 43, kProtocolTypeIPv6FragmentHeader = 44, kProtocolTypeIPSecEncapsulatingSecurityPayload = 50, kProtocolTypeIPSecAuthenticationHeader = 51, kProtocolTypeIcmpV6 = 58, kProtocolTypeIPv6NoNextHeader = 59, kProtocolTypeIPv6DestinationOptions = 60, kProtocolTypeIPv6HopByHopOptions = 0, // #endif }; enum SocketOptionLevel { kSocketOptionLevelSocket = 65535, kSocketOptionLevelIP = 0, kSocketOptionLevelTcp = 6, kSocketOptionLevelUdp = 17, //#if NET_1_1 kSocketOptionLevelIPv6 = 41, //#endif }; enum SocketOptionName { kSocketOptionNameDebug = 1, kSocketOptionNameAcceptConnection = 2, kSocketOptionNameReuseAddress = 4, kSocketOptionNameKeepAlive = 8, kSocketOptionNameDontRoute = 16, kSocketOptionNameBroadcast = 32, kSocketOptionNameUseLoopback = 64, kSocketOptionNameLinger = 128, kSocketOptionNameOutOfBandInline = 256, kSocketOptionNameDontLinger = -129, kSocketOptionNameExclusiveAddressUse = -5, kSocketOptionNameSendBuffer = 4097, kSocketOptionNameReceiveBuffer = 4098, kSocketOptionNameSendLowWater = 4099, kSocketOptionNameReceiveLowWater = 4100, kSocketOptionNameSendTimeout = 4101, kSocketOptionNameReceiveTimeout = 4102, kSocketOptionNameError = 4103, kSocketOptionNameType = 4104, kSocketOptionNameMaxConnections = 2147483647, kSocketOptionNameIPOptions = 1, kSocketOptionNameHeaderIncluded = 2, kSocketOptionNameTypeOfService = 3, kSocketOptionNameIpTimeToLive = 4, kSocketOptionNameMulticastInterface = 9, kSocketOptionNameMulticastTimeToLive = 10, kSocketOptionNameMulticastLoopback = 11, kSocketOptionNameAddMembership = 12, kSocketOptionNameDropMembership = 13, kSocketOptionNameDontFragment = 14, kSocketOptionNameAddSourceMembership = 15, kSocketOptionNameDropSourceMembership = 16, kSocketOptionNameBlockSource = 17, kSocketOptionNameUnblockSource = 18, kSocketOptionNamePacketInformation = 19, kSocketOptionNameNoDelay = 1, kSocketOptionNameBsdUrgent = 2, kSocketOptionNameExpedited = 2, kSocketOptionNameNoChecksum = 1, kSocketOptionNameChecksumCoverage = 20, // #if NET_2_0 kSocketOptionNameHopLimit = 21, kSocketOptionNameUpdateAcceptContext = 28683, kSocketOptionNameUpdateConnectContext = 28688, // #endif }; enum SelectMode { kSelectModeSelectRead = 0, kSelectModeSelectWrite = 1, kSelectModeSelectError = 2, }; enum SocketFlags { kSocketFlagsNone = 0x00000000, kSocketFlagsOutOfBand = 0x00000001, kSocketFlagsPeek = 0x00000002, kSocketFlagsDontRoute = 0x00000004, kSocketFlagsMaxIOVectorLength = 0x00000010, // #if NET_2_0 kSocketFlagsTruncated = 0x00000100, kSocketFlagsControlDataTruncated = 0x00000200, kSocketFlagsBroadcast = 0x00000400, kSocketFlagsMulticast = 0x00000800, // #endif kSocketFlagsPartial = 0x00008000, }; enum TransmitFileOptions { kTransmitFileOptionsUseDefaultWorkerThread = 0x00000000, kTransmitFileOptionsDisconnect = 0x00000001, kTransmitFileOptionsReuseSocket = 0x00000002, kTransmitFileOptionsWriteBehind = 0x00000004, kTransmitFileOptionsUseSystemThread = 0x00000010, kTransmitFileOptionsUseKernelApc = 0x00000020, }; enum SocketShutdown { kSocketShutdownReceive = 0, kSocketShutdownSend = 1, kSocketShutdownBoth = 2, }; class LIBIL2CPP_CODEGEN_API Socket { public: static Il2CppIntPtr Accept(Il2CppIntPtr, int32_t*, bool); static int32_t Available(Il2CppIntPtr, int32_t*); static void Bind(Il2CppIntPtr, Il2CppSocketAddress*, int32_t*); static void Blocking(Il2CppIntPtr, bool, int32_t*); static void Close(Il2CppIntPtr, int32_t*); static void Connect(Il2CppIntPtr, Il2CppSocketAddress*, int32_t*); static void Disconnect(Il2CppIntPtr, bool, int32_t*); static void GetSocketOptionArray(Il2CppIntPtr, SocketOptionLevel, SocketOptionName, Il2CppArray**, int32_t*); static void GetSocketOptionObj(Il2CppIntPtr, SocketOptionLevel, SocketOptionName, Il2CppObject**, int32_t*); static void Listen(Il2CppIntPtr, int32_t, int32_t*); static Il2CppSocketAddress* LocalEndPoint(Il2CppIntPtr, int32_t*); static bool Poll(Il2CppIntPtr, SelectMode, int32_t, int32_t*); static int32_t ReceiveArray(Il2CppIntPtr, Il2CppArray*, SocketFlags, int32_t*); static int32_t Receive(Il2CppIntPtr, Il2CppArray*, int32_t, int32_t, SocketFlags, int32_t*); static int32_t RecvFrom(Il2CppIntPtr, Il2CppArray*, int32_t, int32_t, SocketFlags, Il2CppSocketAddress**, int32_t*); static Il2CppSocketAddress* RemoteEndPoint(Il2CppIntPtr, int32_t*); static void Select(Il2CppArray**, int32_t, int32_t*); static bool SendFile(Il2CppIntPtr, Il2CppString*, Il2CppArray*, Il2CppArray*, TransmitFileOptions); static int32_t SendTo(Il2CppIntPtr, Il2CppArray*, int32_t, int32_t, SocketFlags, Il2CppSocketAddress*, int32_t*); static int32_t SendArray(Il2CppIntPtr, Il2CppArray*, SocketFlags, int32_t*); static int32_t Send(Il2CppIntPtr, Il2CppArray*, int32_t, int32_t, SocketFlags, int32_t*); static void SetSocketOption(Il2CppIntPtr, SocketOptionLevel, SocketOptionName, Il2CppObject*, Il2CppArray*, int32_t, int32_t*); static void Shutdown(Il2CppIntPtr, SocketShutdown, int32_t*); static Il2CppIntPtr Socket_internal(Il2CppObject * self, AddressFamily, SocketType, ProtocolType, int32_t*); static int32_t WSAIoctl(Il2CppIntPtr, int32_t, Il2CppArray*, Il2CppArray*, int32_t*); #if NET_4_0 static bool SendFile_internal(Il2CppIntPtr sock, Il2CppString* filename, Il2CppArray* pre_buffer, Il2CppArray* post_buffer, int32_t flags); static bool SupportsPortReuse(ProtocolType proto); static int32_t IOControl_internal(Il2CppIntPtr sock, int32_t ioctl_code, Il2CppArray* input, Il2CppArray* output, int32_t* error); static int32_t ReceiveFrom_internal(Il2CppIntPtr sock, Il2CppArray* buffer, int32_t offset, int32_t count, int32_t flags, Il2CppSocketAddress** sockaddr, int32_t* error); static int32_t SendTo_internal(Il2CppIntPtr sock, Il2CppArray* buffer, int32_t offset, int32_t count, int32_t flags, Il2CppSocketAddress* sa, int32_t* error); static Il2CppSocketAddress* LocalEndPoint_internal(Il2CppIntPtr socket, int32_t family, int32_t* error); static Il2CppSocketAddress* RemoteEndPoint_internal(Il2CppIntPtr socket, int32_t family, int32_t* error); static void cancel_blocking_socket_operation(Il2CppObject* thread); static void Connect_internal(Il2CppIntPtr sock, Il2CppSocketAddress* sa, int32_t* error); #endif }; } /* namespace Sockets */ } /* namespace Net */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Net.Sockets/SocketException.cpp ================================================ #include "il2cpp-config.h" #include "icalls/System/System.Net.Sockets/SocketException.h" #include "os/Error.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Net { namespace Sockets { int32_t SocketException::WSAGetLastError() { NOT_IMPLEMENTED_ICALL(SocketException::WSAGetLastError); return (int32_t)os::Error::GetLastError(); } } /* namespace Sockets */ } /* namespace Net */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Net.Sockets/SocketException.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppArray; struct Il2CppString; namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Net { namespace Sockets { class LIBIL2CPP_CODEGEN_API SocketException { public: static int32_t WSAGetLastError(); }; } /* namespace Sockets */ } /* namespace Net */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Threading/Semaphore.cpp ================================================ #include "icalls/System/System.Threading/Semaphore.h" #include "os/Semaphore.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Threading { #if !NET_4_0 Il2CppIntPtr Semaphore::CreateSemaphore_internal(int32_t initialCount, int32_t maximumCount, Il2CppString* name, bool* created) { *created = true; os::Semaphore* semaphore = NULL; if (name == NULL) semaphore = new os::Semaphore(initialCount, maximumCount); else NOT_SUPPORTED_IL2CPP(Semaphore::CreateSemaphore_internal, "Named semaphores are not supported."); Il2CppIntPtr ret = { new os::SemaphoreHandle(semaphore) }; return ret; } int32_t Semaphore::ReleaseSemaphore_internal(Il2CppIntPtr handlePtr, int32_t releaseCount, bool* fail) { os::SemaphoreHandle* handle = (os::SemaphoreHandle*)handlePtr.m_value; int32_t previousCount = 0; *fail = !handle->Get().Post(releaseCount, &previousCount); return previousCount; } #else Il2CppIntPtr Semaphore::CreateSemaphore_internal40(int32_t initialCount, int32_t maximumCount, Il2CppString* name, int32_t* errorCode) { *errorCode = true; os::Semaphore* semaphore = NULL; if (name == NULL) semaphore = new os::Semaphore(initialCount, maximumCount); else NOT_SUPPORTED_IL2CPP(Semaphore::CreateSemaphore_internal, "Named semaphores are not supported."); Il2CppIntPtr ret = { new os::SemaphoreHandle(semaphore) }; return ret; } bool Semaphore::ReleaseSemaphore_internal40(Il2CppIntPtr handlePtr, int32_t releaseCount, int32_t* previousCount) { os::SemaphoreHandle* handle = (os::SemaphoreHandle*)handlePtr.m_value; return handle->Get().Post(releaseCount, previousCount); } #endif Il2CppIntPtr Semaphore::OpenSemaphore_internal(Il2CppString* name, int32_t rights, int32_t* error) { NOT_SUPPORTED_IL2CPP(Semaphore::OpenSemaphore_internal, "Named semaphores are not supported."); return Il2CppIntPtr::Zero; } } /* namespace Threading */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System/System.Threading/Semaphore.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppString; namespace il2cpp { namespace icalls { namespace System { namespace System { namespace Threading { class LIBIL2CPP_CODEGEN_API Semaphore { public: #if !NET_4_0 static Il2CppIntPtr CreateSemaphore_internal(int32_t initialCount, int32_t maximumCount, Il2CppString* name, bool* created); static int32_t ReleaseSemaphore_internal(Il2CppIntPtr handlePtr, int32_t releaseCount, bool* fail); #else static Il2CppIntPtr CreateSemaphore_internal40(int32_t initialCount, int32_t maximumCount, Il2CppString* name, int32_t* errorCode); static bool ReleaseSemaphore_internal40(Il2CppIntPtr handlePtr, int32_t releaseCount, int32_t* previousCount); #endif static Il2CppIntPtr OpenSemaphore_internal(Il2CppString* name, int32_t rights, int32_t* error); }; } /* namespace Threading */ } /* namespace System */ } /* namespace System */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/System.Configuration/System.Configuration/InternalConfigurationHost.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "InternalConfigurationHost.h" namespace il2cpp { namespace icalls { namespace System { namespace Configuration { namespace System { namespace Configuration { Il2CppString* InternalConfigurationHost::get_bundled_app_config() { NOT_IMPLEMENTED_ICALL_NO_ASSERT(InternalConfigurationHost::get_bundled_app_config, "Once we properly handle app.config files, implement this icall to return the contents of the app.config file"); return NULL; } } // namespace Configuration } // namespace System } // namespace Configuration } // namespace System } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/System.Configuration/System.Configuration/InternalConfigurationHost.h ================================================ #pragma once #if NET_4_0 namespace il2cpp { namespace icalls { namespace System { namespace Configuration { namespace System { namespace Configuration { class LIBIL2CPP_CODEGEN_API InternalConfigurationHost { public: static Il2CppString* get_bundled_app_config(); }; } // namespace Configuration } // namespace System } // namespace Configuration } // namespace System } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/System.Core/System.IO.MemoryMappedFiles/MemoryMapImpl.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "MemoryMapImpl.h" namespace il2cpp { namespace icalls { namespace System { namespace Core { namespace System { namespace IO { namespace MemoryMappedFiles { bool MemoryMapImpl::Unmap(Il2CppIntPtr mmap_handle) { NOT_IMPLEMENTED_ICALL(MemoryMapImpl::Unmap); IL2CPP_UNREACHABLE; return false; } int32_t MemoryMapImpl::MapInternal(Il2CppIntPtr handle, int64_t offset, int64_t* size, int32_t access, Il2CppIntPtr* mmap_handle, Il2CppIntPtr* base_address) { NOT_IMPLEMENTED_ICALL(MemoryMapImpl::MapInternal); IL2CPP_UNREACHABLE; return 0; } Il2CppIntPtr MemoryMapImpl::OpenFileInternal(Il2CppString* path, int32_t mode, Il2CppString* mapName, int64_t* capacity, int32_t access, int32_t options, int32_t* error) { NOT_IMPLEMENTED_ICALL(MemoryMapImpl::OpenFileInternal); IL2CPP_UNREACHABLE; return Il2CppIntPtr(); } Il2CppIntPtr MemoryMapImpl::OpenHandleInternal(Il2CppIntPtr handle, Il2CppString* mapName, int64_t* capacity, int32_t access, int32_t options, int32_t* error) { NOT_IMPLEMENTED_ICALL(MemoryMapImpl::OpenHandleInternal); IL2CPP_UNREACHABLE; return Il2CppIntPtr(); } void MemoryMapImpl::CloseMapping(Il2CppIntPtr handle) { NOT_IMPLEMENTED_ICALL(MemoryMapImpl::CloseMapping); IL2CPP_UNREACHABLE; } void MemoryMapImpl::ConfigureHandleInheritability(Il2CppIntPtr handle, int32_t inheritability) { NOT_IMPLEMENTED_ICALL(MemoryMapImpl::ConfigureHandleInheritability); IL2CPP_UNREACHABLE; } void MemoryMapImpl::Flush(Il2CppIntPtr file_handle) { NOT_IMPLEMENTED_ICALL(MemoryMapImpl::Flush); IL2CPP_UNREACHABLE; } } // namespace MemoryMappedFiles } // namespace IO } // namespace System } // namespace Core } // namespace System } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/System.Core/System.IO.MemoryMappedFiles/MemoryMapImpl.h ================================================ #pragma once #if NET_4_0 #include "object-internals.h" namespace il2cpp { namespace icalls { namespace System { namespace Core { namespace System { namespace IO { namespace MemoryMappedFiles { class LIBIL2CPP_CODEGEN_API MemoryMapImpl { public: static bool Unmap(Il2CppIntPtr mmap_handle); static int32_t MapInternal(Il2CppIntPtr handle, int64_t offset, int64_t* size, int32_t access, Il2CppIntPtr* mmap_handle, Il2CppIntPtr* base_address); static Il2CppIntPtr OpenFileInternal(Il2CppString* path, int32_t mode, Il2CppString* mapName, int64_t* capacity, int32_t access, int32_t options, int32_t* error); static Il2CppIntPtr OpenHandleInternal(Il2CppIntPtr handle, Il2CppString* mapName, int64_t* capacity, int32_t access, int32_t options, int32_t* error); static void CloseMapping(Il2CppIntPtr handle); static void ConfigureHandleInheritability(Il2CppIntPtr handle, int32_t inheritability); static void Flush(Il2CppIntPtr file_handle); }; } // namespace MemoryMappedFiles } // namespace IO } // namespace System } // namespace Core } // namespace System } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/Mono/Runtime.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/Mono/Runtime.h" #include "vm/String.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace Mono { Il2CppString* Runtime::GetDisplayName() { return il2cpp::vm::String::New("Unity IL2CPP (" __DATE__ " " __TIME__ ")"); } void Runtime::mono_runtime_install_handlers() { NOT_SUPPORTED_IL2CPP(Runtime::mono_runtime_install_handlers, "This method appears to never be called."); } #if NET_4_0 Il2CppString* Runtime::GetNativeStackTrace(Il2CppException* exception) { NOT_IMPLEMENTED_ICALL(Runtime::GetNativeStackTrace); IL2CPP_UNREACHABLE; return NULL; } #endif } /* namespace Mono */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/Mono/Runtime.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppString; namespace il2cpp { namespace icalls { namespace mscorlib { namespace Mono { class LIBIL2CPP_CODEGEN_API Runtime { public: static void mono_runtime_install_handlers(); static Il2CppString* GetDisplayName(); #if NET_4_0 static Il2CppString* GetNativeStackTrace(Il2CppException* exception); #endif }; } /* namespace Mono */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/Mono/RuntimeClassHandle.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "class-internals.h" #include "RuntimeClassHandle.h" #include "vm/Class.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace Mono { Il2CppIntPtr RuntimeClassHandle::GetTypeFromClass(Il2CppClass* klass) { Il2CppIntPtr retVal; retVal.m_value = (void*)il2cpp::vm::Class::GetType(klass); return retVal; } } // namespace Mono } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/Mono/RuntimeClassHandle.h ================================================ #pragma once #if NET_4_0 #include "object-internals.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace Mono { class LIBIL2CPP_CODEGEN_API RuntimeClassHandle { public: static Il2CppIntPtr GetTypeFromClass(Il2CppClass* klass); }; } // namespace Mono } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/Mono/RuntimeGPtrArrayHandle.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "mono-structs.h" #include "RuntimeGPtrArrayHandle.h" #include "utils/Memory.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace Mono { void RuntimeGPtrArrayHandle::GPtrArrayFree(void* value) { IL2CPP_ASSERT(value != NULL); free_gptr_array((GPtrArray*)value); } } // namespace Mono } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/Mono/RuntimeGPtrArrayHandle.h ================================================ #pragma once #if NET_4_0 namespace il2cpp { namespace icalls { namespace mscorlib { namespace Mono { class LIBIL2CPP_CODEGEN_API RuntimeGPtrArrayHandle { public: static void GPtrArrayFree(void* value); }; } // namespace Mono } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/Mono/RuntimeMarshal.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "RuntimeMarshal.h" #include "mono-structs.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace Mono { void RuntimeMarshal::FreeAssemblyName(Il2CppMonoAssemblyName* name) { IL2CPP_FREE(name->name.m_value); IL2CPP_FREE(name->culture.m_value); IL2CPP_FREE(name->hash_value.m_value); IL2CPP_FREE(name->public_key.m_value); } } // namespace Mono } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/Mono/RuntimeMarshal.h ================================================ #pragma once #if NET_4_0 struct Il2CppMonoAssemblyName; namespace il2cpp { namespace icalls { namespace mscorlib { namespace Mono { class LIBIL2CPP_CODEGEN_API RuntimeMarshal { public: static void FreeAssemblyName(Il2CppMonoAssemblyName* name); }; } // namespace Mono } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/Mono/SafeStringMarshal.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "SafeStringMarshal.h" #include "utils/StringUtils.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace Mono { Il2CppIntPtr SafeStringMarshal::StringToUtf8(Il2CppString* str) { Il2CppIntPtr res; std::string strobj = il2cpp::utils::StringUtils::Utf16ToUtf8(str->chars, str->length); size_t size = strobj.size(); char *cstr = new char[size + 1]; memcpy(cstr, strobj.c_str(), size); cstr[size] = 0; res.m_value = cstr; return res; } void SafeStringMarshal::GFree(Il2CppIntPtr ptr) { char *cstr = (char*)ptr.m_value; delete cstr; } } // namespace Mono } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/Mono/SafeStringMarshal.h ================================================ #pragma once #if NET_4_0 #include "object-internals.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace Mono { class LIBIL2CPP_CODEGEN_API SafeStringMarshal { public: static Il2CppIntPtr StringToUtf8(Il2CppString* str); static void GFree(Il2CppIntPtr ptr); }; } // namespace Mono } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/Mono.Globalization.Unicode/Normalization.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/Mono.Globalization.Unicode/Normalization.h" #include "vm/Exception.h" #include "normalization-tables.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace Mono { namespace Globalization { namespace Unicode { void Normalization::load_normalization_resource(Il2CppIntPtr* argProps, Il2CppIntPtr* argMappedChars, Il2CppIntPtr* argCharMapIndex, Il2CppIntPtr* argHelperIndex, Il2CppIntPtr* argMapIdxToComposite, Il2CppIntPtr* argCombiningClass) { argProps->m_value = (uint8_t*)props; argMappedChars->m_value = (uint8_t*)mappedChars; argCharMapIndex->m_value = (uint8_t*)charMapIndex; argHelperIndex->m_value = (uint8_t*)helperIndex; argMapIdxToComposite->m_value = (uint8_t*)mapIdxToComposite; argCombiningClass->m_value = (uint8_t*)combiningClass; } } /* namespace Unicode */ } /* namespace Globalization */ } /* namespace Mono */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/Mono.Globalization.Unicode/Normalization.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace mscorlib { namespace Mono { namespace Globalization { namespace Unicode { class LIBIL2CPP_CODEGEN_API Normalization { public: static void load_normalization_resource(Il2CppIntPtr* argProps, Il2CppIntPtr* argMappedChars, Il2CppIntPtr* argCharMapIndex, Il2CppIntPtr* argHelperIndex, Il2CppIntPtr* argMapIdxToComposite, Il2CppIntPtr* argCombiningClass); }; } /* namespace Unicode */ } /* namespace Globalization */ } /* namespace Mono */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/Mono.Interop/ComInteropProxy.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/Mono.Interop/ComInteropProxy.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace Mono { namespace Interop { void ComInteropProxy::AddProxy(Il2CppIntPtr pItf, mscorlib_Mono_Interop_ComInteropProxy * proxy) { NOT_IMPLEMENTED_ICALL(ComInteropProxy::AddProxy); } mscorlib_Mono_Interop_ComInteropProxy* ComInteropProxy::FindProxy(Il2CppIntPtr pItf) { NOT_IMPLEMENTED_ICALL(ComInteropProxy::FindProxy); return 0; } } /* namespace Interop */ } /* namespace Mono */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/Mono.Interop/ComInteropProxy.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct mscorlib_Mono_Interop_ComInteropProxy; namespace il2cpp { namespace icalls { namespace mscorlib { namespace Mono { namespace Interop { class LIBIL2CPP_CODEGEN_API ComInteropProxy { public: static void AddProxy(Il2CppIntPtr pItf, mscorlib_Mono_Interop_ComInteropProxy * proxy); static mscorlib_Mono_Interop_ComInteropProxy* FindProxy(Il2CppIntPtr pItf); }; } /* namespace Interop */ } /* namespace Mono */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/Mono.Security.Cryptography/KeyPairPersistence.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/Mono.Security.Cryptography/KeyPairPersistence.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace Mono { namespace Security { namespace Cryptography { bool KeyPairPersistence::_CanSecure(Il2CppString* root) { NOT_IMPLEMENTED_ICALL(KeyPairPersistence::_CanSecure); return false; } bool KeyPairPersistence::_ProtectUser(Il2CppString* path) { NOT_IMPLEMENTED_ICALL(KeyPairPersistence::_ProtectUser); return false; } bool KeyPairPersistence::_ProtectMachine(Il2CppString* path) { NOT_IMPLEMENTED_ICALL(KeyPairPersistence::_ProtectMachine); return false; } bool KeyPairPersistence::_IsUserProtected(Il2CppString* path) { NOT_IMPLEMENTED_ICALL(KeyPairPersistence::_IsUserProtected); return false; } bool KeyPairPersistence::_IsMachineProtected(Il2CppString* path) { NOT_IMPLEMENTED_ICALL(KeyPairPersistence::_IsMachineProtected); return false; } } /* namespace Cryptography */ } /* namespace Security */ } /* namespace Mono */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/Mono.Security.Cryptography/KeyPairPersistence.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppString; namespace il2cpp { namespace icalls { namespace mscorlib { namespace Mono { namespace Security { namespace Cryptography { class LIBIL2CPP_CODEGEN_API KeyPairPersistence { public: static bool _CanSecure(Il2CppString* root); static bool _IsUserProtected(Il2CppString* path); static bool _ProtectMachine(Il2CppString* path); static bool _ProtectUser(Il2CppString* path); static bool _IsMachineProtected(Il2CppString* path); }; } /* namespace Cryptography */ } /* namespace Security */ } /* namespace Mono */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Activator.cpp ================================================ #include "il2cpp-config.h" #include "il2cpp-api.h" #include "icalls/mscorlib/System/Activator.h" #include "object-internals.h" #include "class-internals.h" #include "metadata.h" #include "vm/Image.h" #include "vm/Class.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { Il2CppObject * Activator::CreateInstanceInternal(Il2CppReflectionType *type) { Il2CppClass* typeInfo = vm::Class::FromIl2CppType(type->type); if (typeInfo == NULL) return NULL; il2cpp::vm::Class::Init(typeInfo); //you could think "hey, shouldn't we call the constructor here? but we don't because this path is only hit for value //types, and they cannot have default constructors. for reference types with constructors, the c# side of CreateInstance() //actually takes care of its own business by using reflection to create the object and invoke the constructor. return il2cpp_object_new(typeInfo); } } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Activator.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppObject; struct Il2CppReflectionType; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API Activator { public: static Il2CppObject* CreateInstanceInternal(Il2CppReflectionType *type); }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/AppDomain.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System/AppDomain.h" #include "gc/Allocator.h" #include "os/Mutex.h" #include "utils/StringUtils.h" #include "vm/Array.h" #include "vm/Assembly.h" #include "vm/Class.h" #include "vm/Domain.h" #include "vm/Exception.h" #include "vm/Image.h" #include "vm/Object.h" #include "vm/Reflection.h" #include "vm/Thread.h" #include "vm/Type.h" #include "tabledefs.h" #include "il2cpp-string-types.h" #include "class-internals.h" #include "object-internals.h" #include "il2cpp-api.h" #include #include #include using namespace il2cpp::vm; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { Il2CppAppDomain* AppDomain::getCurDomain() { Il2CppDomain *add = Domain::GetCurrent(); if (add->domain) return add->domain; add->domain = (Il2CppAppDomain*)il2cpp::vm::Object::New(il2cpp_defaults.appdomain_class); return add->domain; } Il2CppAppDomain* AppDomain::getRootDomain() { return Domain::GetRoot()->domain; } Il2CppAppDomain* AppDomain::createDomain(Il2CppString*, mscorlib_System_AppDomainSetup*) { NOT_SUPPORTED_IL2CPP(AppDomain::createDomain, "IL2CPP only supports one app domain, others cannot be created."); return NULL; } Il2CppArray* AppDomain::GetAssemblies(Il2CppAppDomain* ad, bool refonly) { static Il2CppClass *System_Reflection_Assembly; if (!System_Reflection_Assembly) { #if !NET_4_0 System_Reflection_Assembly = il2cpp_defaults.assembly_class; #else System_Reflection_Assembly = il2cpp_defaults.mono_assembly_class; #endif } vm::AssemblyVector* assemblies = Assembly::GetAllAssemblies(); int c = 0; Il2CppArray *res = Array::New(System_Reflection_Assembly, (il2cpp_array_size_t)assemblies->size()); for (vm::AssemblyVector::const_iterator assembly = assemblies->begin(); assembly != assemblies->end(); ++assembly) il2cpp_array_setref(res, c++, Reflection::GetAssemblyObject(*assembly)); return res; } Il2CppString * AppDomain::getFriendlyName(Il2CppAppDomain* ad) { return il2cpp_string_new(ad->data->friendly_name); } Il2CppAppDomainSetup* AppDomain::getSetup(Il2CppAppDomain* domain) { IL2CPP_ASSERT(domain != NULL); IL2CPP_ASSERT(domain->data != NULL); return domain->data->setup; } Il2CppAppContext* AppDomain::InternalGetDefaultContext(void) { return vm::Domain::ContextGet(); } Il2CppAppContext* AppDomain::InternalGetContext(void) { return vm::Domain::ContextGet(); } Il2CppString* AppDomain::InternalGetProcessGuid(Il2CppString* newguid) { NOT_SUPPORTED_IL2CPP(AppDomain::InternalGetProcessGuid, "This icall is only used in System.Runtime.Remoting.RemotingConfiguraiton.ProcessId."); return NULL; } void AppDomain::InternalPopDomainRef() { NOT_SUPPORTED_IL2CPP(AppDomain::InternalPopDomainRef, "This icall is only used in the System.Runtime.Remoting namespace."); } void AppDomain::InternalPushDomainRef(mscorlib_System_AppDomain * domain) { NOT_SUPPORTED_IL2CPP(AppDomain::InternalPushDomainRef, "This icall is only used in the System.Runtime.Remoting namespace."); } void AppDomain::InternalPushDomainRefByID(int32_t domain_id) { NOT_SUPPORTED_IL2CPP(AppDomain::InternalPushDomainRefByID, "This icall is only used in the System.Runtime.Remoting namespace."); } mscorlib_System_Runtime_Remoting_Contexts_Context * AppDomain::InternalSetContext(mscorlib_System_Runtime_Remoting_Contexts_Context * context) { NOT_SUPPORTED_IL2CPP(AppDomain::InternalSetContext, "This icall is only used in the System.Runtime.Remoting namespace."); return 0; } mscorlib_System_AppDomain * AppDomain::InternalSetDomain(mscorlib_System_AppDomain * context) { NOT_SUPPORTED_IL2CPP(AppDomain::InternalSetDomain, "This icall is only used in the System.Runtime.Remoting namespace."); return 0; } mscorlib_System_AppDomain * AppDomain::InternalSetDomainByID(int32_t domain_id) { NOT_SUPPORTED_IL2CPP(AppDomain::InternalSetDomainByID, "This icall is only used in the System.Runtime.Remoting namespace."); return 0; } Il2CppReflectionAssembly* AppDomain::LoadAssembly(Il2CppAppDomain* ad, Il2CppString* assemblyRef, struct mscorlib_System_Security_Policy_Evidence* evidence, bool refOnly) { il2cpp::vm::TypeNameParseInfo info; std::string name = il2cpp::utils::StringUtils::Utf16ToUtf8(assemblyRef->chars); il2cpp::vm::TypeNameParser parser(name, info, false); if (!parser.ParseAssembly()) return NULL; //assemblyRef might have been a fullname like System, CultureInfo=bla, Version=4.0, PublicKeyToken=23423423423423 //we ignore all that info except the name. (mono ignores the keytoken, and I'm quite sure it also ignores the version). //il2cpp does not pack multiple assemblies with the same name, and even if that one is not the exact one that is asked for, //it's more useful to return it than not to. (like cases where you want to Deserialize a BinaryFormatter blob that was serialized //on 4.0) const Il2CppAssembly* assembly = vm::Assembly::GetLoadedAssembly(info.assembly_name().name.c_str()); if (assembly != NULL) return Reflection::GetAssemblyObject(assembly); return NULL; } int32_t AppDomain::ExecuteAssembly(Il2CppAppDomain* self, Il2CppAssembly* a, Il2CppArray* args) { NOT_SUPPORTED_IL2CPP(AppDomain::ExecuteAssembly, "This icall is not supported by il2cpp."); return 0; } Il2CppAssembly* AppDomain::LoadAssemblyRaw(Il2CppAppDomain* self, Il2CppArray* rawAssembly, Il2CppArray* rawSymbolStore, void* /* System.Security.Policy.Evidence */ securityEvidence, bool refonly) { NOT_SUPPORTED_IL2CPP(AppDomain::LoadAssemblyRaw, "This icall is not supported by il2cpp."); return 0; } bool AppDomain::InternalIsFinalizingForUnload(int32_t domain_id) { NOT_SUPPORTED_IL2CPP(AppDomain::InternalIsFinalizingForUnload, "This icall is not supported by il2cpp."); return false; } void AppDomain::InternalUnload(int32_t domain_id) { NOT_SUPPORTED_IL2CPP(AppDomain::InternalUnload, "This icall is not supported by il2cpp."); } os::FastMutex s_DomainDataMutex; typedef std::vector, il2cpp::gc::Allocator > > DomainDataStorage; DomainDataStorage* s_DomainData; static inline void InitializeDomainData() { void* memory = utils::Memory::Malloc(sizeof(DomainDataStorage)); s_DomainData = new(memory)DomainDataStorage; } Il2CppObject* AppDomain::GetData(Il2CppAppDomain* self, Il2CppString* name) { os::FastAutoLock lock(&s_DomainDataMutex); if (s_DomainData == NULL) InitializeDomainData(); for (DomainDataStorage::iterator it = s_DomainData->begin(); it != s_DomainData->end(); it++) { if (it->first.compare(name->chars) == 0) return it->second; } return NULL; } void AppDomain::SetData(Il2CppAppDomain* self, Il2CppString* name, Il2CppObject* data) { os::FastAutoLock lock(&s_DomainDataMutex); if (s_DomainData == NULL) InitializeDomainData(); for (DomainDataStorage::iterator it = s_DomainData->begin(); it != s_DomainData->end(); it++) { if (it->first.compare(0, it->first.size(), name->chars, name->length) == 0) { it->second = data; return; } } s_DomainData->push_back(std::make_pair(UTF16String(name->chars, name->length), data)); } #if NET_4_0 void AppDomain::DoUnhandledException(Il2CppObject* _this, Il2CppException* e) { NOT_IMPLEMENTED_ICALL(AppDomain::DoUnhandledException); IL2CPP_UNREACHABLE; } #endif } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/AppDomain.h ================================================ #pragma once #include #include "il2cpp-config.h" struct mscorlib_System_AppDomain; struct mscorlib_System_AppDomainSetup; struct mscorlib_System_Runtime_Remoting_Contexts_Context; struct mscorlib_System_Security_Policy_Evidence; struct mscorlib_System_Reflection_Assembly; struct Il2CppObject; struct Il2CppString; struct Il2CppArray; struct Il2CppAssembly; struct Il2CppAppDomain; struct Il2CppAppDomainSetup; struct Il2CppReflectionAssembly; struct Il2CppAppContext; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API AppDomain { public: static void InternalPopDomainRef(); static Il2CppAppDomain* getCurDomain(); static Il2CppAppDomain* getRootDomain(); static int32_t ExecuteAssembly(Il2CppAppDomain* self, Il2CppAssembly* a, Il2CppArray* args); static Il2CppObject* GetData(Il2CppAppDomain* self, Il2CppString* name); static Il2CppAppContext* InternalGetContext(void); static Il2CppAppContext* InternalGetDefaultContext(void); static Il2CppString* InternalGetProcessGuid(Il2CppString* newguid); static bool InternalIsFinalizingForUnload(int32_t domain_id); static void InternalPushDomainRef(mscorlib_System_AppDomain * domain); static void InternalPushDomainRefByID(int32_t domain_id); static mscorlib_System_Runtime_Remoting_Contexts_Context * InternalSetContext(mscorlib_System_Runtime_Remoting_Contexts_Context * context); static mscorlib_System_AppDomain * InternalSetDomain(mscorlib_System_AppDomain * context); static mscorlib_System_AppDomain * InternalSetDomainByID(int32_t domain_id); static void InternalUnload(int32_t domain_id); static Il2CppReflectionAssembly* LoadAssembly(Il2CppAppDomain* ad, Il2CppString* assemblyRef, struct mscorlib_System_Security_Policy_Evidence* evidence, bool refOnly); static Il2CppAssembly* LoadAssemblyRaw(Il2CppAppDomain* self, Il2CppArray* rawAssembly, Il2CppArray* rawSymbolStore, void* /* System.Security.Policy.Evidence */ securityEvidence, bool refonly); static void SetData(Il2CppAppDomain* self, Il2CppString* name, Il2CppObject* data); static Il2CppAppDomain* createDomain(Il2CppString*, mscorlib_System_AppDomainSetup*); static Il2CppString * getFriendlyName(Il2CppAppDomain* ad); static Il2CppAppDomainSetup* getSetup(Il2CppAppDomain* domain); static Il2CppArray* GetAssemblies(Il2CppAppDomain* ad, bool refonly); #if NET_4_0 static void DoUnhandledException(Il2CppObject* _this, Il2CppException* e); #endif }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/ArgIterator.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System/ArgIterator.h" #include "tabledefs.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { void ArgIterator::Setup(mscorlib_System_ArgIterator * thisPtr, Il2CppIntPtr argsp, Il2CppIntPtr start) { NOT_SUPPORTED_IL2CPP(ArgIterator::Setup, "ArgIterator is not supported. Do not use __argList, use params instead."); } Il2CppTypedRef ArgIterator::IntGetNextArg_mscorlib_System_TypedReference(mscorlib_System_ArgIterator * thisPtr) { NOT_SUPPORTED_IL2CPP(ArgIterator::Setup, "ArgIterator is not supported. Do not use __argList, use params instead."); return Il2CppTypedRef(); } Il2CppTypedRef ArgIterator::IntGetNextArg_mscorlib_System_TypedReference_mscorlib_System_IntPtr(mscorlib_System_ArgIterator * thisPtr, Il2CppIntPtr rth) { NOT_SUPPORTED_IL2CPP(ArgIterator::Setup, "ArgIterator is not supported. Do not use __argList, use params instead."); return Il2CppTypedRef(); } Il2CppIntPtr ArgIterator::IntGetNextArgType(mscorlib_System_ArgIterator * thisPtr) { NOT_SUPPORTED_IL2CPP(ArgIterator::Setup, "ArgIterator is not supported. Do not use __argList, use params instead."); return Il2CppIntPtr(); } void* /* System.TypedReference */ ArgIterator::IntGetNextArg(ArgIterator self) { NOT_SUPPORTED_IL2CPP(ArgIterator::IntGetNextArg, "ArgIterator is not supported. Do not use __argList, use params instead."); return 0; } } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/ArgIterator.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct mscorlib_System_ArgIterator; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API ArgIterator { public: static void* /* System.TypedReference */ IntGetNextArg(ArgIterator self); static Il2CppTypedRef IntGetNextArg_mscorlib_System_TypedReference(mscorlib_System_ArgIterator * thisPtr); static Il2CppTypedRef IntGetNextArg_mscorlib_System_TypedReference_mscorlib_System_IntPtr(mscorlib_System_ArgIterator * thisPtr, Il2CppIntPtr rth); static void Setup(mscorlib_System_ArgIterator * thisPtr, Il2CppIntPtr argsp, Il2CppIntPtr start); static Il2CppIntPtr IntGetNextArgType(mscorlib_System_ArgIterator * thisPtr); }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Array.cpp ================================================ #include "il2cpp-config.h" #include #include "object-internals.h" #include "class-internals.h" #include "icalls/mscorlib/System/Array.h" #include "utils/Exception.h" #include "vm/Array.h" #include "vm/Class.h" #include "vm/Exception.h" #include "vm/Object.h" #include "vm/Type.h" #include #include using namespace il2cpp::vm; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { void Array::ClearInternal(Il2CppArray * arr, int32_t idx, int32_t length) { int sz = il2cpp_array_element_size(arr->klass); memset(il2cpp_array_addr_with_size(arr, sz, idx), 0, length * sz); } Il2CppArray * Array::Clone(Il2CppArray * arr) { Il2CppClass *typeInfo = arr->klass; const uint32_t elem_size = il2cpp::vm::Array::GetElementSize(typeInfo); if (arr->bounds == NULL) { il2cpp_array_size_t len = il2cpp::vm::Array::GetLength(arr); Il2CppArray *clone = (Il2CppArray*)il2cpp::vm::Array::NewFull(typeInfo, &len, NULL); memcpy(il2cpp::vm::Array::GetFirstElementAddress(clone), il2cpp::vm::Array::GetFirstElementAddress(arr), elem_size * len); return clone; } il2cpp_array_size_t size = elem_size; std::vector lengths(typeInfo->rank); std::vector lowerBounds(typeInfo->rank); for (int i = 0; i < typeInfo->rank; ++i) { lengths[i] = arr->bounds[i].length; size *= arr->bounds[i].length; lowerBounds[i] = arr->bounds[i].lower_bound; } Il2CppArray* clone = il2cpp::vm::Array::NewFull(typeInfo, &lengths[0], &lowerBounds[0]); memcpy(il2cpp::vm::Array::GetFirstElementAddress(clone), il2cpp::vm::Array::GetFirstElementAddress(arr), size); return clone; } static std::string FormatCreateInstanceException(const Il2CppType* type) { std::string typeName = vm::Type::GetName(type, IL2CPP_TYPE_NAME_FORMAT_IL); std::string message; message += "Unable to create an array of type '"; message += typeName; message += "'. IL2CPP needs to know about the array type at compile time, so please define a private static field like this:\n\nprivate static "; message += typeName; message += "[] _unused;\n\nin any MonoBehaviour class, and this exception should go away."; return message; } Il2CppArray * Array::CreateInstanceImpl(Il2CppReflectionType * elementType, Il2CppArray* lengths, Il2CppArray* bounds) { il2cpp_array_size_t* i32lengths = NULL; il2cpp_array_size_t* i32bounds = NULL; if (lengths != NULL) i32lengths = (il2cpp_array_size_t*)il2cpp_array_addr_with_size(lengths, il2cpp_array_element_size(lengths->klass), 0); if (bounds != NULL) i32bounds = (il2cpp_array_size_t*)il2cpp_array_addr_with_size(bounds, il2cpp_array_element_size(bounds->klass), 0); Il2CppClass* arrayType = il2cpp::vm::Class::GetArrayClassCached(il2cpp::vm::Class::FromIl2CppType(elementType->type), il2cpp::vm::Array::GetLength(lengths)); if (arrayType == NULL) vm::Exception::Raise(vm::Exception::GetInvalidOperationException(FormatCreateInstanceException(elementType->type).c_str())); return (Il2CppArray*)il2cpp::vm::Array::NewFull(arrayType, i32lengths, i32bounds); } bool Array::FastCopy(Il2CppArray *source, int32_t source_idx, Il2CppArray *dest, int32_t dest_idx, int32_t length) { int element_size; Il2CppClass *src_class; Il2CppClass *dest_class; int i; if (source->klass->rank != dest->klass->rank) return false; if (source->bounds || dest->bounds) return false; // Our max array length is il2cpp_array_size_t, which is currently int32_t, // so Array::GetLength will never return more than 2^31 - 1 // Therefore, casting sum to uint32_t is safe even if it overflows - it if does, // the comparison will succeed and this function will return false if ((static_cast(dest_idx + length) > il2cpp::vm::Array::GetLength(dest)) || (static_cast(source_idx + length) > il2cpp::vm::Array::GetLength(source))) return false; src_class = source->klass->element_class; dest_class = dest->klass->element_class; // object[] -> valuetype[] if (src_class == il2cpp_defaults.object_class && dest_class->valuetype) { for (i = source_idx; i < source_idx + length; ++i) { Il2CppObject *elem = il2cpp_array_get(source, Il2CppObject*, i); if (elem && !Object::IsInst(elem, dest_class)) return false; } element_size = il2cpp_array_element_size(dest->klass); memset(il2cpp_array_addr_with_size(dest, element_size, dest_idx), 0, element_size * length); for (i = 0; i < length; ++i) { Il2CppObject *elem = il2cpp_array_get(source, Il2CppObject*, source_idx + i); #if IL2CPP_ENABLE_MONO_BUG_EMULATION if (!elem) continue; #else if (!elem) Exception::Raise(Exception::GetInvalidCastException("At least one element in the source array could not be cast down to the destination array type.")); #endif NOT_IMPLEMENTED_ICALL_NO_ASSERT(Array::FastCopy, "Need GC write barrier"); memcpy(il2cpp_array_addr_with_size(dest, element_size, dest_idx + i), Object::Unbox(elem), element_size); } return true; } if (src_class != dest_class) { if (Class::IsValuetype(dest_class) || Class::IsEnum(dest_class) || Class::IsValuetype(src_class) || Class::IsEnum(src_class)) return false; // object[] -> reftype[] if (Class::IsSubclassOf(dest_class, src_class, false)) { for (i = source_idx; i < source_idx + length; ++i) { Il2CppObject *elem = il2cpp_array_get(source, Il2CppObject*, i); if (elem && !Object::IsInst(elem, dest_class)) Exception::Raise(Exception::GetInvalidCastException("At least one element in the source array could not be cast down to the destination array type.")); } } else if (!Class::IsSubclassOf(src_class, dest_class, false)) return false; // derivedtype[] -> basetype[] IL2CPP_ASSERT(Type::IsReference(src_class->byval_arg)); IL2CPP_ASSERT(Type::IsReference(dest_class->byval_arg)); } IL2CPP_ASSERT(il2cpp_array_element_size(dest->klass) == il2cpp_array_element_size(source->klass)); NOT_IMPLEMENTED_ICALL_NO_ASSERT(Array::FastCopy, "Need GC write barrier"); memmove( il2cpp_array_addr_with_size(dest, il2cpp_array_element_size(dest->klass), dest_idx), il2cpp_array_addr_with_size(source, il2cpp_array_element_size(source->klass), source_idx), length * il2cpp_array_element_size(dest->klass)); return true; } int32_t Array::GetLength(Il2CppArray * thisPtr, int dimension) { int32_t rank = thisPtr->klass->rank; il2cpp_array_size_t length; if ((dimension < 0) || (dimension >= rank)) il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetIndexOutOfRangeException()); if (thisPtr->bounds == NULL) length = thisPtr->max_length; else length = thisPtr->bounds[dimension].length; #ifdef IL2CPP_BIG_ARRAYS if (length > G_MAXINT32) mono_raise_exception(mono_get_exception_overflow()); #endif return length; } int32_t Array::GetLowerBound(Il2CppArray * thisPtr, int32_t dimension) { int32_t rank = thisPtr->klass->rank; if ((dimension < 0) || (dimension >= rank)) Exception::Raise(Exception::GetIndexOutOfRangeException()); if (thisPtr->bounds == NULL) return false; return thisPtr->bounds[dimension].lower_bound; } int Array::GetRank(Il2CppArray * arr) { return arr->klass->rank; } Il2CppObject * Array::GetValue(Il2CppArray * thisPtr, Il2CppArray* indices) { Il2CppClass *ac, *ic; Il2CppArray *ao, *io; int32_t i, pos, *ind; IL2CPP_CHECK_ARG_NULL(indices); io = (Il2CppArray*)indices; ic = (Il2CppClass*)io->klass; ao = (Il2CppArray*)thisPtr; ac = (Il2CppClass*)ao->klass; IL2CPP_ASSERT(ic->rank == 1); if (io->bounds != NULL || io->max_length != ac->rank) Exception::Raise(Exception::GetArgumentException(NULL, NULL)); ind = (int32_t*)il2cpp::vm::Array::GetFirstElementAddress(io); if (ao->bounds == NULL) { if (*ind < 0 || *ind >= ao->max_length) Exception::Raise(Exception::GetIndexOutOfRangeException()); return GetValueImpl(thisPtr, *ind); } for (i = 0; i < ac->rank; i++) if ((ind[i] < ao->bounds[i].lower_bound) || (ind[i] >= ao->bounds[i].length + ao->bounds[i].lower_bound)) Exception::Raise(Exception::GetIndexOutOfRangeException()); pos = ind[0] - ao->bounds[0].lower_bound; for (i = 1; i < ac->rank; i++) pos = pos * ao->bounds[i].length + ind[i] - ao->bounds[i].lower_bound; return GetValueImpl(thisPtr, pos); } Il2CppObject * Array::GetValueImpl(Il2CppArray * thisPtr, int32_t pos) { Il2CppClass* typeInfo = thisPtr->klass; void **ea; ea = (void**)load_array_elema(thisPtr, pos, typeInfo->element_size); if (typeInfo->element_class->valuetype) return il2cpp::vm::Object::Box(typeInfo->element_class, ea); return (Il2CppObject*)*ea; } void Array::SetValue(Il2CppArray * thisPtr, Il2CppObject* value, Il2CppArray* idxs) { Il2CppClass *ac, *ic; int32_t i, pos, *ind; IL2CPP_CHECK_ARG_NULL(idxs); ic = idxs->klass; ac = thisPtr->klass; IL2CPP_ASSERT(ic->rank == 1); if (idxs->bounds != NULL || idxs->max_length != ac->rank) Exception::Raise(Exception::GetArgumentException(NULL, NULL)); ind = (int32_t*)il2cpp::vm::Array::GetFirstElementAddress(idxs); if (thisPtr->bounds == NULL) { if (*ind < 0 || *ind >= thisPtr->max_length) Exception::Raise(Exception::GetIndexOutOfRangeException()); SetValueImpl(thisPtr, value, *ind); return; } for (i = 0; i < ac->rank; i++) if ((ind[i] < thisPtr->bounds[i].lower_bound) || (ind[i] >= (il2cpp_array_lower_bound_t)thisPtr->bounds[i].length + thisPtr->bounds[i].lower_bound)) Exception::Raise(Exception::GetIndexOutOfRangeException()); pos = ind[0] - thisPtr->bounds[0].lower_bound; for (i = 1; i < ac->rank; i++) pos = pos * thisPtr->bounds[i].length + ind[i] - thisPtr->bounds[i].lower_bound; SetValueImpl(thisPtr, value, pos); } static void ThrowNoWidening() { Exception::Raise(Exception::GetArgumentException("value", "not a widening conversion")); } static void ThrowInvalidCast(const Il2CppClass* a, const Il2CppClass* b) { Exception::Raise(Exception::GetInvalidCastException(utils::Exception::FormatInvalidCastException(b, a).c_str())); } union WidenedValueUnion { int64_t i64; uint64_t u64; double r64; }; WidenedValueUnion ExtractWidenedValue(Il2CppTypeEnum type, void* value) { WidenedValueUnion extractedValue = { 0 }; switch (type) { case IL2CPP_TYPE_U1: extractedValue.u64 = *(uint8_t*)value; break; case IL2CPP_TYPE_CHAR: extractedValue.u64 = *(Il2CppChar*)value; break; case IL2CPP_TYPE_U2: extractedValue.u64 = *(uint16_t*)value; break; case IL2CPP_TYPE_U4: extractedValue.u64 = *(uint32_t*)value; break; case IL2CPP_TYPE_U8: extractedValue.u64 = *(uint64_t*)value; break; case IL2CPP_TYPE_I1: extractedValue.i64 = *(int8_t*)value; break; case IL2CPP_TYPE_I2: extractedValue.i64 = *(int16_t*)value; break; case IL2CPP_TYPE_I4: extractedValue.i64 = *(int32_t*)value; break; case IL2CPP_TYPE_I8: extractedValue.i64 = *(int64_t*)value; break; case IL2CPP_TYPE_R4: extractedValue.r64 = *(float*)value; break; case IL2CPP_TYPE_R8: extractedValue.r64 = *(double*)value; break; default: IL2CPP_ASSERT(0); break; } return extractedValue; } static void CheckWideningConversion(size_t elementSize, size_t valueSize, size_t extra = 0) { if (elementSize < valueSize + (extra)) ThrowNoWidening(); } template static void AssignUnsigned(WidenedValueUnion value, void* elementAddress, Il2CppTypeEnum valueType, size_t elementSize, size_t valueSize) { switch (valueType) { case IL2CPP_TYPE_U1: case IL2CPP_TYPE_U2: case IL2CPP_TYPE_U4: case IL2CPP_TYPE_U8: case IL2CPP_TYPE_CHAR: CheckWideningConversion(elementSize, valueSize); *(T*)elementAddress = (T)value.u64; break; /* You can't assign a signed value to an unsigned array. */ case IL2CPP_TYPE_I1: case IL2CPP_TYPE_I2: case IL2CPP_TYPE_I4: case IL2CPP_TYPE_I8: /* You can't assign a floating point number to an integer array. */ case IL2CPP_TYPE_R4: case IL2CPP_TYPE_R8: ThrowNoWidening(); break; default: IL2CPP_ASSERT(0); break; } } template static void AssignSigned(WidenedValueUnion value, void* elementAddress, Il2CppTypeEnum valueType, size_t elementSize, size_t valueSize) { switch (valueType) { /* You can assign an unsigned value to a signed array if the array's element size is larger than the value size. */ case IL2CPP_TYPE_U1: case IL2CPP_TYPE_U2: case IL2CPP_TYPE_U4: case IL2CPP_TYPE_U8: case IL2CPP_TYPE_CHAR: CheckWideningConversion(elementSize, valueSize, 1); *(T*)elementAddress = (T)value.u64; break; case IL2CPP_TYPE_I1: case IL2CPP_TYPE_I2: case IL2CPP_TYPE_I4: case IL2CPP_TYPE_I8: CheckWideningConversion(elementSize, valueSize); *(T*)elementAddress = (T)value.i64; break; /* You can't assign a floating point number to an integer array. */ case IL2CPP_TYPE_R4: case IL2CPP_TYPE_R8: ThrowNoWidening(); break; default: IL2CPP_ASSERT(0); break; } } template static void AssignReal(WidenedValueUnion value, void* elementAddress, Il2CppTypeEnum valueType, size_t elementSize, size_t valueSize) { switch (valueType) { /* All integers fit into the floating point value range. No need to check size. */ case IL2CPP_TYPE_U1: case IL2CPP_TYPE_U2: case IL2CPP_TYPE_U4: case IL2CPP_TYPE_U8: case IL2CPP_TYPE_CHAR: *(T*)elementAddress = (T)value.u64; break; case IL2CPP_TYPE_I1: case IL2CPP_TYPE_I2: case IL2CPP_TYPE_I4: case IL2CPP_TYPE_I8: *(T*)elementAddress = (T)value.i64; break; case IL2CPP_TYPE_R4: case IL2CPP_TYPE_R8: CheckWideningConversion(elementSize, valueSize); *(T*)elementAddress = (T)value.r64; break; default: IL2CPP_ASSERT(0); break; } } static void NullableInit(uint8_t* buf, Il2CppObject* value, Il2CppClass* klass) { Il2CppClass *parameterClass = klass->castClass; IL2CPP_ASSERT(Class::FromIl2CppType(klass->fields[0].type) == parameterClass); IL2CPP_ASSERT(Class::FromIl2CppType(klass->fields[1].type) == il2cpp_defaults.boolean_class); *(uint8_t*)(buf + klass->fields[1].offset - sizeof(Il2CppObject)) = value ? 1 : 0; if (value) memcpy(buf + klass->fields[0].offset - sizeof(Il2CppObject), Object::Unbox(value), Class::GetValueSize(parameterClass, NULL)); else memset(buf + klass->fields[0].offset - sizeof(Il2CppObject), 0, Class::GetValueSize(parameterClass, NULL)); } void Array::SetValueImpl(Il2CppArray * thisPtr, Il2CppObject * value, int index) { Il2CppClass* typeInfo = thisPtr->klass; Il2CppClass* elementClass = Class::GetElementClass(typeInfo); int elementSize = Class::GetArrayElementSize(elementClass); void* elementAddress = il2cpp_array_addr_with_size(thisPtr, elementSize, index); if (Class::IsNullable(elementClass)) { NullableInit((uint8_t*)elementAddress, value, elementClass); return; } if (value == NULL) { memset(elementAddress, 0, elementSize); return; } if (!Class::IsValuetype(elementClass)) { if (!Object::IsInst(value, elementClass)) Exception::Raise(Exception::GetInvalidCastException(utils::Exception::FormatInvalidCastException(thisPtr->klass->element_class, value->klass).c_str())); il2cpp_array_setref(thisPtr, index, value); return; } if (Object::IsInst(value, elementClass)) { // write barrier memcpy(elementAddress, Object::Unbox(value), elementSize); return; } Il2CppClass* valueClass = Object::GetClass(value); if (!Class::IsValuetype(valueClass)) ThrowInvalidCast(elementClass, valueClass); int valueSize = Class::GetInstanceSize(valueClass) - sizeof(Il2CppObject); Il2CppTypeEnum elementType = Class::IsEnum(elementClass) ? Class::GetEnumBaseType(elementClass)->type : elementClass->byval_arg->type; Il2CppTypeEnum valueType = Class::IsEnum(valueClass) ? Class::GetEnumBaseType(valueClass)->type : valueClass->byval_arg->type; if (elementType == IL2CPP_TYPE_BOOLEAN) { switch (valueType) { case IL2CPP_TYPE_BOOLEAN: break; case IL2CPP_TYPE_CHAR: case IL2CPP_TYPE_U1: case IL2CPP_TYPE_U2: case IL2CPP_TYPE_U4: case IL2CPP_TYPE_U8: case IL2CPP_TYPE_I1: case IL2CPP_TYPE_I2: case IL2CPP_TYPE_I4: case IL2CPP_TYPE_I8: case IL2CPP_TYPE_R4: case IL2CPP_TYPE_R8: ThrowNoWidening(); default: ThrowInvalidCast(elementClass, valueClass); } } WidenedValueUnion widenedValue = ExtractWidenedValue(valueType, Object::Unbox(value)); switch (elementType) { case IL2CPP_TYPE_U1: AssignUnsigned(widenedValue, elementAddress, valueType, elementSize, valueSize); break; case IL2CPP_TYPE_CHAR: AssignUnsigned(widenedValue, elementAddress, valueType, elementSize, valueSize); break; case IL2CPP_TYPE_U2: AssignUnsigned(widenedValue, elementAddress, valueType, elementSize, valueSize); break; case IL2CPP_TYPE_U4: AssignUnsigned(widenedValue, elementAddress, valueType, elementSize, valueSize); break; case IL2CPP_TYPE_U8: AssignUnsigned(widenedValue, elementAddress, valueType, elementSize, valueSize); break; case IL2CPP_TYPE_I1: AssignSigned(widenedValue, elementAddress, valueType, elementSize, valueSize); break; case IL2CPP_TYPE_I2: AssignSigned(widenedValue, elementAddress, valueType, elementSize, valueSize); break; case IL2CPP_TYPE_I4: AssignSigned(widenedValue, elementAddress, valueType, elementSize, valueSize); break; case IL2CPP_TYPE_I8: AssignSigned(widenedValue, elementAddress, valueType, elementSize, valueSize); break; case IL2CPP_TYPE_R4: AssignReal(widenedValue, elementAddress, valueType, elementSize, valueSize); break; case IL2CPP_TYPE_R8: AssignReal(widenedValue, elementAddress, valueType, elementSize, valueSize); break; default: ThrowInvalidCast(elementClass, valueClass); break; } } } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Array.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppArray; struct Il2CppReflectionType; struct Il2CppObject; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API Array { public: static void ClearInternal(Il2CppArray* arr, int32_t idx, int32_t length); static Il2CppArray* Clone(Il2CppArray* arr); static Il2CppArray* CreateInstanceImpl(Il2CppReflectionType* elementType, Il2CppArray* lengths, Il2CppArray* bounds); static bool FastCopy(Il2CppArray* source, int32_t source_idx, Il2CppArray* dest, int32_t dest_idx, int32_t length); static int32_t GetLength(Il2CppArray* thisPtr, int dimension); static int32_t GetLowerBound(Il2CppArray* , int32_t); static Il2CppObject* GetValue(Il2CppArray* thisPtr, Il2CppArray* indices); static Il2CppObject* GetValueImpl(Il2CppArray* thisPtr, int32_t pos); static void SetValue(Il2CppArray* , Il2CppObject* , Il2CppArray*); static void SetValueImpl(Il2CppArray* thisPtr, Il2CppObject* value, int index); static int GetRank(Il2CppArray* array); }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Buffer.cpp ================================================ #include "il2cpp-config.h" #include #include "icalls/mscorlib/System/Buffer.h" #include "class-internals.h" #include "vm/Array.h" #include "vm/Class.h" #include "vm/Exception.h" using il2cpp::vm::Class; #ifdef _MSC_VER # define ISNAN _isnan #else # define ISNAN isnan #endif namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { bool Buffer::BlockCopyInternal(Il2CppArray * src, int src_offset, Il2CppArray * dest, int dest_offset, int count) { IL2CPP_CHECK_ARG_NULL(src); IL2CPP_CHECK_ARG_NULL(dest); /* watch out for integer overflow */ if (((uint32_t)src_offset > il2cpp::vm::Array::GetByteLength(src) - count) || ((uint32_t)dest_offset > il2cpp::vm::Array::GetByteLength(dest) - count)) return false; char *src_buf = ((char*)il2cpp_array_addr_with_size(src, Class::GetInstanceSize(src->klass->element_class), 0)) + src_offset; char *dest_buf = ((char*)il2cpp_array_addr_with_size(dest, Class::GetInstanceSize(dest->klass->element_class), 0)) + dest_offset; if (src != dest) memcpy(dest_buf, src_buf, count); else memmove(dest_buf, src_buf, count); /* Source and dest are the same array */ return true; } int32_t Buffer::ByteLengthInternal(Il2CppArray* arr) { return il2cpp::vm::Array::GetByteLength(arr); } uint8_t Buffer::GetByteInternal(Il2CppArray* arr, int idx) { return il2cpp_array_get(arr, uint8_t, idx); } void Buffer::SetByteInternal(Il2CppArray* arr, int idx, int value) { il2cpp_array_set(arr, uint8_t, idx, value); } #if NET_4_0 uint8_t Buffer::_GetByte(Il2CppArray* array, int32_t index) { return GetByteInternal(array, index); } bool Buffer::InternalBlockCopy(Il2CppArray* src, int32_t srcOffsetBytes, Il2CppArray* dst, int32_t dstOffsetBytes, int32_t byteCount) { return BlockCopyInternal(src, srcOffsetBytes, dst, dstOffsetBytes, byteCount); } int32_t Buffer::_ByteLength(Il2CppArray* array) { return ByteLengthInternal(array); } void Buffer::_SetByte(Il2CppArray* array, int32_t index, uint8_t value) { SetByteInternal(array, index, value); } #endif } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Buffer.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppArray; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API Buffer { public: static bool BlockCopyInternal(Il2CppArray * src, int src_offset, Il2CppArray * dest, int dest_offset, int count); static int32_t ByteLengthInternal(Il2CppArray* arr); static uint8_t GetByteInternal(Il2CppArray* arr, int idx); static void SetByteInternal(Il2CppArray* arr, int idx, int value); #if NET_4_0 static uint8_t _GetByte(Il2CppArray* array, int32_t index); static bool InternalBlockCopy(Il2CppArray* src, int32_t srcOffsetBytes, Il2CppArray* dst, int32_t dstOffsetBytes, int32_t byteCount); static int32_t _ByteLength(Il2CppArray* array); static void _SetByte(Il2CppArray* array, int32_t index, uint8_t value); #endif }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/CLRConfig.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "CLRConfig.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { bool CLRConfig::CheckThrowUnobservedTaskExceptions() { // TODO : Properly support this icall at some point. This requires knowning that the ThrowUnobservedTaskExceptions=true flag was // set in the app.config and return true here if it was return false; } } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/CLRConfig.h ================================================ #pragma once #if NET_4_0 namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API CLRConfig { public: static bool CheckThrowUnobservedTaskExceptions(); }; } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Char.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System/Char.h" #include "char-conversions.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { void Char::GetDataTablePointers( const unsigned char** category_data, const unsigned char** numeric_data, const double** numeric_data_values, const Il2CppChar** to_lower_data_low, const Il2CppChar** to_lower_data_high, const Il2CppChar** to_upper_data_low, const Il2CppChar** to_upper_data_high) { *category_data = CategoryData_v4; *numeric_data = NumericData; *numeric_data_values = NumericDataValues; *to_lower_data_low = ToLowerDataLow; *to_lower_data_high = ToLowerDataHigh; *to_upper_data_low = ToUpperDataLow; *to_upper_data_high = ToUpperDataHigh; } } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Char.h ================================================ #pragma once #include #include "il2cpp-config.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API Char { public: static void GetDataTablePointers( const unsigned char** category_data, const unsigned char** numeric_data, const double** numeric_data_values, const Il2CppChar** to_lower_data_low, const Il2CppChar** to_lower_data_high, const Il2CppChar** to_upper_data_low, const Il2CppChar** to_upper_data_high); }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/ConsoleDriver.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System/ConsoleDriver.h" #include "class-internals.h" #include "os/Console.h" #include "os/File.h" #include "vm/Array.h" #include "vm/Exception.h" #include "utils/StringUtils.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { // Used in .NET 2.0 System.Console -> CStreamReader/CStreamWriter -> TermInfoDriver -> ConsoleDriver -> icalls bool ConsoleDriver::Isatty(Il2CppIntPtr handle) { il2cpp::os::FileHandle* fileHandle = (il2cpp::os::FileHandle*)handle.m_value; return os::File::Isatty(fileHandle); } int32_t ConsoleDriver::InternalKeyAvailable(int32_t ms_timeout) { return il2cpp::os::Console::InternalKeyAvailable(ms_timeout); } bool ConsoleDriver::TtySetup(Il2CppString* keypadXmit, Il2CppString* teardown, Il2CppArray** control_characters, int32_t** size) { const std::string keypadXmitString(keypadXmit ? il2cpp::utils::StringUtils::Utf16ToUtf8(keypadXmit->chars) : ""); const std::string teardownString(teardown ? il2cpp::utils::StringUtils::Utf16ToUtf8(teardown->chars) : ""); uint8_t controlChars[17]; const bool ret = il2cpp::os::Console::TtySetup(keypadXmitString, teardownString, controlChars, size); *control_characters = vm::Array::New(il2cpp_defaults.byte_class, 17); // mono_gc_wbarrier_generic_store (data, Array::New (il2cpp_defaults.byte_class, 17)); if (ret) memcpy(il2cpp_array_addr(*control_characters, uint8_t, 0), controlChars, 17); return true; } bool ConsoleDriver::SetEcho(bool wantEcho) { return il2cpp::os::Console::SetEcho(wantEcho); } bool ConsoleDriver::SetBreak(bool wantBreak) { return il2cpp::os::Console::SetBreak(wantBreak); } } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/ConsoleDriver.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API ConsoleDriver { public: static int32_t InternalKeyAvailable(int32_t ms_timeout); static bool SetBreak(bool wantBreak); static bool SetEcho(bool wantEcho); static bool TtySetup(Il2CppString* keypadXmit, Il2CppString* teardown, Il2CppArray** control_characters, int32_t** size); static bool Isatty(Il2CppIntPtr handle); }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Convert.cpp ================================================ #include "il2cpp-config.h" #include #include "icalls/mscorlib/System/Convert.h" #include "il2cpp-api.h" #include "class-internals.h" #include "object-internals.h" #include "vm/Array.h" #include "vm/Image.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { Il2CppArray* Convert::InternalFromBase64String(Il2CppString* str, bool allowWhitespaceOnly) { return Base64ToByteArray(str->chars, str->length, allowWhitespaceOnly); } Il2CppArray* Convert::InternalFromBase64CharArray(Il2CppArray* chars, int32_t offset, int32_t length) { return Base64ToByteArray(il2cpp_array_addr(chars, Il2CppChar, offset), length, false); } Il2CppArray* Convert::Base64ToByteArray(Il2CppChar* start, int length, bool allowWhitespaceOnly) { int ignored; int i; Il2CppChar c; Il2CppChar last, prev_last, prev2_last; int olength; Il2CppArray *result; unsigned char *res_ptr; int a[4], b[4]; const static unsigned char dbase64[] = { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128, 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 }; ignored = 0; last = prev_last = 0, prev2_last = 0; for (i = 0; i < length; i++) { c = start[i]; if (c >= sizeof(dbase64)) { // The content of this exception message matches Mono, but differs from .Net. il2cpp_raise_exception(vm::Exception::GetFormatException("Invalid character found.")); } else if (isspace(c)) { ignored++; } else { prev2_last = prev_last; prev_last = last; last = c; } } olength = length - ignored; if (allowWhitespaceOnly && olength == 0) return vm::Array::New(il2cpp_defaults.byte_class, 0); if ((olength & 3) != 0 || olength <= 0) { // The content of this exception message matches Mono, but differs from .Net. il2cpp_raise_exception(vm::Exception::GetFormatException("Invalid length.")); } if (prev2_last == '=') { // The content of this exception message matches Mono, but differs from .Net. il2cpp_raise_exception(vm::Exception::GetFormatException("Invalid format.")); } olength = (olength * 3) / 4; if (last == '=') olength--; if (prev_last == '=') olength--; result = vm::Array::New(il2cpp_defaults.byte_class, olength); res_ptr = il2cpp_array_addr(result, unsigned char, 0); for (i = 0; i < length;) { int k; for (k = 0; k < 4 && i < length;) { c = start[i++]; if (isspace(c)) continue; a[k] = (unsigned char)c; if (((b[k] = dbase64[c]) & 0x80) != 0) { // The content of this exception message matches Mono, but differs from .Net. il2cpp_raise_exception(vm::Exception::GetFormatException("Invalid character found.")); } k++; } *res_ptr++ = (b[0] << 2) | (b[1] >> 4); if (a[2] != '=') *res_ptr++ = (b[1] << 4) | (b[2] >> 2); if (a[3] != '=') *res_ptr++ = (b[2] << 6) | b[3]; while (i < length && isspace(start[i])) i++; } return result; } } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Convert.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppArray; struct Il2CppString; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API Convert { public: static Il2CppArray* InternalFromBase64CharArray(Il2CppArray* arr, int32_t offset, int32_t length); static Il2CppArray* InternalFromBase64String(Il2CppString* str, bool allowWhitespaceOnly); static Il2CppArray* Base64ToByteArray(Il2CppChar* start, int length, bool allowWhitespaceOnly); }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/CurrentSystemTimeZone.cpp ================================================ #include "il2cpp-config.h" #include #include "icalls/mscorlib/System/CurrentSystemTimeZone.h" #include "class-internals.h" #include "object-internals.h" #include "vm/Array.h" #include "vm/Exception.h" #include "vm/String.h" #include "os/TimeZone.h" using namespace il2cpp::vm; using namespace il2cpp::os; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { bool CurrentSystemTimeZone::GetTimeZoneData(int year, Il2CppArray** data, Il2CppArray** names) { NOT_IMPLEMENTED_NO_ASSERT(CurrentSystemTimeZone::GetTimeZoneData, "Check arguments and write barriers"); int64_t dataTemp[4] = {0}; std::string namesTemp[2]; IL2CPP_CHECK_ARG_NULL(data); IL2CPP_CHECK_ARG_NULL(names); *data = Array::New(il2cpp_defaults.int64_class, 4); //mono_gc_wbarrier_generic_store (data, Array::New (il2cpp_defaults.int64_class, 4)); *names = Array::New(il2cpp_defaults.string_class, 2); //mono_gc_wbarrier_generic_store (names, Array::New (il2cpp_defaults.string_class, 2)); if (!TimeZone::GetTimeZoneData(year, dataTemp, namesTemp)) return false; for (int i = 0; i < 4; i++) il2cpp_array_set((*data), int64_t, i, dataTemp[i]); for (int i = 0; i < 2; i++) il2cpp_array_setref((*names), i, String::New(namesTemp[i].c_str())); return true; } } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/CurrentSystemTimeZone.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppArray; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API CurrentSystemTimeZone { public: static bool GetTimeZoneData(int, Il2CppArray * *, Il2CppArray * *); }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/DateTime.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System/DateTime.h" #include "os/Time.h" using namespace il2cpp::os; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { int64_t DateTime::GetNow(void) { return Time::GetTicks100NanosecondsDateTime(); } int64_t DateTime::GetTimeMonotonic() { return Time::GetTicks100NanosecondsMonotonic(); } #if NET_4_0 int64_t DateTime::GetSystemTimeAsFileTime() { return Time::GetSystemTimeAsFileTime(); } #endif } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/DateTime.h ================================================ #pragma once #include #include "il2cpp-config.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API DateTime { public: static int64_t GetNow(void); static int64_t GetTimeMonotonic(); #if NET_4_0 static int64_t GetSystemTimeAsFileTime(); #endif }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Decimal.cpp ================================================ #include "il2cpp-config.h" #include "object-internals.h" #include "class-internals.h" #include "icalls/mscorlib/System/Decimal.h" #include "utils/StringUtils.h" #include "vm/Exception.h" #include #include #if !NET_4_0 #define DECIMAL_MAX_SCALE 28 #define DECIMAL_MAX_INTFACTORS 9 #define DECIMAL_SUCCESS 0 #define DECIMAL_FINISHED 1 #define DECIMAL_OVERFLOW 2 #define DECIMAL_INVALID_CHARACTER 2 #define DECIMAL_INTERNAL_ERROR 3 #define DECIMAL_INVALID_BITS 4 #define DECIMAL_DIVIDE_BY_ZERO 5 #define DECIMAL_BUFFER_OVERFLOW 6 #define LIT_GUINT32(x) x #define LIT_GUINT64(x) x##LL #define LIT_GUINT32_HIGHBIT 0x80000000 #define LIT_GUINT64_HIGHBIT LIT_GUINT64(0x8000000000000000) #define DECIMAL_LOG_NEGINF -1000 #define DECINIT(src) memset(src, 0, sizeof(il2cpp_decimal_repr)) #define DECCOPY(dest, src) memcpy(dest, src, sizeof(il2cpp_decimal_repr)) #define DECNEGATE(p1) (p1)->u.signscale.sign = 1 - (p1)->u.signscale.sign #define DECTO128(pd, lo, hi) \ lo = (((uint64_t)(pd)->mid32) << 32) | (pd)->lo32; \ hi = (pd)->hi32; #ifndef MAX #define MAX(a, b) (((a)>(b)) ? (a) : (b)) #endif #ifdef _DEBUG #include #define PRECONDITION(flag) IL2CPP_ASSERT(flag) #define POSTCONDITION(flag) IL2CPP_ASSERT(flag) #else #define PRECONDITION(flag) #define POSTCONDITION(flag) #endif /* _DEBUG */ typedef struct { uint64_t lo; uint64_t hi; } dec128_repr; #define LIT_DEC128(hi, mid, lo) { (((uint64_t)mid)<<32 | lo), hi } static const dec128_repr dec128decadeFactors[DECIMAL_MAX_SCALE + 1] = { LIT_DEC128(0, 0, 1u), /* == 1 */ LIT_DEC128(0, 0, 10u), /* == 10 */ LIT_DEC128(0, 0, 100u), /* == 100 */ LIT_DEC128(0, 0, 1000u), /* == 1e3m */ LIT_DEC128(0, 0, 10000u), /* == 1e4m */ LIT_DEC128(0, 0, 100000u), /* == 1e5m */ LIT_DEC128(0, 0, 1000000u), /* == 1e6m */ LIT_DEC128(0, 0, 10000000u), /* == 1e7m */ LIT_DEC128(0, 0, 100000000u), /* == 1e8m */ LIT_DEC128(0, 0, 1000000000u), /* == 1e9m */ LIT_DEC128(0, 2u, 1410065408u), /* == 1e10m */ LIT_DEC128(0, 23u, 1215752192u), /* == 1e11m */ LIT_DEC128(0, 232u, 3567587328u), /* == 1e12m */ LIT_DEC128(0, 2328u, 1316134912u), /* == 1e13m */ LIT_DEC128(0, 23283u, 276447232u), /* == 1e14m */ LIT_DEC128(0, 232830u, 2764472320u), /* == 1e15m */ LIT_DEC128(0, 2328306u, 1874919424u), /* == 1e16m */ LIT_DEC128(0, 23283064u, 1569325056u), /* == 1e17m */ LIT_DEC128(0, 232830643u, 2808348672u), /* == 1e18m */ LIT_DEC128(0, 2328306436u, 2313682944u), /* == 1e19m */ LIT_DEC128(5u, 1808227885u, 1661992960u), /* == 1e20m */ LIT_DEC128(54u, 902409669u, 3735027712u), /* == 1e21m */ LIT_DEC128(542u, 434162106u, 2990538752u), /* == 1e22m */ LIT_DEC128(5421u, 46653770u, 4135583744u), /* == 1e23m */ LIT_DEC128(54210u, 466537709u, 2701131776u), /* == 1e24m */ LIT_DEC128(542101u, 370409800u, 1241513984u), /* == 1e25m */ LIT_DEC128(5421010u, 3704098002u, 3825205248u), /* == 1e26m */ LIT_DEC128(54210108u, 2681241660u, 3892314112u), /* == 1e27m */ LIT_DEC128(542101086u, 1042612833u, 268435456u), /* == 1e28m */ }; static const uint32_t constantsDecadeInt32Factors[DECIMAL_MAX_INTFACTORS + 1] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; static int pack128toDecimal(il2cpp_decimal_repr* pA, uint64_t alo, uint64_t ahi, int scale, int sign) { if (scale < 0 || scale > DECIMAL_MAX_SCALE || (ahi >> 32) != 0) return DECIMAL_OVERFLOW; pA->lo32 = (uint32_t)alo; pA->mid32 = (uint32_t)(alo >> 32); pA->hi32 = (uint32_t)ahi; pA->u.signscale.sign = sign; pA->u.signscale.scale = scale; return DECIMAL_SUCCESS; } static void add128(uint64_t alo, uint64_t ahi, uint64_t blo, uint64_t bhi, uint64_t* pclo, uint64_t* pchi) { alo += blo; if (alo < blo) ahi++; ahi += bhi; *pclo = alo; *pchi = ahi; } static void sub128(uint64_t alo, uint64_t ahi, uint64_t blo, uint64_t bhi, uint64_t* pclo, uint64_t* pchi) { uint64_t clo, chi; clo = alo - blo; chi = ahi - bhi; if (alo < blo) chi--; /* borrow */ *pclo = clo; *pchi = chi; } static int div128by32(uint64_t* plo, uint64_t* phi, uint32_t factor, uint32_t* pRest) { uint64_t a, b, c, h; h = *phi; a = (uint32_t)(h >> 32); b = a / factor; a -= b * factor; a <<= 32; a |= (uint32_t)h; c = a / factor; a -= c * factor; a <<= 32; *phi = b << 32 | (uint32_t)c; h = *plo; a |= (uint32_t)(h >> 32); b = a / factor; a -= b * factor; a <<= 32; a |= (uint32_t)h; c = a / factor; a -= c * factor; *plo = b << 32 | (uint32_t)c; if (pRest) *pRest = (uint32_t)a; a <<= 1; return (a >= factor || (a == factor && (c & 1) == 1)) ? 1 : 0; } static int mult128by32(uint64_t* pclo, uint64_t* pchi, uint32_t factor, int roundBit) { uint64_t a; uint32_t h0, h1; a = ((uint64_t)(uint32_t)(*pclo)) * factor; if (roundBit) a += factor / 2; h0 = (uint32_t)a; a >>= 32; a += (*pclo >> 32) * factor; h1 = (uint32_t)a; *pclo = ((uint64_t)h1) << 32 | h0; a >>= 32; a += ((uint64_t)(uint32_t)(*pchi)) * factor; h0 = (uint32_t)a; a >>= 32; a += (*pchi >> 32) * factor; h1 = (uint32_t)a; *pchi = ((uint64_t)h1) << 32 | h0; return ((a >> 32) == 0) ? DECIMAL_SUCCESS : DECIMAL_OVERFLOW; } static void mult96by96to192(uint32_t alo, uint32_t ami, uint32_t ahi, uint32_t blo, uint32_t bmi, uint32_t bhi, uint64_t* pclo, uint64_t* pcmi, uint64_t* pchi) { uint64_t a, b, c, d; uint32_t h0, h1, h2, h3, h4, h5; int carry0, carry1; a = ((uint64_t)alo) * blo; h0 = (uint32_t)a; a >>= 32; carry0 = 0; b = ((uint64_t)alo) * bmi; c = ((uint64_t)ami) * blo; a += b; if (a < b) carry0++; a += c; if (a < c) carry0++; h1 = (uint32_t)a; a >>= 32; carry1 = 0; b = ((uint64_t)alo) * bhi; c = ((uint64_t)ami) * bmi; d = ((uint64_t)ahi) * blo; a += b; if (a < b) carry1++; a += c; if (a < c) carry1++; a += d; if (a < d) carry1++; h2 = (uint32_t)a; a >>= 32; a += carry0; carry0 = 0; b = ((uint64_t)ami) * bhi; c = ((uint64_t)ahi) * bmi; a += b; if (a < b) carry0++; a += c; if (a < c) carry0++; h3 = (uint32_t)a; a >>= 32; a += carry1; b = ((uint64_t)ahi) * bhi; a += b; h4 = (uint32_t)a; a >>= 32; a += carry0; h5 = (uint32_t)a; *pclo = ((uint64_t)h1) << 32 | h0; *pcmi = ((uint64_t)h3) << 32 | h2; *pchi = ((uint64_t)h5) << 32 | h4; } static void div192by32(uint64_t* plo, uint64_t* pmi, uint64_t* phi, uint32_t factor) { uint64_t a, b, c, h; h = *phi; a = (uint32_t)(h >> 32); b = a / factor; a -= b * factor; a <<= 32; a |= (uint32_t)h; c = a / factor; a -= c * factor; a <<= 32; *phi = b << 32 | (uint32_t)c; h = *pmi; a |= (uint32_t)(h >> 32); b = a / factor; a -= b * factor; a <<= 32; a |= (uint32_t)h; c = a / factor; a -= c * factor; a <<= 32; *pmi = b << 32 | (uint32_t)c; h = *plo; a |= (uint32_t)(h >> 32); b = a / factor; a -= b * factor; a <<= 32; a |= (uint32_t)h; c = a / factor; a -= c * factor; a <<= 32; *plo = b << 32 | (uint32_t)c; } static int incMultConstant128(uint64_t* palo, uint64_t* pahi, int idx, int factor) { uint64_t blo, bhi, h; IL2CPP_ASSERT(idx >= 0 && idx <= DECIMAL_MAX_SCALE); IL2CPP_ASSERT(factor > 0 && factor <= 9); blo = dec128decadeFactors[idx].lo; h = bhi = dec128decadeFactors[idx].hi; if (factor != 1) { mult128by32(&blo, &bhi, factor, 0); if (h > bhi) return DECIMAL_OVERFLOW; } h = *pahi; add128(*palo, *pahi, blo, bhi, palo, pahi); if (h > *pahi) return DECIMAL_OVERFLOW; return DECIMAL_SUCCESS; } static void roundUp128(uint64_t* pclo, uint64_t* pchi) { if (++(*pclo) == 0) ++(*pchi); } static int decimalIsZero(il2cpp_decimal_repr* pA) { return (pA->lo32 == 0 && pA->mid32 == 0 && pA->hi32 == 0); } static void sub192(uint64_t alo, uint64_t ami, uint64_t ahi , uint64_t blo, uint64_t bmi, uint64_t bhi, uint64_t* pclo, uint64_t* pcmi, uint64_t* pchi) { uint64_t clo, cmi, chi; clo = alo - blo; cmi = ami - bmi; chi = ahi - bhi; if (alo < blo) { if (cmi == 0) chi--; /* borrow mid */ cmi--; /* borrow low */ } if (ami < bmi) chi--; /* borrow mid */ *pclo = clo; *pcmi = cmi; *pchi = chi; } static void mult96by32to128(uint32_t alo, uint32_t ami, uint32_t ahi, uint32_t factor, uint64_t* pclo, uint64_t* pchi) { uint64_t a; uint32_t h0, h1; a = ((uint64_t)alo) * factor; h0 = (uint32_t)a; a >>= 32; a += ((uint64_t)ami) * factor; h1 = (uint32_t)a; a >>= 32; a += ((uint64_t)ahi) * factor; *pclo = ((uint64_t)h1) << 32 | h0; *pchi = a; } static void add192(uint64_t alo, uint64_t ami, uint64_t ahi, uint64_t blo, uint64_t bmi, uint64_t bhi, uint64_t* pclo, uint64_t* pcmi, uint64_t* pchi) { alo += blo; if (alo < blo) { /* carry low */ ami++; if (ami == 0) ahi++; /* carry mid */ } ami += bmi; if (ami < bmi) ahi++; /* carry mid */ ahi += bhi; *pclo = alo; *pcmi = ami; *pchi = ahi; } static uint32_t div192by96to32withRest(uint64_t* palo, uint64_t* pami, uint64_t* pahi, uint32_t blo, uint32_t bmi, uint32_t bhi) { uint64_t rlo, rmi, rhi; /* remainder */ uint64_t tlo, thi; /* term */ uint32_t c; rlo = *palo; rmi = *pami; rhi = *pahi; if (rhi >= (((uint64_t)bhi) << 32)) { c = LIT_GUINT32(0xFFFFFFFF); } else { c = (uint32_t)(rhi / bhi); } mult96by32to128(blo, bmi, bhi, c, &tlo, &thi); sub192(rlo, rmi, rhi, 0, tlo, thi, &rlo, &rmi, &rhi); while (((int64_t)rhi) < 0) { c--; add192(rlo, rmi, rhi, 0, (((uint64_t)bmi) << 32) | blo, bhi, &rlo, &rmi, &rhi); } *palo = rlo; *pami = rmi; *pahi = rhi; POSTCONDITION(rhi >> 32 == 0); return c; } static void div192by96to128(uint64_t alo, uint64_t ami, uint64_t ahi, uint32_t blo, uint32_t bmi, uint32_t bhi, uint64_t* pclo, uint64_t* pchi) { uint64_t rlo, rmi, rhi; /* remainder */ uint32_t h, c; PRECONDITION(ahi < (((uint64_t)bhi) << 32 | bmi) || (ahi == (((uint64_t)bhi) << 32 | bmi) && (ami >> 32) > blo)); /* high 32 bit*/ rlo = alo; rmi = ami; rhi = ahi; h = div192by96to32withRest(&rlo, &rmi, &rhi, blo, bmi, bhi); /* mid 32 bit*/ rhi = (rhi << 32) | (rmi >> 32); rmi = (rmi << 32) | (rlo >> 32); rlo <<= 32; *pchi = (((uint64_t)h) << 32) | div192by96to32withRest(&rlo, &rmi, &rhi, blo, bmi, bhi); /* low 32 bit */ rhi = (rhi << 32) | (rmi >> 32); rmi = (rmi << 32) | (rlo >> 32); rlo <<= 32; h = div192by96to32withRest(&rlo, &rmi, &rhi, blo, bmi, bhi); /* estimate lowest 32 bit (two last bits may be wrong) */ if (rhi >= bhi) { c = LIT_GUINT32(0xFFFFFFFF); } else { rhi <<= 32; c = (uint32_t)(rhi / bhi); } *pclo = (((uint64_t)h) << 32) | c; } static void rshift128(uint64_t* pclo, uint64_t* pchi) { *pclo >>= 1; *pclo |= (*pchi & 1) << 63; *pchi >>= 1; } static void lshift128(uint64_t* pclo, uint64_t* pchi) { *pchi <<= 1; *pchi |= (*pclo & LIT_GUINT64_HIGHBIT) >> 63; *pclo <<= 1; } static inline int my_g_bit_nth_msf(uintptr_t mask) { int i; // Mono uses some architecture and OS-specific code to implement this function. // This is the code from the #else case, which attempts to use sizeof(gsize), // which is sizeof(uintptr_t) for us. This seems to be wrong on 64-bit though, // So we will explicitly always use 4 here. //i = sizeof(gsize) * 8; i = 4 * 8; while (i > 0) { i--; if (mask & static_cast(1ULL << i)) return i; } return -1; } static int decimalDivSub(il2cpp_decimal_repr* pA, il2cpp_decimal_repr* pB, uint64_t* pclo, uint64_t* pchi, int* pExp) { uint64_t alo, ami, ahi; uint64_t tlo, tmi, thi; uint32_t blo, bmi, bhi; int ashift, bshift, extraBit, texp; ahi = (((uint64_t)(pA->hi32)) << 32) | pA->mid32; ami = ((uint64_t)(pA->lo32)) << 32; alo = 0; blo = pB->lo32; bmi = pB->mid32; bhi = pB->hi32; if (blo == 0 && bmi == 0 && bhi == 0) { return DECIMAL_DIVIDE_BY_ZERO; } if (ami == 0 && ahi == 0) { *pclo = *pchi = 0; return DECIMAL_FINISHED; } /* enlarge dividend to get maximal precision */ if (ahi == 0) { ahi = ami; ami = 0; for (ashift = 64; (ahi & LIT_GUINT64_HIGHBIT) == 0; ++ashift) { ahi <<= 1; } } else { for (ashift = 0; (ahi & LIT_GUINT64_HIGHBIT) == 0; ++ashift) { lshift128(&ami, &ahi); } } /* ensure that divisor is at least 2^95 */ if (bhi == 0) { if (bmi == 0) { uint32_t hi_shift; bhi = blo; bmi = 0; blo = 0; //IL2CPP_ASSERT(g_bit_nth_msf (bhi, 32) == my_g_bit_nth_msf (bhi)); hi_shift = 31 - my_g_bit_nth_msf(bhi); bhi <<= hi_shift; bshift = 64 + hi_shift; } else { bhi = bmi; bmi = blo; blo = 0; for (bshift = 32; (bhi & LIT_GUINT32_HIGHBIT) == 0; ++bshift) { bhi <<= 1; bhi |= (bmi & LIT_GUINT32_HIGHBIT) >> 31; bmi <<= 1; } } } else { for (bshift = 0; (bhi & LIT_GUINT32_HIGHBIT) == 0; ++bshift) { bhi <<= 1; bhi |= (bmi & LIT_GUINT32_HIGHBIT) >> 31; bmi <<= 1; bmi |= (blo & LIT_GUINT32_HIGHBIT) >> 31; blo <<= 1; } } thi = ((uint64_t)bhi) << 32 | bmi; tmi = ((uint64_t)blo) << 32; tlo = 0; if (ahi > thi || (ahi == thi && ami >= tmi)) { sub192(alo, ami, ahi, tlo, tmi, thi, &alo, &ami, &ahi); extraBit = 1; } else { extraBit = 0; } div192by96to128(alo, ami, ahi, blo, bmi, bhi, pclo, pchi); texp = 128 + ashift - bshift; if (extraBit) { rshift128(pclo, pchi); *pchi += LIT_GUINT64_HIGHBIT; texp--; } /* try loss free right shift */ while (texp > 0 && (*pclo & 1) == 0) { /* right shift */ rshift128(pclo, pchi); texp--; } *pExp = texp; return DECIMAL_SUCCESS; } static int log2_32(uint32_t a) { if (a == 0) return DECIMAL_LOG_NEGINF; return my_g_bit_nth_msf(a) + 1; } static int log2_64(uint64_t a) { if (a == 0) return DECIMAL_LOG_NEGINF; #if SIZEOF_VOID_P == 8 return my_g_bit_nth_msf(a) + 1; #else if ((a >> 32) == 0) return my_g_bit_nth_msf((uint32_t)a) + 1; else return my_g_bit_nth_msf((uint32_t)(a >> 32)) + 1 + 32; #endif } static int log2_128(uint64_t alo, uint64_t ahi) { if (ahi == 0) return log2_64(alo); else return log2_64(ahi) + 64; } static int log2withScale_128(uint64_t alo, uint64_t ahi, int scale) { int tlog2 = log2_128(alo, ahi); if (tlog2 < 0) tlog2 = 0; return tlog2 - (scale * 33219) / 10000; } static int decimalLog2(il2cpp_decimal_repr* pA) { int tlog2; int scale = pA->u.signscale.scale; if (pA->hi32 != 0) tlog2 = 64 + log2_32(pA->hi32); else if (pA->mid32 != 0) tlog2 = 32 + log2_32(pA->mid32); else tlog2 = log2_32(pA->lo32); if (tlog2 != DECIMAL_LOG_NEGINF) { tlog2 -= (scale * 33219) / 10000; } return tlog2; } static int normalize128(uint64_t* pclo, uint64_t* pchi, int* pScale, int roundFlag, int roundBit) { uint32_t overhang = (uint32_t)(*pchi >> 32); int scale = *pScale; int deltaScale; while (overhang != 0) { for (deltaScale = 1; deltaScale < DECIMAL_MAX_INTFACTORS; deltaScale++) { if (overhang < constantsDecadeInt32Factors[deltaScale]) break; } scale -= deltaScale; if (scale < 0) return DECIMAL_OVERFLOW; roundBit = div128by32(pclo, pchi, constantsDecadeInt32Factors[deltaScale], 0); overhang = (uint32_t)(*pchi >> 32); if (roundFlag && roundBit && *pclo == (uint64_t)-1 && (int32_t)*pchi == (int32_t)-1) overhang = 1; } *pScale = scale; if (roundFlag && roundBit) roundUp128(pclo, pchi); return DECIMAL_SUCCESS; } static int adjustScale128(uint64_t* palo, uint64_t* pahi, int deltaScale) { int idx, rc; if (deltaScale < 0) { deltaScale *= -1; if (deltaScale > DECIMAL_MAX_SCALE) return DECIMAL_INTERNAL_ERROR; while (deltaScale > 0) { idx = (deltaScale > DECIMAL_MAX_INTFACTORS) ? DECIMAL_MAX_INTFACTORS : deltaScale; deltaScale -= idx; div128by32(palo, pahi, constantsDecadeInt32Factors[idx], 0); } } else if (deltaScale > 0) { if (deltaScale > DECIMAL_MAX_SCALE) return DECIMAL_INTERNAL_ERROR; while (deltaScale > 0) { idx = (deltaScale > DECIMAL_MAX_INTFACTORS) ? DECIMAL_MAX_INTFACTORS : deltaScale; deltaScale -= idx; rc = mult128by32(palo, pahi, constantsDecadeInt32Factors[idx], 0); if (rc != DECIMAL_SUCCESS) return rc; } } return DECIMAL_SUCCESS; } static int rescale128(uint64_t* pclo, uint64_t* pchi, int* pScale, int texp, int minScale, int maxScale, int roundFlag) { uint32_t factor, overhang; int scale, i, rc, roundBit = 0; scale = *pScale; if (texp > 0) { /* reduce exp */ while (texp > 0 && scale <= maxScale) { overhang = (uint32_t)(*pchi >> 32); /* The original loop was this: */ /* while (texp > 0 && (overhang > (2<> 32); } */ if (overhang > 0) { int msf = my_g_bit_nth_msf(overhang); int shift = msf - (DECIMAL_MAX_INTFACTORS + 2); if (shift >= texp) shift = texp - 1; if (shift > 0) { texp -= shift; *pclo = (*pclo >> shift) | ((*pchi & ((1 << shift) - 1)) << (64 - shift)); *pchi >>= shift; overhang >>= shift; IL2CPP_ASSERT(texp > 0); IL2CPP_ASSERT(overhang > (2 << DECIMAL_MAX_INTFACTORS)); } } while (texp > 0 && (overhang > (2 << DECIMAL_MAX_INTFACTORS) || (*pclo & 1) == 0)) { if (--texp == 0) roundBit = (int)(*pclo & 1); rshift128(pclo, pchi); overhang >>= 1; } if (texp > DECIMAL_MAX_INTFACTORS) i = DECIMAL_MAX_INTFACTORS; else i = texp; if (scale + i > maxScale) i = maxScale - scale; if (i == 0) break; texp -= i; scale += i; factor = constantsDecadeInt32Factors[i] >> i; /* 10^i/2^i=5^i */ mult128by32(pclo, pchi, factor, 0); /*printf("3: %.17e\n", (((double)chi) * pow(2,64) + clo) * pow(10, -scale) * pow(2, -texp));*/ } while (texp > 0) { if (--texp == 0) roundBit = (int)(*pclo & 1); rshift128(pclo, pchi); } } while (scale > maxScale) { i = scale - maxScale; if (i > DECIMAL_MAX_INTFACTORS) i = DECIMAL_MAX_INTFACTORS; scale -= i; roundBit = div128by32(pclo, pchi, constantsDecadeInt32Factors[i], 0); } while (scale < minScale) { if (!roundFlag) roundBit = 0; i = minScale - scale; if (i > DECIMAL_MAX_INTFACTORS) i = DECIMAL_MAX_INTFACTORS; scale += i; rc = mult128by32(pclo, pchi, constantsDecadeInt32Factors[i], roundBit); if (rc != DECIMAL_SUCCESS) return rc; roundBit = 0; } *pScale = scale; return normalize128(pclo, pchi, pScale, roundFlag, roundBit); } static void div128DecadeFactor(uint64_t* palo, uint64_t* pahi, int powerOfTen) { int idx, roundBit = 0; while (powerOfTen > 0) { idx = (powerOfTen > DECIMAL_MAX_INTFACTORS) ? DECIMAL_MAX_INTFACTORS : powerOfTen; powerOfTen -= idx; roundBit = div128by32(palo, pahi, constantsDecadeInt32Factors[idx], 0); } if (roundBit) roundUp128(palo, pahi); } static void buildIEEE754Double(double* pd, int sign, int texp, uint64_t mantisse) { uint64_t* p = (uint64_t*)pd; *p = (((uint64_t)sign) << 63) | (((uint64_t)((1023 + texp) & 0x7ff)) << 52) | mantisse; NOT_IMPLEMENTED_NO_ASSERT(buildIEEE754Double, "Endianess is not being considered"); } #else // NET_4_0 typedef enum { IL2CPP_DECIMAL_OK, IL2CPP_DECIMAL_OVERFLOW, IL2CPP_DECIMAL_INVALID_ARGUMENT, IL2CPP_DECIMAL_DIVBYZERO, IL2CPP_DECIMAL_ARGUMENT_OUT_OF_RANGE } Il2CppDecimalStatus; #ifndef FC_GC_POLL # define FC_GC_POLL() #endif // Double floating point Bias #define IL2CPP_DOUBLE_BIAS 1022 // Single floating point Bias #define IL2CPP_SINGLE_BIAS 126 static const uint32_t ten_to_nine = 1000000000U; static const uint32_t ten_to_ten_div_4 = 2500000000U; #define POWER10_MAX 9 #define DECIMAL_NEG ((uint8_t)0x80) #define DECMAX 28 #define DECIMAL_SCALE(dec) ((dec).u.u.scale) #define DECIMAL_SIGN(dec) ((dec).u.u.sign) #define DECIMAL_SIGNSCALE(dec) ((dec).u.signscale) #define DECIMAL_LO32(dec) ((dec).v.v.Lo32) #define DECIMAL_MID32(dec) ((dec).v.v.Mid32) #define DECIMAL_HI32(dec) ((dec).Hi32) #if IL2CPP_BYTE_ORDER != IL2CPP_LITTLE_ENDIAN # define DECIMAL_LO64_GET(dec) (((uint64_t)((dec).v.v.Mid32) << 32) | (dec).v.v.Lo32) # define DECIMAL_LO64_SET(dec, value) {(dec).v.v.Lo32 = (value); (dec).v.v.Mid32 = ((value) >> 32); } #else # define DECIMAL_LO64_GET(dec) ((dec).v.Lo64) # define DECIMAL_LO64_SET(dec, value) {(dec).v.Lo64 = value; } #endif #define DECIMAL_SETZERO(dec) {DECIMAL_LO32(dec) = 0; DECIMAL_MID32(dec) = 0; DECIMAL_HI32(dec) = 0; DECIMAL_SIGNSCALE(dec) = 0;} #define COPYDEC(dest, src) {DECIMAL_SIGNSCALE(dest) = DECIMAL_SIGNSCALE(src); DECIMAL_HI32(dest) = DECIMAL_HI32(src); \ DECIMAL_MID32(dest) = DECIMAL_MID32(src); DECIMAL_LO32(dest) = DECIMAL_LO32(src); } #define DEC_SCALE_MAX 28 #define POWER10_MAX 9 #define OVFL_MAX_9_HI 4 #define OVFL_MAX_9_MID 1266874889 #define OVFL_MAX_9_LO 3047500985u #define OVFL_MAX_5_HI 42949 #define OVFL_MAX_5_MID 2890341191 #define OVFL_MAX_1_HI 429496729 typedef union { uint64_t int64; struct { #if IL2CPP_BYTE_ORDER == IL2CPP_BIG_ENDIAN uint32_t Hi; uint32_t Lo; #else uint32_t Lo; uint32_t Hi; #endif } u; } SPLIT64; static const SPLIT64 ten_to_eighteen = { 1000000000000000000ULL }; #if IL2CPP_BYTE_ORDER == IL2CPP_BIG_ENDIAN const Il2CppDouble_double ds2to64 = { { 0, IL2CPP_DOUBLE_BIAS + 65, 0, 0 } }; #else const Il2CppDouble_double ds2to64 = { { 0, 0, IL2CPP_DOUBLE_BIAS + 65, 0 } }; #endif // // Data tables // static const uint32_t power10[POWER10_MAX + 1] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; static const double double_power10[] = { 1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39, 1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47, 1e48, 1e49, 1e50, 1e51, 1e52, 1e53, 1e54, 1e55, 1e56, 1e57, 1e58, 1e59, 1e60, 1e61, 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69, 1e70, 1e71, 1e72, 1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79, 1e80 }; const SPLIT64 sdl_power10[] = { { 10000000000ULL }, // 1E10 { 100000000000ULL }, // 1E11 { 1000000000000ULL }, // 1E12 { 10000000000000ULL }, // 1E13 { 100000000000000ULL } }; // 1E14 static const uint64_t long_power10[] = { 1, 10ULL, 100ULL, 1000ULL, 10000ULL, 100000ULL, 1000000ULL, 10000000ULL, 100000000ULL, 1000000000ULL, 10000000000ULL, 100000000000ULL, 1000000000000ULL, 10000000000000ULL, 100000000000000ULL, 1000000000000000ULL, 10000000000000000ULL, 100000000000000000ULL, 1000000000000000000ULL, 10000000000000000000ULL }; typedef struct { uint32_t Hi, Mid, Lo; } DECOVFL; const DECOVFL power_overflow[] = { // This is a table of the largest values that can be in the upper two // ULONGs of a 96-bit number that will not overflow when multiplied // by a given power. For the upper word, this is a table of // 2^32 / 10^n for 1 <= n <= 9. For the lower word, this is the // remaining fraction part * 2^32. 2^32 = 4294967296. // { 429496729u, 2576980377u, 2576980377u }, // 10^1 remainder 0.6 { 42949672u, 4123168604u, 687194767u }, // 10^2 remainder 0.16 { 4294967u, 1271310319u, 2645699854u }, // 10^3 remainder 0.616 { 429496u, 3133608139u, 694066715u }, // 10^4 remainder 0.1616 { 42949u, 2890341191u, 2216890319u }, // 10^5 remainder 0.51616 { 4294u, 4154504685u, 2369172679u }, // 10^6 remainder 0.551616 { 429u, 2133437386u, 4102387834u }, // 10^7 remainder 0.9551616 { 42u, 4078814305u, 410238783u }, // 10^8 remainder 0.09991616 { 4u, 1266874889u, 3047500985u }, // 10^9 remainder 0.709551616 }; #define UInt32x32To64(a, b) ((uint64_t)((uint32_t)(a)) * (uint64_t)((uint32_t)(b))) #define Div64by32(num, den) ((uint32_t)((uint64_t)(num) / (uint32_t)(den))) #define Mod64by32(num, den) ((uint32_t)((uint64_t)(num) % (uint32_t)(den))) static double fnDblPower10(int ix) { const int maxIx = (sizeof(double_power10) / sizeof(double_power10[0])); IL2CPP_ASSERT(ix >= 0); if (ix < maxIx) return double_power10[ix]; return pow(10.0, ix); } // double fnDblPower10() static inline int64_t DivMod32by32(int32_t num, int32_t den) { SPLIT64 sdl; sdl.u.Lo = num / den; sdl.u.Hi = num % den; return sdl.int64; } static inline int64_t DivMod64by32(int64_t num, int32_t den) { SPLIT64 sdl; sdl.u.Lo = Div64by32(num, den); sdl.u.Hi = Mod64by32(num, den); return sdl.int64; } static uint64_t UInt64x64To128(SPLIT64 op1, SPLIT64 op2, uint64_t *hi) { SPLIT64 tmp1; SPLIT64 tmp2; SPLIT64 tmp3; tmp1.int64 = UInt32x32To64(op1.u.Lo, op2.u.Lo); // lo partial prod tmp2.int64 = UInt32x32To64(op1.u.Lo, op2.u.Hi); // mid 1 partial prod tmp1.u.Hi += tmp2.u.Lo; if (tmp1.u.Hi < tmp2.u.Lo) // test for carry tmp2.u.Hi++; tmp3.int64 = UInt32x32To64(op1.u.Hi, op2.u.Hi) + (uint64_t)tmp2.u.Hi; tmp2.int64 = UInt32x32To64(op1.u.Hi, op2.u.Lo); tmp1.u.Hi += tmp2.u.Lo; if (tmp1.u.Hi < tmp2.u.Lo) // test for carry tmp2.u.Hi++; tmp3.int64 += (uint64_t)tmp2.u.Hi; *hi = tmp3.int64; return tmp1.int64; } /** * FullDiv64By32: * * Entry: * pdlNum - Pointer to 64-bit dividend * ulDen - 32-bit divisor * * Purpose: * Do full divide, yielding 64-bit result and 32-bit remainder. * * Exit: * Quotient overwrites dividend. * Returns remainder. * * Exceptions: * None. */ // Was: FullDiv64By32 static uint32_t FullDiv64By32(uint64_t *num, uint32_t den) { SPLIT64 tmp; SPLIT64 res; tmp.int64 = *num; res.u.Hi = 0; if (tmp.u.Hi >= den) { // DivMod64by32 returns quotient in Lo, remainder in Hi. // res.u.Lo = tmp.u.Hi; res.int64 = DivMod64by32(res.int64, den); tmp.u.Hi = res.u.Hi; res.u.Hi = res.u.Lo; } tmp.int64 = DivMod64by32(tmp.int64, den); res.u.Lo = tmp.u.Lo; *num = res.int64; return tmp.u.Hi; } /*** * SearchScale * * Entry: * res_hi - Top uint32_t of quotient * res_mid - Middle uint32_t of quotient * res_lo - Bottom uint32_t of quotient * scale - Scale factor of quotient, range -DEC_SCALE_MAX to DEC_SCALE_MAX * * Purpose: * Determine the max power of 10, <= 9, that the quotient can be scaled * up by and still fit in 96 bits. * * Exit: * Returns power of 10 to scale by, -1 if overflow error. * ***********************************************************************/ static int SearchScale(uint32_t res_hi, uint32_t res_mid, uint32_t res_lo, int scale) { int cur_scale; // Quick check to stop us from trying to scale any more. // if (res_hi > OVFL_MAX_1_HI || scale >= DEC_SCALE_MAX) { cur_scale = 0; goto HaveScale; } if (scale > DEC_SCALE_MAX - 9) { // We can't scale by 10^9 without exceeding the max scale factor. // See if we can scale to the max. If not, we'll fall into // standard search for scale factor. // cur_scale = DEC_SCALE_MAX - scale; if (res_hi < power_overflow[cur_scale - 1].Hi) goto HaveScale; if (res_hi == power_overflow[cur_scale - 1].Hi) { UpperEq: if (res_mid > power_overflow[cur_scale - 1].Mid || (res_mid == power_overflow[cur_scale - 1].Mid && res_lo > power_overflow[cur_scale - 1].Lo)) { cur_scale--; } goto HaveScale; } } else if (res_hi < OVFL_MAX_9_HI || (res_hi == OVFL_MAX_9_HI && res_mid < OVFL_MAX_9_MID) || (res_hi == OVFL_MAX_9_HI && res_mid == OVFL_MAX_9_MID && res_lo <= OVFL_MAX_9_LO)) return 9; // Search for a power to scale by < 9. Do a binary search // on power_overflow[]. // cur_scale = 5; if (res_hi < OVFL_MAX_5_HI) cur_scale = 7; else if (res_hi > OVFL_MAX_5_HI) cur_scale = 3; else goto UpperEq; // cur_scale is 3 or 7. // if (res_hi < power_overflow[cur_scale - 1].Hi) cur_scale++; else if (res_hi > power_overflow[cur_scale - 1].Hi) cur_scale--; else goto UpperEq; // cur_scale is 2, 4, 6, or 8. // // In all cases, we already found we could not use the power one larger. // So if we can use this power, it is the biggest, and we're done. If // we can't use this power, the one below it is correct for all cases // unless it's 10^1 -- we might have to go to 10^0 (no scaling). // if (res_hi > power_overflow[cur_scale - 1].Hi) cur_scale--; if (res_hi == power_overflow[cur_scale - 1].Hi) goto UpperEq; HaveScale: // cur_scale = largest power of 10 we can scale by without overflow, // cur_scale < 9. See if this is enough to make scale factor // positive if it isn't already. // if (cur_scale + scale < 0) cur_scale = -1; return cur_scale; } /** * Div96By32 * * Entry: * rgulNum - Pointer to 96-bit dividend as array of uint32_ts, least-sig first * ulDen - 32-bit divisor. * * Purpose: * Do full divide, yielding 96-bit result and 32-bit remainder. * * Exit: * Quotient overwrites dividend. * Returns remainder. * * Exceptions: * None. * */ static uint32_t Div96By32(uint32_t *num, uint32_t den) { SPLIT64 tmp; tmp.u.Hi = 0; if (num[2] != 0) goto Div3Word; if (num[1] >= den) goto Div2Word; tmp.u.Hi = num[1]; num[1] = 0; goto Div1Word; Div3Word: tmp.u.Lo = num[2]; tmp.int64 = DivMod64by32(tmp.int64, den); num[2] = tmp.u.Lo; Div2Word: tmp.u.Lo = num[1]; tmp.int64 = DivMod64by32(tmp.int64, den); num[1] = tmp.u.Lo; Div1Word: tmp.u.Lo = num[0]; tmp.int64 = DivMod64by32(tmp.int64, den); num[0] = tmp.u.Lo; return tmp.u.Hi; } /*** * DecFixInt * * Entry: * pdecRes - Pointer to Decimal result location * operand - Pointer to Decimal operand * * Purpose: * Chop the value to integer. Return remainder so Int() function * can round down if non-zero. * * Exit: * Returns remainder. * * Exceptions: * None. * ***********************************************************************/ static uint32_t DecFixInt(Il2CppDecimal * result, Il2CppDecimal * operand) { uint32_t num[3]; uint32_t rem; uint32_t pwr; int scale; if (operand->u.u.scale > 0) { num[0] = operand->v.v.Lo32; num[1] = operand->v.v.Mid32; num[2] = operand->Hi32; scale = operand->u.u.scale; result->u.u.sign = operand->u.u.sign; rem = 0; do { if (scale > POWER10_MAX) pwr = ten_to_nine; else pwr = power10[scale]; rem |= Div96By32(num, pwr); scale -= 9; } while (scale > 0); result->v.v.Lo32 = num[0]; result->v.v.Mid32 = num[1]; result->Hi32 = num[2]; result->u.u.scale = 0; return rem; } COPYDEC(*result, *operand); // Odd, the Microsoft code does not set result->reserved to zero on this case return 0; } /** * ScaleResult: * * Entry: * res - Array of uint32_ts with value, least-significant first. * hi_res - Index of last non-zero value in res. * scale - Scale factor for this value, range 0 - 2 * DEC_SCALE_MAX * * Purpose: * See if we need to scale the result to fit it in 96 bits. * Perform needed scaling. Adjust scale factor accordingly. * * Exit: * res updated in place, always 3 uint32_ts. * New scale factor returned, -1 if overflow error. * */ static int ScaleResult(uint32_t *res, int hi_res, int scale) { int new_scale; int cur; uint32_t pwr; uint32_t tmp; uint32_t sticky; SPLIT64 sdlTmp; // See if we need to scale the result. The combined scale must // be <= DEC_SCALE_MAX and the upper 96 bits must be zero. // // Start by figuring a lower bound on the scaling needed to make // the upper 96 bits zero. hi_res is the index into res[] // of the highest non-zero uint32_t. // new_scale = hi_res * 32 - 64 - 1; if (new_scale > 0) { // Find the MSB. // tmp = res[hi_res]; if (!(tmp & 0xFFFF0000)) { new_scale -= 16; tmp <<= 16; } if (!(tmp & 0xFF000000)) { new_scale -= 8; tmp <<= 8; } if (!(tmp & 0xF0000000)) { new_scale -= 4; tmp <<= 4; } if (!(tmp & 0xC0000000)) { new_scale -= 2; tmp <<= 2; } if (!(tmp & 0x80000000)) { new_scale--; tmp <<= 1; } // Multiply bit position by log10(2) to figure it's power of 10. // We scale the log by 256. log(2) = .30103, * 256 = 77. Doing this // with a multiply saves a 96-byte lookup table. The power returned // is <= the power of the number, so we must add one power of 10 // to make it's integer part zero after dividing by 256. // // Note: the result of this multiplication by an approximation of // log10(2) have been exhaustively checked to verify it gives the // correct result. (There were only 95 to check...) // new_scale = ((new_scale * 77) >> 8) + 1; // new_scale = min scale factor to make high 96 bits zero, 0 - 29. // This reduces the scale factor of the result. If it exceeds the // current scale of the result, we'll overflow. // if (new_scale > scale) return -1; } else new_scale = 0; // Make sure we scale by enough to bring the current scale factor // into valid range. // if (new_scale < scale - DEC_SCALE_MAX) new_scale = scale - DEC_SCALE_MAX; if (new_scale != 0) { // Scale by the power of 10 given by new_scale. Note that this is // NOT guaranteed to bring the number within 96 bits -- it could // be 1 power of 10 short. // scale -= new_scale; sticky = 0; sdlTmp.u.Hi = 0; // initialize remainder for (;;) { sticky |= sdlTmp.u.Hi; // record remainder as sticky bit if (new_scale > POWER10_MAX) pwr = ten_to_nine; else pwr = power10[new_scale]; // Compute first quotient. // DivMod64by32 returns quotient in Lo, remainder in Hi. // sdlTmp.int64 = DivMod64by32(res[hi_res], pwr); res[hi_res] = sdlTmp.u.Lo; cur = hi_res - 1; if (cur >= 0) { // If first quotient was 0, update hi_res. // if (sdlTmp.u.Lo == 0) hi_res--; // Compute subsequent quotients. // do { sdlTmp.u.Lo = res[cur]; sdlTmp.int64 = DivMod64by32(sdlTmp.int64, pwr); res[cur] = sdlTmp.u.Lo; cur--; } while (cur >= 0); } new_scale -= POWER10_MAX; if (new_scale > 0) continue; // scale some more // If we scaled enough, hi_res would be 2 or less. If not, // divide by 10 more. // if (hi_res > 2) { new_scale = 1; scale--; continue; // scale by 10 } // Round final result. See if remainder >= 1/2 of divisor. // If remainder == 1/2 divisor, round up if odd or sticky bit set. // pwr >>= 1; // power of 10 always even if (pwr <= sdlTmp.u.Hi && (pwr < sdlTmp.u.Hi || ((res[0] & 1) | sticky))) { cur = -1; while (++res[++cur] == 0) ; if (cur > 2) { // The rounding caused us to carry beyond 96 bits. // Scale by 10 more. // hi_res = cur; sticky = 0; // no sticky bit sdlTmp.u.Hi = 0; // or remainder new_scale = 1; scale--; continue; // scale by 10 } } // We may have scaled it more than we planned. Make sure the scale // factor hasn't gone negative, indicating overflow. // if (scale < 0) return -1; return scale; } // for(;;) } return scale; } // Returns: IL2CPP_DECIMAL_OK, or IL2CPP_DECIMAL_INVALID_ARGUMENT static Il2CppDecimalStatus il2cpp_decimal_to_double_result(Il2CppDecimal *input, double *result) { SPLIT64 tmp; double dbl; if (DECIMAL_SCALE(*input) > DECMAX || (DECIMAL_SIGN(*input) & ~DECIMAL_NEG) != 0) return IL2CPP_DECIMAL_INVALID_ARGUMENT; tmp.u.Lo = DECIMAL_LO32(*input); tmp.u.Hi = DECIMAL_MID32(*input); if ((int32_t)DECIMAL_MID32(*input) < 0) dbl = (ds2to64.d + (double)(int64_t)tmp.int64 + (double)DECIMAL_HI32(*input) * ds2to64.d) / fnDblPower10(DECIMAL_SCALE(*input)); else dbl = ((double)(int64_t)tmp.int64 + (double)DECIMAL_HI32(*input) * ds2to64.d) / fnDblPower10(DECIMAL_SCALE(*input)); if (DECIMAL_SIGN(*input)) dbl = -dbl; *result = dbl; return IL2CPP_DECIMAL_OK; } // Returns: IL2CPP_DECIMAL_OK, or IL2CPP_DECIMAL_INVALID_ARGUMENT static Il2CppDecimalStatus il2cpp_decimal_to_float_result(Il2CppDecimal *input, float *result) { double dbl; if (DECIMAL_SCALE(*input) > DECMAX || (DECIMAL_SIGN(*input) & ~DECIMAL_NEG) != 0) return IL2CPP_DECIMAL_INVALID_ARGUMENT; // Can't overflow; no errors possible. // il2cpp_decimal_to_double_result(input, &dbl); *result = (float)dbl; return IL2CPP_DECIMAL_OK; } static Il2CppDecimalStatus DecAddSub(Il2CppDecimal *left, Il2CppDecimal *right, Il2CppDecimal *result, int8_t sign) { uint32_t num[6]; uint32_t pwr; int scale; int hi_prod; int cur; SPLIT64 tmp; Il2CppDecimal decRes; Il2CppDecimal decTmp; Il2CppDecimal *pdecTmp; sign ^= (right->u.u.sign ^ left->u.u.sign) & DECIMAL_NEG; if (right->u.u.scale == left->u.u.scale) { // Scale factors are equal, no alignment necessary. // decRes.u.signscale = left->u.signscale; AlignedAdd: if (sign) { // Signs differ - subtract // DECIMAL_LO64_SET(decRes, DECIMAL_LO64_GET(*left) - DECIMAL_LO64_GET(*right)); DECIMAL_HI32(decRes) = DECIMAL_HI32(*left) - DECIMAL_HI32(*right); // Propagate carry // if (DECIMAL_LO64_GET(decRes) > DECIMAL_LO64_GET(*left)) { decRes.Hi32--; if (decRes.Hi32 >= left->Hi32) goto SignFlip; } else if (decRes.Hi32 > left->Hi32) { // Got negative result. Flip its sign. // SignFlip: DECIMAL_LO64_SET(decRes, (uint64_t)DECIMAL_LO64_GET(decRes)); decRes.Hi32 = ~decRes.Hi32; if (DECIMAL_LO64_GET(decRes) == 0) decRes.Hi32++; decRes.u.u.sign ^= DECIMAL_NEG; } } else { // Signs are the same - add // DECIMAL_LO64_SET(decRes, DECIMAL_LO64_GET(*left) + DECIMAL_LO64_GET(*right)); decRes.Hi32 = left->Hi32 + right->Hi32; // Propagate carry // if (DECIMAL_LO64_GET(decRes) < DECIMAL_LO64_GET(*left)) { decRes.Hi32++; if (decRes.Hi32 <= left->Hi32) goto AlignedScale; } else if (decRes.Hi32 < left->Hi32) { AlignedScale: // The addition carried above 96 bits. Divide the result by 10, // dropping the scale factor. // if (decRes.u.u.scale == 0) return IL2CPP_DECIMAL_OVERFLOW; decRes.u.u.scale--; tmp.u.Lo = decRes.Hi32; tmp.u.Hi = 1; tmp.int64 = DivMod64by32(tmp.int64, 10); decRes.Hi32 = tmp.u.Lo; tmp.u.Lo = decRes.v.v.Mid32; tmp.int64 = DivMod64by32(tmp.int64, 10); decRes.v.v.Mid32 = tmp.u.Lo; tmp.u.Lo = decRes.v.v.Lo32; tmp.int64 = DivMod64by32(tmp.int64, 10); decRes.v.v.Lo32 = tmp.u.Lo; // See if we need to round up. // if (tmp.u.Hi >= 5 && (tmp.u.Hi > 5 || (decRes.v.v.Lo32 & 1))) { DECIMAL_LO64_SET(decRes, DECIMAL_LO64_GET(decRes) + 1) if (DECIMAL_LO64_GET(decRes) == 0) decRes.Hi32++; } } } } else { // Scale factors are not equal. Assume that a larger scale // factor (more decimal places) is likely to mean that number // is smaller. Start by guessing that the right operand has // the larger scale factor. The result will have the larger // scale factor. // decRes.u.u.scale = right->u.u.scale; // scale factor of "smaller" decRes.u.u.sign = left->u.u.sign; // but sign of "larger" scale = decRes.u.u.scale - left->u.u.scale; if (scale < 0) { // Guessed scale factor wrong. Swap operands. // scale = -scale; decRes.u.u.scale = left->u.u.scale; decRes.u.u.sign ^= sign; pdecTmp = right; right = left; left = pdecTmp; } // *left will need to be multiplied by 10^scale so // it will have the same scale as *right. We could be // extending it to up to 192 bits of precision. // if (scale <= POWER10_MAX) { // Scaling won't make it larger than 4 uint32_ts // pwr = power10[scale]; DECIMAL_LO64_SET(decTmp, UInt32x32To64(left->v.v.Lo32, pwr)); tmp.int64 = UInt32x32To64(left->v.v.Mid32, pwr); tmp.int64 += decTmp.v.v.Mid32; decTmp.v.v.Mid32 = tmp.u.Lo; decTmp.Hi32 = tmp.u.Hi; tmp.int64 = UInt32x32To64(left->Hi32, pwr); tmp.int64 += decTmp.Hi32; if (tmp.u.Hi == 0) { // Result fits in 96 bits. Use standard aligned add. // decTmp.Hi32 = tmp.u.Lo; left = &decTmp; goto AlignedAdd; } num[0] = decTmp.v.v.Lo32; num[1] = decTmp.v.v.Mid32; num[2] = tmp.u.Lo; num[3] = tmp.u.Hi; hi_prod = 3; } else { // Have to scale by a bunch. Move the number to a buffer // where it has room to grow as it's scaled. // num[0] = left->v.v.Lo32; num[1] = left->v.v.Mid32; num[2] = left->Hi32; hi_prod = 2; // Scan for zeros in the upper words. // if (num[2] == 0) { hi_prod = 1; if (num[1] == 0) { hi_prod = 0; if (num[0] == 0) { // Left arg is zero, return right. // DECIMAL_LO64_SET(decRes, DECIMAL_LO64_GET(*right)); decRes.Hi32 = right->Hi32; decRes.u.u.sign ^= sign; goto RetDec; } } } // Scaling loop, up to 10^9 at a time. hi_prod stays updated // with index of highest non-zero uint32_t. // for (; scale > 0; scale -= POWER10_MAX) { if (scale > POWER10_MAX) pwr = ten_to_nine; else pwr = power10[scale]; tmp.u.Hi = 0; for (cur = 0; cur <= hi_prod; cur++) { tmp.int64 = UInt32x32To64(num[cur], pwr) + tmp.u.Hi; num[cur] = tmp.u.Lo; } if (tmp.u.Hi != 0) // We're extending the result by another uint32_t. num[++hi_prod] = tmp.u.Hi; } } // Scaling complete, do the add. Could be subtract if signs differ. // tmp.u.Lo = num[0]; tmp.u.Hi = num[1]; if (sign) { // Signs differ, subtract. // DECIMAL_LO64_SET(decRes, tmp.int64 - DECIMAL_LO64_GET(*right)); decRes.Hi32 = num[2] - right->Hi32; // Propagate carry // if (DECIMAL_LO64_GET(decRes) > tmp.int64) { decRes.Hi32--; if (decRes.Hi32 >= num[2]) goto LongSub; } else if (decRes.Hi32 > num[2]) { LongSub: // If num has more than 96 bits of precision, then we need to // carry the subtraction into the higher bits. If it doesn't, // then we subtracted in the wrong order and have to flip the // sign of the result. // if (hi_prod <= 2) goto SignFlip; cur = 3; while (num[cur++]-- == 0) ; if (num[hi_prod] == 0) hi_prod--; } } else { // Signs the same, add. // DECIMAL_LO64_SET(decRes, tmp.int64 + DECIMAL_LO64_GET(*right)); decRes.Hi32 = num[2] + right->Hi32; // Propagate carry // if (DECIMAL_LO64_GET(decRes) < tmp.int64) { decRes.Hi32++; if (decRes.Hi32 <= num[2]) goto LongAdd; } else if (decRes.Hi32 < num[2]) { LongAdd: // Had a carry above 96 bits. // cur = 3; do { if (hi_prod < cur) { num[cur] = 1; hi_prod = cur; break; } } while (++num[cur++] == 0); } } if (hi_prod > 2) { num[0] = decRes.v.v.Lo32; num[1] = decRes.v.v.Mid32; num[2] = decRes.Hi32; decRes.u.u.scale = ScaleResult(num, hi_prod, decRes.u.u.scale); if (decRes.u.u.scale == (uint8_t)-1) return IL2CPP_DECIMAL_OVERFLOW; decRes.v.v.Lo32 = num[0]; decRes.v.v.Mid32 = num[1]; decRes.Hi32 = num[2]; } } RetDec: COPYDEC(*result, decRes); // Odd, the Microsoft code does not set result->reserved to zero on this case return IL2CPP_DECIMAL_OK; } // Returns IL2CPP_DECIMAL_OK or IL2CPP_DECIMAL_OVERFLOW static Il2CppDecimalStatus il2cpp_decimal_from_double(double input_d, Il2CppDecimal *result) { int exp; // number of bits to left of binary point int power; // power-of-10 scale factor SPLIT64 sdlMant; SPLIT64 sdlLo; double dbl; int lmax, cur; // temps used during scale reduction uint32_t pwr_cur; uint32_t quo; Il2CppDouble_double input; input.d = input_d; // The most we can scale by is 10^28, which is just slightly more // than 2^93. So a float with an exponent of -94 could just // barely reach 0.5, but smaller exponents will always round to zero. // if ((exp = input.s.exp - IL2CPP_DOUBLE_BIAS) < -94) { DECIMAL_SETZERO(*result); return IL2CPP_DECIMAL_OK; } if (exp > 96) return IL2CPP_DECIMAL_OVERFLOW; // Round the input to a 15-digit integer. The R8 format has // only 15 digits of precision, and we want to keep garbage digits // out of the Decimal were making. // // Calculate max power of 10 input value could have by multiplying // the exponent by log10(2). Using scaled integer multiplcation, // log10(2) * 2 ^ 16 = .30103 * 65536 = 19728.3. // dbl = fabs(input.d); power = 14 - ((exp * 19728) >> 16); if (power >= 0) { // We have less than 15 digits, scale input up. // if (power > DECMAX) power = DECMAX; dbl = dbl * double_power10[power]; } else { if (power != -1 || dbl >= 1E15) dbl = dbl / fnDblPower10(-power); else power = 0; // didn't scale it } IL2CPP_ASSERT(dbl < 1E15); if (dbl < 1E14 && power < DECMAX) { dbl *= 10; power++; IL2CPP_ASSERT(dbl >= 1E14); } // Round to int64 // sdlMant.int64 = (int64_t)dbl; dbl -= (double)(int64_t)sdlMant.int64; // dif between input & integer if (dbl > 0.5 || (dbl == 0.5 && (sdlMant.u.Lo & 1))) sdlMant.int64++; if (sdlMant.int64 == 0) { DECIMAL_SETZERO(*result); return IL2CPP_DECIMAL_OK; } if (power < 0) { // Add -power factors of 10, -power <= (29 - 15) = 14. // power = -power; if (power < 10) { sdlLo.int64 = UInt32x32To64(sdlMant.u.Lo, (uint32_t)long_power10[power]); sdlMant.int64 = UInt32x32To64(sdlMant.u.Hi, (uint32_t)long_power10[power]); sdlMant.int64 += sdlLo.u.Hi; sdlLo.u.Hi = sdlMant.u.Lo; sdlMant.u.Lo = sdlMant.u.Hi; } else { // Have a big power of 10. // IL2CPP_ASSERT(power <= 14); sdlLo.int64 = UInt64x64To128(sdlMant, sdl_power10[power - 10], &sdlMant.int64); if (sdlMant.u.Hi != 0) return IL2CPP_DECIMAL_OVERFLOW; } DECIMAL_LO32(*result) = sdlLo.u.Lo; DECIMAL_MID32(*result) = sdlLo.u.Hi; DECIMAL_HI32(*result) = sdlMant.u.Lo; DECIMAL_SCALE(*result) = 0; } else { // Factor out powers of 10 to reduce the scale, if possible. // The maximum number we could factor out would be 14. This // comes from the fact we have a 15-digit number, and the // MSD must be non-zero -- but the lower 14 digits could be // zero. Note also the scale factor is never negative, so // we can't scale by any more than the power we used to // get the integer. // // DivMod64by32 returns the quotient in Lo, the remainder in Hi. // lmax = std::min(power, 14); // lmax is the largest power of 10 to try, lmax <= 14. // We'll try powers 8, 4, 2, and 1 unless they're too big. // for (cur = 8; cur > 0; cur >>= 1) { if (cur > lmax) continue; pwr_cur = (uint32_t)long_power10[cur]; if (sdlMant.u.Hi >= pwr_cur) { // Overflow if we try to divide in one step. // sdlLo.int64 = DivMod64by32(sdlMant.u.Hi, pwr_cur); quo = sdlLo.u.Lo; sdlLo.u.Lo = sdlMant.u.Lo; sdlLo.int64 = DivMod64by32(sdlLo.int64, pwr_cur); } else { quo = 0; sdlLo.int64 = DivMod64by32(sdlMant.int64, pwr_cur); } if (sdlLo.u.Hi == 0) { sdlMant.u.Hi = quo; sdlMant.u.Lo = sdlLo.u.Lo; power -= cur; lmax -= cur; } } DECIMAL_HI32(*result) = 0; DECIMAL_SCALE(*result) = power; DECIMAL_LO32(*result) = sdlMant.u.Lo; DECIMAL_MID32(*result) = sdlMant.u.Hi; } DECIMAL_SIGN(*result) = (char)input.s.sign << 7; return IL2CPP_DECIMAL_OK; } // Decimal multiply // Returns: IL2CPP_DECIMAL_OVERFLOW or IL2CPP_DECIMAL_OK static Il2CppDecimalStatus il2cpp_decimal_multiply_result(Il2CppDecimal *left, Il2CppDecimal *right, Il2CppDecimal *result) { SPLIT64 tmp; SPLIT64 tmp2; SPLIT64 tmp3; int scale; int hi_prod; uint32_t pwr; uint32_t rem_lo; uint32_t rem_hi; uint32_t prod[6]; scale = left->u.u.scale + right->u.u.scale; if ((left->Hi32 | left->v.v.Mid32 | right->Hi32 | right->v.v.Mid32) == 0) { // Upper 64 bits are zero. // tmp.int64 = UInt32x32To64(left->v.v.Lo32, right->v.v.Lo32); if (scale > DEC_SCALE_MAX) { // Result scale is too big. Divide result by power of 10 to reduce it. // If the amount to divide by is > 19 the result is guaranteed // less than 1/2. [max value in 64 bits = 1.84E19] // scale -= DEC_SCALE_MAX; if (scale > 19) { ReturnZero: DECIMAL_SETZERO(*result); return IL2CPP_DECIMAL_OK; } if (scale > POWER10_MAX) { // Divide by 1E10 first, to get the power down to a 32-bit quantity. // 1E10 itself doesn't fit in 32 bits, so we'll divide by 2.5E9 now // then multiply the next divisor by 4 (which will be a max of 4E9). // rem_lo = FullDiv64By32(&tmp.int64, ten_to_ten_div_4); pwr = power10[scale - 10] << 2; } else { pwr = power10[scale]; rem_lo = 0; } // Power to divide by fits in 32 bits. // rem_hi = FullDiv64By32(&tmp.int64, pwr); // Round result. See if remainder >= 1/2 of divisor. // Divisor is a power of 10, so it is always even. // pwr >>= 1; if (rem_hi >= pwr && (rem_hi > pwr || (rem_lo | (tmp.u.Lo & 1)))) tmp.int64++; scale = DEC_SCALE_MAX; } DECIMAL_LO32(*result) = tmp.u.Lo; DECIMAL_MID32(*result) = tmp.u.Hi; DECIMAL_HI32(*result) = 0; } else { // At least one operand has bits set in the upper 64 bits. // // Compute and accumulate the 9 partial products into a // 192-bit (24-byte) result. // // [l-h][l-m][l-l] left high, middle, low // x [r-h][r-m][r-l] right high, middle, low // ------------------------------ // // [0-h][0-l] l-l * r-l // [1ah][1al] l-l * r-m // [1bh][1bl] l-m * r-l // [2ah][2al] l-m * r-m // [2bh][2bl] l-l * r-h // [2ch][2cl] l-h * r-l // [3ah][3al] l-m * r-h // [3bh][3bl] l-h * r-m // [4-h][4-l] l-h * r-h // ------------------------------ // [p-5][p-4][p-3][p-2][p-1][p-0] prod[] array // tmp.int64 = UInt32x32To64(left->v.v.Lo32, right->v.v.Lo32); prod[0] = tmp.u.Lo; tmp2.int64 = UInt32x32To64(left->v.v.Lo32, right->v.v.Mid32) + tmp.u.Hi; tmp.int64 = UInt32x32To64(left->v.v.Mid32, right->v.v.Lo32); tmp.int64 += tmp2.int64; // this could generate carry prod[1] = tmp.u.Lo; if (tmp.int64 < tmp2.int64) // detect carry tmp2.u.Hi = 1; else tmp2.u.Hi = 0; tmp2.u.Lo = tmp.u.Hi; tmp.int64 = UInt32x32To64(left->v.v.Mid32, right->v.v.Mid32) + tmp2.int64; if (left->Hi32 | right->Hi32) { // Highest 32 bits is non-zero. Calculate 5 more partial products. // tmp2.int64 = UInt32x32To64(left->v.v.Lo32, right->Hi32); tmp.int64 += tmp2.int64; // this could generate carry if (tmp.int64 < tmp2.int64) // detect carry tmp3.u.Hi = 1; else tmp3.u.Hi = 0; tmp2.int64 = UInt32x32To64(left->Hi32, right->v.v.Lo32); tmp.int64 += tmp2.int64; // this could generate carry prod[2] = tmp.u.Lo; if (tmp.int64 < tmp2.int64) // detect carry tmp3.u.Hi++; tmp3.u.Lo = tmp.u.Hi; tmp.int64 = UInt32x32To64(left->v.v.Mid32, right->Hi32); tmp.int64 += tmp3.int64; // this could generate carry if (tmp.int64 < tmp3.int64) // detect carry tmp3.u.Hi = 1; else tmp3.u.Hi = 0; tmp2.int64 = UInt32x32To64(left->Hi32, right->v.v.Mid32); tmp.int64 += tmp2.int64; // this could generate carry prod[3] = tmp.u.Lo; if (tmp.int64 < tmp2.int64) // detect carry tmp3.u.Hi++; tmp3.u.Lo = tmp.u.Hi; tmp.int64 = UInt32x32To64(left->Hi32, right->Hi32) + tmp3.int64; prod[4] = tmp.u.Lo; prod[5] = tmp.u.Hi; hi_prod = 5; } else { prod[2] = tmp.u.Lo; prod[3] = tmp.u.Hi; hi_prod = 3; } // Check for leading zero uint32_ts on the product // while (prod[hi_prod] == 0) { hi_prod--; if (hi_prod < 0) goto ReturnZero; } scale = ScaleResult(prod, hi_prod, scale); if (scale == -1) return IL2CPP_DECIMAL_OVERFLOW; result->v.v.Lo32 = prod[0]; result->v.v.Mid32 = prod[1]; result->Hi32 = prod[2]; } result->u.u.sign = right->u.u.sign ^ left->u.u.sign; result->u.u.scale = (char)scale; return IL2CPP_DECIMAL_OK; } // Add a 32 bit unsigned long to an array of 3 unsigned longs representing a 96 integer // Returns FALSE if there is an overflow static bool Add32To96(uint32_t *num, uint32_t value) { num[0] += value; if (num[0] < value) { if (++num[1] == 0) { if (++num[2] == 0) { return false; } } } return true; } static void OverflowUnscale(uint32_t *quo, bool remainder) { SPLIT64 sdlTmp; // We have overflown, so load the high bit with a one. sdlTmp.u.Hi = 1u; sdlTmp.u.Lo = quo[2]; sdlTmp.int64 = DivMod64by32(sdlTmp.int64, 10u); quo[2] = sdlTmp.u.Lo; sdlTmp.u.Lo = quo[1]; sdlTmp.int64 = DivMod64by32(sdlTmp.int64, 10u); quo[1] = sdlTmp.u.Lo; sdlTmp.u.Lo = quo[0]; sdlTmp.int64 = DivMod64by32(sdlTmp.int64, 10u); quo[0] = sdlTmp.u.Lo; // The remainder is the last digit that does not fit, so we can use it to work out if we need to round up if ((sdlTmp.u.Hi > 5) || ((sdlTmp.u.Hi == 5) && (remainder || (quo[0] & 1)))) { Add32To96(quo, 1u); } } /** * IncreaseScale: * * Entry: * num - Pointer to 96-bit number as array of uint32_ts, least-sig first * pwr - Scale factor to multiply by * * Purpose: * Multiply the two numbers. The low 96 bits of the result overwrite * the input. The last 32 bits of the product are the return value. * * Exit: * Returns highest 32 bits of product. * * Exceptions: * None. * */ static uint32_t IncreaseScale(uint32_t *num, uint32_t pwr) { SPLIT64 sdlTmp; sdlTmp.int64 = UInt32x32To64(num[0], pwr); num[0] = sdlTmp.u.Lo; sdlTmp.int64 = UInt32x32To64(num[1], pwr) + sdlTmp.u.Hi; num[1] = sdlTmp.u.Lo; sdlTmp.int64 = UInt32x32To64(num[2], pwr) + sdlTmp.u.Hi; num[2] = sdlTmp.u.Lo; return sdlTmp.u.Hi; } /*** * Div128By96 * * Entry: * rgulNum - Pointer to 128-bit dividend as array of uint32_ts, least-sig first * den - Pointer to 96-bit divisor. * * Purpose: * Do partial divide, yielding 32-bit result and 96-bit remainder. * Top divisor uint32_t must be larger than top dividend uint32_t. This is * assured in the initial call because the divisor is normalized * and the dividend can't be. In subsequent calls, the remainder * is multiplied by 10^9 (max), so it can be no more than 1/4 of * the divisor which is effectively multiplied by 2^32 (4 * 10^9). * * Exit: * Remainder overwrites lower 96-bits of dividend. * Returns quotient. * * Exceptions: * None. * ***********************************************************************/ static uint32_t Div128By96(uint32_t *num, uint32_t *den) { SPLIT64 sdlQuo; SPLIT64 sdlNum; SPLIT64 sdlProd1; SPLIT64 sdlProd2; sdlNum.u.Lo = num[0]; sdlNum.u.Hi = num[1]; if (num[3] == 0 && num[2] < den[2]) { // Result is zero. Entire dividend is remainder. // return 0; } // DivMod64by32 returns quotient in Lo, remainder in Hi. // sdlQuo.u.Lo = num[2]; sdlQuo.u.Hi = num[3]; sdlQuo.int64 = DivMod64by32(sdlQuo.int64, den[2]); // Compute full remainder, rem = dividend - (quo * divisor). // sdlProd1.int64 = UInt32x32To64(sdlQuo.u.Lo, den[0]); // quo * lo divisor sdlProd2.int64 = UInt32x32To64(sdlQuo.u.Lo, den[1]); // quo * mid divisor sdlProd2.int64 += sdlProd1.u.Hi; sdlProd1.u.Hi = sdlProd2.u.Lo; sdlNum.int64 -= sdlProd1.int64; num[2] = sdlQuo.u.Hi - sdlProd2.u.Hi; // sdlQuo.Hi is remainder // Propagate carries // if (sdlNum.int64 > ~sdlProd1.int64) { num[2]--; if (num[2] >= ~sdlProd2.u.Hi) goto NegRem; } else if (num[2] > ~sdlProd2.u.Hi) { NegRem: // Remainder went negative. Add divisor back in until it's positive, // a max of 2 times. // sdlProd1.u.Lo = den[0]; sdlProd1.u.Hi = den[1]; for (;;) { sdlQuo.u.Lo--; sdlNum.int64 += sdlProd1.int64; num[2] += den[2]; if (sdlNum.int64 < sdlProd1.int64) { // Detected carry. Check for carry out of top // before adding it in. // if (num[2]++ < den[2]) break; } if (num[2] < den[2]) break; // detected carry } } num[0] = sdlNum.u.Lo; num[1] = sdlNum.u.Hi; return sdlQuo.u.Lo; } /** * Div96By64: * * Entry: * rgulNum - Pointer to 96-bit dividend as array of uint32_ts, least-sig first * sdlDen - 64-bit divisor. * * Purpose: * Do partial divide, yielding 32-bit result and 64-bit remainder. * Divisor must be larger than upper 64 bits of dividend. * * Exit: * Remainder overwrites lower 64-bits of dividend. * Returns quotient. * * Exceptions: * None. * */ static uint32_t Div96By64(uint32_t *num, SPLIT64 den) { SPLIT64 quo; SPLIT64 sdlNum; SPLIT64 prod; sdlNum.u.Lo = num[0]; if (num[2] >= den.u.Hi) { // Divide would overflow. Assume a quotient of 2^32, and set // up remainder accordingly. Then jump to loop which reduces // the quotient. // sdlNum.u.Hi = num[1] - den.u.Lo; quo.u.Lo = 0; goto NegRem; } // Hardware divide won't overflow // if (num[2] == 0 && num[1] < den.u.Hi) // Result is zero. Entire dividend is remainder. // return 0; // DivMod64by32 returns quotient in Lo, remainder in Hi. // quo.u.Lo = num[1]; quo.u.Hi = num[2]; quo.int64 = DivMod64by32(quo.int64, den.u.Hi); sdlNum.u.Hi = quo.u.Hi; // remainder // Compute full remainder, rem = dividend - (quo * divisor). // prod.int64 = UInt32x32To64(quo.u.Lo, den.u.Lo); // quo * lo divisor sdlNum.int64 -= prod.int64; if (sdlNum.int64 > ~prod.int64) { NegRem: // Remainder went negative. Add divisor back in until it's positive, // a max of 2 times. // do { quo.u.Lo--; sdlNum.int64 += den.int64; } while (sdlNum.int64 >= den.int64); } num[0] = sdlNum.u.Lo; num[1] = sdlNum.u.Hi; return quo.u.Lo; } // // Returns: IL2CPP_DECIMAL_INVALID_ARGUMENT, IL2CPP_DECIMAL_OK // static Il2CppDecimalStatus il2cpp_decimal_round_result(Il2CppDecimal *input, int cDecimals, Il2CppDecimal *result) { uint32_t num[3]; uint32_t rem; uint32_t sticky; uint32_t pwr; int scale; if (cDecimals < 0) return IL2CPP_DECIMAL_INVALID_ARGUMENT; scale = input->u.u.scale - cDecimals; if (scale > 0) { num[0] = input->v.v.Lo32; num[1] = input->v.v.Mid32; num[2] = input->Hi32; result->u.u.sign = input->u.u.sign; rem = sticky = 0; do { sticky |= rem; if (scale > POWER10_MAX) pwr = ten_to_nine; else pwr = power10[scale]; rem = Div96By32(num, pwr); scale -= 9; } while (scale > 0); // Now round. rem has last remainder, sticky has sticky bits. // To do IEEE rounding, we add LSB of result to sticky bits so // either causes round up if remainder * 2 == last divisor. // sticky |= num[0] & 1; rem = (rem << 1) + (sticky != 0); if (pwr < rem && ++num[0] == 0 && ++num[1] == 0 ) ++num[2]; result->v.v.Lo32 = num[0]; result->v.v.Mid32 = num[1]; result->Hi32 = num[2]; result->u.u.scale = cDecimals; return IL2CPP_DECIMAL_OK; } COPYDEC(*result, *input); // Odd, the Microsoft source does not set the result->reserved to zero here. return IL2CPP_DECIMAL_OK; } // // Returns IL2CPP_DECIMAL_OK or IL2CPP_DECIMAL_OVERFLOW static Il2CppDecimalStatus il2cpp_decimal_from_float(float input_f, Il2CppDecimal* result) { int exp; // number of bits to left of binary point int power; uint32_t mant; double dbl; SPLIT64 sdlLo; SPLIT64 sdlHi; int lmax, cur; // temps used during scale reduction Il2CppSingle_float input; input.f = input_f; // The most we can scale by is 10^28, which is just slightly more // than 2^93. So a float with an exponent of -94 could just // barely reach 0.5, but smaller exponents will always round to zero. // if ((exp = input.s.exp - IL2CPP_SINGLE_BIAS) < -94) { DECIMAL_SETZERO(*result); return IL2CPP_DECIMAL_OK; } if (exp > 96) return IL2CPP_DECIMAL_OVERFLOW; // Round the input to a 7-digit integer. The R4 format has // only 7 digits of precision, and we want to keep garbage digits // out of the Decimal were making. // // Calculate max power of 10 input value could have by multiplying // the exponent by log10(2). Using scaled integer multiplcation, // log10(2) * 2 ^ 16 = .30103 * 65536 = 19728.3. // dbl = fabs(input.f); power = 6 - ((exp * 19728) >> 16); if (power >= 0) { // We have less than 7 digits, scale input up. // if (power > DECMAX) power = DECMAX; dbl = dbl * double_power10[power]; } else { if (power != -1 || dbl >= 1E7) dbl = dbl / fnDblPower10(-power); else power = 0; // didn't scale it } IL2CPP_ASSERT(dbl < 1E7); if (dbl < 1E6 && power < DECMAX) { dbl *= 10; power++; IL2CPP_ASSERT(dbl >= 1E6); } // Round to integer // mant = (int32_t)dbl; dbl -= (double)mant; // difference between input & integer if (dbl > 0.5 || (dbl == 0.5 && (mant & 1))) mant++; if (mant == 0) { DECIMAL_SETZERO(*result); return IL2CPP_DECIMAL_OK; } if (power < 0) { // Add -power factors of 10, -power <= (29 - 7) = 22. // power = -power; if (power < 10) { sdlLo.int64 = UInt32x32To64(mant, (uint32_t)long_power10[power]); DECIMAL_LO32(*result) = sdlLo.u.Lo; DECIMAL_MID32(*result) = sdlLo.u.Hi; DECIMAL_HI32(*result) = 0; } else { // Have a big power of 10. // if (power > 18) { sdlLo.int64 = UInt32x32To64(mant, (uint32_t)long_power10[power - 18]); sdlLo.int64 = UInt64x64To128(sdlLo, ten_to_eighteen, &sdlHi.int64); if (sdlHi.u.Hi != 0) return IL2CPP_DECIMAL_OVERFLOW; } else { sdlLo.int64 = UInt32x32To64(mant, (uint32_t)long_power10[power - 9]); sdlHi.int64 = UInt32x32To64(ten_to_nine, sdlLo.u.Hi); sdlLo.int64 = UInt32x32To64(ten_to_nine, sdlLo.u.Lo); sdlHi.int64 += sdlLo.u.Hi; sdlLo.u.Hi = sdlHi.u.Lo; sdlHi.u.Lo = sdlHi.u.Hi; } DECIMAL_LO32(*result) = sdlLo.u.Lo; DECIMAL_MID32(*result) = sdlLo.u.Hi; DECIMAL_HI32(*result) = sdlHi.u.Lo; } DECIMAL_SCALE(*result) = 0; } else { // Factor out powers of 10 to reduce the scale, if possible. // The maximum number we could factor out would be 6. This // comes from the fact we have a 7-digit number, and the // MSD must be non-zero -- but the lower 6 digits could be // zero. Note also the scale factor is never negative, so // we can't scale by any more than the power we used to // get the integer. // // DivMod32by32 returns the quotient in Lo, the remainder in Hi. // lmax = std::min(power, 6); // lmax is the largest power of 10 to try, lmax <= 6. // We'll try powers 4, 2, and 1 unless they're too big. // for (cur = 4; cur > 0; cur >>= 1) { if (cur > lmax) continue; sdlLo.int64 = DivMod32by32(mant, (uint32_t)long_power10[cur]); if (sdlLo.u.Hi == 0) { mant = sdlLo.u.Lo; power -= cur; lmax -= cur; } } DECIMAL_LO32(*result) = mant; DECIMAL_MID32(*result) = 0; DECIMAL_HI32(*result) = 0; DECIMAL_SCALE(*result) = power; } DECIMAL_SIGN(*result) = (char)input.s.sign << 7; return IL2CPP_DECIMAL_OK; } // il2cpp_decimal_round_to_int - Decimal Int (round down to integer) static void il2cpp_decimal_round_to_int(Il2CppDecimal *pdecOprd, Il2CppDecimal *result) { if (DecFixInt(result, pdecOprd) != 0 && (result->u.u.sign & DECIMAL_NEG)) { // We have chopped off a non-zero amount from a negative value. Since // we round toward -infinity, we must increase the integer result by // 1 to make it more negative. This will never overflow because // in order to have a remainder, we must have had a non-zero scale factor. // Our scale factor is back to zero now. // DECIMAL_LO64_SET(*result, DECIMAL_LO64_GET(*result) + 1); if (DECIMAL_LO64_GET(*result) == 0) result->Hi32++; } } static void il2cpp_decimal_fix(Il2CppDecimal *pdecOprd, Il2CppDecimal *result) { DecFixInt(result, pdecOprd); } #endif // !NET_4_0 namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { #if !NET_4_0 int Decimal::decimalSetExponent(il2cpp_decimal_repr* pA, int texp) { int scale = pA->u.signscale.scale; scale -= texp; if (scale < 0 || scale > DECIMAL_MAX_SCALE) { uint64_t alo; uint64_t ahi; DECTO128(pA, alo, ahi); int status = rescale128(&alo, &ahi, &scale, 0, 0, DECIMAL_MAX_SCALE, 1); if (status != DECIMAL_SUCCESS) return status; return pack128toDecimal(pA, alo, ahi, scale, pA->u.signscale.sign); } else { pA->u.signscale.scale = scale; return DECIMAL_SUCCESS; } } int Decimal::string2decimal(il2cpp_decimal_repr *pA, Il2CppString *str, unsigned int decrDecimal, int sign) { Il2CppChar* buf = utils::StringUtils::GetChars(str); Il2CppChar* p; uint64_t alo, ahi; alo = ahi = 0; int n, rc, i, len, sigLen = -1, firstNonZero; int scale, roundBit = 0; DECINIT(pA); for (p = buf, len = 0; *p != 0; len++, p++) { } for (p = buf, i = 0; *p != 0; i++, p++) { n = *p - '0'; if (n < 0 || n > 9) return DECIMAL_INVALID_CHARACTER; if (n) { if (sigLen < 0) { firstNonZero = i; sigLen = (len - firstNonZero > DECIMAL_MAX_SCALE + 1) ? DECIMAL_MAX_SCALE + 1 + firstNonZero : len; if (decrDecimal > static_cast(sigLen + 1)) return DECIMAL_OVERFLOW; } if (i >= sigLen) break; rc = incMultConstant128(&alo, &ahi, sigLen - 1 - i, n); if (rc != DECIMAL_SUCCESS) return rc; } } scale = sigLen - decrDecimal; if (i < len) /* too much digits, we must round */ { n = buf[i] - '0'; if (n < 0 || n > 9) { return DECIMAL_INVALID_CHARACTER; } if (n > 5) roundBit = 1; else if (n == 5) /* we must take a nearer look */ { n = buf[i - 1] - '0'; for (++i; i < len; ++i) { if (buf[i] != '0') break; /* we are greater than .5 */ } if (i < len /* greater than exactly .5 */ || n % 2 == 1) /* exactly .5, use banker's rule for rounding */ { roundBit = 1; } } } if (ahi != 0) { rc = normalize128(&alo, &ahi, &scale, 1, roundBit); if (rc != DECIMAL_SUCCESS) return rc; } if (alo == 0 && ahi == 0) { DECINIT(pA); return DECIMAL_SUCCESS; } else { return pack128toDecimal(pA, alo, ahi, sigLen - decrDecimal, sign); } return 0; } int Decimal::decimalCompare(il2cpp_decimal_repr *pA, il2cpp_decimal_repr *pB) { int log2a, log2b, delta, sign; il2cpp_decimal_repr aa; sign = (pA->u.signscale.sign) ? -1 : 1; if (pA->u.signscale.sign ^ pB->u.signscale.sign) { return (decimalIsZero(pA) && decimalIsZero(pB)) ? 0 : sign; } /* try fast comparison via log2 */ log2a = decimalLog2(pA); log2b = decimalLog2(pB); delta = log2a - log2b; /* decimalLog2 is not exact, so we can say nothing if abs(delta) <= 1 */ if (delta < -1) return -sign; if (delta > 1) return sign; DECCOPY(&aa, pA); DECNEGATE(&aa); decimalIncr(&aa, pB); if (decimalIsZero(&aa)) return 0; return (aa.u.signscale.sign) ? 1 : -1; } int32_t Decimal::decimalIncr(il2cpp_decimal_repr * pA, il2cpp_decimal_repr * pB) { uint64_t alo, ahi, blo, bhi; int log2A, log2B, log2Result, log10Result, rc; int subFlag, sign, scaleA, scaleB; DECTO128(pA, alo, ahi); DECTO128(pB, blo, bhi); sign = pA->u.signscale.sign; subFlag = sign - (int)pB->u.signscale.sign; scaleA = pA->u.signscale.scale; scaleB = pB->u.signscale.scale; if (scaleA == scaleB) { /* same scale, that's easy */ if (subFlag) { sub128(alo, ahi, blo, bhi, &alo, &ahi); if (ahi & LIT_GUINT64_HIGHBIT) { alo--; alo = ~alo; if (alo == 0) ahi--; ahi = ~ahi; sign = !sign; } } else { add128(alo, ahi, blo, bhi, &alo, &ahi); } rc = normalize128(&alo, &ahi, &scaleA, 1, 0); } else { /* scales must be adjusted */ /* Estimate log10 and scale of result for adjusting scales */ log2A = log2withScale_128(alo, ahi, scaleA); log2B = log2withScale_128(blo, bhi, scaleB); log2Result = MAX(log2A, log2B); if (!subFlag) log2Result++; /* result can have one bit more */ log10Result = (log2Result * 1000) / 3322 + 1; /* we will calculate in 128bit, so we may need to adjust scale */ if (scaleB > scaleA) scaleA = scaleB; if (scaleA + log10Result > DECIMAL_MAX_SCALE + 7) { /* this may not fit in 128bit, so limit it */ scaleA = DECIMAL_MAX_SCALE + 7 - log10Result; } rc = adjustScale128(&alo, &ahi, scaleA - (int)pA->u.signscale.scale); if (rc != DECIMAL_SUCCESS) return rc; rc = adjustScale128(&blo, &bhi, scaleA - scaleB); if (rc != DECIMAL_SUCCESS) return rc; if (subFlag) { sub128(alo, ahi, blo, bhi, &alo, &ahi); if (ahi & LIT_GUINT64_HIGHBIT) { alo--; alo = ~alo; if (alo == 0) ahi--; ahi = ~ahi; sign = !sign; } } else { add128(alo, ahi, blo, bhi, &alo, &ahi); } rc = rescale128(&alo, &ahi, &scaleA, 0, 0, DECIMAL_MAX_SCALE, 1); } if (rc != DECIMAL_SUCCESS) return rc; return pack128toDecimal(pA, alo, ahi, scaleA, sign); } void Decimal::decimalFloorAndTrunc(il2cpp_decimal_repr * pA, int32_t floorFlag) { uint64_t alo, ahi; uint32_t factor, rest; int scale, sign, idx; int hasRest = 0; scale = pA->u.signscale.scale; if (scale == 0) return; /* nothing to do */ DECTO128(pA, alo, ahi); sign = pA->u.signscale.sign; while (scale > 0) { idx = (scale > DECIMAL_MAX_INTFACTORS) ? DECIMAL_MAX_INTFACTORS : scale; factor = constantsDecadeInt32Factors[idx]; scale -= idx; div128by32(&alo, &ahi, factor, &rest); hasRest = hasRest || (rest != 0); } if (floorFlag && hasRest && sign) /* floor: if negative, we must round up */ { roundUp128(&alo, &ahi); } pack128toDecimal(pA, alo, ahi, 0, sign); } int32_t Decimal::decimal2UInt64(il2cpp_decimal_repr * pA, uint64_t* pResult) { uint64_t alo, ahi; int scale; DECTO128(pA, alo, ahi); scale = pA->u.signscale.scale; if (scale > 0) { div128DecadeFactor(&alo, &ahi, scale); } /* overflow if integer too large or < 0 */ if (ahi != 0 || (alo != 0 && pA->u.signscale.sign)) return DECIMAL_OVERFLOW; *pResult = alo; return DECIMAL_SUCCESS; } int32_t Decimal::decimal2Int64(il2cpp_decimal_repr * pA, int64_t* pResult) { uint64_t alo, ahi; int sign, scale; DECTO128(pA, alo, ahi); scale = pA->u.signscale.scale; if (scale > 0) { div128DecadeFactor(&alo, &ahi, scale); } if (ahi != 0) return DECIMAL_OVERFLOW; sign = pA->u.signscale.sign; if (sign && alo != 0) { if (alo > LIT_GUINT64_HIGHBIT) return DECIMAL_OVERFLOW; *pResult = (int64_t) ~(alo - 1); } else { if (alo & LIT_GUINT64_HIGHBIT) return DECIMAL_OVERFLOW; *pResult = (int64_t)alo; } return DECIMAL_SUCCESS; } int32_t Decimal::decimalMult(il2cpp_decimal_repr* pA, il2cpp_decimal_repr* pB) { uint64_t low, mid, high; uint32_t factor; int scale, sign; mult96by96to192(pA->lo32, pA->mid32, pA->hi32, pB->lo32, pB->mid32, pB->hi32, &low, &mid, &high); /* adjust scale and sign */ scale = (int)pA->u.signscale.scale + (int)pB->u.signscale.scale; sign = pA->u.signscale.sign ^ pB->u.signscale.sign; /* first scaling step */ factor = constantsDecadeInt32Factors[DECIMAL_MAX_INTFACTORS]; while (high != 0 || (mid >> 32) >= factor) { if (high < 100) { factor /= 1000; /* we need some digits for final rounding */ scale -= DECIMAL_MAX_INTFACTORS - 3; } else { scale -= DECIMAL_MAX_INTFACTORS; } div192by32(&low, &mid, &high, factor); } /* second and final scaling */ int status = rescale128(&low, &mid, &scale, 0, 0, DECIMAL_MAX_SCALE, 1); if (status != DECIMAL_SUCCESS) return status; return pack128toDecimal(pA, low, mid, scale, sign); } int32_t Decimal::decimalDiv(il2cpp_decimal_repr* pC, il2cpp_decimal_repr* pA, il2cpp_decimal_repr* pB) { uint64_t clo, chi; /* result */ int scale, texp; /* Check for common cases */ if (decimalCompare(pA, pB) == 0) { /* One */ return pack128toDecimal(pC, 1, 0, 0, 0); } pA->u.signscale.sign = pA->u.signscale.sign ? 0 : 1; if (decimalCompare(pA, pB) == 0) { /* Minus one */ return pack128toDecimal(pC, 1, 0, 0, 1); } pA->u.signscale.sign = pA->u.signscale.sign ? 0 : 1; int status = decimalDivSub(pA, pB, &clo, &chi, &texp); if (status != DECIMAL_SUCCESS) { if (status == DECIMAL_FINISHED) status = DECIMAL_SUCCESS; return status; } /* adjust scale and sign */ scale = (int)pA->u.signscale.scale - (int)pB->u.signscale.scale; /*test: printf("0: %.17e\n", (((double)chi) * pow(2,64) + clo) * pow(10, -scale) * pow(2, -exp));*/ status = rescale128(&clo, &chi, &scale, texp, 0, DECIMAL_MAX_SCALE, 1); if (status != DECIMAL_SUCCESS) return status; return pack128toDecimal(pC, clo, chi, scale, pA->u.signscale.sign ^ pB->u.signscale.sign); } double Decimal::decimal2double(il2cpp_decimal_repr * pA) { double d; uint64_t alo, ahi, mantisse; uint32_t overhang, factor, roundBits; int scale, texp, log5, i; ahi = (((uint64_t)(pA->hi32)) << 32) | pA->mid32; alo = ((uint64_t)(pA->lo32)) << 32; /* special case zero */ if (ahi == 0 && alo == 0) return 0.0; texp = 0; scale = pA->u.signscale.scale; /* transform n * 10^-scale and exp = 0 => m * 2^-exp and scale = 0 */ while (scale > 0) { while ((ahi & LIT_GUINT64_HIGHBIT) == 0) { lshift128(&alo, &ahi); texp++; } overhang = (uint32_t)(ahi >> 32); if (overhang >= 5) { /* estimate log5 */ log5 = (log2_32(overhang) * 1000) / 2322; /* ln(5)/ln(2) = 2.3219... */ if (log5 < DECIMAL_MAX_INTFACTORS) { /* get maximal factor=5^i, so that overhang / factor >= 1 */ factor = constantsDecadeInt32Factors[log5] >> log5; /* 5^n = 10^n/2^n */ i = log5 + overhang / factor; } else { i = DECIMAL_MAX_INTFACTORS; /* we have only constants up to 10^DECIMAL_MAX_INTFACTORS */ } if (i > scale) i = scale; factor = constantsDecadeInt32Factors[i] >> i; /* 5^n = 10^n/2^n */ /* n * 10^-scale * 2^-exp => m * 10^-(scale-i) * 2^-(exp+i) with m = n * 5^-i */ div128by32(&alo, &ahi, factor, 0); scale -= i; texp += i; } } /* normalize significand (highest bit should be 1) */ while ((ahi & LIT_GUINT64_HIGHBIT) == 0) { lshift128(&alo, &ahi); texp++; } /* round to nearest even */ roundBits = (uint32_t)ahi & 0x7ff; ahi += 0x400; if ((ahi & LIT_GUINT64_HIGHBIT) == 0) /* overflow ? */ { ahi >>= 1; texp--; } else if ((roundBits & 0x400) == 0) ahi &= ~1; /* 96 bit => 1 implizit bit and 52 explicit bits */ mantisse = (ahi & ~LIT_GUINT64_HIGHBIT) >> 11; buildIEEE754Double(&d, pA->u.signscale.sign, -texp + 95, mantisse); return d; } int32_t Decimal::decimal2string(il2cpp_decimal_repr* val, int32_t digits, int32_t decimals, Il2CppArray* bufDigits, int32_t bufSize, int32_t* decPos, int32_t* sign) { NOT_IMPLEMENTED_ICALL(Decimal::decimal2string); return 0; } int32_t Decimal::decimalIntDiv(il2cpp_decimal_repr* pC, il2cpp_decimal_repr* pA, il2cpp_decimal_repr* pB) { uint64_t clo, chi; /* result */ int scale, texp, rc; rc = decimalDivSub(pA, pB, &clo, &chi, &texp); if (rc != DECIMAL_SUCCESS) { if (rc == DECIMAL_FINISHED) rc = DECIMAL_SUCCESS; return rc; } /* calc scale */ scale = (int)pA->u.signscale.scale - (int)pB->u.signscale.scale; /* truncate result to integer */ rc = rescale128(&clo, &chi, &scale, texp, 0, 0, 0); if (rc != DECIMAL_SUCCESS) return rc; return pack128toDecimal(pC, clo, chi, scale, pA->u.signscale.sign); } #else double Decimal::ToDouble(Il2CppDecimal d) { double result = 0.0; // Note: this can fail if the input is an invalid decimal, but for compatibility we should return 0 il2cpp_decimal_to_double_result(&d, &result); return result; } int32_t Decimal::FCallCompare(Il2CppDecimal* left, Il2CppDecimal* right) { uint32_t left_sign; uint32_t right_sign; Il2CppDecimal result; result.Hi32 = 0; // Just to shut up the compiler // First check signs and whether either are zero. If both are // non-zero and of the same sign, just use subtraction to compare. // left_sign = left->v.v.Lo32 | left->v.v.Mid32 | left->Hi32; right_sign = right->v.v.Lo32 | right->v.v.Mid32 | right->Hi32; if (left_sign != 0) left_sign = (left->u.u.sign & DECIMAL_NEG) | 1; if (right_sign != 0) right_sign = (right->u.u.sign & DECIMAL_NEG) | 1; // left_sign & right_sign have values 1, 0, or 0x81 depending on if the left/right // operand is +, 0, or -. // if (left_sign == right_sign) { if (left_sign == 0) // both are zero return IL2CPP_DECIMAL_CMP_EQ; // return equal DecAddSub(left, right, &result, DECIMAL_NEG); if (DECIMAL_LO64_GET(result) == 0 && result.Hi32 == 0) return IL2CPP_DECIMAL_CMP_EQ; if (result.u.u.sign & DECIMAL_NEG) return IL2CPP_DECIMAL_CMP_LT; return IL2CPP_DECIMAL_CMP_GT; } // // Signs are different. Use signed byte comparison // if ((signed char)left_sign > (signed char)right_sign) return IL2CPP_DECIMAL_CMP_GT; return IL2CPP_DECIMAL_CMP_LT; } int32_t Decimal::FCallToInt32(Il2CppDecimal d) { Il2CppDecimal result; // The following can not return an error, it only returns INVALID_ARG if the decimals is < 0 il2cpp_decimal_round_result(&d, 0, &result); if (DECIMAL_SCALE(result) != 0) { d = result; il2cpp_decimal_fix(&d, &result); } if (DECIMAL_HI32(result) == 0 && DECIMAL_MID32(result) == 0) { int32_t i = DECIMAL_LO32(result); if ((int16_t)DECIMAL_SIGNSCALE(result) >= 0) { if (i >= 0) return i; } else { i = -i; if (i <= 0) return i; } } vm::Exception::RaiseOverflowException(); return 0; } int32_t Decimal::GetHashCode(Il2CppDecimal* _this) { double dbl; if (il2cpp_decimal_to_double_result(_this, &dbl) != IL2CPP_DECIMAL_OK) return 0; if (dbl == 0.0) { // Ensure 0 and -0 have the same hash code return 0; } // conversion to double is lossy and produces rounding errors so we mask off the lowest 4 bits // // For example these two numerically equal decimals with different internal representations produce // slightly different results when converted to double: // // decimal a = new decimal(new int[] { 0x76969696, 0x2fdd49fa, 0x409783ff, 0x00160000 }); // => (decimal)1999021.176470588235294117647000000000 => (double)1999021.176470588 // decimal b = new decimal(new int[] { 0x3f0f0f0f, 0x1e62edcc, 0x06758d33, 0x00150000 }); // => (decimal)1999021.176470588235294117647000000000 => (double)1999021.1764705882 // return ((((int*)&dbl)[0]) & 0xFFFFFFF0) ^ ((int*)&dbl)[1]; } float Decimal::ToSingle(Il2CppDecimal d) { float result = 0.0f; // Note: this can fail if the input is an invalid decimal, but for compatibility we should return 0 il2cpp_decimal_to_float_result(&d, &result); return result; } void Decimal::ConstructorDouble(Il2CppDecimal* _this, double value) { if (il2cpp_decimal_from_double(value, _this) == IL2CPP_DECIMAL_OVERFLOW) { vm::Exception::RaiseOverflowException(); return; } _this->reserved = 0; } void Decimal::ConstructorFloat(Il2CppDecimal* _this, float value) { if (il2cpp_decimal_from_float(value, _this) == IL2CPP_DECIMAL_OVERFLOW) { vm::Exception::RaiseOverflowException(); return; } _this->reserved = 0; } void Decimal::FCallAddSub(Il2CppDecimal* left, Il2CppDecimal* right, uint8_t sign) { Il2CppDecimal result, decTmp; Il2CppDecimal *pdecTmp, *leftOriginal; uint32_t num[6], pwr; int scale, hi_prod, cur; SPLIT64 sdlTmp; IL2CPP_ASSERT(sign == 0 || sign == DECIMAL_NEG); leftOriginal = left; sign ^= (DECIMAL_SIGN(*right) ^ DECIMAL_SIGN(*left)) & DECIMAL_NEG; if (DECIMAL_SCALE(*right) == DECIMAL_SCALE(*left)) { // Scale factors are equal, no alignment necessary. // DECIMAL_SIGNSCALE(result) = DECIMAL_SIGNSCALE(*left); AlignedAdd: if (sign) { // Signs differ - subtract // DECIMAL_LO64_SET(result, (DECIMAL_LO64_GET(*left) - DECIMAL_LO64_GET(*right))); DECIMAL_HI32(result) = DECIMAL_HI32(*left) - DECIMAL_HI32(*right); // Propagate carry // if (DECIMAL_LO64_GET(result) > DECIMAL_LO64_GET(*left)) { DECIMAL_HI32(result)--; if (DECIMAL_HI32(result) >= DECIMAL_HI32(*left)) goto SignFlip; } else if (DECIMAL_HI32(result) > DECIMAL_HI32(*left)) { // Got negative result. Flip its sign. // SignFlip: DECIMAL_LO64_SET(result, -(int64_t)DECIMAL_LO64_GET(result)); DECIMAL_HI32(result) = ~DECIMAL_HI32(result); if (DECIMAL_LO64_GET(result) == 0) DECIMAL_HI32(result)++; DECIMAL_SIGN(result) ^= DECIMAL_NEG; } } else { // Signs are the same - add // DECIMAL_LO64_SET(result, (DECIMAL_LO64_GET(*left) + DECIMAL_LO64_GET(*right))); DECIMAL_HI32(result) = DECIMAL_HI32(*left) + DECIMAL_HI32(*right); // Propagate carry // if (DECIMAL_LO64_GET(result) < DECIMAL_LO64_GET(*left)) { DECIMAL_HI32(result)++; if (DECIMAL_HI32(result) <= DECIMAL_HI32(*left)) goto AlignedScale; } else if (DECIMAL_HI32(result) < DECIMAL_HI32(*left)) { AlignedScale: // The addition carried above 96 bits. Divide the result by 10, // dropping the scale factor. // if (DECIMAL_SCALE(result) == 0) { vm::Exception::RaiseOverflowException(); return; } DECIMAL_SCALE(result)--; sdlTmp.u.Lo = DECIMAL_HI32(result); sdlTmp.u.Hi = 1; sdlTmp.int64 = DivMod64by32(sdlTmp.int64, 10); DECIMAL_HI32(result) = sdlTmp.u.Lo; sdlTmp.u.Lo = DECIMAL_MID32(result); sdlTmp.int64 = DivMod64by32(sdlTmp.int64, 10); DECIMAL_MID32(result) = sdlTmp.u.Lo; sdlTmp.u.Lo = DECIMAL_LO32(result); sdlTmp.int64 = DivMod64by32(sdlTmp.int64, 10); DECIMAL_LO32(result) = sdlTmp.u.Lo; // See if we need to round up. // if (sdlTmp.u.Hi >= 5 && (sdlTmp.u.Hi > 5 || (DECIMAL_LO32(result) & 1))) { DECIMAL_LO64_SET(result, DECIMAL_LO64_GET(result) + 1); if (DECIMAL_LO64_GET(result) == 0) DECIMAL_HI32(result)++; } } } } else { // Scale factors are not equal. Assume that a larger scale // factor (more decimal places) is likely to mean that number // is smaller. Start by guessing that the right operand has // the larger scale factor. The result will have the larger // scale factor. // DECIMAL_SCALE(result) = DECIMAL_SCALE(*right); // scale factor of "smaller" DECIMAL_SIGN(result) = DECIMAL_SIGN(*left); // but sign of "larger" scale = DECIMAL_SCALE(result) - DECIMAL_SCALE(*left); if (scale < 0) { // Guessed scale factor wrong. Swap operands. // scale = -scale; DECIMAL_SCALE(result) = DECIMAL_SCALE(*left); DECIMAL_SIGN(result) ^= sign; pdecTmp = right; right = left; left = pdecTmp; } // *left will need to be multiplied by 10^scale so // it will have the same scale as *right. We could be // extending it to up to 192 bits of precision. // if (scale <= POWER10_MAX) { // Scaling won't make it larger than 4 uint32_ts // pwr = power10[scale]; DECIMAL_LO64_SET(decTmp, UInt32x32To64(DECIMAL_LO32(*left), pwr)); sdlTmp.int64 = UInt32x32To64(DECIMAL_MID32(*left), pwr); sdlTmp.int64 += DECIMAL_MID32(decTmp); DECIMAL_MID32(decTmp) = sdlTmp.u.Lo; DECIMAL_HI32(decTmp) = sdlTmp.u.Hi; sdlTmp.int64 = UInt32x32To64(DECIMAL_HI32(*left), pwr); sdlTmp.int64 += DECIMAL_HI32(decTmp); if (sdlTmp.u.Hi == 0) { // Result fits in 96 bits. Use standard aligned add. // DECIMAL_HI32(decTmp) = sdlTmp.u.Lo; left = &decTmp; goto AlignedAdd; } num[0] = DECIMAL_LO32(decTmp); num[1] = DECIMAL_MID32(decTmp); num[2] = sdlTmp.u.Lo; num[3] = sdlTmp.u.Hi; hi_prod = 3; } else { // Have to scale by a bunch. Move the number to a buffer // where it has room to grow as it's scaled. // num[0] = DECIMAL_LO32(*left); num[1] = DECIMAL_MID32(*left); num[2] = DECIMAL_HI32(*left); hi_prod = 2; // Scan for zeros in the upper words. // if (num[2] == 0) { hi_prod = 1; if (num[1] == 0) { hi_prod = 0; if (num[0] == 0) { // Left arg is zero, return right. // DECIMAL_LO64_SET(result, DECIMAL_LO64_GET(*right)); DECIMAL_HI32(result) = DECIMAL_HI32(*right); DECIMAL_SIGN(result) ^= sign; goto RetDec; } } } // Scaling loop, up to 10^9 at a time. hi_prod stays updated // with index of highest non-zero uint32_t. // for (; scale > 0; scale -= POWER10_MAX) { if (scale > POWER10_MAX) pwr = ten_to_nine; else pwr = power10[scale]; sdlTmp.u.Hi = 0; for (cur = 0; cur <= hi_prod; cur++) { sdlTmp.int64 = UInt32x32To64(num[cur], pwr) + sdlTmp.u.Hi; num[cur] = sdlTmp.u.Lo; } if (sdlTmp.u.Hi != 0) // We're extending the result by another uint32_t. num[++hi_prod] = sdlTmp.u.Hi; } } // Scaling complete, do the add. Could be subtract if signs differ. // sdlTmp.u.Lo = num[0]; sdlTmp.u.Hi = num[1]; if (sign) { // Signs differ, subtract. // DECIMAL_LO64_SET(result, (sdlTmp.int64 - DECIMAL_LO64_GET(*right))); DECIMAL_HI32(result) = num[2] - DECIMAL_HI32(*right); // Propagate carry // if (DECIMAL_LO64_GET(result) > sdlTmp.int64) { DECIMAL_HI32(result)--; if (DECIMAL_HI32(result) >= num[2]) goto LongSub; } else if (DECIMAL_HI32(result) > num[2]) { LongSub: // If num has more than 96 bits of precision, then we need to // carry the subtraction into the higher bits. If it doesn't, // then we subtracted in the wrong order and have to flip the // sign of the result. // if (hi_prod <= 2) goto SignFlip; cur = 3; while (num[cur++]-- == 0) ; if (num[hi_prod] == 0) hi_prod--; } } else { // Signs the same, add. // DECIMAL_LO64_SET(result, (sdlTmp.int64 + DECIMAL_LO64_GET(*right))); DECIMAL_HI32(result) = num[2] + DECIMAL_HI32(*right); // Propagate carry // if (DECIMAL_LO64_GET(result) < sdlTmp.int64) { DECIMAL_HI32(result)++; if (DECIMAL_HI32(result) <= num[2]) goto LongAdd; } else if (DECIMAL_HI32(result) < num[2]) { LongAdd: // Had a carry above 96 bits. // cur = 3; do { if (hi_prod < cur) { num[cur] = 1; hi_prod = cur; break; } } while (++num[cur++] == 0); } } if (hi_prod > 2) { num[0] = DECIMAL_LO32(result); num[1] = DECIMAL_MID32(result); num[2] = DECIMAL_HI32(result); DECIMAL_SCALE(result) = (uint8_t)ScaleResult(num, hi_prod, DECIMAL_SCALE(result)); if (DECIMAL_SCALE(result) == (uint8_t)-1) { vm::Exception::RaiseOverflowException(); return; } DECIMAL_LO32(result) = num[0]; DECIMAL_MID32(result) = num[1]; DECIMAL_HI32(result) = num[2]; } } RetDec: left = leftOriginal; COPYDEC(*left, result); left->reserved = 0; } void Decimal::FCallDivide(Il2CppDecimal* left, Il2CppDecimal* right) { uint32_t quo[3], quo_save[3], rem[4], divisor[3]; uint32_t pwr, tmp, tmp1; SPLIT64 sdlTmp, sdlDivisor; int scale, cur_scale; bool unscale; scale = DECIMAL_SCALE(*left) - DECIMAL_SCALE(*right); unscale = false; divisor[0] = DECIMAL_LO32(*right); divisor[1] = DECIMAL_MID32(*right); divisor[2] = DECIMAL_HI32(*right); if (divisor[1] == 0 && divisor[2] == 0) { // Divisor is only 32 bits. Easy divide. // if (divisor[0] == 0) { vm::Exception::RaiseDivideByZeroException(); return; } quo[0] = DECIMAL_LO32(*left); quo[1] = DECIMAL_MID32(*left); quo[2] = DECIMAL_HI32(*left); rem[0] = Div96By32(quo, divisor[0]); for (;;) { if (rem[0] == 0) { if (scale < 0) { cur_scale = std::min(9, -scale); goto HaveScale; } break; } // We need to unscale if and only if we have a non-zero remainder unscale = true; // We have computed a quotient based on the natural scale // ( - ). We have a non-zero // remainder, so now we should increase the scale if possible to // include more quotient bits. // // If it doesn't cause overflow, we'll loop scaling by 10^9 and // computing more quotient bits as long as the remainder stays // non-zero. If scaling by that much would cause overflow, we'll // drop out of the loop and scale by as much as we can. // // Scaling by 10^9 will overflow if quo[2].quo[1] >= 2^32 / 10^9 // = 4.294 967 296. So the upper limit is quo[2] == 4 and // quo[1] == 0.294 967 296 * 2^32 = 1,266,874,889.7+. Since // quotient bits in quo[0] could be all 1's, then 1,266,874,888 // is the largest value in quo[1] (when quo[2] == 4) that is // assured not to overflow. // cur_scale = SearchScale(quo[2], quo[1], quo[0], scale); if (cur_scale == 0) { // No more scaling to be done, but remainder is non-zero. // Round quotient.T // tmp = rem[0] << 1; if (tmp < rem[0] || (tmp >= divisor[0] && (tmp > divisor[0] || (quo[0] & 1)))) { RoundUp: if (!Add32To96(quo, 1)) { if (scale == 0) { vm::Exception::RaiseOverflowException(); return; } scale--; OverflowUnscale(quo, true); break; } } break; } if (cur_scale < 0) { vm::Exception::RaiseOverflowException(); return; } HaveScale: pwr = power10[cur_scale]; scale += cur_scale; if (IncreaseScale(quo, pwr) != 0) { vm::Exception::RaiseOverflowException(); return; } sdlTmp.int64 = DivMod64by32(UInt32x32To64(rem[0], pwr), divisor[0]); rem[0] = sdlTmp.u.Hi; if (!Add32To96(quo, sdlTmp.u.Lo)) { if (scale == 0) { vm::Exception::RaiseOverflowException(); return; } scale--; OverflowUnscale(quo, (rem[0] != 0)); break; } } // for (;;) } else { // Divisor has bits set in the upper 64 bits. // // Divisor must be fully normalized (shifted so bit 31 of the most // significant uint32_t is 1). Locate the MSB so we know how much to // normalize by. The dividend will be shifted by the same amount so // the quotient is not changed. // if (divisor[2] == 0) tmp = divisor[1]; else tmp = divisor[2]; cur_scale = 0; if (!(tmp & 0xFFFF0000)) { cur_scale += 16; tmp <<= 16; } if (!(tmp & 0xFF000000)) { cur_scale += 8; tmp <<= 8; } if (!(tmp & 0xF0000000)) { cur_scale += 4; tmp <<= 4; } if (!(tmp & 0xC0000000)) { cur_scale += 2; tmp <<= 2; } if (!(tmp & 0x80000000)) { cur_scale++; tmp <<= 1; } // Shift both dividend and divisor left by cur_scale. // sdlTmp.int64 = DECIMAL_LO64_GET(*left) << cur_scale; rem[0] = sdlTmp.u.Lo; rem[1] = sdlTmp.u.Hi; sdlTmp.u.Lo = DECIMAL_MID32(*left); sdlTmp.u.Hi = DECIMAL_HI32(*left); sdlTmp.int64 <<= cur_scale; rem[2] = sdlTmp.u.Hi; rem[3] = (DECIMAL_HI32(*left) >> (31 - cur_scale)) >> 1; sdlDivisor.u.Lo = divisor[0]; sdlDivisor.u.Hi = divisor[1]; sdlDivisor.int64 <<= cur_scale; if (divisor[2] == 0) { // Have a 64-bit divisor in sdlDivisor. The remainder // (currently 96 bits spread over 4 uint32_ts) will be < divisor. // sdlTmp.u.Lo = rem[2]; sdlTmp.u.Hi = rem[3]; quo[2] = 0; quo[1] = Div96By64(&rem[1], sdlDivisor); quo[0] = Div96By64(rem, sdlDivisor); for (;;) { if ((rem[0] | rem[1]) == 0) { if (scale < 0) { cur_scale = std::min(9, -scale); goto HaveScale64; } break; } // We need to unscale if and only if we have a non-zero remainder unscale = true; // Remainder is non-zero. Scale up quotient and remainder by // powers of 10 so we can compute more significant bits. // cur_scale = SearchScale(quo[2], quo[1], quo[0], scale); if (cur_scale == 0) { // No more scaling to be done, but remainder is non-zero. // Round quotient. // sdlTmp.u.Lo = rem[0]; sdlTmp.u.Hi = rem[1]; if (sdlTmp.u.Hi >= 0x80000000 || (sdlTmp.int64 <<= 1) > sdlDivisor.int64 || (sdlTmp.int64 == sdlDivisor.int64 && (quo[0] & 1))) goto RoundUp; break; } if (cur_scale < 0) { vm::Exception::RaiseOverflowException(); return; } HaveScale64: pwr = power10[cur_scale]; scale += cur_scale; if (IncreaseScale(quo, pwr) != 0) { vm::Exception::RaiseOverflowException(); return; } rem[2] = 0; // rem is 64 bits, IncreaseScale uses 96 IncreaseScale(rem, pwr); tmp = Div96By64(rem, sdlDivisor); if (!Add32To96(quo, tmp)) { if (scale == 0) { vm::Exception::RaiseOverflowException(); return; } scale--; OverflowUnscale(quo, (rem[0] != 0 || rem[1] != 0)); break; } } // for (;;) } else { // Have a 96-bit divisor in divisor[]. // // Start by finishing the shift left by cur_scale. // sdlTmp.u.Lo = divisor[1]; sdlTmp.u.Hi = divisor[2]; sdlTmp.int64 <<= cur_scale; divisor[0] = sdlDivisor.u.Lo; divisor[1] = sdlDivisor.u.Hi; divisor[2] = sdlTmp.u.Hi; // The remainder (currently 96 bits spread over 4 uint32_ts) // will be < divisor. // quo[2] = 0; quo[1] = 0; quo[0] = Div128By96(rem, divisor); for (;;) { if ((rem[0] | rem[1] | rem[2]) == 0) { if (scale < 0) { cur_scale = std::min(9, -scale); goto HaveScale96; } break; } // We need to unscale if and only if we have a non-zero remainder unscale = true; // Remainder is non-zero. Scale up quotient and remainder by // powers of 10 so we can compute more significant bits. // cur_scale = SearchScale(quo[2], quo[1], quo[0], scale); if (cur_scale == 0) { // No more scaling to be done, but remainder is non-zero. // Round quotient. // if (rem[2] >= 0x80000000) goto RoundUp; tmp = rem[0] > 0x80000000; tmp1 = rem[1] > 0x80000000; rem[0] <<= 1; rem[1] = (rem[1] << 1) + tmp; rem[2] = (rem[2] << 1) + tmp1; if (rem[2] > divisor[2] || (rem[2] == divisor[2] && (rem[1] > divisor[1] || rem[1] == (divisor[1] && (rem[0] > divisor[0] || (rem[0] == divisor[0] && (quo[0] & 1))))))) goto RoundUp; break; } if (cur_scale < 0) { vm::Exception::RaiseOverflowException(); return; } HaveScale96: pwr = power10[cur_scale]; scale += cur_scale; if (IncreaseScale(quo, pwr) != 0) { vm::Exception::RaiseOverflowException(); return; } rem[3] = IncreaseScale(rem, pwr); tmp = Div128By96(rem, divisor); if (!Add32To96(quo, tmp)) { if (scale == 0) { vm::Exception::RaiseOverflowException(); return; } scale--; OverflowUnscale(quo, (rem[0] != 0 || rem[1] != 0 || rem[2] != 0 || rem[3] != 0)); break; } } // for (;;) } } // We need to unscale if and only if we have a non-zero remainder if (unscale) { // Try extracting any extra powers of 10 we may have // added. We do this by trying to divide out 10^8, 10^4, 10^2, and 10^1. // If a division by one of these powers returns a zero remainder, then // we keep the quotient. If the remainder is not zero, then we restore // the previous value. // // Since 10 = 2 * 5, there must be a factor of 2 for every power of 10 // we can extract. We use this as a quick test on whether to try a // given power. // while ((quo[0] & 0xFF) == 0 && scale >= 8) { quo_save[0] = quo[0]; quo_save[1] = quo[1]; quo_save[2] = quo[2]; if (Div96By32(quo_save, 100000000) == 0) { quo[0] = quo_save[0]; quo[1] = quo_save[1]; quo[2] = quo_save[2]; scale -= 8; } else break; } if ((quo[0] & 0xF) == 0 && scale >= 4) { quo_save[0] = quo[0]; quo_save[1] = quo[1]; quo_save[2] = quo[2]; if (Div96By32(quo_save, 10000) == 0) { quo[0] = quo_save[0]; quo[1] = quo_save[1]; quo[2] = quo_save[2]; scale -= 4; } } if ((quo[0] & 3) == 0 && scale >= 2) { quo_save[0] = quo[0]; quo_save[1] = quo[1]; quo_save[2] = quo[2]; if (Div96By32(quo_save, 100) == 0) { quo[0] = quo_save[0]; quo[1] = quo_save[1]; quo[2] = quo_save[2]; scale -= 2; } } if ((quo[0] & 1) == 0 && scale >= 1) { quo_save[0] = quo[0]; quo_save[1] = quo[1]; quo_save[2] = quo[2]; if (Div96By32(quo_save, 10) == 0) { quo[0] = quo_save[0]; quo[1] = quo_save[1]; quo[2] = quo_save[2]; scale -= 1; } } } DECIMAL_SIGN(*left) = DECIMAL_SIGN(*left) ^ DECIMAL_SIGN(*right); DECIMAL_HI32(*left) = quo[2]; DECIMAL_MID32(*left) = quo[1]; DECIMAL_LO32(*left) = quo[0]; DECIMAL_SCALE(*left) = (uint8_t)scale; left->reserved = 0; } void Decimal::FCallFloor(Il2CppDecimal* d) { Il2CppDecimal decRes; il2cpp_decimal_round_to_int(d, &decRes); // copy decRes into d COPYDEC(*d, decRes); d->reserved = 0; FC_GC_POLL(); } void Decimal::FCallMultiply(Il2CppDecimal* d1, Il2CppDecimal* d2) { Il2CppDecimal decRes; Il2CppDecimalStatus status = il2cpp_decimal_multiply_result(d1, d2, &decRes); if (status != IL2CPP_DECIMAL_OK) { vm::Exception::RaiseOverflowException(); return; } COPYDEC(*d1, decRes); d1->reserved = 0; FC_GC_POLL(); } void Decimal::FCallRound(Il2CppDecimal* d, int32_t decimals) { Il2CppDecimal decRes; // GC is only triggered for throwing, no need to protect result if (decimals < 0 || decimals > 28) { vm::Exception::RaiseArgumentOutOfRangeException("d"); return; } il2cpp_decimal_round_result(d, decimals, &decRes); // copy decRes into d COPYDEC(*d, decRes); d->reserved = 0; FC_GC_POLL(); } void Decimal::FCallTruncate(Il2CppDecimal* d) { Il2CppDecimal decRes; il2cpp_decimal_fix(d, &decRes); // copy decRes into d COPYDEC(*d, decRes); d->reserved = 0; FC_GC_POLL(); } #endif } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Decimal.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppString; struct mscorlib_System_Decimal; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API Decimal { public: #if !NET_4_0 static int32_t decimal2Int64(il2cpp_decimal_repr* val, int64_t* result); static int32_t decimal2UInt64(il2cpp_decimal_repr* val, uint64_t* result); static int32_t decimal2string(il2cpp_decimal_repr* val, int32_t digits, int32_t decimals, Il2CppArray* bufDigits, int32_t bufSize, int32_t* decPos, int32_t* sign); static int decimalCompare(il2cpp_decimal_repr *pA, il2cpp_decimal_repr *pB); static int32_t decimalDiv(il2cpp_decimal_repr* pC, il2cpp_decimal_repr* pA, il2cpp_decimal_repr* pB); static void decimalFloorAndTrunc(il2cpp_decimal_repr * pA, int32_t floorFlag); static int32_t decimalIncr(il2cpp_decimal_repr * d1, il2cpp_decimal_repr * d2); static int32_t decimalIntDiv(il2cpp_decimal_repr* pc, il2cpp_decimal_repr* pa, il2cpp_decimal_repr* pb); static int32_t decimalMult(il2cpp_decimal_repr* pA, il2cpp_decimal_repr* pB); static int decimalSetExponent(il2cpp_decimal_repr*, int); static int string2decimal(il2cpp_decimal_repr *pA, Il2CppString *str, unsigned int decrDecimal, int sign); static double decimal2double(il2cpp_decimal_repr* val); #else static double ToDouble(Il2CppDecimal d); static int32_t FCallCompare(Il2CppDecimal* left, Il2CppDecimal* right); static int32_t FCallToInt32(Il2CppDecimal d); static int32_t GetHashCode(Il2CppDecimal* _this); static float ToSingle(Il2CppDecimal d); static void ConstructorDouble(Il2CppDecimal* _this, double value); static void ConstructorFloat(Il2CppDecimal* _this, float value); static void FCallAddSub(Il2CppDecimal* left, Il2CppDecimal* right, uint8_t sign); static void FCallDivide(Il2CppDecimal* left, Il2CppDecimal* right); static void FCallFloor(Il2CppDecimal* d); static void FCallMultiply(Il2CppDecimal* d1, Il2CppDecimal* d2); static void FCallRound(Il2CppDecimal* d, int32_t decimals); static void FCallTruncate(Il2CppDecimal* d); #endif }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Delegate.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System/Delegate.h" #include "vm/Class.h" #include "vm/Method.h" #include "vm/Object.h" #include "vm/Type.h" #include "vm/Runtime.h" #include "class-internals.h" #include "object-internals.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { Il2CppDelegate * Delegate::CreateDelegate_internal(Il2CppReflectionType *__type, Il2CppObject *target, Il2CppReflectionMethod *info, bool throwOnBindFailure) { Il2CppClass *delegate_class = il2cpp::vm::Class::FromIl2CppType(__type->type); const MethodInfo *method = info->method; IL2CPP_ASSERT(delegate_class->parent == il2cpp_defaults.multicastdelegate_class); //if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) { // if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure)) // return NULL; //} Il2CppObject* delegate = il2cpp::vm::Object::New(delegate_class); Il2CppMethodPointer func = method->methodPointer; il2cpp::vm::Type::ConstructDelegate((Il2CppDelegate*)delegate, target, func, method); return (Il2CppDelegate*)delegate; } void Delegate::SetMulticastInvoke(Il2CppDelegate * delegate) { const MethodInfo* invokeMethod = il2cpp::vm::Runtime::GetDelegateInvoke(delegate->object.klass); delegate->invoke_impl = invokeMethod->invoker_method; } #if NET_4_0 Il2CppMulticastDelegate* Delegate::AllocDelegateLike_internal(Il2CppDelegate* d) { IL2CPP_ASSERT(d->object.klass->parent == il2cpp_defaults.multicastdelegate_class); Il2CppMulticastDelegate *ret = (Il2CppMulticastDelegate*)il2cpp::vm::Object::New(d->object.klass); Il2CppMethodPointer func = d->method_ptr; il2cpp::vm::Type::ConstructDelegate(&ret->delegate, &d->object, func, d->method); const MethodInfo* invokeMethod = il2cpp::vm::Runtime::GetDelegateInvoke(d->object.klass); ret->delegate.invoke_impl = invokeMethod->invoker_method; return ret; } Il2CppObject* Delegate::GetVirtualMethod_internal(Il2CppObject* _this) { NOT_IMPLEMENTED_ICALL(Delegate::GetVirtualMethod_internal); IL2CPP_UNREACHABLE; return NULL; } #endif } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Delegate.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppObject; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppDelegate; struct Il2CppMulticastDelegate; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API Delegate { public: static Il2CppDelegate * CreateDelegate_internal(Il2CppReflectionType *, Il2CppObject *, Il2CppReflectionMethod *, bool); static void SetMulticastInvoke(Il2CppDelegate *); #if NET_4_0 static Il2CppMulticastDelegate* AllocDelegateLike_internal(Il2CppDelegate* d); static Il2CppObject* GetVirtualMethod_internal(Il2CppObject* _this); #endif }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Double.cpp ================================================ #include "il2cpp-config.h" #include #include "icalls/mscorlib/System/Double.h" #include "os/Locale.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { bool Double::ParseImpl(char *ptr, double *result) { char *endptr = NULL; *result = 0.0; if (*ptr) { #if IL2CPP_SUPPORT_LOCALE_INDEPENDENT_PARSING *result = il2cpp::os::Locale::DoubleParseLocaleIndependentImpl(ptr, &endptr); #else *result = strtod(ptr, &endptr); #endif } if (!*ptr || (endptr && *endptr)) return false; return true; } } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Double.h ================================================ #pragma once #include #include "il2cpp-config.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API Double { public: static bool ParseImpl(char *, double *); }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Enum.cpp ================================================ #include "il2cpp-config.h" #include "object-internals.h" #include "class-internals.h" #include "icalls/mscorlib/System/Enum.h" #include "vm/Class.h" #include "vm/Object.h" #include "vm/Exception.h" #include "vm/Reflection.h" #include "vm/Enum.h" using namespace il2cpp::vm; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { Il2CppObject * Enum::get_value(Il2CppObject *thisPtr) { if (!thisPtr) return NULL; IL2CPP_ASSERT(thisPtr->klass->enumtype); Il2CppClass* enumClass = Class::FromIl2CppType(Class::GetEnumBaseType(thisPtr->klass)); Il2CppObject* res = Object::New(enumClass); void* dst = (char*)res + sizeof(Il2CppObject); void* src = (char*)thisPtr + sizeof(Il2CppObject); int32_t size = Class::GetValueSize(enumClass, NULL); memcpy(dst, src, size); return res; return il2cpp::vm::Object::Box(thisPtr->klass->element_class, (char*)thisPtr + sizeof(Il2CppObject)); } int Enum::compare_value_to(Il2CppObject * thisPtr, Il2CppObject * other) { void* tdata = (char*)thisPtr + sizeof(Il2CppObject); void* odata = (char*)other + sizeof(Il2CppObject); const Il2CppType *basetype = Class::GetEnumBaseType(Object::GetClass(thisPtr)); IL2CPP_ASSERT(basetype); #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \ ENUM_TYPE me = *((ENUM_TYPE*)tdata); \ ENUM_TYPE other = *((ENUM_TYPE*)odata); \ if (me == other) \ return 0; \ return me > other ? 1 : -1; \ } while (0) #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \ ENUM_TYPE me = *((ENUM_TYPE*)tdata); \ ENUM_TYPE other = *((ENUM_TYPE*)odata); \ if (me == other) \ return 0; \ return me - other; \ } while (0) switch (basetype->type) { case IL2CPP_TYPE_U1: COMPARE_ENUM_VALUES(uint8_t); case IL2CPP_TYPE_I1: COMPARE_ENUM_VALUES(int8_t); case IL2CPP_TYPE_CHAR: COMPARE_ENUM_VALUES_RANGE(Il2CppChar); case IL2CPP_TYPE_U2: COMPARE_ENUM_VALUES_RANGE(uint16_t); case IL2CPP_TYPE_I2: COMPARE_ENUM_VALUES(int16_t); case IL2CPP_TYPE_U4: COMPARE_ENUM_VALUES(uint32_t); case IL2CPP_TYPE_I4: COMPARE_ENUM_VALUES(int32_t); case IL2CPP_TYPE_U8: COMPARE_ENUM_VALUES(uint64_t); case IL2CPP_TYPE_I8: COMPARE_ENUM_VALUES(int64_t); default: IL2CPP_ASSERT(false && "Implement type 0x%02x in compare_value_to"); } #undef COMPARE_ENUM_VALUES_RANGE #undef COMPARE_ENUM_VALUES return 0; } int32_t Enum::get_hashcode(Il2CppObject * thisPtr) { void* data = (char*)thisPtr + sizeof(Il2CppObject); Il2CppClass *basetype = thisPtr->klass->element_class; IL2CPP_ASSERT(basetype); if (basetype == il2cpp_defaults.sbyte_class) return *((int8_t*)data); if (basetype == il2cpp_defaults.byte_class) return *((uint8_t*)data); if (basetype == il2cpp_defaults.char_class) return *((Il2CppChar*)data); if (basetype == il2cpp_defaults.uint16_class) return *((uint16_t*)data); if (basetype == il2cpp_defaults.int16_class) return *((uint16_t*)data); if (basetype == il2cpp_defaults.uint32_class) return *((uint32_t*)data); if (basetype == il2cpp_defaults.int32_class) return *((int32_t*)data); if (basetype == il2cpp_defaults.uint64_class || basetype == il2cpp_defaults.int64_class) { int64_t value = *((int64_t*)data); return (int32_t)(value & 0xffffffff) ^ (int32_t)(value >> 32); } IL2CPP_ASSERT(0 && "System_Enum_get_hashcode_icall"); return 0; } static uint64_t read_enum_value(char *mem, Il2CppClass* type) { if (type == il2cpp_defaults.byte_class) return *(int8_t*)mem; if (type == il2cpp_defaults.sbyte_class) return *(uint8_t*)mem; if (type == il2cpp_defaults.uint16_class) return *(uint16_t*)mem; if (type == il2cpp_defaults.int16_class) return *(int16_t*)mem; if (type == il2cpp_defaults.uint32_class) return *(uint32_t*)mem; if (type == il2cpp_defaults.int32_class) return *(int32_t*)mem; if (type == il2cpp_defaults.uint64_class) return *(uint64_t*)mem; if (type == il2cpp_defaults.int64_class) return *(int64_t*)mem; IL2CPP_ASSERT(0); return 0; } static void write_enum_value(char *mem, Il2CppClass* type, uint64_t value) { if (type == il2cpp_defaults.byte_class || type == il2cpp_defaults.sbyte_class) { uint8_t *p = (uint8_t*)mem; *p = (uint8_t)value; } else if (type == il2cpp_defaults.uint16_class || type == il2cpp_defaults.int16_class) { uint16_t *p = (uint16_t*)mem; *p = (uint16_t)value; } else if (type == il2cpp_defaults.uint32_class || type == il2cpp_defaults.int32_class) { uint32_t *p = (uint32_t*)mem; *p = (uint32_t)value; } else if (type == il2cpp_defaults.uint64_class || type == il2cpp_defaults.int64_class) { uint64_t *p = (uint64_t*)mem; *p = value; } else { IL2CPP_ASSERT(0); } } Il2CppObject * Enum::ToObject(Il2CppReflectionType * enumType, Il2CppObject * value) { //MonoDomain *domain; Il2CppClass *enumc, *objc; Il2CppObject *res; Il2CppClass *etype; uint64_t val; IL2CPP_CHECK_ARG_NULL(enumType); IL2CPP_CHECK_ARG_NULL(value); //domain = mono_object_domain (enumType); enumc = Class::FromIl2CppType(enumType->type); objc = Object::GetClass(value); //if (!enumc->enumtype) // mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum.")); //if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8))) // mono_raise_exception (mono_get_exception_argument ("value", "The value passed in must be an enum base or an underlying type for an enum, such as an Int32.")); etype = Class::GetElementClass(enumc); if (!etype) /* MS throws this for typebuilders */ il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetArgumentException("Type must be a type provided by the runtime.", "enumType")); res = (Il2CppObject*)il2cpp::vm::Object::New(enumc); //val = read_enum_value ((char *)value + sizeof (mscorlib_System_Object), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type); val = read_enum_value((char*)value + sizeof(Il2CppObject), objc->enumtype ? objc->element_class : objc); write_enum_value((char*)res + sizeof(Il2CppObject), etype, val); return res; } Il2CppReflectionType * Enum::get_underlying_type(Il2CppReflectionType *type) { const Il2CppType *etype; etype = Class::GetEnumBaseType(Class::FromIl2CppType(type->type)); if (!etype) /* MS throws this for typebuilders */ il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetArgumentException("Type must be a type provided by the runtime.", "enumType")); return il2cpp::vm::Reflection::GetTypeObject(etype); } #if NET_4_0 bool Enum::GetEnumValuesAndNames(Il2CppReflectionRuntimeType* enumType, Il2CppArray** values, Il2CppArray** names) { return vm::Enum::GetEnumValuesAndNames(Class::FromIl2CppType(enumType->type.type), values, names); } bool Enum::InternalHasFlag(Il2CppObject* thisPtr, Il2CppObject* flags) { Il2CppClass* enumClass = Class::FromIl2CppType(Class::GetEnumBaseType(thisPtr->klass)); int32_t size = Class::GetValueSize(enumClass, NULL); uint64_t a_val = 0, b_val = 0; memcpy(&a_val, Object::Unbox(thisPtr), size); memcpy(&b_val, Object::Unbox(flags), size); return (a_val & b_val) == b_val; } int32_t Enum::InternalCompareTo(Il2CppObject* o1, Il2CppObject* o2) { return compare_value_to(o1, o2); } Il2CppObject* Enum::InternalBoxEnum(Il2CppReflectionRuntimeType* enumType, int64_t value) { return Object::Box(Class::FromIl2CppType(enumType->type.type), &value); } Il2CppReflectionRuntimeType* Enum::InternalGetUnderlyingType(Il2CppReflectionRuntimeType* enumType) { return reinterpret_cast(get_underlying_type(&enumType->type)); } #endif } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Enum.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppObject; struct Il2CppReflectionType; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API Enum { public: static Il2CppObject* ToObject(Il2CppReflectionType* enumType, Il2CppObject* value); static int compare_value_to(Il2CppObject* thisPtr, Il2CppObject* other); static int32_t get_hashcode(Il2CppObject* thisPtr); static Il2CppObject* get_value(Il2CppObject* thisPtr); static Il2CppReflectionType* get_underlying_type(Il2CppReflectionType* type); #if NET_4_0 static bool GetEnumValuesAndNames(Il2CppReflectionRuntimeType* enumType, Il2CppArray** values, Il2CppArray** names); static bool InternalHasFlag(Il2CppObject* thisPtr, Il2CppObject* flags); static int32_t InternalCompareTo(Il2CppObject* o1, Il2CppObject* o2); static Il2CppObject* InternalBoxEnum(Il2CppReflectionRuntimeType* enumType, int64_t value); static Il2CppReflectionRuntimeType* InternalGetUnderlyingType(Il2CppReflectionRuntimeType* enumType); #endif }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Environment.cpp ================================================ #include "il2cpp-config.h" #include "object-internals.h" #include "class-internals.h" #include "icalls/mscorlib/System/Environment.h" #include "os/Time.h" #include "os/Environment.h" #include "vm/Array.h" #include "vm/Class.h" #include "vm/Domain.h" #include "vm/Runtime.h" #include "vm/String.h" #include "vm/Exception.h" #include "utils/PathUtils.h" #include "utils/StringUtils.h" #include "utils/Environment.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { static int32_t exitcode = 0; static bool socket_security_enabled = false; static Il2CppArray* ToIl2CppArray(const std::vector& strings) { Il2CppClass *klass = il2cpp::vm::Class::GetArrayClass(il2cpp_defaults.string_class, 1); Il2CppArray* array = (Il2CppArray*)il2cpp::vm::Array::NewSpecific(klass, (il2cpp_array_size_t)strings.size()); for (size_t i = 0, size = strings.size(); i < size; ++i) il2cpp_array_setref(array, i, il2cpp::vm::String::New(strings[i].c_str())); return array; } Il2CppString* Environment::get_MachineName() { return il2cpp::vm::String::New(il2cpp::os::Environment::GetMachineName().c_str()); } Il2CppString* Environment::get_NewLine(void) { return il2cpp::vm::String::NewUtf16(kIl2CppNewLine); } bool Environment::get_SocketSecurityEnabled() { return socket_security_enabled; } int32_t Environment::get_TickCount() { return il2cpp::os::Time::GetTicksMillisecondsMonotonic(); } int32_t Environment::get_ProcessorCount() { return il2cpp::os::Environment::GetProcessorCount(); } Il2CppArray* Environment::GetCommandLineArgs() { Il2CppArray *res; int i; int num_main_args = utils::Environment::GetNumMainArgs(); const std::vector& mainArgs = utils::Environment::GetMainArgs(); Il2CppClass *klass = il2cpp::vm::Class::GetArrayClass(il2cpp_defaults.string_class, 1); res = (Il2CppArray*)il2cpp::vm::Array::NewSpecific(klass, num_main_args); for (i = 0; i < num_main_args; ++i) il2cpp_array_setref(res, i, il2cpp::vm::String::NewUtf16(mainArgs[i].c_str(), static_cast(mainArgs[i].length()))); return res; } Il2CppArray* Environment::GetEnvironmentVariableNames() { return ToIl2CppArray(il2cpp::os::Environment::GetEnvironmentVariableNames()); } Il2CppString* Environment::GetWindowsFolderPath(int32_t folder) { return il2cpp::vm::String::New(il2cpp::os::Environment::GetWindowsFolderPath(folder).c_str()); } Il2CppString* Environment::internalGetHome() { return il2cpp::vm::String::New(il2cpp::os::Environment::GetHomeDirectory().c_str()); } Il2CppArray* Environment::GetLogicalDrivesInternal() { return ToIl2CppArray(il2cpp::os::Environment::GetLogicalDrives()); } void Environment::InternalSetEnvironmentVariable(Il2CppString* variable, Il2CppString* value) { const std::string variableStr(utils::StringUtils::Utf16ToUtf8(utils::StringUtils::GetChars(variable))); const bool clearValue = value == NULL || utils::StringUtils::GetLength(value) == 0 || utils::StringUtils::GetChars(0) == 0; const std::string valueStr = clearValue ? std::string() : utils::StringUtils::Utf16ToUtf8(utils::StringUtils::GetChars(value)); il2cpp::os::Environment::SetEnvironmentVariable(variableStr, valueStr); } void Environment::internalBroadcastSettingChange() { NOT_IMPLEMENTED_ICALL(Environment::internalBroadcastSettingChange); } Il2CppString * Environment::GetMachineConfigPath(void) { const char* frameworkVersion = vm::Runtime::GetFrameworkVersion(); std::string path = utils::PathUtils::Combine( vm::Runtime::GetConfigDir(), utils::PathUtils::Combine( utils::StringView("mono"), utils::PathUtils::Combine( utils::StringView(frameworkVersion, strlen(frameworkVersion)), utils::StringView("machine.config")))); return vm::String::NewWrapper(path.c_str()); } Il2CppString * Environment::internalGetEnvironmentVariable(Il2CppString *name) { const std::string nameStr(utils::StringUtils::Utf16ToUtf8(utils::StringUtils::GetChars(name))); const std::string variable(il2cpp::os::Environment::GetEnvironmentVariable(nameStr)); return variable.empty() ? NULL : il2cpp::vm::String::New(variable.c_str()); } Il2CppString * Environment::GetOSVersionString(void) { return il2cpp::vm::String::New(il2cpp::os::Environment::GetOsVersionString().c_str()); } int Environment::get_Platform(void) { #ifdef _MSC_VER return 2; #else return 4; #endif } int32_t Environment::get_ExitCode() { return exitcode; } void Environment::set_ExitCode(int32_t value) { exitcode = value; } bool Environment::get_HasShutdownStarted() { return vm::Runtime::IsShuttingDown(); } Il2CppString* Environment::get_EmbeddingHostName() { return il2cpp::vm::String::New("IL2CPP"); } Il2CppString* Environment::get_UserName() { return il2cpp::vm::String::New(il2cpp::os::Environment::GetOsUserName().c_str()); } void Environment::Exit(int32_t exitCode) { il2cpp::os::Environment::Exit(exitCode); } Il2CppString* Environment::internalGetGacPath() { // Not used by the runtime. Used only by the Mono compiler (mcs). NOT_IMPLEMENTED_ICALL(Environment::internalGetGacPatH); return 0; } #if NET_4_0 bool Environment::GetIs64BitOperatingSystem() { if (sizeof(void*) == 8) return true; return il2cpp::os::Environment::Is64BitOs(); } int32_t Environment::GetPageSize() { return IL2CPP_PAGE_SIZE; } Il2CppString* Environment::GetNewLine() { return get_NewLine(); } Il2CppString* Environment::internalGetEnvironmentVariable_native(Il2CppIntPtr variablePtr) { const char *value = (char*)variablePtr.m_value; if (!value) return NULL; const std::string nameStr(value); const std::string variable(il2cpp::os::Environment::GetEnvironmentVariable(nameStr)); return variable.empty() ? NULL : il2cpp::vm::String::New(variable.c_str()); } Il2CppString* Environment::get_bundled_machine_config() { NOT_IMPLEMENTED_ICALL(Environment::get_bundled_machine_config); IL2CPP_UNREACHABLE; } #endif } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Environment.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppString; struct Il2CppArray; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API Environment { public: static Il2CppString* internalGetGacPath(); static int32_t get_ProcessorCount(); static bool get_SocketSecurityEnabled(); static void internalBroadcastSettingChange(); static Il2CppString* GetOSVersionString(); static Il2CppString* GetMachineConfigPath(); static Il2CppArray* GetLogicalDrivesInternal(); static Il2CppArray* GetEnvironmentVariableNames(); static Il2CppArray* GetCommandLineArgs(); static Il2CppString* internalGetHome(); static Il2CppString* get_NewLine(); static Il2CppString* get_MachineName(); static int32_t get_ExitCode(); static bool get_HasShutdownStarted(); static Il2CppString* get_EmbeddingHostName(); static Il2CppString* get_UserName(); static int get_Platform(); static int32_t get_TickCount(); static void Exit(int32_t exitCode); static Il2CppString* GetWindowsFolderPath(int32_t folder); static Il2CppString* internalGetEnvironmentVariable(Il2CppString *); static void set_ExitCode(int32_t value); static void InternalSetEnvironmentVariable(Il2CppString* variable, Il2CppString* value); #if NET_4_0 static bool GetIs64BitOperatingSystem(); static int32_t GetPageSize(); static Il2CppString* GetNewLine(); static Il2CppString* internalGetEnvironmentVariable_native(Il2CppIntPtr variable); static Il2CppString* get_bundled_machine_config(); #endif }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Exception.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { bool Exception::nIsTransient(int32_t hr) { NOT_IMPLEMENTED_ICALL(Exception::nIsTransient); IL2CPP_UNREACHABLE; return false; } Il2CppObject* Exception::GetMethodFromStackTrace(Il2CppObject* stackTrace) { NOT_IMPLEMENTED_ICALL(Exception::GetMethodFromStackTrace); IL2CPP_UNREACHABLE; return NULL; } } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Exception.h ================================================ #pragma once #if NET_4_0 namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API Exception { public: static bool nIsTransient(int32_t hr); static Il2CppObject* GetMethodFromStackTrace(Il2CppObject* stackTrace); }; } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/GC.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "icalls/mscorlib/System/GC.h" #include "gc/GarbageCollector.h" #include "vm/Exception.h" #include "vm/Object.h" #include "vm/Array.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { void GC::SuppressFinalize(Il2CppObject *obj) { if (obj == NULL) il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetArgumentNullException("obj")); il2cpp::gc::GarbageCollector::SuppressFinalizer(obj); } int32_t GC::GetGeneration(Il2CppObject* obj) { return il2cpp::gc::GarbageCollector::GetGeneration(obj); } void GC::KeepAlive(Il2CppObject* obj) { // do nothing. icall just prevents compilers from optimizing away references to object being passed in } void GC::InternalCollect(int generation) { il2cpp::gc::GarbageCollector::Collect(generation); } int32_t GC::get_MaxGeneration() { return il2cpp::gc::GarbageCollector::GetMaxGeneration(); } void GC::RecordPressure(int64_t bytesAllocated) { il2cpp::gc::GarbageCollector::AddMemoryPressure(bytesAllocated); } void GC::WaitForPendingFinalizers() { il2cpp::gc::GarbageCollector::WaitForPendingFinalizers(); } int64_t GC::GetTotalMemory(bool forceFullCollection) { if (forceFullCollection) il2cpp::gc::GarbageCollector::Collect(il2cpp::gc::GarbageCollector::GetMaxGeneration()); return il2cpp::gc::GarbageCollector::GetUsedHeapSize(); } void GC::ReRegisterForFinalize(Il2CppObject* obj) { if (obj == NULL) il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetArgumentNullException("obj")); il2cpp::gc::GarbageCollector::RegisterFinalizer(obj); } int32_t GC::CollectionCount(int32_t generation) { return il2cpp::gc::GarbageCollector::GetCollectionCount(generation); } #if NET_4_0 Il2CppObject* GC::get_ephemeron_tombstone() { return vm::Object::New(il2cpp_defaults.object_class); } void GC::register_ephemeron_array(Il2CppArray* array) { // Mono only does something in this icall when SGEN is in use. We don't have SGEN, // so there is nothing to do here. } int32_t GC::GetCollectionCount(int32_t generation) { return CollectionCount(generation); } int32_t GC::GetMaxGeneration() { return get_MaxGeneration(); } void GC::_ReRegisterForFinalize(Il2CppObject* o) { ReRegisterForFinalize(o); } void GC::_SuppressFinalize(Il2CppObject* o) { SuppressFinalize(o); } #endif } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/GC.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppObject; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API GC { public: static int get_MaxGeneration(); static int32_t CollectionCount(int32_t generation); static int32_t GetGeneration(Il2CppObject* obj); static int64_t GetTotalMemory(bool forceFullCollection); static void InternalCollect(int generation); static void KeepAlive(Il2CppObject* obj); static void ReRegisterForFinalize(Il2CppObject* obj); static void SuppressFinalize(Il2CppObject *); static void RecordPressure(int64_t bytesAllocated); static void WaitForPendingFinalizers(); #if NET_4_0 static Il2CppObject* get_ephemeron_tombstone(); static void register_ephemeron_array(Il2CppArray* array); static int32_t GetCollectionCount(int32_t generation); static int32_t GetMaxGeneration(); static void _ReRegisterForFinalize(Il2CppObject* o); static void _SuppressFinalize(Il2CppObject* o); #endif }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Math.cpp ================================================ #include "il2cpp-config.h" #include #include #include #include "icalls/mscorlib/System/Math.h" #include "vm/Exception.h" #ifdef _MSC_VER # define ISNAN _isnan #else # define ISNAN isnan #endif namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { double Math::Acos(double val) { return acos(val); } double Math::Asin(double val) { return asin(val); } double Math::Atan(double val) { return atan(val); } double Math::Atan2(double y, double x) { return atan2(y, x); } double Math::Cos(double val) { return cos(val); } double Math::Cosh(double val) { return cosh(val); } double Math::Exp(double val) { return exp(val); } double Math::Floor(double x) { return floor(x); } double Math::Log(double x) { NOT_IMPLEMENTED_ICALL_NO_ASSERT(Math::Log, "Determin what value of NAN to use"); if (x == 0) return -HUGE_VAL; else if (x < 0) return std::numeric_limits::signaling_NaN(); //return NAN; return log(x); } double Math::Log10(double val) { return log10(val); } double Math::Pow(double val, double exp) { double res = pow(val, exp); if (ISNAN(res)) return 1.0; if (res == -0.0) return 0.0; return res; } double Math::Round(double x) { double int_part, dec_part; int_part = floor(x); dec_part = x - int_part; if (((dec_part == 0.5) && ((2.0 * ((int_part / 2.0) - floor(int_part / 2.0))) != 0.0)) || (dec_part > 0.5)) { int_part++; } return int_part; } double Math::Sin(double val) { return sin(val); } double Math::Sinh(double val) { return sinh(val); } double Math::Sqrt(double val) { return sqrt(val); } double Math::Tan(double val) { return tan(val); } double Math::Tanh(double val) { return tanh(val); } double Math::Round2(double value, int32_t digits, bool away_from_zero) { double p; if (value == HUGE_VAL) return HUGE_VAL; if (value == -HUGE_VAL) return -HUGE_VAL; if (digits == 0 && !away_from_zero) return Round(value); p = pow(10.0, digits); // Note: Migrate to C++11 when possible #if 0 if (away_from_zero) return std::round(value * p) / p; else return std::rint(value * p) / p; #else if (away_from_zero) return (value >= 0.0) ? floor(value * p + 0.5) / p : ceil(value * p - 0.5) / p; else return (value >= 0.0) ? ceil(value * p - 0.5) / p : floor(value * p + 0.5) / p; #endif } #if NET_4_0 double Math::Abs(double value) { return fabs(value); } double Math::Ceiling(double a) { return ceil(a); } double Math::SplitFractionDouble(double* value) { return modf(*value, value); } float Math::Abs(float value) { return fabsf(value); } #endif } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Math.h ================================================ #pragma once #include "il2cpp-config.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API Math { public: static double Acos(double val); static double Asin(double val); static double Atan(double val); static double Atan2(double y, double x); static double Cos(double val); static double Cosh(double val); static double Exp(double val); static double Floor(double x); static double Log(double x); static double Log10(double val); static double Pow(double val, double exp); static double Round(double x); static double Round2(double value, int32_t digits, bool away_from_zero); static double Sin(double val); static double Sinh(double val); static double Sqrt(double val); static double Tan(double val); static double Tanh(double val); #if NET_4_0 static double Abs(double value); static double Ceiling(double a); static double SplitFractionDouble(double* value); static float Abs(float value); #endif }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/MissingMemberException.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "MissingMemberException.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { Il2CppString* MissingMemberException::FormatSignature(Il2CppArray* signature) { NOT_IMPLEMENTED_ICALL(MissingMemberException::FormatSignature); IL2CPP_UNREACHABLE; return NULL; } } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/MissingMemberException.h ================================================ #pragma once #if NET_4_0 namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API MissingMemberException { public: static Il2CppString* FormatSignature(Il2CppArray* signature); }; } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/MonoCustomAttrs.cpp ================================================ #include "il2cpp-config.h" #include #include "icalls/mscorlib/System/MonoCustomAttrs.h" #include "class-internals.h" #include "object-internals.h" #include "vm/Array.h" #include "vm/Class.h" #include "vm/Object.h" #include "vm/Reflection.h" #include "vm/Runtime.h" #include "vm/Exception.h" using namespace il2cpp::vm; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { Il2CppArray * MonoCustomAttrs::GetCustomAttributesInternal(Il2CppObject* obj, Il2CppReflectionType* type, bool pseudoAttrs) { IL2CPP_ASSERT(pseudoAttrs == false && "System_MonoCustomAttrs_GetCustomAttributesInternal_icall with pseudoAttrs == true has not been implemented yet"); CustomAttributesCache *cinfo = il2cpp::vm::Reflection::GetCustomAttrsInfo(obj); if (!cinfo) { return il2cpp::vm::Array::New(il2cpp_defaults.object_class, 0); } if (!type) { Il2CppArray *result = il2cpp::vm::Array::New(il2cpp_defaults.object_class, cinfo->count); memcpy(il2cpp_array_addr(result, Il2CppObject*, 0), cinfo->attributes, sizeof(Il2CppObject*) * cinfo->count); return result; } Il2CppClass* attributeClass = Class::FromIl2CppType(type->type); int count = 0; for (int i = 0; i < cinfo->count; i++) { Il2CppObject* attr = cinfo->attributes[i]; if (Class::IsAssignableFrom(attributeClass, attr->klass)) count++; } Il2CppArray *result = il2cpp::vm::Array::New(il2cpp_defaults.object_class, count); int index = 0; for (int i = 0; i < cinfo->count; i++) { Il2CppObject* attr = cinfo->attributes[i]; if (!Class::IsAssignableFrom(attributeClass, attr->klass)) continue; il2cpp_array_setref(result, index, cinfo->attributes[i]); index++; } return result; } bool MonoCustomAttrs::IsDefinedInternal(Il2CppObject *obj, Il2CppReflectionType *attr_type) { return il2cpp::vm::Reflection::HasAttribute(obj, Class::FromIl2CppType(attr_type->type)); } #if !NET_4_0 static Il2CppObject* CreateCustomAttributeData(Il2CppObject* attribute) { static const MethodInfo* customAttributeDataConstructor; void *params[3]; if (!customAttributeDataConstructor) customAttributeDataConstructor = vm::Class::GetMethodFromName(il2cpp_defaults.customattribute_data_class, ".ctor", 3); const MethodInfo* attributeConstructor = vm::Class::GetMethodFromName(attribute->klass, ".ctor", 0); if (attributeConstructor == NULL) NOT_IMPLEMENTED_ICALL(MonoCustomAttrs::GetCustomAttributesDataInternal); Il2CppObject* customAttributeData = vm::Object::New(il2cpp_defaults.customattribute_data_class); params[0] = vm::Reflection::GetMethodObject(attributeConstructor, NULL); params[1] = params[2] = NULL; vm::Runtime::Invoke(customAttributeDataConstructor, customAttributeData, params, NULL); return customAttributeData; } #else static Il2CppObject* CreateCustomAttributeData(Il2CppObject* attribute) { static const MethodInfo* customAttributeDataConstructor; void *params[4]; if (!customAttributeDataConstructor) customAttributeDataConstructor = vm::Class::GetMethodFromName(il2cpp_defaults.customattribute_data_class, ".ctor", 4); const MethodInfo* attributeConstructor = vm::Class::GetMethodFromName(attribute->klass, ".ctor", 0); if (attributeConstructor == NULL) NOT_IMPLEMENTED_ICALL(MonoCustomAttrs::GetCustomAttributesDataInternal); Il2CppObject* customAttributeData = vm::Object::New(il2cpp_defaults.customattribute_data_class); int argCount = 0; params[0] = vm::Reflection::GetMethodObject(attributeConstructor, NULL); params[1] = vm::Reflection::GetAssemblyObject(MetadataCache::GetAssemblyFromIndex(attribute->klass->image->assemblyIndex)); params[2] = &Il2CppIntPtr::Zero; params[3] = &argCount; vm::Runtime::Invoke(customAttributeDataConstructor, customAttributeData, params, NULL); return customAttributeData; } #endif Il2CppArray* MonoCustomAttrs::GetCustomAttributesDataInternal(Il2CppObject* obj) { CustomAttributesCache *cinfo = il2cpp::vm::Reflection::GetCustomAttrsInfo(obj); if (!cinfo) return il2cpp::vm::Array::New(il2cpp_defaults.customattribute_data_class, 0); Il2CppArray* result = il2cpp::vm::Array::New(il2cpp_defaults.customattribute_data_class, cinfo->count); for (int i = 0; i < cinfo->count; ++i) { Il2CppObject* attribute = CreateCustomAttributeData(cinfo->attributes[i]); il2cpp_array_setref(result, i, attribute); } return result; } } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/MonoCustomAttrs.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppArray; struct Il2CppObject; struct Il2CppReflectionType; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API MonoCustomAttrs { public: static Il2CppArray* GetCustomAttributesDataInternal(Il2CppObject* obj); static Il2CppArray * GetCustomAttributesInternal(Il2CppObject* obj, Il2CppReflectionType* type, bool pseudoAttrs); static bool IsDefinedInternal(Il2CppObject *obj, Il2CppReflectionType *attr_type); }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/MonoEnumInfo.cpp ================================================ #include "il2cpp-config.h" #include #include "object-internals.h" #include "class-internals.h" #include "icalls/mscorlib/System/MonoEnumInfo.h" #include "vm/Array.h" #include "vm/Class.h" #include "vm/Enum.h" #include "vm/Field.h" #include "vm/GenericClass.h" #include "vm/String.h" #include "vm/Reflection.h" #include "vm/Type.h" #include "utils/MemoryRead.h" #if !NET_4_0 using namespace il2cpp::vm; using namespace il2cpp::utils; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { void MonoEnumInfo::get_enum_info(Il2CppReflectionType* type, Il2CppEnumInfo* info) { IL2CPP_OBJECT_SETREF(info, utype, Reflection::GetTypeObject(Type::GetUnderlyingType(type->type))); vm::Enum::GetEnumValuesAndNames(Class::FromIl2CppType(type->type), &info->values, &info->names); } } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/MonoEnumInfo.h ================================================ #pragma once #include "il2cpp-config.h" #if !NET_4_0 struct Il2CppReflectionType; struct Il2CppEnumInfo; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API MonoEnumInfo { public: static void get_enum_info(Il2CppReflectionType* type, Il2CppEnumInfo* info); }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/MonoType.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "object-internals.h" #include "tabledefs.h" #include "gc/Allocator.h" #include "icalls/mscorlib/System/MonoType.h" #include "utils/Functional.h" #include "utils/StringUtils.h" #include "utils/Il2CppHashMap.h" #include "vm/Array.h" #include "vm/Class.h" #include "vm/Field.h" #include "vm/GenericClass.h" #include "vm/GenericContainer.h" #include "vm/Method.h" #include "vm/MetadataCache.h" #include "vm/Reflection.h" #include "vm/String.h" #include "vm/Type.h" #include "vm/Exception.h" #include "vm-utils/VmStringUtils.h" #include #include using namespace il2cpp::vm; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { struct Il2CppEventInfoHash { size_t operator()(const EventInfo* eventInfo) const { return il2cpp::utils::StringUtils::Hash(eventInfo->name); } }; struct Il2CppEventInfoCompare { bool operator()(const EventInfo* event1, const EventInfo* event2) const { // You can't overload events return strcmp(event1->name, event2->name) == 0; } }; struct PropertyPair { const PropertyInfo *property; Il2CppClass* originalType; PropertyPair(const PropertyInfo *property, Il2CppClass* originalType) : property(property), originalType(originalType) { } }; typedef std::vector PropertyPairVector; typedef Il2CppHashMap EventMap; bool MonoType::PropertyEqual(const PropertyInfo* prop1, const PropertyInfo* prop2) { // Name check is not enough, property can be overloaded if (strcmp(prop1->name, prop2->name) != 0) return false; return vm::Method::IsSameOverloadSignature(prop1, prop2); } static bool PropertyPairVectorContains(const PropertyPairVector& properties, const PropertyInfo* property) { for (PropertyPairVector::const_iterator it = properties.begin(), end = properties.end(); it != end; ++it) if (MonoType::PropertyEqual(it->property, property)) return true; return false; } static inline bool IsPublic(const FieldInfo* field) { return (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC; } static inline bool IsPrivate(const FieldInfo* field) { return (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PRIVATE; } static inline bool IsStatic(const FieldInfo* field) { return (field->type->attrs & FIELD_ATTRIBUTE_STATIC) != 0; } static inline bool IsPublic(const PropertyInfo* property) { if (property->get != NULL && (property->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) return true; if (property->set != NULL && (property->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) return true; return false; } static inline bool IsPrivate(const PropertyInfo* property) { if (property->get != NULL && (property->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) return false; if (property->set != NULL && (property->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) return false; return true; } static inline bool IsStatic(const PropertyInfo* property) { if (property->get != NULL) return (property->get->flags & METHOD_ATTRIBUTE_STATIC) != 0; if (property->set != NULL) return (property->set->flags & METHOD_ATTRIBUTE_STATIC) != 0; return false; } static inline bool IsPublic(const MethodInfo* method) { return (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC; } static inline bool IsPrivate(const MethodInfo* method) { return (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE; } static inline bool IsStatic(const MethodInfo* method) { return (method->flags & METHOD_ATTRIBUTE_STATIC) != 0; } // From MSDN: An event is considered public to reflection if it has at least one method or accessor that is public. static inline bool IsPublic(const EventInfo* event) { if (event->add != NULL && (event->add->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) return true; if (event->remove != NULL && (event->remove->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) return true; if (event->raise != NULL && (event->raise->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) return true; return false; } static inline bool IsPrivate(const EventInfo* event) { if (event->add != NULL && (event->add->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) return false; if (event->remove != NULL && (event->remove->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) return false; if (event->raise != NULL && (event->raise->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) return false; return true; } static inline bool IsStatic(const EventInfo* event) { if (event->add != NULL) return (event->add->flags & METHOD_ATTRIBUTE_STATIC) != 0; if (event->remove != NULL) return (event->remove->flags & METHOD_ATTRIBUTE_STATIC) != 0; if (event->raise != NULL) return (event->raise->flags & METHOD_ATTRIBUTE_STATIC) != 0; return false; } template static bool CheckMemberMatch(const MemberInfo* member, const Il2CppClass* type, const Il2CppClass* originalType, int32_t bindingFlags, const NameFilter& nameFilter) { uint32_t accessBindingFlag = IsPublic(member) ? BFLAGS_Public : BFLAGS_NonPublic; if ((bindingFlags & accessBindingFlag) == 0) return false; if (type != originalType && IsPrivate(member)) // Private members are not part of derived class return false; if (IsStatic(member)) { if ((bindingFlags & BFLAGS_Static) == 0) return false; if ((bindingFlags & BFLAGS_FlattenHierarchy) == 0 && type != originalType) return false; } else if ((bindingFlags & BFLAGS_Instance) == 0) { return false; } if (!nameFilter(member->name)) return false; return true; } static inline bool ValidBindingFlagsForGetMember(uint32_t bindingFlags) { return (bindingFlags & BFLAGS_Static) != 0 || (bindingFlags & BFLAGS_Instance) != 0; } Il2CppReflectionAssembly* MonoType::get_Assembly(Il2CppReflectionType* type) { Il2CppClass* klass = Class::FromIl2CppType(type->type); return il2cpp::vm::Reflection::GetAssemblyObject(MetadataCache::GetAssemblyFromIndex(klass->image->assemblyIndex)); } int MonoType::get_attributes(Il2CppReflectionType *type) { Il2CppClass *klass = Class::FromSystemType(type); return klass->flags; } int MonoType::GetArrayRank(Il2CppReflectionType *type) { if (type->type->type != IL2CPP_TYPE_ARRAY && type->type->type != IL2CPP_TYPE_SZARRAY) IL2CPP_ASSERT("Type must be an array type"); Il2CppClass* klass = Class::FromIl2CppType(type->type); return klass->rank; } Il2CppReflectionType* MonoType::get_DeclaringType(Il2CppReflectionMonoType *monoType) { return vm::Type::GetDeclaringType(monoType->GetIl2CppType()); } bool MonoType::IsGenericParameter(const Il2CppType *type) { return !type->byref && (type->type == IL2CPP_TYPE_VAR || type->type == IL2CPP_TYPE_MVAR); } bool MonoType::get_IsGenericParameter(Il2CppReflectionType* type) { return IsGenericParameter(type->type); } Il2CppReflectionModule* MonoType::get_Module(Il2CppReflectionType* type) { Il2CppClass* klass = Class::FromIl2CppType(type->type); return il2cpp::vm::Reflection::GetModuleObject(klass->image); } Il2CppString * MonoType::get_Name(Il2CppReflectionType * type) { Il2CppClass* typeInfo = Class::FromIl2CppType(type->type); if (type->type->byref) { std::string n = il2cpp::utils::StringUtils::Printf("%s&", typeInfo->name); return String::New(n.c_str()); } else { return il2cpp::vm::String::NewWrapper(typeInfo->name); } } Il2CppString * MonoType::get_Namespace(Il2CppReflectionType *type) { Il2CppClass* typeInfo = Class::FromIl2CppType(type->type); while (Il2CppClass* declaringType = Class::GetDeclaringType(typeInfo)) typeInfo = declaringType; if (typeInfo->namespaze[0] == '\0') return NULL; else return il2cpp::vm::String::NewWrapper(typeInfo->namespaze); } Il2CppReflectionType * MonoType::get_BaseType(Il2CppReflectionType * type) { Il2CppClass* klass = Class::FromIl2CppType(type->type); return klass->parent ? il2cpp::vm::Reflection::GetTypeObject(klass->parent->byval_arg) : NULL; } Il2CppArray* MonoType::GetConstructors_internal(Il2CppReflectionType* type, int32_t bflags, Il2CppReflectionType *reftype) { static Il2CppClass *System_Reflection_ConstructorInfo = NULL; Il2CppClass *startklass, *klass, *refklass; Il2CppArray *res; const MethodInfo *method; int match; void* iter = NULL; typedef std::vector > MethodPairVector; MethodPairVector tmp_vec; if (type->type->byref) return il2cpp::vm::Array::NewCached(il2cpp_defaults.method_info_class, 0); klass = startklass = Class::FromIl2CppType(type->type); refklass = Class::FromIl2CppType(reftype->type); if (!System_Reflection_ConstructorInfo) System_Reflection_ConstructorInfo = Class::FromName(il2cpp_defaults.corlib, "System.Reflection", "ConstructorInfo"); iter = NULL; while ((method = Class::GetMethods(klass, &iter))) { match = 0; if (strcmp(method->name, ".ctor") && strcmp(method->name, ".cctor")) continue; if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) { if (bflags & BFLAGS_Public) match++; } else { if (bflags & BFLAGS_NonPublic) match++; } if (!match) continue; match = 0; if (method->flags & METHOD_ATTRIBUTE_STATIC) { if (bflags & BFLAGS_Static) if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass)) match++; } else { if (bflags & BFLAGS_Instance) match++; } if (!match) continue; tmp_vec.push_back(std::make_pair(method, refklass)); } res = il2cpp::vm::Array::NewCached(System_Reflection_ConstructorInfo, (il2cpp_array_size_t)tmp_vec.size()); for (size_t i = 0; i < tmp_vec.size(); ++i) il2cpp_array_setref(res, i, (Il2CppObject*)Reflection::GetMethodObject(tmp_vec[i].first, tmp_vec[i].second)); return res; } mscorlib_System_Reflection_MethodInfo * MonoType::GetCorrespondingInflatedMethod(Il2CppReflectionMonoType *, Il2CppReflectionMonoType *) { NOT_SUPPORTED_IL2CPP(MonoType::GetCorrespondingInflatedMethod, "This icall is only used by System.Reflection.Emit.TypeBuilder."); return 0; } Il2CppReflectionType* MonoType::GetElementType(Il2CppReflectionType * type) { Il2CppClass *klass; klass = Class::FromIl2CppType(type->type); // GetElementType should only return a type for: // Array Pointer PassedByRef if (type->type->byref) return il2cpp::vm::Reflection::GetTypeObject(klass->byval_arg); else if (klass->element_class && IL2CPP_CLASS_IS_ARRAY(klass)) return il2cpp::vm::Reflection::GetTypeObject(klass->element_class->byval_arg); else if (klass->element_class && type->type->type == IL2CPP_TYPE_PTR) return il2cpp::vm::Reflection::GetTypeObject(klass->element_class->byval_arg); else return NULL; } template static inline Il2CppReflectionField* GetFieldFromType(Il2CppClass* type, Il2CppClass* const originalType, int32_t bindingFlags, const NameFilter& nameFilter) { void* iter = NULL; while (FieldInfo* field = Class::GetFields(type, &iter)) { if (CheckMemberMatch(field, type, originalType, bindingFlags, nameFilter)) { return Reflection::GetFieldObject(originalType, field); } } return NULL; } template static Il2CppReflectionField* GetFieldImpl(Il2CppClass* type, int32_t bindingFlags, const NameFilter& nameFilter) { Il2CppReflectionField* field = GetFieldFromType(type, type, bindingFlags, nameFilter); if (field == NULL && (bindingFlags & BFLAGS_DeclaredOnly) == 0) { Il2CppClass* const originalType = type; type = Class::GetParent(type); while (field == NULL && type != NULL) { field = GetFieldFromType(type, originalType, bindingFlags, nameFilter); type = Class::GetParent(type); } } return field; } Il2CppReflectionField* MonoType::GetField(Il2CppReflectionType* _this, Il2CppString* name, int32_t bindingFlags) { using namespace utils; using namespace utils::functional; if (_this->type->byref) return NULL; Il2CppClass* type = Class::FromIl2CppType(_this->type); if (bindingFlags & BFLAGS_IgnoreCase) { return GetFieldImpl(type, bindingFlags, Filter(StringUtils::Utf16ToUtf8(name->chars))); } return GetFieldImpl(type, bindingFlags, Filter(StringUtils::Utf16ToUtf8(name->chars))); } template static inline void CollectTypeFields(Il2CppClass* type, const Il2CppClass* const originalType, int32_t bindingFlags, std::vector& fields, const NameFilter& nameFilter) { void* iterator = NULL; FieldInfo* field = NULL; while ((field = Class::GetFields(type, &iterator)) != NULL) { if (CheckMemberMatch(field, type, originalType, bindingFlags, nameFilter)) fields.push_back(field); } } template static inline Il2CppArray* GetFieldsImpl(Il2CppReflectionType* _this, int bindingFlags, Il2CppReflectionType* reflectedType, const NameFilter& nameFilter) { if (reflectedType->type->byref || !ValidBindingFlagsForGetMember(bindingFlags)) return Array::New(il2cpp_defaults.field_info_class, 0); std::vector fields; Il2CppClass* typeInfo = Class::FromIl2CppType(reflectedType->type); Il2CppClass* const originalType = typeInfo; CollectTypeFields(typeInfo, typeInfo, bindingFlags, fields, nameFilter); if ((bindingFlags & BFLAGS_DeclaredOnly) == 0) { typeInfo = typeInfo->parent; while (typeInfo != NULL) { CollectTypeFields(typeInfo, originalType, bindingFlags, fields, nameFilter); typeInfo = typeInfo->parent; } } size_t fieldCount = fields.size(); Il2CppArray* result = Array::NewCached(il2cpp_defaults.field_info_class, (il2cpp_array_size_t)fieldCount); for (size_t i = 0; i < fieldCount; i++) { il2cpp_array_setref(result, i, Reflection::GetFieldObject(originalType, fields[i])); } return result; } Il2CppArray* MonoType::GetFields_internal(Il2CppReflectionType* _this, int bindingFlags, Il2CppReflectionType* reflectedType) { return GetFieldsImpl(_this, bindingFlags, reflectedType, utils::functional::TrueFilter()); } Il2CppArray* MonoType::GetFieldsByName(Il2CppReflectionType* _this, Il2CppString* name, int bindingFlags, Il2CppReflectionType* reflectedType) { using namespace utils; using namespace utils::functional; if (name == NULL) return GetFieldsImpl(_this, bindingFlags, reflectedType, utils::functional::TrueFilter()); if (bindingFlags & BFLAGS_IgnoreCase) { return GetFieldsImpl(_this, bindingFlags, reflectedType, Filter(StringUtils::Utf16ToUtf8(name->chars))); } return GetFieldsImpl(_this, bindingFlags, reflectedType, Filter(StringUtils::Utf16ToUtf8(name->chars))); } Il2CppString * MonoType::getFullName(Il2CppReflectionType * type, bool full_name, bool assembly_qualified) { Il2CppTypeNameFormat format; if (full_name) format = assembly_qualified ? IL2CPP_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : IL2CPP_TYPE_NAME_FORMAT_FULL_NAME; else format = IL2CPP_TYPE_NAME_FORMAT_REFLECTION; std::string name(Type::GetName(type->type, format)); if (name.empty()) return NULL; if (full_name && (type->type->type == IL2CPP_TYPE_VAR || type->type->type == IL2CPP_TYPE_MVAR)) { return NULL; } return il2cpp::vm::String::NewWrapper(name.c_str()); } Il2CppArray * MonoType::GetGenericArguments(Il2CppReflectionType* type) { return vm::Type::GetGenericArgumentsInternal(type, false); } Il2CppArray* MonoType::GetInterfaces(Il2CppReflectionType* type) { Il2CppClass* klass = Class::FromIl2CppType(type->type); typedef std::set InterfaceVector; InterfaceVector itfs; Il2CppClass* currentType = klass; while (currentType != NULL) { void* iter = NULL; while (Il2CppClass* itf = Class::GetInterfaces(currentType, &iter)) itfs.insert(itf); currentType = Class::GetParent(currentType); } Il2CppArray* res = Array::New(il2cpp_defaults.systemtype_class, (il2cpp_array_size_t)itfs.size()); int i = 0; for (InterfaceVector::const_iterator iter = itfs.begin(); iter != itfs.end(); ++iter, ++i) il2cpp_array_setref(res, i, Reflection::GetTypeObject((*iter)->byval_arg)); return res; } static bool method_public(MethodInfo* method) { return (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC; } bool MonoType::MethodNonPublic(const MethodInfo* method, bool start_klass) { switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) { case METHOD_ATTRIBUTE_ASSEM: return (start_klass || il2cpp_defaults.generic_ilist_class); case METHOD_ATTRIBUTE_PRIVATE: return start_klass; case METHOD_ATTRIBUTE_PUBLIC: return false; default: return true; } } static bool method_rt_special_name(MethodInfo* method) { return (method->flags & METHOD_ATTRIBUTE_RESERVED_MASK) == METHOD_ATTRIBUTE_RT_SPECIAL_NAME; } static bool method_static(MethodInfo* method) { return (method->flags & METHOD_ATTRIBUTE_STATIC) != 0; } template void CollectTypeMethods(Il2CppClass* type, const Il2CppClass* originalType, uint32_t bindingFlags, const NameFilter& nameFilter, std::vector& methods, bool(&filledSlots)[65535]) { void* iter = NULL; while (const MethodInfo* method = Class::GetMethods(type, &iter)) { if ((method->flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME) != 0 && (strcmp(method->name, ".ctor") == 0 || strcmp(method->name, ".cctor") == 0)) continue; if (CheckMemberMatch(method, type, originalType, bindingFlags, nameFilter)) { if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) != 0) { if (filledSlots[method->slot]) continue; filledSlots[method->slot] = true; } methods.push_back(method); } } } template static Il2CppArray* GetMethodsByNameImpl(const Il2CppType* type, uint32_t bindingFlags, const NameFilter& nameFilter) { std::vector methods; bool filledSlots[65535] = { 0 }; Il2CppClass* typeInfo = Class::FromIl2CppType(type); Il2CppClass* const originalTypeInfo = typeInfo; CollectTypeMethods(typeInfo, typeInfo, bindingFlags, nameFilter, methods, filledSlots); if ((bindingFlags & BFLAGS_DeclaredOnly) == 0) { for (typeInfo = Class::GetParent(typeInfo); typeInfo != NULL; typeInfo = Class::GetParent(typeInfo)) { CollectTypeMethods(typeInfo, originalTypeInfo, bindingFlags, nameFilter, methods, filledSlots); } } size_t methodCount = methods.size(); Il2CppArray* result = Array::NewCached(il2cpp_defaults.method_info_class, (il2cpp_array_size_t)methodCount); for (size_t i = 0; i < methodCount; i++) { Il2CppReflectionMethod* method = Reflection::GetMethodObject(methods[i], originalTypeInfo); il2cpp_array_setref(result, i, method); } return result; } Il2CppArray* MonoType::GetMethodsByName(Il2CppReflectionType* _this, Il2CppString* name, int bindingFlags, bool ignoreCase, Il2CppReflectionType* type) { using namespace utils; using namespace utils::functional; if (type->type->byref || !ValidBindingFlagsForGetMember(bindingFlags)) return Array::NewCached(il2cpp_defaults.property_info_class, 0); if (name != NULL) { if (ignoreCase) { return GetMethodsByNameImpl(type->type, bindingFlags, Filter(StringUtils::Utf16ToUtf8(name->chars))); } return GetMethodsByNameImpl(type->type, bindingFlags, Filter(StringUtils::Utf16ToUtf8(name->chars))); } return GetMethodsByNameImpl(type->type, bindingFlags, TrueFilter()); } template static void CollectTypeProperties(Il2CppClass* type, uint32_t bindingFlags, const NameFilter& nameFilter, Il2CppClass* const originalType, PropertyPairVector& properties) { void* iter = NULL; while (const PropertyInfo* property = Class::GetProperties(type, &iter)) { if (CheckMemberMatch(property, type, originalType, bindingFlags, nameFilter)) { if (PropertyPairVectorContains(properties, property)) continue; properties.push_back(PropertyPair(property, originalType)); } } } template static Il2CppArray* GetPropertiesByNameImpl(const Il2CppType* type, uint32_t bindingFlags, const NameFilter& nameFilter) { PropertyPairVector properties; Il2CppClass* typeInfo = Class::FromIl2CppType(type); Il2CppClass* const originalTypeInfo = typeInfo; properties.reserve(typeInfo->property_count); CollectTypeProperties(typeInfo, bindingFlags, nameFilter, originalTypeInfo, properties); if ((bindingFlags & BFLAGS_DeclaredOnly) == 0) { for (typeInfo = typeInfo->parent; typeInfo != NULL; typeInfo = typeInfo->parent) { CollectTypeProperties(typeInfo, bindingFlags, nameFilter, originalTypeInfo, properties); } } int i = 0; Il2CppArray* res = Array::NewCached(il2cpp_defaults.property_info_class, (il2cpp_array_size_t)properties.size()); for (PropertyPairVector::const_iterator iter = properties.begin(); iter != properties.end(); iter++) { il2cpp_array_setref(res, i, Reflection::GetPropertyObject(iter->originalType, iter->property)); i++; } return res; } Il2CppArray* MonoType::GetPropertiesByName(Il2CppReflectionType* _this, Il2CppString* name, uint32_t bindingFlags, bool ignoreCase, Il2CppReflectionType* type) { using namespace utils; using namespace utils::functional; if (type->type->byref || !ValidBindingFlagsForGetMember(bindingFlags)) return Array::NewCached(il2cpp_defaults.property_info_class, 0); if (name != NULL) { if (ignoreCase) { return GetPropertiesByNameImpl(type->type, bindingFlags, Filter(StringUtils::Utf16ToUtf8(name->chars))); } return GetPropertiesByNameImpl(type->type, bindingFlags, Filter(StringUtils::Utf16ToUtf8(name->chars))); } return GetPropertiesByNameImpl(type->type, bindingFlags, TrueFilter()); } bool MonoType::IsByRefImpl(Il2CppReflectionType* type) { return type->type->byref; } bool MonoType::IsCOMObjectImpl(Il2CppReflectionMonoType *) { return false; // il2cpp does not support COM objects, so this is always false } bool MonoType::IsPointerImpl(Il2CppReflectionType* type) { return type->type->type == IL2CPP_TYPE_PTR; } bool MonoType::IsPrimitiveImpl(Il2CppReflectionType *type) { return (!type->type->byref && (((type->type->type >= IL2CPP_TYPE_BOOLEAN) && (type->type->type <= IL2CPP_TYPE_R8)) || (type->type->type == IL2CPP_TYPE_I) || (type->type->type == IL2CPP_TYPE_U))); } template static inline Il2CppReflectionEvent* GetEventFromType(Il2CppClass* const type, Il2CppClass* const originalType, int32_t bindingFlags, const NameFilter& nameFilter) { void* iter = NULL; while (const EventInfo* event = Class::GetEvents(type, &iter)) { if (CheckMemberMatch(event, type, originalType, bindingFlags, nameFilter)) { return Reflection::GetEventObject(originalType, event); } } return NULL; } template static Il2CppReflectionEvent* GetEventImpl(Il2CppClass* type, int32_t bindingFlags, const NameFilter& nameFilter) { Il2CppReflectionEvent* event = GetEventFromType(type, type, bindingFlags, nameFilter); if (event == NULL && (bindingFlags & BFLAGS_DeclaredOnly) == 0) { Il2CppClass* const originalType = type; type = type->parent; while (event == NULL && type != NULL) { event = GetEventFromType(type, originalType, bindingFlags, nameFilter); type = type->parent; } } return event; } Il2CppReflectionEvent* MonoType::InternalGetEvent(Il2CppReflectionType* _this, Il2CppString* name, int32_t bindingFlags) { using namespace utils; using namespace utils::functional; if (_this->type->byref || !ValidBindingFlagsForGetMember(bindingFlags)) return NULL; Il2CppClass* type = Class::FromIl2CppType(_this->type); if (bindingFlags & BFLAGS_IgnoreCase) { return GetEventImpl(type, bindingFlags, Filter(StringUtils::Utf16ToUtf8(name->chars))); } return GetEventImpl(type, bindingFlags, Filter(StringUtils::Utf16ToUtf8(name->chars))); } template static inline void CollectTypeEvents(Il2CppClass* type, Il2CppClass* const originalType, int32_t bindingFlags, EventMap& events, const NameFilter& nameFilter) { void* iter = NULL; while (const EventInfo* event = Class::GetEvents(type, &iter)) { if (CheckMemberMatch(event, type, originalType, bindingFlags, nameFilter)) { if (events.find(event) != events.end()) continue; events[event] = originalType; } } } template static inline Il2CppArray* GetEventsImpl(Il2CppReflectionType* type, int bindingFlags, Il2CppReflectionType* reflectedType, const NameFilter& nameFilter) { if (type->type->byref || !ValidBindingFlagsForGetMember(bindingFlags)) return Array::New(il2cpp_defaults.event_info_class, 0); EventMap events; Il2CppClass* typeInfo = Class::FromIl2CppType(type->type); CollectTypeEvents(typeInfo, typeInfo, bindingFlags, events, nameFilter); if ((bindingFlags & BFLAGS_DeclaredOnly) == 0) { Il2CppClass* const originalType = typeInfo; typeInfo = Class::GetParent(typeInfo); while (typeInfo != NULL) { CollectTypeEvents(typeInfo, originalType, bindingFlags, events, nameFilter); typeInfo = Class::GetParent(typeInfo); } } int i = 0; Il2CppArray* result = Array::NewCached(il2cpp_defaults.event_info_class, (il2cpp_array_size_t)events.size()); for (EventMap::const_iterator iter = events.begin(); iter != events.end(); iter++) { il2cpp_array_setref(result, i, Reflection::GetEventObject(iter->second, iter->first.key)); i++; } return result; } Il2CppArray* MonoType::GetEvents_internal(Il2CppReflectionType* _this, int32_t bindingFlags, Il2CppReflectionType* type) { return GetEventsImpl(_this, bindingFlags, type, utils::functional::TrueFilter()); } Il2CppArray* MonoType::GetEventsByName(Il2CppReflectionType* _this, Il2CppString* name, int bindingFlags, Il2CppReflectionType* reflectedType) { using namespace utils; using namespace utils::functional; if (name == NULL) return GetEventsImpl(_this, bindingFlags, reflectedType, utils::functional::TrueFilter()); if (bindingFlags & BFLAGS_IgnoreCase) { return GetEventsImpl(_this, bindingFlags, reflectedType, Filter(StringUtils::Utf16ToUtf8(name->chars))); } return GetEventsImpl(_this, bindingFlags, reflectedType, Filter(StringUtils::Utf16ToUtf8(name->chars))); } void MonoType::type_from_obj(void* /* System.MonoType */ type, Il2CppObject* obj) { NOT_SUPPORTED_IL2CPP(MonoType::type_from_obj, "This icall is only used by System.MonoType constructor, which throws NotImplementedException right after this call."); } void* /* System.Reflection.ConstructorInfo */ MonoType::GetCorrespondingInflatedConstructor(void* /* System.MonoType */ self, void* /* System.Reflection.ConstructorInfo */ genericInfo) { NOT_SUPPORTED_IL2CPP(MonoType::GetCorrespondingInflatedConstructor, "This icall is only used by System.Reflection.Emit.TypeBuilder."); return 0; } static inline bool CheckNestedTypeMatch(Il2CppClass* nestedType, BindingFlags bindingFlags) { uint32_t accessFlag = (nestedType->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC ? BFLAGS_Public : BFLAGS_NonPublic; return (accessFlag & bindingFlags) != 0; } template Il2CppReflectionType* GetNestedTypeImpl(Il2CppClass* typeInfo, BindingFlags bindingFlags, const NameFilter& nameFilter) { void* iter = NULL; while (Il2CppClass* nestedType = Class::GetNestedTypes(typeInfo, &iter)) { if (CheckNestedTypeMatch(nestedType, bindingFlags) && nameFilter(nestedType->name)) return Reflection::GetTypeObject(nestedType->byval_arg); } return NULL; } Il2CppReflectionType* MonoType::GetNestedType(Il2CppReflectionType* type, Il2CppString* name, BindingFlags bindingFlags) { using namespace utils; using namespace utils::functional; bool validBindingFlags = (bindingFlags & BFLAGS_NonPublic) != 0 || (bindingFlags & BFLAGS_Public) != 0; if (type->type->byref || !validBindingFlags) return NULL; Il2CppClass* typeInfo = Class::FromIl2CppType(type->type); // nested types are always generic type definitions, even for inflated types. As such we only store/retrieve them on // type definitions and generic type definitions. If we are a generic instance, use our generic type definition instead. if (typeInfo->generic_class) typeInfo = GenericClass::GetTypeDefinition(typeInfo->generic_class); if (bindingFlags & BFLAGS_IgnoreCase) { return GetNestedTypeImpl(typeInfo, bindingFlags, Filter(StringUtils::Utf16ToUtf8(name->chars))); } return GetNestedTypeImpl(typeInfo, bindingFlags, Filter(StringUtils::Utf16ToUtf8(name->chars))); } template static Il2CppArray* GetNestedTypesImpl(Il2CppReflectionType* type, int32_t bindingFlags, const NameFilter& nameFilter) { bool validBindingFlags = (bindingFlags & BFLAGS_NonPublic) != 0 || (bindingFlags & BFLAGS_Public) != 0; if (type->type->byref || !validBindingFlags) return Array::New(il2cpp_defaults.monotype_class, 0); Il2CppClass* typeInfo = Class::FromIl2CppType(type->type); // nested types are always generic type definitions, even for inflated types. As such we only store/retrieve them on // type definitions and generic type definitions. If we are a generic instance, use our generic type definition instead. if (typeInfo->generic_class) typeInfo = GenericClass::GetTypeDefinition(typeInfo->generic_class); std::vector nestedTypes; void* iter = NULL; while (Il2CppClass* nestedType = Class::GetNestedTypes(typeInfo, &iter)) { if (CheckNestedTypeMatch(nestedType, bindingFlags) && nameFilter(nestedType->name)) nestedTypes.push_back(nestedType); } size_t nestedTypeCount = nestedTypes.size(); Il2CppArray* result = Array::New(il2cpp_defaults.monotype_class, (il2cpp_array_size_t)nestedTypeCount); for (size_t i = 0; i < nestedTypeCount; i++) { il2cpp_array_setref(result, i, Reflection::GetTypeObject(nestedTypes[i]->byval_arg)); } return result; } Il2CppArray* MonoType::GetNestedTypesByName(Il2CppReflectionType* type, Il2CppString* name, int32_t bindingFlags) { using namespace utils; using namespace utils::functional; if (name == NULL) return GetNestedTypesImpl(type, bindingFlags, utils::functional::TrueFilter()); if (bindingFlags & BFLAGS_IgnoreCase) return GetNestedTypesImpl(type, bindingFlags, Filter(StringUtils::Utf16ToUtf8(name->chars))); return GetNestedTypesImpl(type, bindingFlags, Filter(StringUtils::Utf16ToUtf8(name->chars))); } Il2CppArray* MonoType::GetNestedTypes(Il2CppReflectionType* type, int32_t bindingFlags) { return GetNestedTypesImpl(type, bindingFlags, utils::functional::TrueFilter()); } void* /* System.Reflection.MethodBase */ MonoType::get_DeclaringMethod(void* /* System.MonoType */ self) { NOT_IMPLEMENTED_ICALL(MonoType::get_DeclaringMethod); return 0; } bool MonoType::PropertyAccessorNonPublic(const MethodInfo* accessor, bool start_klass) { if (!accessor) return false; return MethodNonPublic(accessor, start_klass); } } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/MonoType.h ================================================ #pragma once #include #include "il2cpp-config.h" struct mscorlib_System_Reflection_MethodInfo; struct Il2CppArray; struct Il2CppString; struct Il2CppReflectionAssembly; struct Il2CppReflectionField; struct Il2CppReflectionModule; struct Il2CppReflectionMonoType; struct Il2CppReflectionType; struct Il2CppReflectionEvent; typedef int32_t BindingFlags; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { enum { BFLAGS_IgnoreCase = 1, BFLAGS_DeclaredOnly = 2, BFLAGS_Instance = 4, BFLAGS_Static = 8, BFLAGS_Public = 0x10, BFLAGS_NonPublic = 0x20, BFLAGS_FlattenHierarchy = 0x40, BFLAGS_InvokeMethod = 0x100, BFLAGS_CreateInstance = 0x200, BFLAGS_GetField = 0x400, BFLAGS_SetField = 0x800, BFLAGS_GetProperty = 0x1000, BFLAGS_SetProperty = 0x2000, BFLAGS_ExactBinding = 0x10000, BFLAGS_SuppressChangeType = 0x20000, BFLAGS_OptionalParamBinding = 0x40000 }; class LIBIL2CPP_CODEGEN_API MonoType { public: static Il2CppString* getFullName(Il2CppReflectionType* type, bool full_name, bool assembly_qualified); static Il2CppArray* GetFields_internal(Il2CppReflectionType* _this, int, Il2CppReflectionType* reflectedType); static Il2CppArray* GetFieldsByName(Il2CppReflectionType* _this, Il2CppString* name, int, Il2CppReflectionType* reflectedType); static int GetArrayRank(Il2CppReflectionType* type); static Il2CppArray* GetConstructors_internal(Il2CppReflectionType* type, int32_t bflags, Il2CppReflectionType* reftype); static void* /* System.Reflection.ConstructorInfo */ GetCorrespondingInflatedConstructor(void* /* System.MonoType */ self, void* /* System.Reflection.ConstructorInfo */ genericInfo); static mscorlib_System_Reflection_MethodInfo* GetCorrespondingInflatedMethod(Il2CppReflectionMonoType* , Il2CppReflectionMonoType*); static Il2CppReflectionType* GetElementType(Il2CppReflectionType* type); static Il2CppArray* GetEvents_internal(Il2CppReflectionType* thisPtr, int32_t bindingFlags, Il2CppReflectionType* type); static Il2CppArray* GetEventsByName(Il2CppReflectionType* _this, Il2CppString* name, int bindingFlags, Il2CppReflectionType* reflectedType); static Il2CppReflectionField* GetField(Il2CppReflectionType* _this, Il2CppString* name, int32_t bindingFlags); static Il2CppArray* GetGenericArguments(Il2CppReflectionType* type); static Il2CppArray* GetInterfaces(Il2CppReflectionType* type); static Il2CppArray* GetMethodsByName(Il2CppReflectionType* _this, Il2CppString* name, int bindingFlags, bool ignoreCase, Il2CppReflectionType* type); static Il2CppReflectionType* GetNestedType(Il2CppReflectionType* type, Il2CppString* name, BindingFlags bindingFlags); static Il2CppArray* GetNestedTypesByName(Il2CppReflectionType* type, Il2CppString* name, int32_t bindingAttr); static Il2CppArray* GetNestedTypes(Il2CppReflectionType* type, int32_t bindingAttr); static Il2CppArray* GetPropertiesByName(Il2CppReflectionType* _this, Il2CppString* name, uint32_t bindingFlags, bool ignoreCase, Il2CppReflectionType* type); static Il2CppReflectionEvent* InternalGetEvent(Il2CppReflectionType* _this, Il2CppString* name, int32_t bindingFlags); static bool IsByRefImpl(Il2CppReflectionType* type); static bool IsCOMObjectImpl(Il2CppReflectionMonoType*); static bool IsPointerImpl(Il2CppReflectionType* type); static Il2CppReflectionAssembly* get_Assembly(Il2CppReflectionType*); static Il2CppReflectionType* get_BaseType(Il2CppReflectionType* type); static void* /* System.Reflection.MethodBase */ get_DeclaringMethod(void* /* System.MonoType */ self); static Il2CppReflectionType* get_DeclaringType(Il2CppReflectionMonoType*); static bool get_IsGenericParameter(Il2CppReflectionType*); static bool IsGenericParameter(const Il2CppType *type); static Il2CppReflectionModule* get_Module(Il2CppReflectionType* thisPtr); static Il2CppString* get_Name(Il2CppReflectionType* type); static Il2CppString* get_Namespace(Il2CppReflectionType* type); static int get_attributes(Il2CppReflectionType* type); static void type_from_obj(void* /* System.MonoType */ type, Il2CppObject* obj); static bool IsPrimitiveImpl(Il2CppReflectionType*); static bool PropertyEqual(const PropertyInfo* prop1, const PropertyInfo* prop2); static bool PropertyAccessorNonPublic(const MethodInfo* accessor, bool start_klass); static bool MethodNonPublic(const MethodInfo* method, bool start_klass); }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Number.cpp ================================================ // The MIT License(MIT) // // Copyright(c) Unity Technologies, Microsoft Corporation // // 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_4_0 #include "il2cpp-config.h" #include "Number.h" #include "utils/StringUtils.h" #include #define NUMBER_MAXDIGITS 50 struct NUMBER { int precision; int scale; int sign; Il2CppChar digits[NUMBER_MAXDIGITS + 1]; Il2CppChar* allDigits; NUMBER() : precision(0), scale(0), sign(0), allDigits(NULL) { } }; struct FPDOUBLE { #if IL2CPP_BYTE_ORDER == IL2CPP_BIG_ENDIAN unsigned int sign : 1; unsigned int exp : 11; unsigned int mantHi : 20; unsigned int mantLo; #else unsigned int mantLo; unsigned int mantHi : 20; unsigned int exp : 11; unsigned int sign : 1; #endif }; // // precomputed tables with powers of 10. These allows us to do at most // two Mul64 during the conversion. This is important not only // for speed, but also for precision because of Mul64 computes with 1 bit error. // static const uint64_t rgval64Power10[] = { // powers of 10 /*1*/ 0xa000000000000000ULL, /*2*/ 0xc800000000000000ULL, /*3*/ 0xfa00000000000000ULL, /*4*/ 0x9c40000000000000ULL, /*5*/ 0xc350000000000000ULL, /*6*/ 0xf424000000000000ULL, /*7*/ 0x9896800000000000ULL, /*8*/ 0xbebc200000000000ULL, /*9*/ 0xee6b280000000000ULL, /*10*/ 0x9502f90000000000ULL, /*11*/ 0xba43b74000000000ULL, /*12*/ 0xe8d4a51000000000ULL, /*13*/ 0x9184e72a00000000ULL, /*14*/ 0xb5e620f480000000ULL, /*15*/ 0xe35fa931a0000000ULL, // powers of 0.1 /*1*/ 0xcccccccccccccccdULL, /*2*/ 0xa3d70a3d70a3d70bULL, /*3*/ 0x83126e978d4fdf3cULL, /*4*/ 0xd1b71758e219652eULL, /*5*/ 0xa7c5ac471b478425ULL, /*6*/ 0x8637bd05af6c69b7ULL, /*7*/ 0xd6bf94d5e57a42beULL, /*8*/ 0xabcc77118461ceffULL, /*9*/ 0x89705f4136b4a599ULL, /*10*/ 0xdbe6fecebdedd5c2ULL, /*11*/ 0xafebff0bcb24ab02ULL, /*12*/ 0x8cbccc096f5088cfULL, /*13*/ 0xe12e13424bb40e18ULL, /*14*/ 0xb424dc35095cd813ULL, /*15*/ 0x901d7cf73ab0acdcULL, }; static const int8_t rgexp64Power10[] = { // exponents for both powers of 10 and 0.1 /*1*/ 4, /*2*/ 7, /*3*/ 10, /*4*/ 14, /*5*/ 17, /*6*/ 20, /*7*/ 24, /*8*/ 27, /*9*/ 30, /*10*/ 34, /*11*/ 37, /*12*/ 40, /*13*/ 44, /*14*/ 47, /*15*/ 50, }; static const uint64_t rgval64Power10By16[] = { // powers of 10^16 /*1*/ 0x8e1bc9bf04000000ULL, /*2*/ 0x9dc5ada82b70b59eULL, /*3*/ 0xaf298d050e4395d6ULL, /*4*/ 0xc2781f49ffcfa6d4ULL, /*5*/ 0xd7e77a8f87daf7faULL, /*6*/ 0xefb3ab16c59b14a0ULL, /*7*/ 0x850fadc09923329cULL, /*8*/ 0x93ba47c980e98cdeULL, /*9*/ 0xa402b9c5a8d3a6e6ULL, /*10*/ 0xb616a12b7fe617a8ULL, /*11*/ 0xca28a291859bbf90ULL, /*12*/ 0xe070f78d39275566ULL, /*13*/ 0xf92e0c3537826140ULL, /*14*/ 0x8a5296ffe33cc92cULL, /*15*/ 0x9991a6f3d6bf1762ULL, /*16*/ 0xaa7eebfb9df9de8aULL, /*17*/ 0xbd49d14aa79dbc7eULL, /*18*/ 0xd226fc195c6a2f88ULL, /*19*/ 0xe950df20247c83f8ULL, /*20*/ 0x81842f29f2cce373ULL, /*21*/ 0x8fcac257558ee4e2ULL, // powers of 0.1^16 /*1*/ 0xe69594bec44de160ULL, /*2*/ 0xcfb11ead453994c3ULL, /*3*/ 0xbb127c53b17ec165ULL, /*4*/ 0xa87fea27a539e9b3ULL, /*5*/ 0x97c560ba6b0919b5ULL, /*6*/ 0x88b402f7fd7553abULL, /*7*/ 0xf64335bcf065d3a0ULL, /*8*/ 0xddd0467c64bce4c4ULL, /*9*/ 0xc7caba6e7c5382edULL, /*10*/ 0xb3f4e093db73a0b7ULL, /*11*/ 0xa21727db38cb0053ULL, /*12*/ 0x91ff83775423cc29ULL, /*13*/ 0x8380dea93da4bc82ULL, /*14*/ 0xece53cec4a314f00ULL, /*15*/ 0xd5605fcdcf32e217ULL, /*16*/ 0xc0314325637a1978ULL, /*17*/ 0xad1c8eab5ee43ba2ULL, /*18*/ 0x9becce62836ac5b0ULL, /*19*/ 0x8c71dcd9ba0b495cULL, /*20*/ 0xfd00b89747823938ULL, /*21*/ 0xe3e27a444d8d991aULL, }; static const int16_t rgexp64Power10By16[] = { // exponents for both powers of 10^16 and 0.1^16 /*1*/ 54, /*2*/ 107, /*3*/ 160, /*4*/ 213, /*5*/ 266, /*6*/ 319, /*7*/ 373, /*8*/ 426, /*9*/ 479, /*10*/ 532, /*11*/ 585, /*12*/ 638, /*13*/ 691, /*14*/ 745, /*15*/ 798, /*16*/ 851, /*17*/ 904, /*18*/ 957, /*19*/ 1010, /*20*/ 1064, /*21*/ 1117, }; #define Mul32x32To64(a, b) ((uint64_t)((uint32_t)(a)) * (uint64_t)((uint32_t)(b))) #ifdef _DEBUG // // slower high precision version of Mul64 for computation of the tables // static uint64_t Mul64Precise(uint64_t a, uint64_t b, int* pexp) { uint64_t hilo = ((Mul32x32To64(a >> 32, b) >> 1) + (Mul32x32To64(a, b >> 32) >> 1) + (Mul32x32To64(a, b) >> 33)) >> 30; uint64_t val = Mul32x32To64(a >> 32, b >> 32) + (hilo >> 1) + (hilo & 1); // normalize if ((val & 0x8000000000000000L) == 0) { val <<= 1; *pexp -= 1; } return val; } // // debug-only verification of the precomputed tables // static void CheckTable(uint64_t val, int exp, const void* table, int size, const char* name, int tabletype) { uint64_t multval = val; int mulexp = exp; bool fBad = false; for (int i = 0; i < size; i++) { switch (tabletype) { case 1: if (((uint64_t*)table)[i] != val) { if (!fBad) { fprintf(stderr, "%s:\n", name); fBad = true; } fprintf(stderr, "/*%d*/ I64(0x%llx),\n", i + 1, val); } break; case 2: if (((int8_t*)table)[i] != exp) { if (!fBad) { fprintf(stderr, "%s:\n", name); fBad = true; } fprintf(stderr, "/*%d*/ %d,\n", i + 1, exp); } break; case 3: if (((int16_t*)table)[i] != exp) { if (!fBad) { fprintf(stderr, "%s:\n", name); fBad = true; } fprintf(stderr, "/*%d*/ %d,\n", i + 1, exp); } break; default: IL2CPP_ASSERT(false); break; } exp += mulexp; val = Mul64Precise(val, multval, &exp); } IL2CPP_ASSERT(!fBad || !"NumberToDouble table not correct. Correct version dumped to stderr."); } void CheckTables() { uint64_t val; int exp; val = 0xa000000000000000L; exp = 4; // 10 CheckTable(val, exp, rgval64Power10, 15, "rgval64Power10", 1); CheckTable(val, exp, rgexp64Power10, 15, "rgexp64Power10", 2); val = 0x8e1bc9bf04000000L; exp = 54; //10^16 CheckTable(val, exp, rgval64Power10By16, 21, "rgval64Power10By16", 1); CheckTable(val, exp, rgexp64Power10By16, 21, "rgexp64Power10By16", 3); val = 0xCCCCCCCCCCCCCCCDL; exp = -3; // 0.1 CheckTable(val, exp, rgval64Power10 + 15, 15, "rgval64Power10 - inv", 1); val = 0xe69594bec44de160L; exp = -53; // 0.1^16 CheckTable(val, exp, rgval64Power10By16 + 21, 21, "rgval64Power10By16 - inv", 1); } #endif // _DEBUG namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { #define DECIMAL_NEG ((uint8_t)0x80) #define DECIMAL_PRECISION 29 #define DECIMAL_SCALE(dec) ((dec).u.u.scale) #define DECIMAL_SIGN(dec) ((dec).u.u.sign) #define DECIMAL_SIGNSCALE(dec) ((dec).u.signscale) #define DECIMAL_LO32(dec) ((dec).v.v.Lo32) #define DECIMAL_MID32(dec) ((dec).v.v.Mid32) #define DECIMAL_HI32(dec) ((dec).Hi32) static void DecShiftLeft(Il2CppDecimal* value) { unsigned int c0 = DECIMAL_LO32(*value) & 0x80000000 ? 1 : 0; unsigned int c1 = DECIMAL_MID32(*value) & 0x80000000 ? 1 : 0; IL2CPP_ASSERT(value != NULL); DECIMAL_LO32(*value) <<= 1; DECIMAL_MID32(*value) = DECIMAL_MID32(*value) << 1 | c0; DECIMAL_HI32(*value) = DECIMAL_HI32(*value) << 1 | c1; } static int D32AddCarry(uint32_t* value, uint32_t i) { uint32_t v = *value; uint32_t sum = v + i; *value = sum; return sum < v || sum < i ? 1 : 0; } static void DecAdd(Il2CppDecimal *value, Il2CppDecimal* d) { IL2CPP_ASSERT(value != NULL && d != NULL); if (D32AddCarry(&DECIMAL_LO32(*value), DECIMAL_LO32(*d))) { if (D32AddCarry(&DECIMAL_MID32(*value), 1)) { D32AddCarry(&DECIMAL_HI32(*value), 1); } } if (D32AddCarry(&DECIMAL_MID32(*value), DECIMAL_MID32(*d))) { D32AddCarry(&DECIMAL_HI32(*value), 1); } D32AddCarry(&DECIMAL_HI32(*value), DECIMAL_HI32(*d)); } static void DecMul10(Il2CppDecimal* value) { Il2CppDecimal d = *value; IL2CPP_ASSERT(value != NULL); DecShiftLeft(value); DecShiftLeft(value); DecAdd(value, &d); DecShiftLeft(value); } static void DecAddInt32(Il2CppDecimal* value, unsigned int i) { IL2CPP_ASSERT(value != NULL); if (D32AddCarry(&DECIMAL_LO32(*value), i)) { if (D32AddCarry(&DECIMAL_MID32(*value), 1)) { D32AddCarry(&DECIMAL_HI32(*value), 1); } } } bool Number::NumberBufferToDecimal(uint8_t* number, Il2CppDecimal* value) { IL2CPP_ASSERT(number != NULL); IL2CPP_ASSERT(value != NULL); NUMBER* numberStruct = (NUMBER*)number; Il2CppChar* p = numberStruct->digits; Il2CppDecimal d; int e = numberStruct->scale; d.reserved = 0; DECIMAL_SIGNSCALE(d) = 0; DECIMAL_HI32(d) = 0; DECIMAL_LO32(d) = 0; DECIMAL_MID32(d) = 0; IL2CPP_ASSERT(p != NULL); if (!*p) { // To avoid risking an app-compat issue with pre 4.5 (where some app was illegally using Reflection to examine the internal scale bits), we'll only force // the scale to 0 if the scale was previously positive if (e > 0) { e = 0; } } else { if (e > DECIMAL_PRECISION) return 0; while ((e > 0 || (*p && e > -28)) && (DECIMAL_HI32(d) < 0x19999999 || (DECIMAL_HI32(d) == 0x19999999 && (DECIMAL_MID32(d) < 0x99999999 || (DECIMAL_MID32(d) == 0x99999999 && (DECIMAL_LO32(d) < 0x99999999 || (DECIMAL_LO32(d) == 0x99999999 && *p <= '5'))))))) { DecMul10(&d); if (*p) DecAddInt32(&d, *p++ - '0'); e--; } if (*p++ >= '5') { bool round = true; if (*(p - 1) == '5' && *(p - 2) % 2 == 0) { // Check if previous digit is even, only if the when we are unsure whether hows to do Banker's rounding // For digits > 5 we will be roundinp up anyway. int count = 20; // Look at the next 20 digits to check to round while (*p == '0' && count != 0) { p++; count--; } if (*p == '\0' || count == 0) round = false;// Do nothing } if (round) { DecAddInt32(&d, 1); if ((DECIMAL_HI32(d) | DECIMAL_MID32(d) | DECIMAL_LO32(d)) == 0) { DECIMAL_HI32(d) = 0x19999999; DECIMAL_MID32(d) = 0x99999999; DECIMAL_LO32(d) = 0x9999999A; e++; } } } } if (e > 0) return 0; if (e <= -DECIMAL_PRECISION) { // Parsing a large scale zero can give you more precision than fits in the decimal. // This should only happen for actual zeros or very small numbers that round to zero. DECIMAL_SIGNSCALE(d) = 0; DECIMAL_HI32(d) = 0; DECIMAL_LO32(d) = 0; DECIMAL_MID32(d) = 0; DECIMAL_SCALE(d) = (DECIMAL_PRECISION - 1); } else { DECIMAL_SCALE(d) = (uint8_t)(-e); } DECIMAL_SIGN(d) = numberStruct->sign ? DECIMAL_NEG : 0; *value = d; return 1; } // // get 32-bit integer from at most 9 digits // static inline unsigned DigitsToInt(Il2CppChar* p, int count) { IL2CPP_ASSERT(1 <= count && count <= 9); Il2CppChar* end = p + count; unsigned res = *p - '0'; for (p = p + 1; p < end; p++) res = 10 * res + *p - '0'; return res; } static uint64_t Mul64Lossy(uint64_t a, uint64_t b, int* pexp) { // it's ok to losse some precision here - Mul64 will be called // at most twice during the conversion, so the error won't propagate // to any of the 53 significant bits of the result uint64_t val = Mul32x32To64(a >> 32, b >> 32) + (Mul32x32To64(a >> 32, b) >> 32) + (Mul32x32To64(a, b >> 32) >> 32); // normalize if ((val & 0x8000000000000000ULL) == 0) { val <<= 1; *pexp -= 1; } return val; } static inline void NumberToDouble(NUMBER* number, double* value) { uint64_t val; int exp; Il2CppChar* src = number->digits; int remaining; int total; int count; int scale; int absscale; int index; #ifdef _DEBUG static bool fCheckedTables = false; if (!fCheckedTables) { CheckTables(); fCheckedTables = true; } #endif // _DEBUG total = (int)utils::StringUtils::StrLen(src); remaining = total; // skip the leading zeros while (*src == '0') { remaining--; src++; } if (remaining == 0) { *value = 0; goto done; } count = std::min(remaining, 9); remaining -= count; val = DigitsToInt(src, count); if (remaining > 0) { count = std::min(remaining, 9); remaining -= count; // get the denormalized power of 10 uint32_t mult = (uint32_t)(rgval64Power10[count - 1] >> (64 - rgexp64Power10[count - 1])); val = Mul32x32To64(val, mult) + DigitsToInt(src + 9, count); } scale = number->scale - (total - remaining); absscale = abs(scale); if (absscale >= 22 * 16) { // overflow / underflow *(uint64_t*)value = (scale > 0) ? 0x7FF0000000000000ULL : 0; goto done; } exp = 64; // normalize the mantissa if ((val & 0xFFFFFFFF00000000ULL) == 0) { val <<= 32; exp -= 32; } if ((val & 0xFFFF000000000000ULL) == 0) { val <<= 16; exp -= 16; } if ((val & 0xFF00000000000000ULL) == 0) { val <<= 8; exp -= 8; } if ((val & 0xF000000000000000ULL) == 0) { val <<= 4; exp -= 4; } if ((val & 0xC000000000000000ULL) == 0) { val <<= 2; exp -= 2; } if ((val & 0x8000000000000000ULL) == 0) { val <<= 1; exp -= 1; } index = absscale & 15; if (index) { int multexp = rgexp64Power10[index - 1]; // the exponents are shared between the inverted and regular table exp += (scale < 0) ? (-multexp + 1) : multexp; uint64_t multval = rgval64Power10[index + ((scale < 0) ? 15 : 0) - 1]; val = Mul64Lossy(val, multval, &exp); } index = absscale >> 4; if (index) { int multexp = rgexp64Power10By16[index - 1]; // the exponents are shared between the inverted and regular table exp += (scale < 0) ? (-multexp + 1) : multexp; uint64_t multval = rgval64Power10By16[index + ((scale < 0) ? 21 : 0) - 1]; val = Mul64Lossy(val, multval, &exp); } // round & scale down if ((uint32_t)val & (1 << 10)) { // IEEE round to even uint64_t tmp = val + ((1 << 10) - 1) + (((uint32_t)val >> 11) & 1); if (tmp < val) { // overflow tmp = (tmp >> 1) | 0x8000000000000000ULL; exp += 1; } val = tmp; } // return the exponent to a biased state exp += 0x3FE; // handle overflow, underflow, "Epsilon - 1/2 Epsilon", denormalized, and the normal case if (exp <= 0) { if (exp == -52 && (val >= 0x8000000000000058ULL)) { // round X where {Epsilon > X >= 2.470328229206232730000000E-324} up to Epsilon (instead of down to zero) val = 0x0000000000000001ULL; } else if (exp <= -52) { // underflow val = 0; } else { // denormalized val >>= (-exp + 11 + 1); } } else if (exp >= 0x7FF) { // overflow val = 0x7FF0000000000000ULL; } else { // normal postive exponent case val = ((uint64_t)exp << 52) + ((val >> 11) & 0x000FFFFFFFFFFFFFULL); } *(uint64_t*)value = val; done: if (number->sign) *(uint64_t*)value |= 0x8000000000000000ULL; } bool Number::NumberBufferToDouble(uint8_t* number, double* value) { double d = 0; NumberToDouble((NUMBER*)number, &d); unsigned int e = ((FPDOUBLE*)&d)->exp; unsigned int fmntLow = ((FPDOUBLE*)&d)->mantLo; unsigned int fmntHigh = ((FPDOUBLE*)&d)->mantHi; if (e == 0x7FF) return false; if (e == 0 && fmntLow == 0 && fmntHigh == 0) d = 0; *value = d; return true; } } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Number.h ================================================ #pragma once #if NET_4_0 #include "object-internals.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API Number { public: static bool NumberBufferToDecimal(uint8_t* number, Il2CppDecimal* value); static bool NumberBufferToDouble(uint8_t* number, double* value); }; } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/NumberFormatter.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System/NumberFormatter.h" #include "number-formatter.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { void NumberFormatter::GetFormatterTables(uint64_t * * mantissas, int32_t * * exponents, int16_t * * digitLowerTable, int16_t * * digitUpperTable, int64_t * * tenPowersList, int32_t * * decHexDigits) { *mantissas = (uint64_t*)Formatter_MantissaBitsTable; *exponents = (int32_t*)Formatter_TensExponentTable; *digitLowerTable = (int16_t*)Formatter_DigitLowerTable; *digitUpperTable = (int16_t*)Formatter_DigitUpperTable; *tenPowersList = (int64_t*)Formatter_TenPowersList; *decHexDigits = (int32_t*)Formatter_DecHexDigits; } } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/NumberFormatter.h ================================================ #pragma once #include #include "il2cpp-config.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API NumberFormatter { public: static void GetFormatterTables(uint64_t * * mantissas, int32_t * * exponents, int16_t * * digitLowerTable, int16_t * * digitUpperTable, int64_t * * tenPowersList, int32_t * * decHexDigits); }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Object.cpp ================================================ #include "il2cpp-config.h" #include "object-internals.h" #include "class-internals.h" #include "icalls/mscorlib/System/Object.h" #include "vm/Object.h" #include "vm/Reflection.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { int Object::InternalGetHashCode(Il2CppObject* obj) { return il2cpp::vm::Object::GetHash(obj); } Il2CppReflectionType* Object::GetType(Il2CppObject* obj) { return il2cpp::vm::Reflection::GetTypeObject(obj->klass->byval_arg); } Il2CppObject* Object::MemberwiseClone(Il2CppObject* obj) { return il2cpp::vm::Object::Clone(obj); } Il2CppIntPtr Object::obj_address(Il2CppObject* obj) { Il2CppIntPtr addr = { obj }; return addr; } } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Object.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppObject; struct Il2CppReflectionType; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API Object { public: static Il2CppReflectionType* GetType(Il2CppObject* obj); static int InternalGetHashCode(Il2CppObject* obj); static Il2CppIntPtr obj_address(Il2CppObject* obj); static Il2CppObject* MemberwiseClone(Il2CppObject* obj); }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/RuntimeFieldHandle.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "RuntimeFieldHandle.h" #include "icalls/mscorlib/System.Reflection/MonoField.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { void RuntimeFieldHandle::SetValueDirect(Il2CppObject* field, Il2CppObject* fieldType, void* pTypedRef, Il2CppObject* value, Il2CppObject* contextType) { NOT_IMPLEMENTED_ICALL(RuntimeFieldHandle::SetValueDirect); IL2CPP_UNREACHABLE; } void RuntimeFieldHandle::SetValueInternal(Il2CppReflectionField* fi, Il2CppObject* obj, Il2CppObject* value) { // In mono's icall-def.h file, this maps to the same icall as MonoField.SetValueInternal // so our implementation will do the same Reflection::MonoField::SetValueInternal(fi, obj, value); } } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/RuntimeFieldHandle.h ================================================ #pragma once #if NET_4_0 #include "object-internals.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API RuntimeFieldHandle { public: static void SetValueDirect(Il2CppObject* field, Il2CppObject* fieldType, void* pTypedRef, Il2CppObject* value, Il2CppObject* contextType); static void SetValueInternal(Il2CppReflectionField* fi, Il2CppObject* obj, Il2CppObject* value); }; } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/RuntimeMethodHandle.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System/RuntimeMethodHandle.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { Il2CppIntPtr RuntimeMethodHandle::GetFunctionPointer(Il2CppIntPtr m) { NOT_IMPLEMENTED_ICALL(RuntimeMethodHandle::GetFunctionPointer); return Il2CppIntPtr::Zero; } } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/RuntimeMethodHandle.h ================================================ #pragma once #include #include "object-internals.h" #include "il2cpp-config.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API RuntimeMethodHandle { public: static Il2CppIntPtr GetFunctionPointer(Il2CppIntPtr m); }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/RuntimeType.cpp ================================================ #include "il2cpp-config.h" #if NET_4_0 #include "Activator.h" #include "metadata.h" #include "MonoType.h" #include "RuntimeType.h" #include "Type.h" #include "vm/Array.h" #include "vm/Type.h" #include "vm/Class.h" #include "vm/Field.h" #include "vm/String.h" #include "vm/GenericClass.h" #include "utils/dynamic_array.h" #include "utils/Il2CppHashSet.h" #include "utils/StringUtils.h" #include "il2cpp-api.h" #include "icalls/mscorlib/System/MonoType.h" #include "tabledefs.h" #include "mono-structs.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { bool RuntimeType::IsTypeExportedToWindowsRuntime(Il2CppObject* type) { NOT_IMPLEMENTED_ICALL(RuntimeType::IsTypeExportedToWindowsRuntime); IL2CPP_UNREACHABLE; return false; } bool RuntimeType::IsWindowsRuntimeObjectType(Il2CppObject* type) { NOT_IMPLEMENTED_ICALL(RuntimeType::IsWindowsRuntimeObjectType); IL2CPP_UNREACHABLE; return false; } int32_t RuntimeType::get_core_clr_security_level(Il2CppObject* _this) { NOT_IMPLEMENTED_ICALL(RuntimeType::get_core_clr_security_level); IL2CPP_UNREACHABLE; return 0; } int32_t RuntimeType::GetGenericParameterPosition(Il2CppReflectionRuntimeType* _this) { return Type::GetGenericParameterPosition(&_this->type); } Il2CppObject* RuntimeType::CreateInstanceInternal(Il2CppReflectionType* type) { return Activator::CreateInstanceInternal(type); } int32_t RuntimeType::GetGenericParameterAttributes(Il2CppReflectionRuntimeType* _this) { return Type::GetGenericParameterAttributes(&_this->type); } Il2CppObject* RuntimeType::get_DeclaringMethod(Il2CppObject* _this) { NOT_IMPLEMENTED_ICALL(RuntimeType::get_DeclaringMethod); IL2CPP_UNREACHABLE; return NULL; } Il2CppArray* RuntimeType::GetConstructors_internal(Il2CppReflectionRuntimeType* _this, int32_t bindingAttr, Il2CppReflectionType* reflected_type) { return MonoType::GetConstructors_internal(&_this->type, bindingAttr, reflected_type); } Il2CppArray* RuntimeType::GetEvents_internal(Il2CppReflectionRuntimeType* _this, Il2CppString* name, int32_t bindingAttr, Il2CppReflectionType* reflected_type) { return MonoType::GetEventsByName(&_this->type, name, bindingAttr, reflected_type); } Il2CppArray* RuntimeType::GetFields_internal(Il2CppReflectionRuntimeType* _this, Il2CppString* name, int32_t bindingAttr, Il2CppReflectionType* reflected_type) { return MonoType::GetFieldsByName(&_this->type, name, bindingAttr, reflected_type); } Il2CppArray* RuntimeType::GetMethodsByName(Il2CppReflectionRuntimeType* _this, Il2CppString* name, int32_t bindingAttr, bool ignoreCase, Il2CppReflectionType* reflected_type) { return MonoType::GetMethodsByName(&_this->type, name, bindingAttr, ignoreCase, reflected_type); } Il2CppArray* RuntimeType::GetPropertiesByName(Il2CppReflectionRuntimeType* _this, Il2CppString* name, int32_t bindingAttr, bool icase, Il2CppReflectionType* reflected_type) { return MonoType::GetPropertiesByName(&_this->type, name, bindingAttr, icase, reflected_type); } Il2CppArray* RuntimeType::GetNestedTypes_internal(Il2CppReflectionRuntimeType* _this, Il2CppString* name, int32_t bindingFlags) { return MonoType::GetNestedTypesByName(&_this->type, name, bindingFlags); } Il2CppString* RuntimeType::get_Name(Il2CppReflectionRuntimeType* _this) { return MonoType::get_Name(&_this->type); } Il2CppString* RuntimeType::get_Namespace(Il2CppReflectionRuntimeType* _this) { return MonoType::get_Namespace(&_this->type); } Il2CppString* RuntimeType::getFullName(Il2CppReflectionRuntimeType* _this, bool full_name, bool assembly_qualified) { return MonoType::getFullName(&_this->type, full_name, assembly_qualified); } Il2CppReflectionType* RuntimeType::get_DeclaringType(Il2CppReflectionRuntimeType* _this) { return vm::Type::GetDeclaringType(_this->type.type); } Il2CppReflectionType* RuntimeType::make_array_type(Il2CppReflectionRuntimeType* _this, int32_t rank) { return Type::make_array_type(&_this->type, rank); } Il2CppReflectionType* RuntimeType::make_byref_type(Il2CppReflectionRuntimeType* _this) { return Type::make_byref_type(&_this->type); } Il2CppReflectionType* RuntimeType::MakeGenericType(Il2CppReflectionType* gt, Il2CppArray* types) { return Type::MakeGenericType(gt, types); } Il2CppReflectionType* RuntimeType::MakePointerType(Il2CppReflectionType* type) { return Type::MakePointerType(type); } Il2CppArray* RuntimeType::GetGenericArgumentsInternal(Il2CppReflectionRuntimeType* _this, bool runtimeArray) { return vm::Type::GetGenericArgumentsInternal(&_this->type, runtimeArray); } Il2CppArray* RuntimeType::GetGenericParameterConstraints_impl(Il2CppReflectionRuntimeType* _this) { return Type::GetGenericParameterConstraints_impl(&_this->type); } Il2CppArray* RuntimeType::GetInterfaces(Il2CppReflectionRuntimeType* _this) { return MonoType::GetInterfaces(&_this->type); } int32_t RuntimeType::GetTypeCodeImplInternal(Il2CppReflectionType* type) { return Type::GetTypeCodeInternal(type); } void RuntimeType::GetInterfaceMapData(Il2CppReflectionType* t, Il2CppReflectionType* iface, Il2CppArray** targets, Il2CppArray** methods) { Type::GetInterfaceMapData(t, iface, targets, methods); } void RuntimeType::GetPacking(Il2CppReflectionRuntimeType* _this, int32_t* packing, int32_t* size) { Type::GetPacking(&_this->type, packing, size); } Il2CppIntPtr RuntimeType::GetConstructors_native(Il2CppReflectionRuntimeType* thisPtr, int32_t bindingAttr) { Il2CppReflectionMethod *method; Il2CppIntPtr retVal; if (thisPtr->type.type->byref) { retVal.m_value = empty_gptr_array(); return retVal; } VoidPtrArray res_array; res_array.reserve(4); Il2CppArray* constructors = MonoType::GetConstructors_internal(&thisPtr->type, bindingAttr, &thisPtr->type); for (unsigned int i = 0; i < il2cpp::vm::Array::GetLength(constructors); i++) { method = il2cpp_array_get(constructors, Il2CppReflectionMethod*, i); res_array.push_back((MethodInfo*)method->method); } retVal.m_value = void_ptr_array_to_gptr_array(res_array); return retVal; } Il2CppIntPtr RuntimeType::GetEvents_native(Il2CppReflectionRuntimeType* thisPtr, Il2CppIntPtr name, int32_t bindingAttr) { Il2CppReflectionMonoEvent *event; VoidPtrArray res_array; Il2CppIntPtr retVal; const char *utf8_name = (const char*)name.m_value; if (thisPtr->type.type->byref) { retVal.m_value = empty_gptr_array(); return retVal; } res_array.reserve(4); Il2CppString* nameStr = name.m_value == NULL ? NULL : il2cpp::vm::String::New((const char*)name.m_value); Il2CppArray* events = MonoType::GetEventsByName(&thisPtr->type, nameStr, bindingAttr, &thisPtr->type); for (unsigned int i = 0; i < il2cpp::vm::Array::GetLength(events); i++) { event = il2cpp_array_get(events, Il2CppReflectionMonoEvent*, i); res_array.push_back((EventInfo*)event->eventInfo); } retVal.m_value = void_ptr_array_to_gptr_array(res_array); return retVal; } Il2CppIntPtr RuntimeType::GetFields_native(Il2CppReflectionRuntimeType* thisPtr, Il2CppIntPtr name, int32_t bindingAttr) { Il2CppReflectionField *field; Il2CppIntPtr retVal; VoidPtrArray res_array; if (thisPtr->type.type->byref) { retVal.m_value = empty_gptr_array(); return retVal; } res_array.reserve(16); Il2CppString* nameStr = name.m_value == NULL ? NULL : il2cpp::vm::String::New((const char*)name.m_value); Il2CppArray* fields = MonoType::GetFieldsByName(&thisPtr->type, nameStr, bindingAttr, &thisPtr->type); for (unsigned int i = 0; i < il2cpp::vm::Array::GetLength(fields); i++) { field = il2cpp_array_get(fields, Il2CppReflectionField*, i); res_array.push_back(field->field); } retVal.m_value = void_ptr_array_to_gptr_array(res_array); return retVal; } Il2CppIntPtr RuntimeType::GetMethodsByName_native(Il2CppReflectionRuntimeType* thisPtr, Il2CppIntPtr namePtr, int32_t bindingAttr, bool ignoreCase) { VoidPtrArray res_array; Il2CppIntPtr retVal; Il2CppReflectionMethod *method; if (thisPtr->type.type->byref) { Il2CppIntPtr retVal; retVal.m_value = empty_gptr_array(); return retVal; } Il2CppString* nameStr = namePtr.m_value == NULL ? NULL : il2cpp::vm::String::New((const char*)namePtr.m_value); Il2CppArray* methods = MonoType::GetMethodsByName(&thisPtr->type, nameStr, bindingAttr, ignoreCase, &thisPtr->type); for (unsigned int i = 0; i < il2cpp::vm::Array::GetLength(methods); i++) { method = il2cpp_array_get(methods, Il2CppReflectionMethod*, i); res_array.push_back((MethodInfo*)method->method); } retVal.m_value = void_ptr_array_to_gptr_array(res_array); return retVal; } Il2CppIntPtr RuntimeType::GetNestedTypes_native(Il2CppReflectionRuntimeType* thisPtr, Il2CppIntPtr name, int32_t bindingAttr) { Il2CppReflectionType *nested; VoidPtrArray res_array; Il2CppIntPtr retVal; if (thisPtr->type.type->byref) { retVal.m_value = empty_gptr_array(); return retVal; } Il2CppString* nameStr = name.m_value == NULL ? NULL : il2cpp::vm::String::New((const char*)name.m_value); Il2CppArray* nestedTypes = MonoType::GetNestedTypesByName(&thisPtr->type, nameStr, bindingAttr); for (unsigned int i = 0; i < il2cpp::vm::Array::GetLength(nestedTypes); i++) { nested = il2cpp_array_get(nestedTypes, Il2CppReflectionType*, i); res_array.push_back((Il2CppType*)nested->type); } retVal.m_value = void_ptr_array_to_gptr_array(res_array); return retVal; } Il2CppIntPtr RuntimeType::GetPropertiesByName_native(Il2CppReflectionRuntimeType* thisPtr, Il2CppIntPtr name, int32_t bindingAttr, bool icase) { Il2CppReflectionProperty *prop; VoidPtrArray res_array; Il2CppIntPtr retVal; if (thisPtr->type.type->byref) { retVal.m_value = empty_gptr_array(); return retVal; } res_array.reserve(8); Il2CppString* nameStr = name.m_value == NULL ? NULL : il2cpp::vm::String::New((const char*)name.m_value); Il2CppArray* properties = MonoType::GetPropertiesByName(&thisPtr->type, nameStr, bindingAttr, icase, &thisPtr->type); for (unsigned int i = 0; i < il2cpp::vm::Array::GetLength(properties); i++) { prop = il2cpp_array_get(properties, Il2CppReflectionProperty*, i); res_array.push_back((PropertyInfo*)prop->property); } retVal.m_value = void_ptr_array_to_gptr_array(res_array); return retVal; } } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/RuntimeType.h ================================================ #pragma once #if NET_4_0 struct Il2CppReflectionRuntimeType; struct Il2CppIntPtr; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API RuntimeType { public: static bool IsTypeExportedToWindowsRuntime(Il2CppObject* type); static bool IsWindowsRuntimeObjectType(Il2CppObject* type); static int32_t get_core_clr_security_level(Il2CppObject* _this); static int32_t GetGenericParameterPosition(Il2CppReflectionRuntimeType* _this); static Il2CppObject* CreateInstanceInternal(Il2CppReflectionType* type); static int32_t GetGenericParameterAttributes(Il2CppReflectionRuntimeType* _this); static Il2CppObject* get_DeclaringMethod(Il2CppObject* _this); static Il2CppArray* GetConstructors_internal(Il2CppReflectionRuntimeType* _this, int32_t bindingAttr, Il2CppReflectionType* reflected_type); static Il2CppArray* GetEvents_internal(Il2CppReflectionRuntimeType* _this, Il2CppString* name, int32_t bindingAttr, Il2CppReflectionType* reflected_type); static Il2CppArray* GetFields_internal(Il2CppReflectionRuntimeType* _this, Il2CppString* name, int32_t bindingAttr, Il2CppReflectionType* reflected_type); static Il2CppArray* GetMethodsByName(Il2CppReflectionRuntimeType* _this, Il2CppString* name, int32_t bindingAttr, bool ignoreCase, Il2CppReflectionType* reflected_type); static Il2CppArray* GetPropertiesByName(Il2CppReflectionRuntimeType* _this, Il2CppString* name, int32_t bindingAttr, bool icase, Il2CppReflectionType* reflected_type); static Il2CppArray* GetNestedTypes_internal(Il2CppReflectionRuntimeType* _this, Il2CppString* name, int32_t bindingFlags); static Il2CppString* get_Name(Il2CppReflectionRuntimeType* _this); static Il2CppString* get_Namespace(Il2CppReflectionRuntimeType* _this); static Il2CppString* getFullName(Il2CppReflectionRuntimeType* _this, bool full_name, bool assembly_qualified); static Il2CppReflectionType* get_DeclaringType(Il2CppReflectionRuntimeType* _this); static Il2CppReflectionType* make_array_type(Il2CppReflectionRuntimeType* _this, int32_t rank); static Il2CppReflectionType* make_byref_type(Il2CppReflectionRuntimeType* _this); static Il2CppReflectionType* MakeGenericType(Il2CppReflectionType* gt, Il2CppArray* types); static Il2CppReflectionType* MakePointerType(Il2CppReflectionType* type); static Il2CppArray* GetGenericArgumentsInternal(Il2CppReflectionRuntimeType* _this, bool runtimeArray); static Il2CppArray* GetGenericParameterConstraints_impl(Il2CppReflectionRuntimeType* _this); static Il2CppArray* GetInterfaces(Il2CppReflectionRuntimeType* _this); static int32_t GetTypeCodeImplInternal(Il2CppReflectionType* type); static void GetInterfaceMapData(Il2CppReflectionType* t, Il2CppReflectionType* iface, Il2CppArray** targets, Il2CppArray** methods); static void GetPacking(Il2CppReflectionRuntimeType* _this, int32_t* packing, int32_t* size); static Il2CppIntPtr GetConstructors_native(Il2CppReflectionRuntimeType* thisPtr, int32_t bindingAttr); static Il2CppIntPtr GetEvents_native(Il2CppReflectionRuntimeType* thisPtr, Il2CppIntPtr name, int32_t bindingAttr); static Il2CppIntPtr GetFields_native(Il2CppReflectionRuntimeType* thisPtr, Il2CppIntPtr name, int32_t bindingAttr); static Il2CppIntPtr GetMethodsByName_native(Il2CppReflectionRuntimeType* thisPtr, Il2CppIntPtr namePtr, int32_t bindingAttr, bool ignoreCase); static Il2CppIntPtr GetNestedTypes_native(Il2CppReflectionRuntimeType* thisPtr, Il2CppIntPtr name, int32_t bindingAttr); static Il2CppIntPtr GetPropertiesByName_native(Il2CppReflectionRuntimeType* thisPtr, Il2CppIntPtr name, int32_t bindingAttr, bool icase); }; } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/RuntimeTypeHandle.cpp ================================================ #include "il2cpp-config.h" #include "object-internals.h" #include "mono-structs.h" #include "MonoType.h" #include "RuntimeTypeHandle.h" #include "Type.h" #include "vm/Class.h" #include "vm/Image.h" #include "vm/Reflection.h" #include "vm/MetadataCache.h" #if NET_4_0 namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { bool RuntimeTypeHandle::HasInstantiation(Il2CppReflectionRuntimeType* type) { return Type::get_IsGenericType(&type->type); } bool RuntimeTypeHandle::IsArray(Il2CppReflectionRuntimeType* type) { return Type::IsArrayImpl(&type->type); } bool RuntimeTypeHandle::IsByRef(Il2CppReflectionRuntimeType* type) { return MonoType::IsByRefImpl(&type->type); } bool RuntimeTypeHandle::IsComObject(Il2CppReflectionRuntimeType* type) { return false; // il2cpp does not support COM objects, so this is always false } bool RuntimeTypeHandle::IsGenericTypeDefinition(Il2CppReflectionRuntimeType* type) { return Type::get_IsGenericTypeDefinition(&type->type); } bool RuntimeTypeHandle::IsGenericVariable(Il2CppReflectionRuntimeType* type) { return MonoType::get_IsGenericParameter(&type->type); } bool RuntimeTypeHandle::IsInstanceOfType(Il2CppReflectionRuntimeType* type, Il2CppObject* o) { return Type::IsInstanceOfType(&type->type, o); } bool RuntimeTypeHandle::IsPointer(Il2CppReflectionRuntimeType* type) { return MonoType::IsPointerImpl(&type->type); } bool RuntimeTypeHandle::IsPrimitive(Il2CppReflectionRuntimeType* type) { return MonoType::IsPrimitiveImpl(&type->type); } bool RuntimeTypeHandle::type_is_assignable_from(Il2CppReflectionType* a, Il2CppReflectionType* b) { return Type::type_is_assignable_from(a, b); } int32_t RuntimeTypeHandle::GetArrayRank(Il2CppReflectionRuntimeType* type) { return MonoType::GetArrayRank(&type->type); } int32_t RuntimeTypeHandle::GetMetadataToken(Il2CppReflectionRuntimeType* type) { return vm::Class::FromSystemType(&type->type)->token; } Il2CppReflectionAssembly* RuntimeTypeHandle::GetAssembly(Il2CppReflectionRuntimeType* type) { return vm::Reflection::GetAssemblyObject(vm::Image::GetAssembly(vm::Class::GetImage(vm::Class::FromIl2CppType(type->type.type)))); } Il2CppReflectionModule* RuntimeTypeHandle::GetModule(Il2CppReflectionRuntimeType* type) { return vm::Reflection::GetModuleObject(vm::Class::GetImage(vm::Class::FromIl2CppType(type->type.type))); } int32_t RuntimeTypeHandle::GetAttributes(Il2CppReflectionRuntimeType* type) { return MonoType::get_attributes(&type->type); } Il2CppReflectionRuntimeType* RuntimeTypeHandle::GetBaseType(Il2CppReflectionRuntimeType* type) { return reinterpret_cast(MonoType::get_BaseType(&type->type)); } Il2CppReflectionRuntimeType* RuntimeTypeHandle::GetElementType(Il2CppReflectionRuntimeType* type) { return reinterpret_cast(MonoType::GetElementType(&type->type)); } Il2CppReflectionType* RuntimeTypeHandle::GetGenericTypeDefinition_impl(Il2CppReflectionRuntimeType* type) { return Type::GetGenericTypeDefinition_impl(&type->type); } Il2CppIntPtr RuntimeTypeHandle::GetGenericParameterInfo(Il2CppReflectionRuntimeType* type) { Il2CppIntPtr retVal; retVal.m_value = NULL; const Il2CppType *thisType = type->type.type; if ((thisType->type == IL2CPP_TYPE_VAR) || (thisType->type == IL2CPP_TYPE_MVAR)) { const Il2CppGenericParameter *param = il2cpp::vm::MetadataCache::GetGenericParameterFromIndex(thisType->data.genericParameterIndex); if (param) { MonoGenericParameterInfo *monoParam = (MonoGenericParameterInfo*)il2cpp::vm::Reflection::GetMonoGenericParameterInfo(param); if (monoParam) { retVal.m_value = monoParam; } else { monoParam = (MonoGenericParameterInfo*)IL2CPP_MALLOC(sizeof(MonoGenericParameterInfo)); monoParam->flags = param->flags; monoParam->token = param->num; monoParam->name = il2cpp::vm::MetadataCache::GetStringFromIndex(param->nameIndex); const Il2CppGenericContainer *container = il2cpp::vm::MetadataCache::GetGenericContainerFromIndex(param->ownerIndex); monoParam->pklass = NULL; if (container) monoParam->pklass = il2cpp::vm::MetadataCache::GetTypeInfoFromTypeIndex(container->ownerIndex); monoParam->constraints = (Il2CppClass**)IL2CPP_MALLOC(sizeof(Il2CppClass*) * (param->constraintsCount + 1)); for (int i = 0; i < param->constraintsCount; ++i) { const Il2CppType *constraintType = il2cpp::vm::MetadataCache::GetGenericParameterConstraintFromIndex(param->constraintsStart + i); monoParam->constraints[i] = il2cpp::vm::Class::FromIl2CppType(constraintType); } monoParam->constraints[param->constraintsCount] = NULL; il2cpp::vm::Reflection::SetMonoGenericParameterInfo(param, monoParam); retVal.m_value = monoParam; } } } return retVal; } } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/RuntimeTypeHandle.h ================================================ #pragma once #if NET_4_0 namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API RuntimeTypeHandle { public: static bool HasInstantiation(Il2CppReflectionRuntimeType* type); static bool IsArray(Il2CppReflectionRuntimeType* type); static bool IsByRef(Il2CppReflectionRuntimeType* type); static bool IsComObject(Il2CppReflectionRuntimeType* type); static bool IsGenericTypeDefinition(Il2CppReflectionRuntimeType* type); static bool IsGenericVariable(Il2CppReflectionRuntimeType* type); static bool IsInstanceOfType(Il2CppReflectionRuntimeType* type, Il2CppObject* o); static bool IsPointer(Il2CppReflectionRuntimeType* type); static bool IsPrimitive(Il2CppReflectionRuntimeType* type); static bool type_is_assignable_from(Il2CppReflectionType* a, Il2CppReflectionType* b); static int32_t GetArrayRank(Il2CppReflectionRuntimeType* type); static int32_t GetMetadataToken(Il2CppReflectionRuntimeType* type); static Il2CppReflectionAssembly* GetAssembly(Il2CppReflectionRuntimeType* type); static Il2CppReflectionModule* GetModule(Il2CppReflectionRuntimeType* type); static int32_t GetAttributes(Il2CppReflectionRuntimeType* type); static Il2CppReflectionRuntimeType* GetBaseType(Il2CppReflectionRuntimeType* type); static Il2CppReflectionRuntimeType* GetElementType(Il2CppReflectionRuntimeType* type); static Il2CppReflectionType* GetGenericTypeDefinition_impl(Il2CppReflectionRuntimeType* type); static Il2CppIntPtr GetGenericParameterInfo(Il2CppReflectionRuntimeType* type); }; } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/SizedReference.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "SizedReference.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { int64_t SizedReference::GetApproximateSizeOfSizedRef(Il2CppIntPtr h) { NOT_IMPLEMENTED_ICALL(SizedReference::GetApproximateSizeOfSizedRef); IL2CPP_UNREACHABLE; } Il2CppIntPtr SizedReference::CreateSizedRef(Il2CppObject* o) { NOT_IMPLEMENTED_ICALL(SizedReference::CreateSizedRef); IL2CPP_UNREACHABLE; } Il2CppObject* SizedReference::GetTargetOfSizedRef(Il2CppIntPtr h) { NOT_IMPLEMENTED_ICALL(SizedReference::GetTargetOfSizedRef); IL2CPP_UNREACHABLE; } void SizedReference::FreeSizedRef(Il2CppIntPtr h) { NOT_IMPLEMENTED_ICALL(SizedReference::FreeSizedRef); IL2CPP_UNREACHABLE; } } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/SizedReference.h ================================================ #pragma once #if NET_4_0 #include "object-internals.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API SizedReference { public: static int64_t GetApproximateSizeOfSizedRef(Il2CppIntPtr h); static Il2CppIntPtr CreateSizedRef(Il2CppObject* o); static Il2CppObject* GetTargetOfSizedRef(Il2CppIntPtr h); static void FreeSizedRef(Il2CppIntPtr h); }; } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/String.cpp ================================================ #include "il2cpp-config.h" #include #include "il2cpp-api.h" #include "object-internals.h" #include "class-internals.h" #include "icalls/mscorlib/System/String.h" #include "utils/StringUtils.h" #include "vm/Array.h" #include "vm/Class.h" #include "vm/String.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { void String::RedirectToCreateString() { NOT_SUPPORTED_IL2CPP(String::RedirectToCreateString, "All String constructors should be redirected to String.CreateString."); } Il2CppString * String::InternalAllocateStr(int length) { return il2cpp::vm::String::NewSize(length); } static bool string_icall_is_in_array(Il2CppArray *chars, int32_t arraylength, Il2CppChar chr) { Il2CppChar cmpchar; int32_t arrpos; for (arrpos = 0; arrpos != arraylength; arrpos++) { cmpchar = il2cpp_array_get(chars, Il2CppChar, arrpos); if (cmpchar == chr) return true; } return false; } /* System.StringSplitOptions */ typedef enum { STRINGSPLITOPTIONS_NONE = 0, STRINGSPLITOPTIONS_REMOVE_EMPTY_ENTRIES = 1 } StringSplitOptions; Il2CppArray * String::InternalSplit(Il2CppString* me, Il2CppArray* separator, int count, int options) { static Il2CppClass *String_array; Il2CppString * tmpstr; Il2CppArray * retarr; Il2CppChar *src; int32_t arrsize, srcsize, splitsize; int32_t i, lastpos, arrpos; int32_t tmpstrsize; int32_t remempty; int32_t flag; Il2CppChar *tmpstrptr; remempty = options & STRINGSPLITOPTIONS_REMOVE_EMPTY_ENTRIES; src = il2cpp::utils::StringUtils::GetChars(me); srcsize = il2cpp::utils::StringUtils::GetLength(me); arrsize = il2cpp::vm::Array::GetLength(separator); if (!String_array) { Il2CppClass *klass = il2cpp::vm::Class::GetArrayClass(il2cpp_defaults.string_class, 1); //mono_memory_barrier (); String_array = klass; } splitsize = 1; /* Count the number of elements we will return. Note that this operation * guarantees that we will return exactly splitsize elements, and we will * have enough data to fill each. This allows us to skip some checks later on. */ if (remempty == 0) { for (i = 0; i != srcsize && splitsize < count; i++) { if (string_icall_is_in_array(separator, arrsize, src[i])) splitsize++; } } else if (count > 1) { /* Require pattern "Nondelim + Delim + Nondelim" to increment counter. * Lastpos != 0 means first nondelim found. * Flag = 0 means last char was delim. * Efficient, though perhaps confusing. */ lastpos = 0; flag = 0; for (i = 0; i != srcsize && splitsize < count; i++) { if (string_icall_is_in_array(separator, arrsize, src[i])) { flag = 0; } else if (flag == 0) { if (lastpos == 1) splitsize++; flag = 1; lastpos = 1; } } /* Nothing but separators */ if (lastpos == 0) { retarr = il2cpp::vm::Array::NewSpecific(String_array, 0); return retarr; } } /* if no split chars found return the string */ if (splitsize == 1) { if (remempty == 0 || count == 1) { /* Copy the whole string */ retarr = il2cpp::vm::Array::NewSpecific(String_array, 1); il2cpp_array_setref(retarr, 0, me); } else { /* otherwise we have to filter out leading & trailing delims */ /* find first non-delim char */ for (; srcsize != 0; srcsize--, src++) { if (!string_icall_is_in_array(separator, arrsize, src[0])) break; } /* find last non-delim char */ for (; srcsize != 0; srcsize--) { if (!string_icall_is_in_array(separator, arrsize, src[srcsize - 1])) break; } tmpstr = il2cpp::vm::String::NewSize(srcsize); tmpstrptr = il2cpp::utils::StringUtils::GetChars(tmpstr); memcpy(tmpstrptr, src, srcsize * sizeof(Il2CppChar)); retarr = il2cpp::vm::Array::NewSpecific(String_array, 1); il2cpp_array_setref(retarr, 0, tmpstr); } return retarr; } lastpos = 0; arrpos = 0; retarr = il2cpp::vm::Array::NewSpecific(String_array, splitsize); for (i = 0; i != srcsize && arrpos != splitsize; i++) { if (string_icall_is_in_array(separator, arrsize, src[i])) { if (lastpos != i || remempty == 0) { tmpstrsize = i - lastpos; tmpstr = il2cpp::vm::String::NewSize(tmpstrsize); tmpstrptr = il2cpp::utils::StringUtils::GetChars(tmpstr); memcpy(tmpstrptr, src + lastpos, tmpstrsize * sizeof(Il2CppChar)); il2cpp_array_setref(retarr, arrpos, tmpstr); arrpos++; if (arrpos == splitsize - 1) { /* Shortcut the last array element */ lastpos = i + 1; if (remempty != 0) { /* Search for non-delim starting char (guaranteed to find one) Note that loop * condition is only there for safety. It will never actually terminate the loop. */ for (; lastpos != srcsize; lastpos++) { if (!string_icall_is_in_array(separator, arrsize, src[lastpos])) break; } if (count > splitsize) { /* Since we have fewer results than our limit, we must remove * trailing delimiters as well. */ for (; srcsize != lastpos + 1; srcsize--) { if (!string_icall_is_in_array(separator, arrsize, src[srcsize - 1])) break; } } } tmpstrsize = srcsize - lastpos; tmpstr = il2cpp::vm::String::NewSize(tmpstrsize); tmpstrptr = il2cpp::utils::StringUtils::GetChars(tmpstr); memcpy(tmpstrptr, src + lastpos, tmpstrsize * sizeof(Il2CppChar)); il2cpp_array_setref(retarr, arrpos, tmpstr); /* Loop will ALWAYS end here. Test criteria in the FOR loop is technically unnecessary. */ break; } } lastpos = i + 1; } } return retarr; } Il2CppString* String::InternalIntern(Il2CppString* str) { return il2cpp_string_intern(str); } Il2CppString* String::InternalIsInterned(Il2CppString* str) { return il2cpp_string_is_interned(str); } #if NET_4_0 Il2CppString* String::FastAllocateString(int32_t length) { return vm::String::NewSize(length); } #endif } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/String.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppString; struct Il2CppArray; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API String { public: static void RedirectToCreateString(); static Il2CppString* InternalAllocateStr(int length); static Il2CppString* InternalIntern(Il2CppString* str); static Il2CppArray* InternalSplit(Il2CppString *, Il2CppArray*, int, int); static Il2CppString* InternalIsInterned(Il2CppString* str); #if NET_4_0 static Il2CppString* FastAllocateString(int32_t length); #endif }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/TimeSpan.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "TimeSpan.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { bool TimeSpan::LegacyFormatMode() { NOT_IMPLEMENTED_ICALL(TimeSpan::LegacyFormatMode); IL2CPP_UNREACHABLE; return false; } } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/TimeSpan.h ================================================ #pragma once #if NET_4_0 namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API TimeSpan { public: static bool LegacyFormatMode(); }; } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/TimeZoneInfo.h ================================================ #pragma once #if NET_4_0 namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API TimeZoneInfo { public: static inline bool UseRegistryForTimeZoneInformation() { return IL2CPP_TARGET_WINDOWS_DESKTOP; } }; } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Type.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System/Type.h" #include "icalls/mscorlib/System/MonoType.h" #include "class-internals.h" #include "object-internals.h" #include "il2cpp-api.h" #include #include "tabledefs.h" #include "metadata/GenericMetadata.h" #include "metadata/Il2CppTypeVector.h" #include "vm/Array.h" #include "vm/Assembly.h" #include "vm/Class.h" #include "vm/GenericClass.h" #include "vm/MetadataCache.h" #include "vm/Object.h" #include "vm/Runtime.h" #include "vm/String.h" #include "vm/Type.h" #include "vm/Thread.h" #include "vm/Exception.h" #include "vm/Reflection.h" #include "utils/StringUtils.h" #include using namespace il2cpp::vm; using il2cpp::metadata::GenericMetadata; using il2cpp::metadata::Il2CppTypeVector; using il2cpp::utils::StringUtils; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { bool Type::EqualsInternal(Il2CppReflectionType * left, Il2CppReflectionType * right) { return (left->type == right->type); } bool Type::get_IsGenericType(Il2CppReflectionType* type) { Il2CppClass *klass; NOT_IMPLEMENTED_ICALL_NO_ASSERT(MonoType::get_IsGenericTypeDefinition, "Check for custom Type implementations"); //if (!IS_MONOTYPE (type)) // return FALSE; if (type->type->byref) return false; klass = Class::FromIl2CppType(type->type); return klass->generic_class != NULL || Class::IsGeneric(klass); } bool Type::get_IsGenericTypeDefinition(Il2CppReflectionType * type) { Il2CppClass *klass; NOT_IMPLEMENTED_ICALL_NO_ASSERT(MonoType::get_IsGenericTypeDefinition, "Check for custom Type implementations"); //if (!IS_MONOTYPE (type)) // return FALSE; if (type->type->byref) return false; klass = Class::FromIl2CppType(type->type); return Class::IsGeneric(klass); } int32_t Type::GetGenericParameterPosition(Il2CppReflectionType* type) { if (MonoType::get_IsGenericParameter(type)) return vm::Type::GetGenericParameter(type->type)->num; return -1; } Il2CppReflectionType * Type::GetGenericTypeDefinition_impl(Il2CppReflectionType* type) { Il2CppClass *klass; if (type->type->byref) return NULL; klass = Class::FromIl2CppType(type->type); if (Class::IsGeneric(klass)) return type; if (klass->generic_class) { Il2CppClass *generic_class = GenericClass::GetTypeDefinition(klass->generic_class); return Reflection::GetTypeObject(generic_class->byval_arg); } return NULL; } /* System.TypeCode */ typedef enum { TYPECODE_EMPTY, TYPECODE_OBJECT, TYPECODE_DBNULL, TYPECODE_BOOLEAN, TYPECODE_CHAR, TYPECODE_SBYTE, TYPECODE_BYTE, TYPECODE_INT16, TYPECODE_UINT16, TYPECODE_INT32, TYPECODE_UINT32, TYPECODE_INT64, TYPECODE_UINT64, TYPECODE_SINGLE, TYPECODE_DOUBLE, TYPECODE_DECIMAL, TYPECODE_DATETIME, TYPECODE_STRING = 18 } TypeCode; int Type::GetTypeCodeInternal(Il2CppReflectionType* type) { int t = type->type->type; if (type->type->byref) return TYPECODE_OBJECT; handle_enum: switch (t) { case IL2CPP_TYPE_VOID: return TYPECODE_OBJECT; case IL2CPP_TYPE_BOOLEAN: return TYPECODE_BOOLEAN; case IL2CPP_TYPE_U1: return TYPECODE_BYTE; case IL2CPP_TYPE_I1: return TYPECODE_SBYTE; case IL2CPP_TYPE_U2: return TYPECODE_UINT16; case IL2CPP_TYPE_I2: return TYPECODE_INT16; case IL2CPP_TYPE_CHAR: return TYPECODE_CHAR; case IL2CPP_TYPE_PTR: case IL2CPP_TYPE_U: case IL2CPP_TYPE_I: return TYPECODE_OBJECT; case IL2CPP_TYPE_U4: return TYPECODE_UINT32; case IL2CPP_TYPE_I4: return TYPECODE_INT32; case IL2CPP_TYPE_U8: return TYPECODE_UINT64; case IL2CPP_TYPE_I8: return TYPECODE_INT64; case IL2CPP_TYPE_R4: return TYPECODE_SINGLE; case IL2CPP_TYPE_R8: return TYPECODE_DOUBLE; case IL2CPP_TYPE_VALUETYPE: { if (vm::Type::IsEnum(type->type)) { t = Class::GetEnumBaseType(vm::Type::GetClass(type->type))->type; goto handle_enum; } else { if (vm::Type::IsSystemDecimal(type->type)) return TYPECODE_DECIMAL; else if (vm::Type::IsSystemDateTime(type->type)) return TYPECODE_DATETIME; } return TYPECODE_OBJECT; } case IL2CPP_TYPE_STRING: return TYPECODE_STRING; case IL2CPP_TYPE_SZARRAY: case IL2CPP_TYPE_ARRAY: case IL2CPP_TYPE_OBJECT: case IL2CPP_TYPE_VAR: case IL2CPP_TYPE_MVAR: case IL2CPP_TYPE_TYPEDBYREF: return TYPECODE_OBJECT; case IL2CPP_TYPE_CLASS: { if (vm::Type::IsSystemDBNull(type->type)) return TYPECODE_DBNULL; } return TYPECODE_OBJECT; case IL2CPP_TYPE_GENERICINST: return TYPECODE_OBJECT; default: abort(); } return false; } Il2CppReflectionType * Type::internal_from_handle(Il2CppIntPtr ptr) { const Il2CppType* type = (const Il2CppType*)ptr.m_value; Il2CppClass *klass = Class::FromIl2CppType(type); return il2cpp::vm::Reflection::GetTypeObject(klass->byval_arg); } #define CHECK_IF_NULL(v) \ if ( (v) == NULL && throwOnError ) \ Exception::Raise (Exception::GetTypeLoadException ()); \ if ( (v) == NULL ) \ return NULL; Il2CppReflectionType * Type::internal_from_name(Il2CppString* name, bool throwOnError, bool ignoreCase) { std::string str = StringUtils::Utf16ToUtf8(utils::StringUtils::GetChars(name)); il2cpp::vm::TypeNameParseInfo info; il2cpp::vm::TypeNameParser parser(str, info, false); if (!parser.Parse()) { if (throwOnError) Exception::Raise(Exception::GetArgumentException("typeName", "Invalid type name")); else return NULL; } const Il2CppType *type = vm::Class::il2cpp_type_from_type_info(info, throwOnError, ignoreCase); CHECK_IF_NULL(type); return il2cpp::vm::Reflection::GetTypeObject(type); } bool Type::IsArrayImpl(Il2CppReflectionType *t) { NOT_IMPLEMENTED_ICALL_NO_ASSERT(Type::IsArrayImpl, "Faulty implementation?"); Il2CppClass* typeInfo = Class::FromSystemType(t); return typeInfo->rank > 0; } bool Type::IsInstanceOfType(Il2CppReflectionType *type, Il2CppObject * obj) { Il2CppClass *klass = Class::FromIl2CppType(type->type); return il2cpp::vm::Object::IsInst(obj, klass) != NULL; } void validate_make_array_type_inputs(Il2CppReflectionType* type, int32_t rank) { // Per MSDN: http://msdn.microsoft.com/en-us/library/w0ykk2sw(v=vs.110).aspx if (rank > 32) { std::stringstream message; message << vm::Type::GetName(type->type, IL2CPP_TYPE_NAME_FORMAT_FULL_NAME) << " with rank " << rank << " has too many dimensions."; il2cpp_raise_exception(vm::Exception::GetTypeLoadException(message.str().c_str())); } if (type->type->byref) { std::stringstream message; message << "Could not create array type '" << vm::Type::GetName(type->type, IL2CPP_TYPE_NAME_FORMAT_FULL_NAME) << "'."; il2cpp_raise_exception(vm::Exception::GetTypeLoadException(message.str().c_str())); } const Il2CppClass *klass = Class::FromIl2CppType(type->type); if ((strcmp(klass->namespaze, "System") == 0 && strcmp(klass->name, "TypedReference") == 0)) { std::stringstream message; message << "Could not create array type '" << klass->namespaze << "." << klass->name << "[]'."; il2cpp_raise_exception(vm::Exception::GetTypeLoadException(message.str().c_str())); } } Il2CppReflectionType* Type::make_array_type(Il2CppReflectionType* type, int32_t rank) { validate_make_array_type_inputs(type, rank); Il2CppClass* arrayClass; Il2CppClass* klass = il2cpp_class_from_il2cpp_type(type->type); if (rank == 0) //single dimentional array arrayClass = il2cpp_array_class_get(klass, 1); else arrayClass = il2cpp_bounded_array_class_get(klass, rank, true); return arrayClass != NULL ? Reflection::GetTypeObject(arrayClass->byval_arg) : NULL; } static std::string FormatExceptionMessageForNonConstructableGenericType(const Il2CppType* type, const Il2CppTypeVector& genericArguments) { std::string message; message += "Failed to construct generic type '"; message += il2cpp::vm::Type::GetName(type, IL2CPP_TYPE_NAME_FORMAT_FULL_NAME); message += "' with generic arguments ["; for (Il2CppTypeVector::const_iterator iter = genericArguments.begin(); iter != genericArguments.end(); ++iter) { if (iter != genericArguments.begin()) message += ", "; message += il2cpp::vm::Type::GetName(*iter, IL2CPP_TYPE_NAME_FORMAT_FULL_NAME); } message += "] at runtime."; return message; } Il2CppReflectionType * Type::MakeGenericType(Il2CppReflectionType* type, Il2CppArray* genericArgumentTypes) { const Il2CppType* genericTypeDefinitionType = type->type; Il2CppClass* genericTypeDefinitionClass = Class::FromIl2CppType(genericTypeDefinitionType); IL2CPP_ASSERT(Class::IsGeneric(genericTypeDefinitionClass)); uint32_t arrayLength = Array::GetLength(genericArgumentTypes); Il2CppTypeVector genericArguments; genericArguments.reserve(arrayLength); for (uint32_t i = 0; i < arrayLength; i++) { Il2CppReflectionType* genericArgumentType = il2cpp_array_get(genericArgumentTypes, Il2CppReflectionType*, i); genericArguments.push_back(genericArgumentType->type); } const Il2CppGenericInst* inst = MetadataCache::GetGenericInst(genericArguments); Il2CppGenericClass* genericClass = GenericMetadata::GetGenericClass(genericTypeDefinitionClass, inst); Il2CppClass* genericInstanceTypeClass = GenericClass::GetClass(genericClass); if (!genericInstanceTypeClass) { Exception::Raise(Exception::GetNotSupportedException(FormatExceptionMessageForNonConstructableGenericType(genericTypeDefinitionType, genericArguments).c_str())); return NULL; } return Reflection::GetTypeObject(genericInstanceTypeClass->byval_arg); } bool Type::type_is_assignable_from(Il2CppReflectionType * type, Il2CppReflectionType * c) { Il2CppClass *klass; Il2CppClass *klassc; klass = Class::FromIl2CppType(type->type); klassc = Class::FromIl2CppType(c->type); if (type->type->byref && !c->type->byref) return false; return Class::IsAssignableFrom(klass, klassc); } bool Type::type_is_subtype_of(Il2CppReflectionType *type, Il2CppReflectionType *c, bool check_interfaces) { Il2CppClass *klass; Il2CppClass *klassc; IL2CPP_ASSERT(type != NULL); if (!c) /* FIXME: dont know what do do here */ return false; klass = Class::FromSystemType(type); klassc = Class::FromSystemType(c); /*if (type->type->byref) return klassc == mono_defaults.object_class;*/ return Class::IsSubclassOf(klass, klassc, check_interfaces); } Il2CppReflectionType* Type::make_byref_type(Il2CppReflectionType *type) { Il2CppClass *klass; klass = Class::FromIl2CppType(type->type); return il2cpp::vm::Reflection::GetTypeObject(klass->this_arg); } Il2CppReflectionType * Type::MakePointerType(Il2CppReflectionType* type) { Il2CppClass* pointerType = Class::GetPtrClass(type->type); return Reflection::GetTypeObject(pointerType->byval_arg); } void Type::GetInterfaceMapData(Il2CppReflectionType* type, Il2CppReflectionType* iface, Il2CppArray** targets, Il2CppArray** methods) { Il2CppClass* klass = il2cpp_class_from_il2cpp_type(type->type); Il2CppClass* iklass = il2cpp_class_from_il2cpp_type(iface->type); int32_t numberOfMethods = (int32_t)Class::GetNumMethods(iklass); *targets = il2cpp_array_new(il2cpp_defaults.method_info_class, numberOfMethods); *methods = il2cpp_array_new(il2cpp_defaults.method_info_class, numberOfMethods); if (numberOfMethods == 0) return; void* unused = NULL; Class::Init(klass); const VirtualInvokeData* invokeDataStart; // So this part is tricky. GetInterfaceInvokeDataFromVTable takes an object pointer in order to support // COM peculiarities, like being able to return invoke data for an interface only if native side implements it // So here we create a fake object of the class we want to query and pass that to GetInterfaceInvokeDataFromVTable // It is safe because the only fields GetInterfaceInvokeDataFromVTable accesses are the klass and identity fields if (!klass->is_import_or_windows_runtime) { Il2CppObject fakeObject; fakeObject.klass = klass; fakeObject.monitor = NULL; invokeDataStart = &Class::GetInterfaceInvokeDataFromVTable(&fakeObject, iklass, 0); } else { Il2CppComObject fakeComObject; fakeComObject.klass = klass; fakeComObject.monitor = NULL; // This makes GetInterfaceInvokeDataFromVTable believe that the COM object is dead, // thus making it skip asking native side whether a particular interface is supported fakeComObject.identity = NULL; invokeDataStart = &Class::GetInterfaceInvokeDataFromVTable(&fakeComObject, iklass, 0); } for (int i = 0; i < numberOfMethods; ++i) { const MethodInfo *method = il2cpp_class_get_methods(iklass, &unused); Il2CppReflectionMethod* member = il2cpp_method_get_object(method, iklass); il2cpp_array_setref(*methods, i, member); member = il2cpp_method_get_object(invokeDataStart[i].method, klass); il2cpp_array_setref(*targets, i, member); } } GenericParameterAttributes Type::GetGenericParameterAttributes(Il2CppReflectionType* type) { const Il2CppGenericParameter* genericParameter = vm::Type::GetGenericParameter(type->type); if (genericParameter->ownerIndex == kGenericContainerIndexInvalid) return 0; return genericParameter->flags; } Il2CppArray* Type::GetGenericParameterConstraints_impl(Il2CppReflectionType* type) { const Il2CppGenericParameter* genericParameter = vm::Type::GetGenericParameter(type->type); if (genericParameter->ownerIndex == kGenericContainerIndexInvalid) return NULL; Il2CppArray* res = il2cpp_array_new(il2cpp_defaults.monotype_class, genericParameter->constraintsCount); for (int i = 0; i < genericParameter->constraintsCount; i++) il2cpp_array_setref(res, i, il2cpp_type_get_object(MetadataCache::GetGenericParameterConstraintFromIndex(genericParameter->constraintsStart + i))); return res; } void Type::GetPacking(Il2CppReflectionType* type, int32_t* packing, int32_t* size) { NOT_IMPLEMENTED_ICALL_NO_ASSERT(Type::GetPacking, "In progress, need this function to not assert to test other aspects of StructLayout attribute"); *packing = 8; *size = 0; } } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/Type.h ================================================ #pragma once #include "il2cpp-config.h" #include "object-internals.h" struct mscorlib_System_Reflection_Assembly; struct mscorlib_System_Reflection_Module; struct mscorlib_System_Reflection_MethodInfo; typedef int32_t GenericParameterAttributes; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API Type { public: static bool EqualsInternal(Il2CppReflectionType* left, Il2CppReflectionType* right); static GenericParameterAttributes GetGenericParameterAttributes(Il2CppReflectionType* type); static Il2CppArray* GetGenericParameterConstraints_impl(Il2CppReflectionType* type); static int32_t GetGenericParameterPosition(Il2CppReflectionType* type); static Il2CppReflectionType* GetGenericTypeDefinition_impl(Il2CppReflectionType*); static void GetInterfaceMapData(Il2CppReflectionType* t, Il2CppReflectionType* iface, Il2CppArray** targets, Il2CppArray** methods); static void GetPacking(Il2CppReflectionType* type, int32_t* packing, int32_t* size); static int GetTypeCodeInternal(Il2CppReflectionType*); static bool IsArrayImpl(Il2CppReflectionType* t); static bool IsInstanceOfType(Il2CppReflectionType* type, Il2CppObject* obj); static Il2CppReflectionType* MakeGenericType(Il2CppReflectionType* , Il2CppArray*); static Il2CppReflectionType* MakePointerType(Il2CppReflectionType* thisPtr); static bool get_IsGenericType(Il2CppReflectionType*); static bool get_IsGenericTypeDefinition(Il2CppReflectionType* type); static Il2CppReflectionType* internal_from_handle(Il2CppIntPtr ptr); static Il2CppReflectionType* internal_from_name(Il2CppString* name, bool throwOnError, bool ignoreCase); static Il2CppReflectionType* make_array_type(Il2CppReflectionType* type, int32_t rank); static bool type_is_assignable_from(Il2CppReflectionType* type, Il2CppReflectionType* c); static bool type_is_subtype_of(Il2CppReflectionType* type, Il2CppReflectionType* c, bool check_interfaces); static Il2CppReflectionType* make_byref_type(Il2CppReflectionType* type); }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/TypedReference.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System/TypedReference.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { Il2CppObject* TypedReference::ToObject(void* /* System.TypedReference */ value) { NOT_SUPPORTED_IL2CPP(TypedReference::ToObject, "This icall is not supported by il2cpp."); return 0; } #if NET_4_0 Il2CppObject* TypedReference::InternalToObject(void* value) { NOT_IMPLEMENTED_ICALL(TypedReference::InternalToObject); IL2CPP_UNREACHABLE; return NULL; } Il2CppTypedRef TypedReference::MakeTypedReferenceInternal(Il2CppObject* target, Il2CppArray* fields) { NOT_IMPLEMENTED_ICALL(TypedReference::MakeTypedReferenceInternal); IL2CPP_UNREACHABLE; return Il2CppTypedRef(); } #endif } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/TypedReference.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API TypedReference { public: static Il2CppObject* ToObject(void* /* System.TypedReference */ value); #if NET_4_0 static Il2CppObject* InternalToObject(void* value); static Il2CppTypedRef MakeTypedReferenceInternal(Il2CppObject* target, Il2CppArray* fields); #endif }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/ValueType.cpp ================================================ #include "il2cpp-config.h" #include #include "icalls/mscorlib/System/ValueType.h" #include "tabledefs.h" #include "class-internals.h" #include "object-internals.h" #include "gc/WriteBarrier.h" #include "utils/StringUtils.h" #include "vm/Array.h" #include "vm/Class.h" #include "vm/Exception.h" #include "vm/Field.h" #include "vm/Object.h" #include "vm/String.h" using namespace il2cpp::vm; using il2cpp::gc::WriteBarrier; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { bool ValueType::InternalEquals(Il2CppObject * thisPtr, Il2CppObject * that, Il2CppArray** fields) { Il2CppClass *klass; Il2CppObject **values = NULL; Il2CppObject *o; FieldInfo* field; void* iter; int count = 0; IL2CPP_CHECK_ARG_NULL(that); if (thisPtr->klass != that->klass) return false; klass = Object::GetClass(thisPtr); if (klass->enumtype && Class::GetEnumBaseType(klass) && Class::GetEnumBaseType(klass)->type == IL2CPP_TYPE_I4) return (*(int32_t*)((uint8_t*)thisPtr + sizeof(Il2CppObject)) == *(int32_t*)((uint8_t*)that + sizeof(Il2CppObject))); /* * Do the comparison for fields of primitive type and return a result if * possible. Otherwise, return the remaining fields in an array to the * managed side. This way, we can avoid costly reflection operations in * managed code. */ *fields = NULL; iter = NULL; while ((field = Class::GetFields(klass, &iter))) { if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) continue; if (Field::IsDeleted(field)) continue; /* FIXME: Add more types */ switch (field->type->type) { case IL2CPP_TYPE_I1: case IL2CPP_TYPE_U1: case IL2CPP_TYPE_BOOLEAN: if (*((uint8_t*)thisPtr + field->offset) != *((uint8_t*)that + field->offset)) return false; break; case IL2CPP_TYPE_I2: case IL2CPP_TYPE_U2: case IL2CPP_TYPE_CHAR: if (*(int16_t*)((uint8_t*)thisPtr + field->offset) != *(int16_t*)((uint8_t*)that + field->offset)) return false; break; case IL2CPP_TYPE_I4: case IL2CPP_TYPE_U4: if (*(int32_t*)((uint8_t*)thisPtr + field->offset) != *(int32_t*)((uint8_t*)that + field->offset)) return false; break; case IL2CPP_TYPE_I8: case IL2CPP_TYPE_U8: if (*(int64_t*)((uint8_t*)thisPtr + field->offset) != *(int64_t*)((uint8_t*)that + field->offset)) return false; break; case IL2CPP_TYPE_R4: if (*(float*)((uint8_t*)thisPtr + field->offset) != *(float*)((uint8_t*)that + field->offset)) return false; break; case IL2CPP_TYPE_R8: if (*(double*)((uint8_t*)thisPtr + field->offset) != *(double*)((uint8_t*)that + field->offset)) return false; break; case IL2CPP_TYPE_STRING: Il2CppString *s1, *s2; uint32_t s1len, s2len; s1 = *(Il2CppString**)((uint8_t*)thisPtr + field->offset); s2 = *(Il2CppString**)((uint8_t*)that + field->offset); if (s1 == s2) break; if ((s1 == NULL) || (s2 == NULL)) return false; s1len = utils::StringUtils::GetLength(s1); s2len = utils::StringUtils::GetLength(s2); if (s1len != s2len) return false; if (memcmp(utils::StringUtils::GetChars(s1), utils::StringUtils::GetChars(s2), s1len * sizeof(Il2CppChar)) != 0) return false; break; default: if (!values) values = (Il2CppObject**)alloca(sizeof(Il2CppObject*) * (Class::GetNumFields(klass) * 2)); o = Field::GetValueObject(field, thisPtr); values[count++] = o; o = Field::GetValueObject(field, that); values[count++] = o; } if (klass->enumtype) /* enums only have one non-static field */ break; } if (values) { int i; WriteBarrier::GenericStore(fields, (Il2CppObject*)Array::New(il2cpp_defaults.object_class, count)); for (i = 0; i < count; ++i) il2cpp_array_setref(*fields, i, values[i]); return false; } else { return true; } } int ValueType::InternalGetHashCode(Il2CppObject* obj, Il2CppArray** fields) { Il2CppObject **values = NULL; int count = 0; int32_t result = 0; FieldInfo* field = NULL; void* iter = NULL; Il2CppClass* klass = Object::GetClass(obj); if (Class::GetNumFields(klass) == 0) return Object::GetHash(obj); /* * Compute the starting value of the hashcode for fields of primitive * types, and return the remaining fields in an array to the managed side. * This way, we can avoid costly reflection operations in managed code. */ iter = NULL; while ((field = Class::GetFields(klass, &iter))) { if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) continue; if (Field::IsDeleted(field)) continue; /* FIXME: Add more types */ switch (field->type->type) { case IL2CPP_TYPE_I4: result ^= *(int32_t*)((uint8_t*)obj + field->offset); break; case IL2CPP_TYPE_STRING: { Il2CppString *s; s = *(Il2CppString**)((uint8_t*)obj + field->offset); if (s != NULL) result ^= String::GetHash(s); break; } default: if (!values) values = (Il2CppObject**)alloca(sizeof(Il2CppObject*) * Class::GetNumFields(klass)); Il2CppObject* o = Field::GetValueObject(field, obj); values[count++] = o; } } if (values) { int i; WriteBarrier::GenericStore(fields, (Il2CppObject*)Array::New(il2cpp_defaults.object_class, count)); for (i = 0; i < count; ++i) il2cpp_array_setref(*fields, i, values[i]); } else { *fields = NULL; } return result; } } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/ValueType.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppArray; struct Il2CppObject; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API ValueType { public: static bool InternalEquals(Il2CppObject * thisPtr, Il2CppObject * that, Il2CppArray** fields); static int InternalGetHashCode(Il2CppObject *, Il2CppArray * *); }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/__ComObject.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System/__ComObject.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { mscorlib_System___ComObject * __ComObject::CreateRCW(Il2CppReflectionType * t) { NOT_IMPLEMENTED_ICALL(__ComObject::CreateRCW); return 0; } void __ComObject::ReleaseInterfaces(mscorlib_System___ComObject * thisPtr) { NOT_IMPLEMENTED_ICALL(__ComObject::ReleaseInterfaces); } Il2CppIntPtr __ComObject::GetInterfaceInternal(mscorlib_System___ComObject * thisPtr, Il2CppReflectionType * t, bool throwException) { NOT_IMPLEMENTED_ICALL(__ComObject::GetInterfaceInternal); return Il2CppIntPtr(); } } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System/__ComObject.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppReflectionType; struct mscorlib_System___ComObject; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { class LIBIL2CPP_CODEGEN_API __ComObject { public: static mscorlib_System___ComObject * CreateRCW(Il2CppReflectionType * t); static void ReleaseInterfaces(mscorlib_System___ComObject * thisPtr); static Il2CppIntPtr GetInterfaceInternal(mscorlib_System___ComObject * thisPtr, Il2CppReflectionType * t, bool throwException); }; } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Diagnostics/Assert.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "Assert.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Diagnostics { int32_t Assert::ShowDefaultAssertDialog(Il2CppString* conditionString, Il2CppString* message, Il2CppString* stackTrace, Il2CppString* windowTitle) { NOT_IMPLEMENTED_ICALL(Assert::ShowDefaultAssertDialog); IL2CPP_UNREACHABLE; return 0; } } // namespace Diagnostics } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Diagnostics/Assert.h ================================================ #pragma once #if NET_4_0 namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Diagnostics { class LIBIL2CPP_CODEGEN_API Assert { public: static int32_t ShowDefaultAssertDialog(Il2CppString* conditionString, Il2CppString* message, Il2CppString* stackTrace, Il2CppString* windowTitle); }; } // namespace Diagnostics } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Diagnostics/Debugger.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Diagnostics/Debugger.h" #include "os/Debug.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Diagnostics { // Until we have il2cpp debugger, return whether a native debugger is attached bool Debugger::IsAttached_internal() { return os::Debug::IsDebuggerPresent(); } #if NET_4_0 bool Debugger::IsLogging() { NOT_IMPLEMENTED_ICALL(Debugger::IsLogging); IL2CPP_UNREACHABLE; return false; } void Debugger::Log(int32_t level, Il2CppString* category, Il2CppString* message) { NOT_IMPLEMENTED_ICALL(Debugger::Log); IL2CPP_UNREACHABLE; } #endif } /* namespace Diagnostics */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Diagnostics/Debugger.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Diagnostics { class LIBIL2CPP_CODEGEN_API Debugger { public: static bool IsAttached_internal(); #if NET_4_0 static bool IsLogging(); static void Log(int32_t level, Il2CppString* category, Il2CppString* message); #endif }; } /* namespace Diagnostics */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Diagnostics/StackFrame.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Diagnostics/StackFrame.h" #include "vm/Reflection.h" #include "vm/StackTrace.h" #include "class-internals.h" using namespace il2cpp::vm; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Diagnostics { static bool IsCalledFromSystemDiagnosticsStackTrace(const StackFrames& stack) { for (StackFrames::const_iterator frame = stack.begin(); frame != stack.end(); ++frame) if (strcmp(frame->method->declaring_type->namespaze, "System.Diagnostics") == 0 && strcmp(frame->method->declaring_type->name, "StackTrace") == 0) return true; return false; } static bool FrameNeedsSkipped(const Il2CppStackFrameInfo& frame) { return strcmp(frame.method->declaring_type->namespaze, "System.Diagnostics") == 0 && (strcmp(frame.method->declaring_type->name, "StackFrame") == 0 || strcmp(frame.method->declaring_type->name, "StackTrace") == 0); } bool StackFrame::get_frame_info( int32_t skip, bool needFileInfo, Il2CppReflectionMethod ** method, int32_t* iloffset, int32_t* native_offset, Il2CppString** file, int32_t* line, int32_t* column) { const int kSkippedFramesFromMSCorlibStackFrameMethods = 2; const int kSkippedFramesFromMSCorlibStackTraceMethods = 2; const StackFrames& stack = *StackTrace::GetStackFrames(); // Always ignore the skipped frames from System.Diagnostics.StackFrame, as we know we are always called from it. // These frames might be inlined or optimized away by the C++ compiler, so we will inspect the actual stack // frames later to see if we need to add skipped frames back in for System.Diagnostics.StackFrame. skip -= kSkippedFramesFromMSCorlibStackFrameMethods; // Sometimes ignore the skipped frames from System.Diagnostics.StackTrace, as we may or may not be called from it. // These frames might be inlined or optimized away by the C++ compiler, so we will inspect the actual stack // frames later to see if we need to add skipped frames back in for System.Diagnostics.StackTrace. if (IsCalledFromSystemDiagnosticsStackTrace(stack)) skip -= kSkippedFramesFromMSCorlibStackTraceMethods; // Now look in the actual stack trace to see if anything we ignored above is really there. We don't know what the C++ // compile will do with these frames, so we need to inspect each frame and check. for (StackFrames::const_iterator frame = stack.begin(); frame != stack.end(); ++frame) { if (FrameNeedsSkipped(*frame)) skip++; } // Finally, find the location in the stack we actually want to use by offsetting from the end of the stack the number of // frames we skipped, and offsetting it by one more to account for this icall itself. int64_t index = stack.size() - skip - 1; if (static_cast(index) >= stack.size() || index < 0) return false; const Il2CppStackFrameInfo& info = stack[static_cast(index)]; NOT_IMPLEMENTED_ICALL_NO_ASSERT(StackFrame::get_frame_info, "use gc write barrier"); *method = Reflection::GetMethodObject(info.method, info.method->declaring_type); return true; } } /* namespace Diagnostics */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Diagnostics/StackFrame.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppString; struct Il2CppReflectionMethod; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Diagnostics { class LIBIL2CPP_CODEGEN_API StackFrame { public: static bool get_frame_info( int32_t skip, bool needFileInfo, Il2CppReflectionMethod ** method, int32_t* iloffset, int32_t* native_offset, Il2CppString** file, int32_t* line, int32_t* column); }; } /* namespace Diagnostics */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Diagnostics/StackTrace.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "object-internals.h" #include "vm/Array.h" #include "vm/Object.h" #include "vm/Reflection.h" #include "icalls/mscorlib/System.Diagnostics/StackTrace.h" using namespace il2cpp::vm; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Diagnostics { Il2CppArray* StackTrace::get_trace(Il2CppException *exc, int32_t skip, bool need_file_info) { Il2CppArray *res; Il2CppArray *ta = exc->trace_ips; int i, len; if (ta == NULL) { /* Exception is not thrown yet */ return Array::New(il2cpp_defaults.stack_frame_class, 0); } len = Array::GetLength(ta); res = Array::New(il2cpp_defaults.stack_frame_class, len > skip ? len - skip : 0); for (i = skip; i < len; i++) { Il2CppStackFrame *sf = (Il2CppStackFrame*)Object::New(il2cpp_defaults.stack_frame_class); MethodInfo* method = il2cpp_array_get(ta, MethodInfo*, i); IL2CPP_OBJECT_SETREF(sf, method, Reflection::GetMethodObject(method, NULL)); il2cpp_array_setref(res, i, sf); } return res; } } /* namespace Diagnostics */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Diagnostics/StackTrace.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppArray; struct Il2CppException; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Diagnostics { class LIBIL2CPP_CODEGEN_API StackTrace { public: static Il2CppArray* get_trace(Il2CppException *exc, int32_t skip, bool need_file_info); }; } /* namespace Diagnostics */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Globalization/CalendarData.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "CalendarData.h" #include "object-internals.h" #include "CultureInfoTables.h" #include "il2cpp-api.h" #include "class-internals.h" #include "vm/Array.h" #include "vm/String.h" #include #include "utils/StringUtils.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Globalization { static Il2CppArray* create_names_array_idx(const uint16_t* names, int max) { if (names == NULL) return NULL; int len = 0; for (int i = 0; i < max; i++) { if (names[i] == 0) break; len++; } Il2CppArray* ret = il2cpp_array_new_specific(il2cpp_array_class_get(il2cpp_defaults.string_class, 1), len + 1); for (int i = 0; i < len; i++) il2cpp_array_setref(ret, i, il2cpp_string_new(idx2string(names[i]))); il2cpp_array_setref(ret, len, vm::String::Empty()); return ret; } static int culture_name_locator(const void *a, const void *b) { const char* aa = (const char*)a; const CultureInfoNameEntry* bb = (const CultureInfoNameEntry*)b; int ret; ret = strcmp(aa, idx2string(bb->name)); return ret; } bool CalendarData::fill_calendar_data(Il2CppCalendarData* _this, Il2CppString* localeName, int32_t datetimeIndex) { const DateTimeFormatEntry *dfe; const CultureInfoEntry *ci; std::string cultureName = il2cpp::utils::StringUtils::Utf16ToUtf8(localeName->chars); const CultureInfoNameEntry* ne = (const CultureInfoNameEntry*)bsearch(cultureName.c_str(), culture_name_entries, NUM_CULTURE_ENTRIES, sizeof(CultureInfoNameEntry), culture_name_locator); if (ne == NULL) { return false; } ci = &culture_entries[ne->culture_entry_index]; dfe = &datetime_format_entries[ci->datetime_format_index]; IL2CPP_OBJECT_SETREF(_this, NativeName, il2cpp_string_new(idx2string(ci->nativename))); Il2CppArray *short_date_patterns = create_names_array_idx(dfe->short_date_patterns, NUM_SHORT_DATE_PATTERNS); IL2CPP_OBJECT_SETREF(_this, ShortDatePatterns, short_date_patterns); Il2CppArray *year_month_patterns = create_names_array_idx(dfe->year_month_patterns, NUM_YEAR_MONTH_PATTERNS); IL2CPP_OBJECT_SETREF(_this, YearMonthPatterns, year_month_patterns); Il2CppArray *long_date_patterns = create_names_array_idx(dfe->long_date_patterns, NUM_LONG_DATE_PATTERNS); IL2CPP_OBJECT_SETREF(_this, LongDatePatterns, long_date_patterns); IL2CPP_OBJECT_SETREF(_this, MonthDayPattern, il2cpp_string_new(idx2string(dfe->month_day_pattern))); Il2CppArray *day_names = create_names_array_idx(dfe->day_names, NUM_DAYS); IL2CPP_OBJECT_SETREF(_this, DayNames, day_names); Il2CppArray *abbr_day_names = create_names_array_idx(dfe->abbreviated_day_names, NUM_DAYS); IL2CPP_OBJECT_SETREF(_this, AbbreviatedDayNames, abbr_day_names); Il2CppArray *ss_day_names = create_names_array_idx(dfe->shortest_day_names, NUM_DAYS); IL2CPP_OBJECT_SETREF(_this, SuperShortDayNames, ss_day_names); Il2CppArray *month_names = create_names_array_idx(dfe->month_names, NUM_MONTHS); IL2CPP_OBJECT_SETREF(_this, MonthNames, month_names); Il2CppArray *abbr_mon_names = create_names_array_idx(dfe->abbreviated_month_names, NUM_MONTHS); IL2CPP_OBJECT_SETREF(_this, AbbreviatedMonthNames, abbr_mon_names); Il2CppArray *gen_month_names = create_names_array_idx(dfe->month_genitive_names, NUM_MONTHS); IL2CPP_OBJECT_SETREF(_this, GenitiveMonthNames, gen_month_names); Il2CppArray *gen_abbr_mon_names = create_names_array_idx(dfe->abbreviated_month_genitive_names, NUM_MONTHS); IL2CPP_OBJECT_SETREF(_this, GenitiveAbbreviatedMonthNames, gen_abbr_mon_names); return true; } } // namespace Globalization } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Globalization/CalendarData.h ================================================ #pragma once #if NET_4_0 struct Il2CppCalendarData; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Globalization { class LIBIL2CPP_CODEGEN_API CalendarData { public: static bool fill_calendar_data(Il2CppCalendarData* _this, Il2CppString* localeName, int32_t datetimeIndex); }; } // namespace Globalization } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Globalization/CompareInfo.cpp ================================================ #include "il2cpp-config.h" #include #include "object-internals.h" #include "class-internals.h" #include "icalls/mscorlib/System.Globalization/CompareInfo.h" #include "icalls/mscorlib/System.Globalization/CompareOptions.h" #include "vm/String.h" #include "vm/Exception.h" #include "vm/Array.h" #include "utils/StringUtils.h" #include "vm-utils/VmStringUtils.h" #include #include namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Globalization { void CompareInfo::free_internal_collator(mscorlib_System_Globalization_CompareInfo * thisPtr) { // This method does not need any implementation. } static int string_invariant_indexof(Il2CppString *source, int sindex, int count, Il2CppString *value, bool first) { int lencmpstr = il2cpp::utils::StringUtils::GetLength(value); Il2CppChar* src = il2cpp::utils::StringUtils::GetChars(source); Il2CppChar* cmpstr = il2cpp::utils::StringUtils::GetChars(value); if (first) { count -= lencmpstr; for (int pos = sindex; pos <= sindex + count; pos++) { for (int i = 0; src[pos + i] == cmpstr[i];) { if (++i == lencmpstr) return (pos); } } return (-1); } else { for (int pos = sindex - lencmpstr + 1; pos > sindex - count; pos--) { if (memcmp(src + pos, cmpstr, lencmpstr * sizeof(Il2CppChar)) == 0) return (pos); } return (-1); } } int CompareInfo::internal_index(mscorlib_System_Globalization_CompareInfo *thisPtr, Il2CppString *source, int sindex, int count, Il2CppString *value, int options, bool first) { return (string_invariant_indexof(source, sindex, count, value, first)); } static int string_invariant_compare_char(Il2CppChar c1, Il2CppChar c2, int options) { int result = 0; // Ordinal can not be mixed with other options, and must return the difference, not only -1, 0, 1. if (options & CompareOptions_Ordinal) return (int)(c1 - c2); if (options & CompareOptions_IgnoreCase) { result = towlower(c1) - towlower(c2); } else { /* * No options. Kana, symbol and spacing options don't * apply to the invariant culture. */ /* * FIXME: here we must use the information from c1type and c2type * to find out the proper collation, even on the InvariantCulture, the * sorting is not done by computing the unicode values, but their * actual sort order. */ result = (int)(c1 - c2); } return ((result < 0) ? -1 : (result > 0) ? 1 : 0); } static int string_invariant_compare(Il2CppString *str1, int off1, int len1, Il2CppString *str2, int off2, int len2, int options) { int length; if (len1 >= len2) length = len1; else length = len2; Il2CppChar* ustr1 = il2cpp::utils::StringUtils::GetChars(str1) + off1; Il2CppChar* ustr2 = il2cpp::utils::StringUtils::GetChars(str2) + off2; int pos = 0; for (pos = 0; pos != length; pos++) { if (pos >= len1 || pos >= len2) break; int charcmp = string_invariant_compare_char(ustr1[pos], ustr2[pos], options); if (charcmp != 0) return (charcmp); } // The lesser wins, so if we have looped until length we just need to check the last char. if (pos == length) return (string_invariant_compare_char(ustr1[pos - 1], ustr2[pos - 1], options)); // Test if one of the strings has been compared to the end. if (pos >= len1) { if (pos >= len2) return (0); else return (-1); } else if (pos >= len2) return (1); // If not, check our last char only.. (can this happen?) return (string_invariant_compare_char(ustr1[pos], ustr2[pos], options)); } int CompareInfo::internal_compare(mscorlib_System_Globalization_CompareInfo *thisPtr, Il2CppString *str1, int off1, int len1, Il2CppString *str2, int off2, int len2, int options) { //MONO_ARCH_SAVE_REGS; // Do a normal ascii string compare, as we only know the invariant locale if we dont have ICU. return (string_invariant_compare(str1, off1, len1, str2, off2, len2, options)); } void CompareInfo::construct_compareinfo(mscorlib_System_Globalization_CompareInfo *, Il2CppString *) { // This method does not need any implementation. } static Il2CppArray* GetSortKeyCaseSensitive(Il2CppString* source) { const int32_t keyLength = sizeof(Il2CppChar) * source->length; Il2CppArray* keyBytes = vm::Array::New(il2cpp_defaults.byte_class, keyLength); memcpy(il2cpp_array_addr(keyBytes, uint8_t, 0), source->chars, keyLength); return keyBytes; } static Il2CppArray* GetSortKeyIgnoreCase(Il2CppString* source) { const int32_t keyLength = sizeof(Il2CppChar) * source->length; Il2CppArray* keyBytes = vm::Array::New(il2cpp_defaults.byte_class, keyLength); Il2CppChar* destination = reinterpret_cast(il2cpp_array_addr(keyBytes, uint8_t, 0)); for (int i = 0; i < source->length; i++, destination++) { *destination = utils::VmStringUtils::Utf16ToLower(source->chars[i]); } return keyBytes; } void CompareInfo::assign_sortkey(void* /* System.Globalization.CompareInfo */ self, Il2CppSortKey* key, Il2CppString* source, CompareOptions options) { if ((options & CompareOptions_IgnoreCase) != 0 || (options & CompareOptions_OrdinalIgnoreCase) != 0) { key->key = GetSortKeyIgnoreCase(source); } else { key->key = GetSortKeyCaseSensitive(source); } } } /* namespace Globalization */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Globalization/CompareInfo.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "CompareOptions.h" struct Il2CppString; struct Il2CppObject; struct Il2CppSortKey; struct mscorlib_System_Globalization_CompareInfo; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Globalization { class LIBIL2CPP_CODEGEN_API CompareInfo { public: static void assign_sortkey(void* /* System.Globalization.CompareInfo */ self, Il2CppSortKey* key, Il2CppString* source, CompareOptions options); static void free_internal_collator(mscorlib_System_Globalization_CompareInfo * thisPtr); static int internal_compare(mscorlib_System_Globalization_CompareInfo *, Il2CppString *, int, int, Il2CppString *, int, int, int); static int internal_index(mscorlib_System_Globalization_CompareInfo *thisPtr, Il2CppString *source, int sindex, int count, Il2CppString *value, int options, bool first); static void construct_compareinfo(mscorlib_System_Globalization_CompareInfo *, Il2CppString *); }; } /* namespace Globalization */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Globalization/CompareOptions.h ================================================ #pragma once #include namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Globalization { // System.Globalization.CompareOptions typedef enum { CompareOptions_None = 0x00, CompareOptions_IgnoreCase = 0x01, CompareOptions_IgnoreNonSpace = 0x02, CompareOptions_IgnoreSymbols = 0x04, CompareOptions_IgnoreKanaType = 0x08, CompareOptions_IgnoreWidth = 0x10, CompareOptions_StringSort = 0x20000000, CompareOptions_Ordinal = 0x40000000, CompareOptions_OrdinalIgnoreCase = 0x10000000 } CompareOptions; } /* namespace Globalization */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Globalization/CultureData.cpp ================================================ #ifdef NET_4_0 #include "il2cpp-config.h" #include "CultureData.h" #include "CultureInfoInternals.h" #include "CultureInfoTables.h" #include "il2cpp-api.h" #include "object-internals.h" #include "class-internals.h" #include "vm/Array.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Globalization { static Il2CppArray* create_names_array_idx(const uint16_t* names, int max) { if (names == NULL) return NULL; int len = 0; for (int i = 0; i < max; i++) { if (names[i] == 0) break; len++; } Il2CppArray* ret = il2cpp_array_new_specific(il2cpp_array_class_get(il2cpp_defaults.string_class, 1), len); for (int i = 0; i < len; i++) il2cpp_array_setref(ret, i, il2cpp_string_new(idx2string(names[i]))); return ret; } static Il2CppArray* create_group_sizes_array(const int *gs, int ml) { int i, len = 0; for (i = 0; i < ml; i++) { if (gs[i] == -1) break; len++; } Il2CppArray* ret = il2cpp_array_new_specific(il2cpp_array_class_get(il2cpp_defaults.int32_class, 1), len); for (i = 0; i < len; i++) il2cpp_array_set(ret, int32_t, i, gs[i]); return ret; } void CultureData::fill_culture_data(Il2CppCultureData* _this, int32_t datetimeIndex) { const DateTimeFormatEntry *dfe; IL2CPP_ASSERT(datetimeIndex >= 0); dfe = &datetime_format_entries[datetimeIndex]; IL2CPP_OBJECT_SETREF(_this, AMDesignator, il2cpp_string_new(idx2string(dfe->am_designator))); IL2CPP_OBJECT_SETREF(_this, PMDesignator, il2cpp_string_new(idx2string(dfe->pm_designator))); IL2CPP_OBJECT_SETREF(_this, TimeSeparator, il2cpp_string_new(idx2string(dfe->time_separator))); Il2CppArray *long_time_patterns = create_names_array_idx(dfe->long_time_patterns, NUM_LONG_TIME_PATTERNS); IL2CPP_OBJECT_SETREF(_this, LongTimePatterns, long_time_patterns); Il2CppArray *short_time_patterns = create_names_array_idx(dfe->short_time_patterns, NUM_SHORT_TIME_PATTERNS); IL2CPP_OBJECT_SETREF(_this, ShortTimePatterns, short_time_patterns); _this->FirstDayOfWeek = dfe->first_day_of_week; _this->CalendarWeekRule = dfe->calendar_week_rule; } void CultureData::fill_number_data(Il2CppNumberFormatInfo* number, int32_t numberIndex) { const NumberFormatEntry *nfe; IL2CPP_ASSERT(numberIndex >= 0); nfe = &number_format_entries[numberIndex]; number->currencyDecimalDigits = nfe->currency_decimal_digits; IL2CPP_OBJECT_SETREF(number, currencyDecimalSeparator, il2cpp_string_new(idx2string(nfe->currency_decimal_separator))); IL2CPP_OBJECT_SETREF(number, currencyGroupSeparator, il2cpp_string_new(idx2string(nfe->currency_group_separator))); Il2CppArray *currency_sizes_arr = create_group_sizes_array(nfe->currency_group_sizes, GROUP_SIZE); IL2CPP_OBJECT_SETREF(number, currencyGroupSizes, currency_sizes_arr); number->currencyNegativePattern = nfe->currency_negative_pattern; number->currencyPositivePattern = nfe->currency_positive_pattern; IL2CPP_OBJECT_SETREF(number, currencySymbol, il2cpp_string_new(idx2string(nfe->currency_symbol))); IL2CPP_OBJECT_SETREF(number, naNSymbol, il2cpp_string_new(idx2string(nfe->nan_symbol))); IL2CPP_OBJECT_SETREF(number, negativeInfinitySymbol, il2cpp_string_new(idx2string(nfe->negative_infinity_symbol))); IL2CPP_OBJECT_SETREF(number, negativeSign, il2cpp_string_new(idx2string(nfe->negative_sign))); number->numberDecimalDigits = nfe->number_decimal_digits; IL2CPP_OBJECT_SETREF(number, numberDecimalSeparator, il2cpp_string_new(idx2string(nfe->number_decimal_separator))); IL2CPP_OBJECT_SETREF(number, numberGroupSeparator, il2cpp_string_new(idx2string(nfe->number_group_separator))); Il2CppArray *number_sizes_arr = create_group_sizes_array(nfe->number_group_sizes, GROUP_SIZE); IL2CPP_OBJECT_SETREF(number, numberGroupSizes, number_sizes_arr); number->numberNegativePattern = nfe->number_negative_pattern; number->percentNegativePattern = nfe->percent_negative_pattern; number->percentPositivePattern = nfe->percent_positive_pattern; IL2CPP_OBJECT_SETREF(number, percentSymbol, il2cpp_string_new(idx2string(nfe->percent_symbol))); IL2CPP_OBJECT_SETREF(number, perMilleSymbol, il2cpp_string_new(idx2string(nfe->per_mille_symbol))); IL2CPP_OBJECT_SETREF(number, positiveInfinitySymbol, il2cpp_string_new(idx2string(nfe->positive_infinity_symbol))); IL2CPP_OBJECT_SETREF(number, positiveSign, il2cpp_string_new(idx2string(nfe->positive_sign))); } } // namespace Globalization } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Globalization/CultureData.h ================================================ #pragma once #if NET_4_0 #include "object-internals.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Globalization { class LIBIL2CPP_CODEGEN_API CultureData { public: static void fill_culture_data(Il2CppCultureData* _this, int32_t datetimeIndex); static void fill_number_data(Il2CppNumberFormatInfo* number, int32_t numberIndex); }; } // namespace Globalization } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Globalization/CultureInfo.cpp ================================================ #include "il2cpp-config.h" #include #include #include "il2cpp-api.h" #include "object-internals.h" #include "class-internals.h" #include "utils/Memory.h" #include "utils/StringUtils.h" #include "vm/Array.h" #include "vm/Exception.h" #include "vm/String.h" #include "os/Locale.h" #include "icalls/mscorlib/System.Globalization/CultureInfo.h" #include "CultureInfoInternals.h" #include "CultureInfoTables.h" /* * The following methods is modified from the ICU source code. (http://oss.software.ibm.com/icu) * Copyright (c) 1995-2003 International Business Machines Corporation and others * All rights reserved. */ static std::string get_current_locale_name(void) { char* locale; char* corrected = NULL; const char* p; std::string locale_str = il2cpp::os::Locale::GetLocale(); if (locale_str.empty()) return std::string(); locale = il2cpp::utils::StringUtils::StringDuplicate(locale_str.c_str()); if ((p = strchr(locale, '.')) != NULL) { /* assume new locale can't be larger than old one? */ corrected = (char*)IL2CPP_MALLOC(strlen(locale)); strncpy(corrected, locale, p - locale); corrected[p - locale] = 0; /* do not copy after the @ */ if ((p = strchr(corrected, '@')) != NULL) corrected[p - corrected] = 0; } /* Note that we scan the *uncorrected* ID. */ if ((p = strrchr(locale, '@')) != NULL) { /* * Mono we doesn't handle the '@' modifier because it does * not have any cultures that use it. Just trim it * off of the end of the name. */ if (corrected == NULL) { corrected = (char*)IL2CPP_MALLOC(strlen(locale)); strncpy(corrected, locale, p - locale); corrected[p - locale] = 0; } } if (corrected == NULL) corrected = locale; else IL2CPP_FREE(locale); char* c; if ((c = strchr(corrected, '_')) != NULL) *c = '-'; std::string result(corrected); IL2CPP_FREE(corrected); std::transform(result.begin(), result.end(), result.begin(), ::tolower); return result; } namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Globalization { static Il2CppArray* create_names_array_idx(const uint16_t* names, int max) { if (names == NULL) return NULL; int len = 0; for (int i = 0; i < max; i++) { if (names[i] == 0) break; len++; } Il2CppArray* ret = il2cpp_array_new_specific(il2cpp_array_class_get(il2cpp_defaults.string_class, 1), len); for (int i = 0; i < len; i++) il2cpp_array_setref(ret, i, il2cpp_string_new(idx2string(names[i]))); return ret; } static bool construct_culture(Il2CppCultureInfo* cultureInfo, const CultureInfoEntry *ci) { cultureInfo->lcid = ci->lcid; IL2CPP_OBJECT_SETREF(cultureInfo, name, il2cpp_string_new(idx2string(ci->name))); #if !NET_4_0 IL2CPP_OBJECT_SETREF(cultureInfo, icu_name, il2cpp_string_new(idx2string(ci->icu_name))); IL2CPP_OBJECT_SETREF(cultureInfo, displayname, il2cpp_string_new(idx2string(ci->displayname))); #endif IL2CPP_OBJECT_SETREF(cultureInfo, englishname, il2cpp_string_new(idx2string(ci->englishname))); IL2CPP_OBJECT_SETREF(cultureInfo, nativename, il2cpp_string_new(idx2string(ci->nativename))); IL2CPP_OBJECT_SETREF(cultureInfo, win3lang, il2cpp_string_new(idx2string(ci->win3lang))); IL2CPP_OBJECT_SETREF(cultureInfo, iso3lang, il2cpp_string_new(idx2string(ci->iso3lang))); IL2CPP_OBJECT_SETREF(cultureInfo, iso2lang, il2cpp_string_new(idx2string(ci->iso2lang))); #if !NET_4_0 IL2CPP_OBJECT_SETREF(cultureInfo, territory, il2cpp_string_new(idx2string(ci->territory))); #else // It's null for neutral cultures if(ci->territory > 0) IL2CPP_OBJECT_SETREF(cultureInfo, territory, il2cpp_string_new(idx2string(ci->territory))); #endif cultureInfo->parent_lcid = ci->parent_lcid; #if !NET_4_0 cultureInfo->specific_lcid = ci->specific_lcid; cultureInfo->calendar_data = ci->calendar_data; #endif cultureInfo->datetime_index = ci->datetime_format_index; cultureInfo->number_index = ci->number_format_index; cultureInfo->text_info_data = &ci->text_info; #if NET_4_0 IL2CPP_OBJECT_SETREF(cultureInfo, native_calendar_names, create_names_array_idx(ci->native_calendar_names, NUM_OPT_CALS)); cultureInfo->default_calendar_type = ci->calendar_type; #endif return true; } static int culture_name_locator(const void *a, const void *b) { const char* aa = (const char*)a; const CultureInfoNameEntry* bb = (const CultureInfoNameEntry*)b; int ret; ret = strcmp(aa, idx2string(bb->name)); return ret; } static int culture_lcid_locator(const void *a, const void *b) { const CultureInfoEntry *aa = (const CultureInfoEntry *)a; const CultureInfoEntry *bb = (const CultureInfoEntry *)b; return (aa->lcid - bb->lcid); } static const CultureInfoEntry* culture_info_entry_from_lcid(int lcid) { CultureInfoEntry key; key.lcid = lcid; return (const CultureInfoEntry*)bsearch(&key, culture_entries, NUM_CULTURE_ENTRIES, sizeof(CultureInfoEntry), culture_lcid_locator); } #if !NET_4_0 static bool construct_culture_from_specific_name(Il2CppCultureInfo* cultureInfo, const char *name) { const CultureInfoNameEntry* ne = (const CultureInfoNameEntry *)bsearch(name, culture_name_entries, NUM_CULTURE_ENTRIES, sizeof(CultureInfoNameEntry), culture_name_locator); if (ne == NULL) return false; const CultureInfoEntry* entry = &culture_entries[ne->culture_entry_index]; /* try avoiding another lookup, often the culture is its own specific culture */ if (entry->lcid != entry->specific_lcid) entry = culture_info_entry_from_lcid(entry->specific_lcid); if (entry) return construct_culture(cultureInfo, entry); else return false; } #endif static Il2CppArray* create_group_sizes_array(const int *gs, int ml) { int i, len = 0; for (i = 0; i < ml; i++) { if (gs[i] == -1) break; len++; } Il2CppArray* ret = il2cpp_array_new_specific(il2cpp_array_class_get(il2cpp_defaults.int32_class, 1), len); for (i = 0; i < len; i++) il2cpp_array_set(ret, int32_t, i, gs[i]); return ret; } #if !NET_4_0 void CultureInfo::construct_datetime_format(Il2CppCultureInfo* cultureInfo) { IL2CPP_ASSERT(cultureInfo->datetime_index >= 0); Il2CppDateTimeFormatInfo* datetime = cultureInfo->datetime_format; const DateTimeFormatEntry* dfe = &datetime_format_entries[cultureInfo->datetime_index]; datetime->readOnly = cultureInfo->is_read_only; IL2CPP_OBJECT_SETREF(datetime, AbbreviatedDayNames, create_names_array_idx(dfe->abbreviated_day_names, NUM_DAYS)); IL2CPP_OBJECT_SETREF(datetime, AbbreviatedMonthNames, create_names_array_idx(dfe->abbreviated_month_names, NUM_MONTHS)); IL2CPP_OBJECT_SETREF(datetime, AMDesignator, il2cpp_string_new(idx2string(dfe->am_designator))); datetime->CalendarWeekRule = dfe->calendar_week_rule; IL2CPP_OBJECT_SETREF(datetime, DateSeparator, il2cpp_string_new(idx2string(dfe->date_separator))); IL2CPP_OBJECT_SETREF(datetime, DayNames, create_names_array_idx(dfe->day_names, NUM_DAYS)); datetime->FirstDayOfWeek = dfe->first_day_of_week; IL2CPP_OBJECT_SETREF(datetime, FullDateTimePattern, il2cpp_string_new(idx2string(dfe->full_date_time_pattern))); IL2CPP_OBJECT_SETREF(datetime, LongDatePattern, il2cpp_string_new(idx2string(dfe->long_date_pattern))); IL2CPP_OBJECT_SETREF(datetime, LongTimePattern, il2cpp_string_new(idx2string(dfe->long_time_pattern))); IL2CPP_OBJECT_SETREF(datetime, MonthDayPattern, il2cpp_string_new(idx2string(dfe->month_day_pattern))); IL2CPP_OBJECT_SETREF(datetime, MonthNames, create_names_array_idx(dfe->month_names, NUM_MONTHS)); IL2CPP_OBJECT_SETREF(datetime, PMDesignator, il2cpp_string_new(idx2string(dfe->pm_designator))); IL2CPP_OBJECT_SETREF(datetime, ShortDatePattern, il2cpp_string_new(idx2string(dfe->short_date_pattern))); IL2CPP_OBJECT_SETREF(datetime, ShortTimePattern, il2cpp_string_new(idx2string(dfe->short_time_pattern))); IL2CPP_OBJECT_SETREF(datetime, TimeSeparator, il2cpp_string_new(idx2string(dfe->time_separator))); IL2CPP_OBJECT_SETREF(datetime, YearMonthPattern, il2cpp_string_new(idx2string(dfe->year_month_pattern))); IL2CPP_OBJECT_SETREF(datetime, ShortDatePatterns, create_names_array_idx(dfe->short_date_patterns, NUM_SHORT_DATE_PATTERNS)); IL2CPP_OBJECT_SETREF(datetime, LongDatePatterns, create_names_array_idx(dfe->long_date_patterns, NUM_LONG_DATE_PATTERNS)); IL2CPP_OBJECT_SETREF(datetime, ShortTimePatterns, create_names_array_idx(dfe->short_time_patterns, NUM_SHORT_TIME_PATTERNS)); IL2CPP_OBJECT_SETREF(datetime, LongTimePatterns, create_names_array_idx(dfe->long_time_patterns, NUM_LONG_TIME_PATTERNS)); } bool CultureInfo::construct_internal_locale_from_current_locale(Il2CppCultureInfo* cultureInfo) { std::string locale = ::get_current_locale_name(); if (locale.empty()) return false; bool status = construct_culture_from_specific_name(cultureInfo, locale.c_str()); cultureInfo->is_read_only = true; cultureInfo->use_user_override = true; return status; } #endif bool CultureInfo::construct_internal_locale_from_lcid(Il2CppCultureInfo* cultureInfo, int lcid) { const CultureInfoEntry* ci = culture_info_entry_from_lcid(lcid); if (ci == NULL) return false; return construct_culture(cultureInfo, ci); } bool CultureInfo::construct_internal_locale_from_name(Il2CppCultureInfo* cultureInfo, Il2CppString* name) { std::string cultureName = il2cpp::utils::StringUtils::Utf16ToUtf8(name->chars); const CultureInfoNameEntry* ne = (const CultureInfoNameEntry*)bsearch(cultureName.c_str(), culture_name_entries, NUM_CULTURE_ENTRIES, sizeof(CultureInfoNameEntry), culture_name_locator); if (ne == NULL) return false; return construct_culture(cultureInfo, &culture_entries[ne->culture_entry_index]); } #if !NET_4_0 void CultureInfo::construct_number_format(Il2CppCultureInfo* cultureInfo) { IL2CPP_ASSERT(cultureInfo->number_format != 0); if (cultureInfo->number_index < 0) return; Il2CppNumberFormatInfo* number = cultureInfo->number_format; const NumberFormatEntry* nfe = &number_format_entries[cultureInfo->number_index]; number->readOnly = cultureInfo->is_read_only; number->currencyDecimalDigits = nfe->currency_decimal_digits; IL2CPP_OBJECT_SETREF(number, currencyDecimalSeparator, il2cpp_string_new(idx2string(nfe->currency_decimal_separator))); IL2CPP_OBJECT_SETREF(number, currencyGroupSeparator, il2cpp_string_new(idx2string(nfe->currency_group_separator))); IL2CPP_OBJECT_SETREF(number, currencyGroupSizes, create_group_sizes_array(nfe->currency_group_sizes, GROUP_SIZE)); number->currencyNegativePattern = nfe->currency_negative_pattern; number->currencyPositivePattern = nfe->currency_positive_pattern; IL2CPP_OBJECT_SETREF(number, currencySymbol, il2cpp_string_new(idx2string(nfe->currency_symbol))); IL2CPP_OBJECT_SETREF(number, naNSymbol, il2cpp_string_new(idx2string(nfe->nan_symbol))); IL2CPP_OBJECT_SETREF(number, negativeInfinitySymbol, il2cpp_string_new(idx2string(nfe->negative_infinity_symbol))); IL2CPP_OBJECT_SETREF(number, negativeSign, il2cpp_string_new(idx2string(nfe->negative_sign))); number->numberDecimalDigits = nfe->number_decimal_digits; IL2CPP_OBJECT_SETREF(number, numberDecimalSeparator, il2cpp_string_new(idx2string(nfe->number_decimal_separator))); IL2CPP_OBJECT_SETREF(number, numberGroupSeparator, il2cpp_string_new(idx2string(nfe->number_group_separator))); IL2CPP_OBJECT_SETREF(number, numberGroupSizes, create_group_sizes_array(nfe->number_group_sizes, GROUP_SIZE)); number->numberNegativePattern = nfe->number_negative_pattern; number->percentDecimalDigits = nfe->percent_decimal_digits; IL2CPP_OBJECT_SETREF(number, percentDecimalSeparator, il2cpp_string_new(idx2string(nfe->percent_decimal_separator))); IL2CPP_OBJECT_SETREF(number, percentGroupSeparator, il2cpp_string_new(idx2string(nfe->percent_group_separator))); IL2CPP_OBJECT_SETREF(number, percentGroupSizes, create_group_sizes_array(nfe->percent_group_sizes, GROUP_SIZE)); number->percentNegativePattern = nfe->percent_negative_pattern; number->percentPositivePattern = nfe->percent_positive_pattern; IL2CPP_OBJECT_SETREF(number, percentSymbol, il2cpp_string_new(idx2string(nfe->percent_symbol))); IL2CPP_OBJECT_SETREF(number, perMilleSymbol, il2cpp_string_new(idx2string(nfe->per_mille_symbol))); IL2CPP_OBJECT_SETREF(number, positiveInfinitySymbol, il2cpp_string_new(idx2string(nfe->positive_infinity_symbol))); IL2CPP_OBJECT_SETREF(number, positiveSign, il2cpp_string_new(idx2string(nfe->positive_sign))); } bool CultureInfo::construct_internal_locale_from_specific_name (Il2CppCultureInfo* cultureInfo, Il2CppString* name) { std::string cultureName = il2cpp::utils::StringUtils::Utf16ToUtf8 (name->chars); return construct_culture_from_specific_name (cultureInfo, cultureName.c_str()); } #endif static bool IsMatchingCultureInfoEntry (const CultureInfoEntry& entry, bool neutral, bool specific, bool installed) { #if !NET_4_0 const bool isNeutral = ((entry.lcid & 0xff00) == 0) || (entry.specific_lcid == 0); #else const bool isNeutral = entry.territory == 0; #endif return ((neutral && isNeutral) || (specific && !isNeutral)); } Il2CppArray* CultureInfo::internal_get_cultures (bool neutral, bool specific, bool installed) { // Count culture infos that match. int numMatchingCultures = 0; for (int i = 0; i < NUM_CULTURE_ENTRIES; ++i) { const CultureInfoEntry& entry = culture_entries[i]; if (IsMatchingCultureInfoEntry (entry, neutral, specific, installed)) ++numMatchingCultures; } if (neutral) ++numMatchingCultures; // Allocate result array. Il2CppClass* cultureInfoClass = il2cpp_defaults.culture_info; Il2CppArray* array = il2cpp_array_new (cultureInfoClass, numMatchingCultures); int index = 0; // InvariantCulture is not in culture table. We reserve the first // array element for it. if (neutral) il2cpp_array_set (array, Il2CppCultureInfo*, index++, NULL); // Populate CultureInfo entries. for (int i = 0; i < NUM_CULTURE_ENTRIES; ++i) { const CultureInfoEntry& entry = culture_entries[i]; if (!IsMatchingCultureInfoEntry (entry, neutral, specific, installed)) continue; Il2CppCultureInfo* info = reinterpret_cast (il2cpp_object_new (cultureInfoClass)); construct_culture (info, &entry); il2cpp_array_set (array, Il2CppCultureInfo*, index++, info); } return array; } bool CultureInfo::internal_is_lcid_neutral (int32_t lcid, bool* is_neutral) { NOT_SUPPORTED_IL2CPP (CultureInfo::internal_is_lcid_neutral, "This icall is not supported by il2cpp."); return false; } Il2CppString* CultureInfo::get_current_locale_name() { return vm::String::New(::get_current_locale_name().c_str()); } } /* namespace Globalization */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Globalization/CultureInfo.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppString; struct Il2CppCultureInfo; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Globalization { class LIBIL2CPP_CODEGEN_API CultureInfo { public: #if !NET_4_0 static void construct_datetime_format(Il2CppCultureInfo* cultureInfo); static bool construct_internal_locale_from_current_locale(Il2CppCultureInfo* cultureInfo); #endif static bool construct_internal_locale_from_lcid(Il2CppCultureInfo* cultureInfo, int lcid); static bool construct_internal_locale_from_name(Il2CppCultureInfo* cultureInfo, Il2CppString* name); #if !NET_4_0 static bool construct_internal_locale_from_specific_name(Il2CppCultureInfo* cultureInfo, Il2CppString* name); #endif static Il2CppArray* internal_get_cultures(bool neutral, bool specific, bool installed); static bool internal_is_lcid_neutral(int32_t lcid, bool* is_neutral); #if !NET_4_0 static void construct_number_format(Il2CppCultureInfo* cultureInfo); #endif static Il2CppString* get_current_locale_name(); }; } /* namespace Diagnostics */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Globalization/CultureInfoInternals.h ================================================ #pragma once #include #if !NET_4_0 #define NUM_DAYS 7 #define NUM_MONTHS 13 #define GROUP_SIZE 5 #define NUM_OPT_CALS 5 #define NUM_SHORT_DATE_PATTERNS 14 #define NUM_LONG_DATE_PATTERNS 8 #define NUM_SHORT_TIME_PATTERNS 11 #define NUM_LONG_TIME_PATTERNS 10 #else #define NUM_DAYS 7 #define NUM_MONTHS 13 #define GROUP_SIZE 2 #define NUM_OPT_CALS 4 #define NUM_SHORT_DATE_PATTERNS 14 #define NUM_LONG_DATE_PATTERNS 10 #define NUM_SHORT_TIME_PATTERNS 12 #define NUM_LONG_TIME_PATTERNS 9 #define NUM_YEAR_MONTH_PATTERNS 8 #endif #define idx2string(idx) (locale_strings + (idx)) #if !NET_4_0 struct DateTimeFormatEntry { const uint16_t full_date_time_pattern; const uint16_t long_date_pattern; const uint16_t short_date_pattern; const uint16_t long_time_pattern; const uint16_t short_time_pattern; const uint16_t year_month_pattern; const uint16_t month_day_pattern; const uint16_t am_designator; const uint16_t pm_designator; const uint16_t day_names[NUM_DAYS]; const uint16_t abbreviated_day_names[NUM_DAYS]; const uint16_t month_names[NUM_MONTHS]; const uint16_t abbreviated_month_names[NUM_MONTHS]; int8_t calendar_week_rule; int8_t first_day_of_week; const uint16_t date_separator; const uint16_t time_separator; const uint16_t short_date_patterns[NUM_SHORT_DATE_PATTERNS]; const uint16_t long_date_patterns[NUM_LONG_DATE_PATTERNS]; const uint16_t short_time_patterns[NUM_SHORT_TIME_PATTERNS]; const uint16_t long_time_patterns[NUM_LONG_TIME_PATTERNS]; }; #else struct DateTimeFormatEntry { const uint16_t month_day_pattern; const uint16_t am_designator; const uint16_t pm_designator; const uint16_t day_names[NUM_DAYS]; const uint16_t abbreviated_day_names[NUM_DAYS]; const uint16_t shortest_day_names[NUM_DAYS]; const uint16_t month_names[NUM_MONTHS]; const uint16_t month_genitive_names[NUM_MONTHS]; const uint16_t abbreviated_month_names[NUM_MONTHS]; const uint16_t abbreviated_month_genitive_names[NUM_MONTHS]; const int8_t calendar_week_rule; const int8_t first_day_of_week; const uint16_t date_separator; const uint16_t time_separator; const uint16_t short_date_patterns[NUM_SHORT_DATE_PATTERNS]; const uint16_t long_date_patterns[NUM_LONG_DATE_PATTERNS]; const uint16_t short_time_patterns[NUM_SHORT_TIME_PATTERNS]; const uint16_t long_time_patterns[NUM_LONG_TIME_PATTERNS]; const uint16_t year_month_patterns[NUM_YEAR_MONTH_PATTERNS]; }; #endif struct NumberFormatEntry { const uint16_t currency_decimal_separator; const uint16_t currency_group_separator; #if !NET_4_0 const uint16_t percent_decimal_separator; const uint16_t percent_group_separator; #endif const uint16_t number_decimal_separator; const uint16_t number_group_separator; const uint16_t currency_symbol; const uint16_t percent_symbol; const uint16_t nan_symbol; const uint16_t per_mille_symbol; const uint16_t negative_infinity_symbol; const uint16_t positive_infinity_symbol; const uint16_t negative_sign; const uint16_t positive_sign; int8_t currency_negative_pattern; int8_t currency_positive_pattern; int8_t percent_negative_pattern; int8_t percent_positive_pattern; int8_t number_negative_pattern; int8_t currency_decimal_digits; #if !NET_4_0 int8_t percent_decimal_digits; #endif int8_t number_decimal_digits; const int currency_group_sizes[GROUP_SIZE]; #if !NET_4_0 const int percent_group_sizes[GROUP_SIZE]; #endif const int number_group_sizes[GROUP_SIZE]; }; struct TextInfoEntry { /*const*/ int ansi; /*const*/ int ebcdic; /*const*/ int mac; /*const*/ int oem; #if NET_4_0 /*const*/ bool is_right_to_left; #endif /*const*/ char list_sep; }; #if !NET_4_0 struct CultureInfoEntry { int16_t lcid; int16_t parent_lcid; int16_t specific_lcid; int16_t region_entry_index; /*const*/ uint16_t name; /*const*/ uint16_t icu_name; /*const*/ uint16_t englishname; /*const*/ uint16_t displayname; /*const*/ uint16_t nativename; /*const*/ uint16_t win3lang; /*const*/ uint16_t iso3lang; /*const*/ uint16_t iso2lang; /*const*/ uint16_t territory; int calendar_data[NUM_OPT_CALS]; int16_t datetime_format_index; int16_t number_format_index; TextInfoEntry text_info; }; #else struct CultureInfoEntry { int16_t lcid; int16_t parent_lcid; int16_t calendar_type; int16_t region_entry_index; /*const*/ uint16_t name; /*const*/ uint16_t englishname; /*const*/ uint16_t nativename; /*const*/ uint16_t win3lang; /*const*/ uint16_t iso3lang; /*const*/ uint16_t iso2lang; /*const*/ uint16_t territory; /*const*/ uint16_t native_calendar_names[NUM_OPT_CALS]; int16_t datetime_format_index; int16_t number_format_index; TextInfoEntry text_info; }; #endif struct CultureInfoNameEntry { const uint16_t name; int16_t culture_entry_index; }; #if !NET_4_0 struct RegionInfoEntry { int16_t lcid; int16_t region_id; const uint16_t iso2name; const uint16_t iso3name; const uint16_t win3name; const uint16_t english_name; const uint16_t currency_symbol; const uint16_t iso_currency_symbol; const uint16_t currency_english_name; }; #else struct RegionInfoEntry { const int16_t geo_id; const uint16_t iso2name; const uint16_t iso3name; const uint16_t win3name; const uint16_t english_name; const uint16_t native_name; const uint16_t currency_symbol; const uint16_t iso_currency_symbol; const uint16_t currency_english_name; const uint16_t currency_native_name; }; #endif struct RegionInfoNameEntry { const uint16_t name; int16_t region_entry_index; }; ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Globalization/CultureInfoTables.h ================================================ #pragma once #include "CultureInfoInternals.h" /* This is a generated file. Do not edit. See tools/locale-builder. */ #ifndef MONO_METADATA_CULTURE_INFO_TABLES #define MONO_METADATA_CULTURE_INFO_TABLES 1 #if !NET_4_0 #define NUM_CULTURE_ENTRIES 167 #define NUM_REGION_ENTRIES 230 #else #define NUM_CULTURE_ENTRIES 281 #define NUM_REGION_ENTRIES 117 #endif #if !NET_4_0 static const DateTimeFormatEntry datetime_format_entries[] = { { 1, 24, 37, 46, 56, 63, 74, 81, 84, { 87, 98, 113, 130, 147, 160, 173 }, { 184, 187, 190, 193, 196, 199, 202 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, 0, 6, 344, 346, { 348, 37 }, { 357, 24 }, { 370, 56 }, { 376, 46 } }, { 387, 409, 422, 438, 370, 447, 457, 465, 468, { 471, 484, 505, 520, 531, 550, 561 }, { 574, 582, 590, 596, 602, 612, 620 }, { 628, 641, 658, 667, 678, 685, 692, 699, 712, 731, 748, 763, 343 }, { 780, 786, 658, 794, 678, 685, 692, 802, 810, 818, 826, 836, 343 }, 0, 1, 344, 346, { 348, 844, 422 }, { 357, 409 }, { 370 }, { 376, 438 } }, { 853, 876, 888, 376, 370, 447, 457, 465, 468, { 897, 906, 914, 922, 931, 938, 948 }, { 957, 961, 965, 969, 973, 977, 981 }, { 985, 991, 998, 1004, 1010, 1015, 1020, 1027, 1033, 1042, 1050, 1059, 343 }, { 1068, 1073, 998, 1078, 1010, 1015, 1083, 1088, 1092, 1097, 1102, 1107, 343 }, 0, 0, 344, 346, { 348, 888 }, { 357, 876 }, { 370 }, { 376 } }, { 1112, 357, 348, 376, 370, 1136, 1146, 1154, 1161, { 1168, 1178, 1188, 1198, 1208, 1218, 1228 }, { 1238, 1242, 1246, 1250, 1254, 1258, 1262 }, { 1266, 1273, 1280, 1287, 1294, 1301, 1308, 1315, 1322, 1329, 1336, 1346, 343 }, { 1266, 1273, 1280, 1287, 1294, 1301, 1308, 1315, 1322, 1329, 1336, 1346, 343 }, 0, 0, 344, 346, { 348 }, { 357 }, { 370 }, { 376 } }, { 1356, 1379, 1392, 1399, 1409, 447, 1414, 1422, 1427, { 1432, 1440, 1450, 1458, 1466, 1475, 1482 }, { 1489, 1492, 1495, 1499, 1502, 1506, 1510 }, { 1513, 1519, 1525, 1533, 1539, 1547, 1555, 1565, 1571, 1579, 1587, 1596, 343 }, { 1605, 1607, 1610, 1614, 1617, 1619, 1622, 1626, 1631, 1634, 1636, 1639, 343 }, 0, 1, 344, 346, { 348, 1392 }, { 357, 1379 }, { 370, 1409 }, { 376, 1399 } }, { 1643, 1664, 1676, 438, 370, 447, 1687, 465, 468, { 1696, 1704, 1711, 1719, 1726, 1734, 1741 }, { 1749, 1754, 1758, 1762, 1766, 1770, 1774 }, { 1779, 1786, 1794, 1800, 1806, 1810, 1815, 1820, 1827, 1837, 1845, 1854, 343 }, { 1863, 1867, 1871, 1875, 1806, 1879, 1883, 1887, 1891, 1895, 1899, 1903, 343 }, 0, 1, 344, 346, { 348, 1907, 1676 }, { 357, 1664 }, { 370 }, { 376, 438 } }, { 1916, 1379, 1938, 438, 370, 447, 1414, 1949, 1955, { 1962, 1970, 1977, 1986, 1995, 2006, 2014 }, { 2022, 2025, 2028, 2031, 2034, 2037, 2040 }, { 2043, 2050, 2058, 2064, 2070, 2074, 2079, 2084, 2091, 2101, 2109, 2118, 343 }, { 2127, 2131, 2135, 2139, 2070, 2143, 2147, 2151, 2155, 2159, 2163, 2167, 343 }, 0, 1, 344, 346, { 348, 844, 1938 }, { 357, 1379 }, { 370 }, { 376, 438 } }, { 2171, 409, 37, 2195, 56, 447, 457, 2206, 2211, { 2216, 2231, 2246, 2257, 2272, 2285, 2304 }, { 2319, 2326, 2333, 2340, 2347, 2354, 2361 }, { 2368, 2389, 2412, 2427, 2444, 2455, 2470, 2485, 2504, 2527, 2546, 2565, 343 }, { 2586, 2593, 2600, 2607, 2614, 2621, 2630, 2639, 2646, 2653, 2660, 2667, 343 }, 0, 1, 344, 346, { 348, 2674, 37 }, { 357, 409 }, { 370, 56 }, { 376, 2685, 2195 } }, { 2697, 2728, 2748, 2195, 2755, 447, 2763, 465, 468, { 2770, 2777, 2784, 2792, 2802, 2811, 2818 }, { 2827, 2831, 2835, 2839, 2843, 2847, 2851 }, { 2855, 2863, 2872, 2064, 2878, 2882, 2887, 2084, 2091, 2892, 2109, 2900, 343 }, { 2127, 2131, 2909, 2139, 2878, 2143, 2147, 2151, 2155, 2913, 2163, 2917, 343 }, 0, 0, 344, 346, { 348, 2748 }, { 2728, 2728, 2921, 2935, 2955 }, { 2755, 2755, 2970, 1409, 370 }, { 2195, 2195, 2979, 2991, 438 } }, { 2999, 3033, 3055, 2979, 370, 3066, 3071, 3083, 3088, { 3093, 3101, 3107, 3114, 3125, 3132, 3140 }, { 3148, 3152, 1871, 3156, 3161, 3165, 3169 }, { 3174, 3180, 3188, 1004, 3194, 3199, 3205, 3211, 3218, 1042, 3229, 3239, 343 }, { 3249, 1867, 1871, 3253, 3257, 1879, 1883, 3261, 1891, 3265, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 3273, 3055 }, { 357, 3033 }, { 370 }, { 376, 2979 } }, { 3281, 3306, 3323, 2991, 370, 3332, 3345, 465, 468, { 3357, 3367, 3377, 3385, 3397, 3405, 3415 }, { 3424, 3427, 3430, 3433, 3436, 3439, 3442 }, { 3445, 3454, 3463, 3473, 3482, 3491, 3500, 3510, 3517, 3525, 3533, 3543, 343 }, { 3552, 3558, 3564, 3571, 3577, 3583, 3589, 3596, 3600, 3605, 3610, 3617, 343 }, 0, 1, 344, 346, { 348, 3323 }, { 357, 3306 }, { 370 }, { 376, 2991 } }, { 3623, 3649, 888, 438, 370, 447, 74, 465, 468, { 3666, 3675, 3681, 3687, 3696, 3702, 3711 }, { 3718, 3723, 3728, 3733, 3738, 3743, 3748 }, { 3753, 3761, 3770, 3775, 3781, 3785, 3790, 3798, 3804, 3814, 1050, 3822, 343 }, { 3832, 3838, 3770, 3845, 3781, 3785, 3850, 3798, 3856, 1097, 1102, 3862, 343 }, 0, 0, 344, 346, { 888, 3868, 3273 }, { 357, 876, 3649 }, { 370 }, { 376, 438 } }, { 3878, 876, 2674, 438, 370, 447, 74, 465, 468, { 3899, 3917, 3931, 3949, 3967, 3985, 4001 }, { 4008, 4011, 4014, 4017, 4020, 4023, 4026 }, { 4029, 4040, 4053, 4060, 4071, 4078, 4087, 4096, 4109, 4122, 4137, 4150, 343 }, { 4161, 4168, 4053, 4175, 4071, 4182, 4189, 4196, 4203, 4210, 4217, 4224, 343 }, 0, 0, 344, 346, { 348, 888, 2674 }, { 357, 876 }, { 370 }, { 376, 438 } }, { 4231, 4253, 4267, 2991, 1409, 4281, 4292, 4300, 4303, { 4306, 4316, 4324, 4329, 4336, 4349, 4357 }, { 1617, 4365, 4367, 4369, 4373, 4376, 4378 }, { 4382, 4390, 4399, 4408, 4417, 4424, 4432, 4440, 4450, 4461, 1845, 1854, 343 }, { 4470, 4475, 4481, 4488, 4494, 4500, 4506, 4512, 4517, 4524, 1102, 4529, 343 }, 0, 1, 344, 346, { 348, 4534, 4267 }, { 357, 4253 }, { 370, 1409 }, { 376, 1399, 2991 } }, { 1916, 1379, 3323, 438, 370, 447, 1414, 465, 468, { 4546, 4557, 4568, 4582, 4596, 4608, 4620 }, { 4632, 4636, 4641, 4646, 4651, 4655, 4660 }, { 4664, 4672, 3770, 4681, 4688, 4693, 4700, 4707, 1827, 4461, 4715, 4725, 343 }, { 1863, 1867, 1871, 1875, 4688, 4734, 4739, 4744, 1891, 1895, 4750, 4755, 343 }, 0, 0, 344, 346, { 348, 3323 }, { 357, 1379 }, { 370 }, { 376, 438 } }, { 4759, 409, 888, 376, 370, 447, 74, 4783, 4786, { 4789, 4798, 4806, 4815, 4826, 4835, 4844 }, { 3148, 3152, 1871, 4851, 4855, 4859, 4863 }, { 4867, 4875, 3188, 4884, 4891, 4898, 4905, 3211, 4912, 4922, 1050, 4930, 343 }, { 4939, 1867, 1871, 1875, 4943, 4947, 4951, 3261, 4955, 4959, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 888 }, { 357, 409 }, { 370 }, { 376 } }, { 4963, 4993, 5015, 2991, 1409, 5026, 5042, 5055, 5062, { 5069, 5079, 5089, 5099, 5109, 5119, 5129 }, { 1238, 5139, 5143, 5147, 5151, 5155, 5159 }, { 5163, 5168, 5173, 5178, 5183, 5188, 5193, 5198, 5203, 5208, 5214, 5220, 343 }, { 5226, 5228, 5230, 5232, 5234, 5236, 5238, 5240, 5242, 5244, 5247, 5250, 343 }, 0, 0, 344, 346, { 5015, 5015, 348, 5253, 5260, 5269, 5288, 5305 }, { 4993, 4993, 5324, 5348, 5375 }, { 1409, 1409, 370, 5404, 5412 }, { 2991, 438, 5421, 5432 } }, { 5444, 5497, 5524, 5533, 5559, 5577, 5594, 5608, 5615, { 5622, 5632, 5642, 5652, 5662, 5672, 5682 }, { 5692, 5696, 5700, 5704, 5708, 5712, 5716 }, { 5720, 5725, 5730, 5735, 5740, 5745, 5750, 5755, 5760, 5765, 5771, 5777, 343 }, { 5720, 5725, 5730, 5735, 5740, 5745, 5750, 5755, 5760, 5765, 5771, 5777, 343 }, 0, 0, 344, 346, { 348, 5524 }, { 357, 5497 }, { 370, 5559 }, { 376, 5533 } }, { 5783, 876, 5805, 1399, 1409, 447, 74, 465, 468, { 5812, 5819, 5827, 5835, 5844, 5854, 5862 }, { 5871, 3427, 5874, 5877, 5880, 5883, 5886 }, { 5889, 5897, 5906, 1800, 5912, 1810, 1815, 5916, 1827, 1837, 1845, 1854, 343 }, { 1863, 1867, 5925, 1875, 5912, 1879, 1883, 1887, 1891, 1895, 1899, 1903, 343 }, 0, 1, 344, 346, { 348, 5805 }, { 357, 876 }, { 370, 1409 }, { 376, 1399 } }, { 5929, 1379, 844, 5953, 5964, 447, 1414, 465, 468, { 1696, 1704, 1711, 1719, 1726, 1734, 1741 }, { 5970, 3427, 3430, 5974, 3436, 5977, 5980 }, { 1779, 1786, 3770, 1800, 3781, 1810, 1815, 1820, 1827, 1837, 1845, 4725, 343 }, { 1863, 1867, 1871, 1875, 3781, 1879, 1883, 1887, 1891, 1895, 1899, 4755, 343 }, 0, 1, 344, 346, { 348, 844 }, { 357, 1379 }, { 370, 5964 }, { 376, 5953 } }, { 5984, 876, 6005, 438, 370, 447, 74, 465, 468, { 6016, 6026, 6040, 6047, 6054, 6063, 1482 }, { 6071, 6073, 6076, 6079, 6083, 6086, 2022 }, { 6089, 6098, 6103, 6110, 1806, 6120, 6129, 6136, 6146, 6156, 1587, 6169, 343 }, { 6179, 6183, 1871, 6187, 1806, 6191, 6195, 6199, 6203, 6207, 6212, 6216, 343 }, 0, 1, 344, 346, { 348, 5524, 6005 }, { 357, 876 }, { 370 }, { 376, 438 } }, { 6220, 3033, 1676, 376, 370, 3066, 3071, 465, 468, { 3093, 6253, 6267, 6280, 6293, 6306, 3140 }, { 3148, 6318, 6322, 6326, 6330, 6334, 3169 }, { 6338, 6346, 6356, 1004, 6363, 6368, 6374, 3211, 6380, 6389, 6397, 6406, 343 }, { 1863, 6415, 1871, 3253, 3781, 1879, 1883, 3261, 4955, 6419, 1899, 6423, 343 }, 0, 0, 344, 346, { 348, 1676 }, { 357, 3033 }, { 370 }, { 376 } }, { 5984, 876, 1938, 438, 370, 447, 74, 465, 468, { 6427, 6437, 6442, 6449, 6458, 6462, 6469 }, { 6480, 6482, 6484, 2031, 6487, 1617, 6489 }, { 6491, 6500, 6510, 6517, 3781, 6525, 6531, 1820, 6537, 6548, 6558, 6568, 343 }, { 6578, 2131, 2909, 2139, 2070, 6582, 6586, 2151, 2155, 2913, 2163, 2917, 343 }, 0, 1, 344, 346, { 348, 1938 }, { 357, 876 }, { 370 }, { 376, 438 } }, { 6590, 6616, 1938, 2991, 1409, 6634, 74, 465, 468, { 6650, 6673, 505, 6696, 6707, 6722, 6737 }, { 6752, 6757, 6762, 6767, 6772, 6777, 6782 }, { 6787, 6800, 6815, 6824, 6837, 6844, 6853, 6862, 6875, 6892, 6907, 6920, 343 }, { 6935, 6942, 6949, 6956, 678, 6963, 6970, 6977, 6984, 6991, 6998, 7005, 343 }, 0, 1, 344, 346, { 348, 844, 1938 }, { 357, 6616 }, { 370, 1409 }, { 376, 1399, 2991 } }, { 7012, 7034, 3323, 2991, 370, 4281, 1146, 465, 468, { 7048, 7057, 7069, 7076, 7084, 7094, 7100 }, { 7107, 7111, 7115, 7119, 7123, 7128, 7132 }, { 7136, 7146, 7155, 7163, 7171, 7179, 7186, 7193, 7201, 1587, 7207, 7215, 343 }, { 7224, 7228, 7232, 7237, 7241, 6195, 7245, 7249, 7253, 6212, 7257, 7261, 343 }, 0, 1, 344, 346, { 348, 7265, 3323 }, { 357, 7034 }, { 370 }, { 376, 2991 } }, { 7276, 1379, 7297, 2991, 1409, 447, 1414, 465, 468, { 7308, 7316, 7325, 7332, 7339, 7348, 7355 }, { 7362, 7365, 7368, 7371, 7374, 7378, 2022 }, { 4382, 4390, 7381, 4681, 7387, 4734, 4739, 1820, 1827, 4461, 1845, 1854, 343 }, { 1863, 1867, 1871, 1875, 7387, 4734, 4739, 1887, 1891, 1895, 1899, 1903, 343 }, 0, 1, 344, 346, { 348, 3323, 7297 }, { 357, 1379 }, { 370, 1409 }, { 376, 1399, 2991 } }, { 7392, 409, 6005, 7416, 7427, 447, 457, 7434, 7437, { 7440, 7447, 7456, 7465, 7477, 7485, 7494 }, { 7504, 7508, 2909, 7513, 7518, 7522, 7526 }, { 7530, 7536, 3770, 7543, 1806, 7549, 7557, 7564, 7570, 7578, 7584, 7592, 343 }, { 2127, 7600, 2909, 7604, 7608, 7612, 7616, 7620, 7526, 7624, 7628, 7633, 343 }, 0, 1, 344, 346, { 348, 5524, 6005 }, { 357, 409 }, { 370, 7427 }, { 376, 7637, 7416 } }, { 7649, 7677, 6005, 5953, 5964, 447, 74, 7694, 7697, { 7700, 7708, 7716, 1719, 1726, 1734, 7723 }, { 7731, 7735, 3430, 5974, 3436, 5977, 7739 }, { 5889, 5897, 3770, 1800, 1806, 1810, 1815, 7743, 1827, 1837, 1845, 1854, 343 }, { 1863, 1867, 1871, 1875, 1806, 1879, 1883, 1887, 1891, 1895, 1899, 1903, 343 }, 0, 1, 344, 346, { 348, 6005 }, { 357, 7677 }, { 370, 5964 }, { 376, 5953 } }, { 7751, 876, 37, 2991, 1409, 447, 74, 7772, 7803, { 7834, 7865, 7893, 7921, 7940, 7974, 7999 }, { 8024, 8032, 8037, 8042, 8047, 8055, 8060 }, { 8065, 8084, 8115, 8134, 8153, 8175, 8200, 8222, 8244, 8266, 8285, 8313, 343 }, { 8335, 8344, 8353, 8365, 8377, 8386, 8398, 8407, 8416, 8425, 8434, 8443, 343 }, 0, 0, 344, 346, { 348, 37 }, { 357, 876 }, { 370, 1409 }, { 376, 8452, 2991 } }, { 8492, 8519, 1938, 438, 370, 447, 457, 465, 468, { 8537, 8543, 8553, 8559, 8570, 8580, 8585 }, { 8595, 8599, 8603, 8607, 8612, 8616, 8620 }, { 8624, 8629, 8636, 8641, 8647, 8654, 8662, 8669, 8678, 8685, 8690, 8697, 343 }, { 8705, 8709, 2909, 8714, 2878, 8718, 8722, 8726, 8731, 8735, 8739, 8743, 343 }, 0, 1, 344, 346, { 348, 1938 }, { 357, 8519 }, { 370 }, { 376, 438 } }, { 1112, 357, 348, 376, 370, 1136, 1146, 465, 468, { 8747, 8754, 8760, 8767, 8772, 8778, 8784 }, { 8790, 8794, 8798, 8802, 8806, 8810, 8814 }, { 8818, 8826, 8835, 2064, 8841, 2074, 2079, 8845, 2091, 2101, 2109, 8853, 343 }, { 2127, 2131, 2909, 2139, 8841, 2143, 2147, 8862, 2155, 2159, 2163, 8866, 343 }, 0, 0, 344, 346, { 348 }, { 357 }, { 370 }, { 376 } }, { 8870, 876, 1938, 2991, 370, 8890, 74, 465, 468, { 8906, 8919, 8938, 8955, 8968, 8981, 8997 }, { 9010, 6757, 6762, 6767, 6772, 6777, 6782 }, { 9015, 9026, 9039, 9054, 9067, 9080, 9093, 9104, 9117, 9132, 9145, 9164, 343 }, { 9177, 9184, 9191, 9198, 9207, 9216, 9225, 9232, 9241, 9248, 9257, 9266, 343 }, 0, 1, 344, 346, { 348, 844, 1938 }, { 357, 876 }, { 370 }, { 376, 2991 } }, { 9275, 876, 1392, 5953, 5964, 447, 74, 465, 468, { 9298, 9313, 9334, 9349, 9362, 9375, 9390 }, { 9403, 9408, 9413, 9418, 9423, 9428, 9433 }, { 9438, 9455, 9464, 9479, 678, 9496, 9511, 9524, 9539, 9556, 9577, 9594, 343 }, { 9609, 9184, 9616, 9623, 678, 9630, 9637, 9644, 9241, 9651, 9658, 9665, 343 }, 0, 1, 344, 346, { 348, 1392 }, { 357, 876 }, { 370, 5964 }, { 376, 5953 } }, { 9672, 9694, 3323, 2991, 1409, 447, 1687, 465, 468, { 9708, 9716, 9727, 9733, 9739, 9748, 1482 }, { 7107, 7111, 1766, 9754, 7123, 7128, 9758 }, { 1779, 1786, 7381, 1800, 1806, 9762, 9768, 9774, 1827, 1837, 1845, 1854, 343 }, { 1863, 1867, 1871, 1875, 1806, 1879, 1883, 9781, 1891, 1895, 1899, 1903, 343 }, 0, 1, 344, 346, { 348, 9785, 3323 }, { 357, 9694 }, { 370, 1409 }, { 376, 1399, 2991 } }, { 8870, 876, 9792, 2991, 1409, 447, 9802, 465, 468, { 9810, 9821, 9832, 9843, 9854, 9865, 9871 }, { 4376, 9880, 9882, 4367, 6071, 9884, 6482 }, { 9886, 9894, 9903, 9910, 3781, 9917, 9923, 1820, 1827, 9929, 1845, 9938, 343 }, { 9948, 9953, 9903, 1875, 3781, 9917, 9923, 1887, 9959, 1895, 1899, 9964, 343 }, 0, 1, 344, 346, { 348, 844, 9792 }, { 357, 876 }, { 370, 1409 }, { 376, 1399, 2991 } }, { 9969, 9998, 4534, 2991, 370, 10019, 1414, 465, 468, { 10037, 10048, 10058, 10067, 10078, 10090, 10101 }, { 10111, 4376, 10114, 9882, 10116, 10118, 6489 }, { 10121, 10131, 1794, 10142, 10151, 10157, 10165, 10173, 10181, 10192, 10201, 10211, 343 }, { 2127, 2131, 2909, 2139, 2070, 10221, 10226, 2151, 2155, 2159, 2163, 2917, 343 }, 0, 1, 344, 346, { 348, 10231, 4534 }, { 357, 9998 }, { 370 }, { 376, 2991 } }, { 10238, 10271, 7265, 376, 370, 10293, 10308, 465, 468, { 10320, 10332, 10344, 10356, 10370, 10385, 10398 }, { 10412, 10415, 10418, 10421, 10424, 6073, 7374 }, { 10427, 10434, 10442, 10447, 10458, 10468, 10478, 10485, 10497, 10506, 10513, 10524, 343 }, { 10534, 10538, 10542, 10546, 10550, 10554, 10558, 10562, 10566, 10570, 10574, 10578, 343 }, 0, 1, 344, 346, { 348, 7265 }, { 357, 10271 }, { 370 }, { 376 } }, { 10582, 876, 10606, 2979, 370, 447, 74, 10615, 10622, { 10629, 10645, 10658, 10674, 10691, 10709, 10718 }, { 10727, 10731, 10735, 10739, 10743, 10747, 10751 }, { 10755, 10768, 229, 10779, 10790, 10795, 10804, 10815, 10822, 10837, 10848, 10861, 343 }, { 10874, 10881, 10888, 10895, 10902, 10909, 10916, 10815, 10923, 10930, 10937, 10944, 343 }, 0, 0, 344, 346, { 348, 10951, 10606 }, { 357, 876 }, { 370 }, { 376, 10961, 2979 } }, { 10974, 409, 2674, 2195, 370, 447, 457, 10998, 11001, { 11004, 11017, 11027, 11036, 11046, 11057, 11068 }, { 11080, 11083, 11088, 11093, 11098, 11103, 11108 }, { 11113, 11126, 11137, 11147, 11158, 11170, 11182, 11195, 11207, 11220, 11235, 11256, 343 }, { 11275, 11281, 11287, 11293, 11299, 11305, 11311, 11317, 11323, 11329, 11336, 11343, 343 }, 0, 1, 344, 346, { 348, 2674 }, { 357, 409 }, { 370 }, { 376, 2195 } }, { 11350, 2921, 1938, 2991, 370, 447, 2763, 11372, 11380, { 11388, 11401, 11422, 11441, 11462, 11481, 11494 }, { 11505, 11512, 11519, 11526, 11533, 11540, 11547 }, { 11554, 11571, 11588, 11597, 11608, 11619, 11632, 11645, 11660, 11679, 11698, 11715, 343 }, { 11734, 11741, 11748, 11755, 11762, 11769, 11776, 11783, 11790, 11797, 11804, 11811, 343 }, 0, 1, 344, 346, { 348, 11818, 1938 }, { 357, 2921 }, { 370 }, { 376, 2991 } }, { 1112, 357, 348, 376, 370, 1136, 1146, 465, 468, { 11827, 11835, 11846, 11856, 11867, 11876, 11885 }, { 11895, 11898, 11901, 11904, 11907, 11910, 11913 }, { 11916, 11926, 11934, 11942, 11950, 11958, 11965, 11973, 11981, 11988, 11994, 12001, 343 }, { 12009, 12013, 1871, 12017, 3781, 12021, 12025, 12029, 12033, 12037, 12041, 12045, 343 }, 0, 0, 344, 346, { 348 }, { 357 }, { 370 }, { 376 } }, { 387, 409, 1938, 438, 370, 447, 457, 465, 468, { 12049, 484, 505, 6696, 12062, 12079, 12090 }, { 574, 582, 590, 12103, 12111, 612, 12119 }, { 12127, 641, 658, 667, 12142, 12149, 12158, 699, 712, 731, 748, 763, 343 }, { 12167, 786, 12175, 794, 12183, 12191, 12199, 802, 12207, 818, 826, 12217, 343 }, 0, 1, 344, 346, { 348, 12229, 1938 }, { 357, 409 }, { 370 }, { 376, 438 } }, { 1112, 357, 348, 376, 370, 1136, 1146, 12237, 12240, { 12243, 12250, 12258, 12266, 12275, 12285, 12292 }, { 2022, 6484, 2028, 12301, 2034, 12304, 2040 }, { 12307, 12316, 12326, 2064, 8841, 12332, 12338, 12344, 2091, 2101, 2109, 8853, 343 }, { 2127, 2131, 2909, 2139, 8841, 2143, 2147, 2151, 2155, 2159, 2163, 8866, 343 }, 0, 0, 344, 346, { 348 }, { 357 }, { 370 }, { 376 } }, { 12353, 12373, 348, 376, 370, 12382, 1146, 12389, 12405, { 5226, 5228, 5230, 5232, 5234, 5236, 5238 }, { 5226, 5228, 5230, 5232, 5234, 5236, 5238 }, { 5226, 5228, 5230, 5232, 5234, 5236, 5238, 5240, 5242, 5244, 5247, 5250, 343 }, { 5226, 5228, 5230, 5232, 5234, 5236, 5238, 5240, 5242, 5244, 5247, 5250, 343 }, 0, 0, 344, 346, { 348 }, { 357, 12373 }, { 370 }, { 376 } }, { 12427, 1664, 1907, 376, 370, 447, 457, 465, 468, { 4546, 12450, 12461, 12471, 12481, 12491, 12505 }, { 4632, 4636, 12517, 12522, 12526, 12531, 12536 }, { 1779, 1786, 3770, 4681, 3781, 1810, 1815, 1820, 1827, 1837, 1845, 4725, 343 }, { 1863, 1867, 1871, 1875, 3781, 1879, 1883, 1887, 1891, 1895, 1899, 4755, 343 }, 0, 0, 344, 346, { 348, 1907 }, { 357, 1664 }, { 370 }, { 376 } }, { 1112, 357, 348, 376, 370, 1136, 1146, 12540, 12568, { 12590, 12609, 12628, 12650, 12669, 12691, 12716 }, { 12735, 12745, 12755, 12768, 12778, 12791, 12807 }, { 12817, 12833, 12849, 12865, 12884, 12891, 12901, 12917, 12933, 12955, 12977, 12996, 343 }, { 12817, 12833, 12849, 12865, 12884, 12891, 12901, 12917, 12933, 12955, 12977, 12996, 343 }, 0, 0, 344, 346, { 348 }, { 357 }, { 370 }, { 376 } }, { 1112, 357, 348, 376, 370, 1136, 1146, 465, 468, { 13018, 13027, 13036, 13044, 13053, 13062, 13069 }, { 13078, 13082, 13086, 13090, 13094, 13098, 13102 }, { 8818, 8826, 13106, 13112, 8841, 2074, 13119, 13125, 13132, 13141, 13148, 13156, 343 }, { 2127, 2131, 2909, 2139, 8841, 2143, 2147, 13164, 2155, 2159, 2163, 8866, 343 }, 0, 6, 344, 346, { 348 }, { 357 }, { 370 }, { 376 } }, { 1112, 357, 348, 376, 370, 1136, 1146, 13168, 13210, { 13252, 13271, 13290, 13312, 13331, 13353, 13378 }, { 13397, 13407, 13417, 13430, 13440, 13453, 13469 }, { 13479, 13507, 13535, 13551, 13570, 13577, 13587, 13603, 13619, 13647, 13669, 13691, 343 }, { 13716, 13735, 13535, 13551, 13570, 13577, 13587, 13603, 13754, 13770, 13786, 13796, 343 }, 0, 0, 344, 346, { 348 }, { 357 }, { 370 }, { 376 } }, { 1112, 357, 348, 376, 370, 1136, 1146, 13809, 13822, { 13835, 13854, 13876, 13901, 13917, 13939, 13958 }, { 13968, 13975, 13982, 13989, 13996, 14003, 14010 }, { 14014, 14030, 14055, 14074, 14093, 14100, 14113, 14126, 14145, 14176, 14201, 14223, 343 }, { 14248, 14256, 14270, 14284, 14093, 14100, 14113, 14295, 14303, 14317, 14328, 14336, 343 }, 0, 0, 344, 346, { 348 }, { 357 }, { 370 }, { 376 } }, { 1112, 357, 348, 376, 370, 1136, 1146, 14347, 14375, { 14397, 14419, 14441, 14466, 14488, 14513, 14541 }, { 14563, 14573, 14583, 14596, 14606, 14619, 14635 }, { 14645, 14661, 14686, 14705, 14727, 14734, 14747, 14760, 14779, 14810, 14835, 14854, 343 }, { 14645, 14661, 14686, 14705, 14727, 14734, 14747, 14760, 14779, 14810, 14835, 14854, 343 }, 0, 0, 344, 346, { 348 }, { 357 }, { 370 }, { 376 } }, { 1112, 357, 348, 376, 370, 1136, 1146, 14879, 14907, { 14929, 14948, 14967, 14989, 15008, 15030, 15055 }, { 15074, 15079, 15087, 15095, 15103, 15111, 15119 }, { 15130, 15146, 15171, 15190, 15212, 15219, 15232, 15245, 15264, 15292, 15317, 15339, 343 }, { 15130, 15146, 15171, 15190, 15212, 15219, 15232, 15245, 15264, 15292, 15317, 15339, 343 }, 0, 0, 344, 346, { 348 }, { 357 }, { 370 }, { 376 } }, { 1112, 357, 348, 376, 370, 1136, 1146, 15364, 15376, { 12590, 12609, 15388, 12650, 12669, 12691, 12716 }, { 12735, 12745, 15410, 12768, 12778, 12791, 12807 }, { 15423, 15448, 12849, 15473, 15492, 12891, 15499, 15512, 15528, 15556, 15578, 15606, 343 }, { 15423, 15448, 12849, 15473, 15492, 12891, 15499, 15512, 15528, 15556, 15578, 15606, 343 }, 0, 0, 344, 346, { 348 }, { 357 }, { 370 }, { 376 } }, { 1112, 357, 348, 376, 370, 1136, 1146, 465, 468, { 15628, 15636, 15641, 15648, 15658, 15664, 15671 }, { 15679, 15683, 2909, 15687, 15692, 15696, 15700 }, { 15705, 15713, 15722, 15728, 15734, 15739, 15745, 15751, 15758, 15767, 15775, 15784, 343 }, { 15793, 2131, 2909, 15797, 2070, 15801, 15806, 13164, 15810, 15814, 2163, 2917, 343 }, 0, 0, 344, 346, { 348 }, { 357 }, { 370 }, { 376 } }, { 1112, 357, 348, 376, 370, 1136, 1146, 15364, 15376, { 15818, 12609, 15846, 12650, 12669, 12691, 12716 }, { 12735, 12745, 15410, 12768, 12778, 12791, 12807 }, { 15423, 15865, 12849, 15473, 15492, 12891, 15499, 15512, 15528, 15556, 15578, 15606, 343 }, { 15423, 15448, 12849, 15473, 15492, 12891, 15499, 15512, 15528, 15556, 15578, 15606, 343 }, 0, 0, 344, 346, { 348 }, { 357 }, { 370 }, { 376 } }, { 1, 24, 37, 46, 56, 63, 74, 81, 84, { 87, 98, 113, 130, 147, 160, 173 }, { 87, 98, 113, 130, 147, 160, 173 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, 0, 6, 344, 346, { 348, 37 }, { 357, 24 }, { 370, 56 }, { 376, 46 } }, { 387, 409, 422, 438, 370, 447, 457, 465, 468, { 471, 484, 505, 520, 531, 550, 561 }, { 574, 582, 590, 596, 602, 612, 620 }, { 628, 641, 658, 667, 678, 685, 692, 699, 712, 731, 748, 763, 343 }, { 780, 786, 658, 794, 678, 685, 692, 802, 810, 818, 826, 836, 343 }, 0, 1, 344, 346, { 348, 844, 422 }, { 357, 409 }, { 370 }, { 376, 438 } }, { 5984, 876, 2674, 438, 370, 447, 457, 465, 468, { 897, 906, 914, 922, 931, 938, 948 }, { 957, 961, 965, 969, 973, 977, 981 }, { 985, 991, 998, 1004, 1010, 1015, 1020, 1027, 1033, 1042, 1050, 1059, 343 }, { 1068, 1073, 998, 1078, 1010, 1015, 1083, 1088, 1092, 1097, 1102, 1107, 343 }, 0, 1, 344, 346, { 348, 888, 2674 }, { 357, 876 }, { 370 }, { 376, 438 } }, { 15896, 4993, 5260, 15941, 15964, 5026, 5042, 1154, 1161, { 1168, 1178, 1188, 1198, 1208, 1218, 1228 }, { 1238, 1242, 1246, 1250, 1254, 1258, 1262 }, { 1266, 1273, 1280, 1287, 1294, 1301, 1308, 1315, 1322, 1329, 1336, 1346, 343 }, { 1266, 1273, 1280, 1287, 1294, 1301, 1308, 1315, 1322, 1329, 1336, 1346, 343 }, 0, 0, 344, 346, { 348, 5260 }, { 357, 4993 }, { 370, 15964 }, { 376, 15941 } }, { 7276, 1379, 3323, 2991, 1409, 447, 1414, 1422, 1427, { 1432, 1440, 1450, 1458, 1466, 1475, 1482 }, { 1489, 1492, 1495, 1499, 1502, 1506, 1510 }, { 1513, 1519, 1525, 1533, 1539, 1547, 1555, 1565, 1571, 1579, 1587, 1596, 343 }, { 1605, 1607, 1610, 1614, 1617, 1619, 1622, 1626, 1631, 1634, 1636, 1639, 343 }, 0, 1, 344, 346, { 348, 1392, 3323 }, { 357, 1379 }, { 370, 1409 }, { 376, 1399, 2991 } }, { 1643, 1664, 1676, 438, 370, 447, 1687, 465, 468, { 1696, 1704, 1711, 1719, 1726, 1734, 1741 }, { 1749, 1754, 1758, 1762, 1766, 1770, 1774 }, { 1779, 1786, 1794, 1800, 1806, 1810, 1815, 1820, 1827, 1837, 1845, 1854, 343 }, { 1863, 1867, 1871, 1875, 1806, 1879, 1883, 1887, 1891, 1895, 1899, 1903, 343 }, 0, 1, 344, 346, { 348, 1907, 1676 }, { 357, 1664 }, { 370 }, { 376, 438 } }, { 1916, 1379, 1938, 438, 370, 447, 1414, 1949, 1955, { 1962, 1970, 1977, 1986, 1995, 2006, 2014 }, { 2022, 2025, 2028, 2031, 2034, 2037, 2040 }, { 2043, 2050, 2058, 2064, 2070, 2074, 2079, 2084, 2091, 2101, 2109, 2118, 343 }, { 2127, 2131, 2135, 2139, 2070, 2143, 2147, 2151, 2155, 2159, 2163, 2167, 343 }, 0, 1, 344, 346, { 348, 844, 1938 }, { 357, 1379 }, { 370 }, { 376, 438 } }, { 2171, 409, 37, 2195, 56, 447, 457, 2206, 2211, { 2216, 2231, 2246, 2257, 2272, 2285, 2304 }, { 2319, 2326, 2333, 2340, 2347, 2354, 2361 }, { 2368, 2389, 2412, 2427, 2444, 2455, 2470, 2485, 2504, 2527, 2546, 2565, 343 }, { 2586, 2593, 2600, 2607, 2614, 2621, 2630, 2639, 2646, 2653, 2660, 2667, 343 }, 0, 1, 344, 346, { 348, 2674, 37 }, { 357, 409 }, { 370, 56 }, { 376, 2685, 2195 } }, { 2697, 2728, 10606, 2195, 2755, 63, 2763, 465, 468, { 2770, 2777, 2784, 2792, 2802, 2811, 2818 }, { 2827, 2831, 2835, 2839, 2843, 2847, 2851 }, { 2855, 2863, 2872, 2064, 2878, 2882, 2887, 2084, 2091, 2892, 2109, 2900, 343 }, { 2127, 2131, 2909, 2139, 2878, 2143, 2147, 2151, 2155, 2913, 2163, 2917, 343 }, 0, 0, 344, 346, { 10606, 10606, 2748, 2748, 11818, 3055, 348, 6005, 15971 }, { 2728, 2728, 2921, 2935, 2955 }, { 2755, 2755, 2970, 1409, 370 }, { 2195, 2195, 2979, 2991, 438 } }, { 3281, 3306, 3323, 2991, 370, 3332, 3345, 465, 468, { 3357, 3367, 3377, 3385, 3397, 3405, 3415 }, { 3424, 3427, 3430, 3433, 3436, 3439, 3442 }, { 3445, 3454, 3463, 3473, 3482, 3491, 3500, 3510, 3517, 3525, 3533, 3543, 343 }, { 3552, 3558, 3564, 3571, 3577, 3583, 3589, 3596, 3600, 3605, 3610, 3617, 343 }, 0, 1, 344, 346, { 348, 3323 }, { 357, 3306 }, { 370 }, { 376, 2991 } }, { 3623, 3649, 2674, 438, 370, 447, 74, 465, 468, { 3666, 3675, 3681, 3687, 3696, 3702, 3711 }, { 3718, 3723, 3728, 3733, 3738, 3743, 3748 }, { 3753, 3761, 3770, 3775, 3781, 3785, 3790, 3798, 3804, 3814, 1050, 3822, 343 }, { 3832, 3838, 3770, 3845, 3781, 3785, 3850, 3798, 3856, 1097, 1102, 3862, 343 }, 0, 1, 344, 346, { 888, 3868, 3273, 2674 }, { 357, 876, 3649 }, { 370 }, { 376, 438 } }, { 3878, 876, 2674, 438, 370, 447, 74, 465, 468, { 3899, 3917, 3931, 3949, 3967, 3985, 4001 }, { 4008, 4011, 4014, 4017, 4020, 4023, 4026 }, { 4029, 4040, 4053, 4060, 4071, 4078, 4087, 4096, 4109, 4122, 4137, 4150, 343 }, { 4161, 4168, 4053, 4175, 4071, 4182, 4189, 4196, 4203, 4210, 4217, 4224, 343 }, 0, 0, 344, 346, { 348, 888, 2674 }, { 357, 876 }, { 370 }, { 376, 438 } }, { 4231, 4253, 4267, 2991, 1409, 4281, 4292, 4300, 4303, { 4306, 4316, 4324, 4329, 4336, 4349, 4357 }, { 1617, 4365, 4367, 4369, 4373, 4376, 4378 }, { 4382, 4390, 4399, 4408, 4417, 4424, 4432, 4440, 4450, 4461, 1845, 1854, 343 }, { 4470, 4475, 4481, 4488, 4494, 4500, 4506, 4512, 4517, 4524, 1102, 4529, 343 }, 0, 1, 344, 346, { 348, 4534, 4267 }, { 357, 4253 }, { 370, 1409 }, { 376, 1399, 2991 } }, { 1916, 1379, 3323, 438, 370, 447, 1414, 465, 468, { 4546, 4557, 4568, 4582, 4596, 4608, 4620 }, { 4632, 4636, 4641, 4646, 4651, 4655, 4660 }, { 4664, 4672, 3770, 4681, 4688, 4693, 4700, 4707, 1827, 4461, 4715, 4725, 343 }, { 1863, 1867, 1871, 1875, 4688, 4734, 4739, 4744, 1891, 1895, 4750, 4755, 343 }, 0, 0, 344, 346, { 348, 3323 }, { 357, 1379 }, { 370 }, { 376, 438 } }, { 15981, 409, 2674, 16002, 370, 447, 74, 4783, 4786, { 4789, 4798, 4806, 4815, 4826, 4835, 4844 }, { 3148, 3152, 1871, 4851, 4855, 4859, 4863 }, { 4867, 4875, 3188, 4884, 4891, 4898, 4905, 3211, 4912, 4922, 1050, 4930, 343 }, { 4939, 1867, 1871, 1875, 4943, 4947, 4951, 3261, 4955, 4959, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 888, 2674 }, { 357, 409 }, { 370 }, { 376, 1399, 16002 } }, { 4963, 4993, 5015, 2991, 1409, 5026, 5042, 5055, 5062, { 5069, 5079, 5089, 5099, 5109, 5119, 5129 }, { 1238, 5139, 5143, 5147, 5151, 5155, 5159 }, { 5163, 5168, 5173, 5178, 5183, 5188, 5193, 5198, 5203, 5208, 5214, 5220, 343 }, { 5226, 5228, 5230, 5232, 5234, 5236, 5238, 5240, 5242, 5244, 5247, 5250, 343 }, 0, 0, 344, 346, { 5015, 5015, 348, 5253, 5260, 5269, 5288, 5305 }, { 4993, 4993, 5324, 5348, 5375 }, { 1409, 1409, 370, 5404, 5412 }, { 2991, 438, 5421, 5432 } }, { 16010, 16060, 5015, 16084, 5404, 5577, 5594, 5608, 5615, { 5622, 5632, 5642, 5652, 5662, 5672, 5682 }, { 5692, 5696, 5700, 5704, 5708, 5712, 5716 }, { 5720, 5725, 5730, 5735, 5740, 5745, 5750, 5755, 5760, 5765, 5771, 5777, 343 }, { 5720, 5725, 5730, 5735, 5740, 5745, 5750, 5755, 5760, 5765, 5771, 5777, 343 }, 0, 0, 344, 346, { 5015, 5015, 348, 5253, 5260, 16110, 16123 }, { 16060, 16060, 16134, 16160, 16182 }, { 5404, 1409, 370, 16206, 16220, 16235, 5404, 5412, 16251, 16268, 16286 }, { 16084, 16084, 16305, 16327, 2991, 438, 16351, 16376, 5421, 5432 } }, { 8870, 876, 16403, 2991, 1409, 447, 74, 465, 468, { 5812, 5819, 5827, 5835, 5844, 5854, 5862 }, { 5871, 3427, 5874, 5877, 5880, 5883, 5886 }, { 5889, 5897, 5906, 1800, 5912, 1810, 1815, 5916, 1827, 1837, 1845, 1854, 343 }, { 1863, 1867, 5925, 1875, 5912, 1879, 1883, 1887, 1891, 1895, 1899, 1903, 343 }, 0, 1, 344, 346, { 348, 5805, 16403 }, { 357, 876 }, { 370, 1409 }, { 376, 1399, 2991 } }, { 5929, 1379, 844, 5953, 5964, 447, 1414, 465, 468, { 1696, 1704, 1711, 1719, 1726, 1734, 1741 }, { 5970, 3427, 3430, 5974, 3436, 5977, 5980 }, { 1779, 1786, 3770, 1800, 3781, 1810, 1815, 1820, 1827, 1837, 1845, 4725, 343 }, { 1863, 1867, 1871, 1875, 3781, 1879, 1883, 1887, 1891, 1895, 1899, 4755, 343 }, 0, 1, 344, 346, { 348, 844 }, { 357, 1379 }, { 370, 5964 }, { 376, 5953 } }, { 5984, 876, 6005, 438, 370, 447, 74, 465, 468, { 6016, 6026, 6040, 6047, 6054, 6063, 1482 }, { 6071, 6073, 6076, 6079, 6083, 6086, 2022 }, { 6089, 6098, 6103, 6110, 1806, 6120, 6129, 6136, 6146, 6156, 1587, 6169, 343 }, { 6179, 6183, 1871, 6187, 1806, 6191, 6195, 6199, 6203, 6207, 6212, 6216, 343 }, 0, 1, 344, 346, { 348, 5524, 6005 }, { 357, 876 }, { 370 }, { 376, 438 } }, { 16412, 3033, 37, 438, 370, 3066, 3071, 465, 468, { 3093, 6253, 6267, 6280, 6293, 6306, 3140 }, { 3148, 6318, 6322, 6326, 6330, 6334, 3169 }, { 6338, 6346, 6356, 1004, 6363, 6368, 6374, 3211, 6380, 6389, 6397, 6406, 343 }, { 1863, 6415, 1871, 3253, 3781, 1879, 1883, 3261, 4955, 6419, 1899, 6423, 343 }, 0, 0, 344, 346, { 348, 1676, 888, 37 }, { 357, 3033 }, { 370 }, { 376, 16443, 438 } }, { 5984, 876, 1938, 438, 370, 447, 74, 465, 468, { 6427, 6437, 6442, 6449, 6458, 6462, 6469 }, { 6480, 6482, 6484, 2031, 6487, 1617, 6489 }, { 6491, 6500, 6510, 6517, 3781, 6525, 6531, 1820, 6537, 6548, 6558, 6568, 343 }, { 6578, 2131, 2909, 2139, 2070, 6582, 6586, 2151, 2155, 2913, 2163, 2917, 343 }, 0, 1, 344, 346, { 348, 1938 }, { 357, 876 }, { 370 }, { 376, 438 } }, { 6590, 6616, 1938, 2991, 1409, 6634, 74, 465, 468, { 6650, 6673, 505, 6696, 6707, 6722, 6737 }, { 6752, 6757, 6762, 6767, 6772, 6777, 6782 }, { 6787, 6800, 6815, 6824, 6837, 6844, 6853, 6862, 6875, 6892, 6907, 6920, 343 }, { 6935, 6942, 6949, 6956, 678, 6963, 6970, 6977, 6984, 6991, 6998, 7005, 343 }, 0, 1, 344, 346, { 348, 844, 1938 }, { 357, 6616 }, { 370, 1409 }, { 376, 1399, 2991 } }, { 7012, 7034, 3323, 2991, 370, 4281, 1146, 465, 468, { 7048, 7057, 7069, 7076, 7084, 7094, 7100 }, { 7107, 7111, 7115, 7119, 7123, 7128, 7132 }, { 7136, 7146, 7155, 7163, 7171, 7179, 7186, 7193, 7201, 1587, 7207, 7215, 343 }, { 7224, 7228, 7232, 7237, 7241, 6195, 7245, 7249, 7253, 6212, 7257, 7261, 343 }, 0, 1, 344, 346, { 348, 7265, 3323 }, { 357, 7034 }, { 370 }, { 376, 2991 } }, { 7276, 1379, 7297, 2991, 1409, 447, 1414, 465, 468, { 7308, 7316, 7325, 7332, 7339, 7348, 7355 }, { 7362, 7365, 7368, 7371, 7374, 7378, 2022 }, { 4382, 4390, 7381, 4681, 7387, 4734, 4739, 1820, 1827, 4461, 1845, 1854, 343 }, { 1863, 1867, 1871, 1875, 7387, 4734, 4739, 1887, 1891, 1895, 1899, 1903, 343 }, 0, 1, 344, 346, { 348, 3323, 7297 }, { 357, 1379 }, { 370, 1409 }, { 376, 1399, 2991 } }, { 7392, 409, 6005, 7416, 7427, 447, 457, 7434, 7437, { 7440, 7447, 7456, 7465, 7477, 7485, 7494 }, { 7504, 7508, 2909, 7513, 7518, 7522, 7526 }, { 7530, 7536, 3770, 7543, 1806, 7549, 7557, 7564, 7570, 7578, 7584, 7592, 343 }, { 2127, 7600, 2909, 7604, 7608, 7612, 7616, 7620, 7526, 7624, 7628, 7633, 343 }, 0, 1, 344, 346, { 348, 5524, 6005 }, { 357, 409 }, { 370, 7427 }, { 376, 7637, 7416 } }, { 16460, 7677, 6005, 438, 370, 447, 74, 7694, 7697, { 7700, 7708, 7716, 1719, 1726, 1734, 7723 }, { 7731, 7735, 3430, 5974, 3436, 5977, 7739 }, { 5889, 5897, 3770, 1800, 1806, 1810, 1815, 7743, 1827, 1837, 1845, 1854, 343 }, { 1863, 1867, 1871, 1875, 1806, 1879, 1883, 1887, 1891, 1895, 1899, 1903, 343 }, 0, 1, 344, 346, { 348, 6005 }, { 357, 7677 }, { 370, 5964 }, { 376, 5953, 438 } }, { 7751, 876, 37, 2991, 1409, 447, 74, 7772, 7803, { 7834, 7865, 7893, 7921, 7940, 7974, 7999 }, { 8024, 8032, 8037, 8042, 8047, 8055, 8060 }, { 8065, 8084, 8115, 8134, 8153, 8175, 8200, 8222, 8244, 8266, 8285, 8313, 343 }, { 8335, 8344, 8353, 8365, 8377, 8386, 8398, 8407, 8416, 8425, 8434, 8443, 343 }, 0, 0, 344, 346, { 348, 37 }, { 357, 876 }, { 370, 1409 }, { 376, 8452, 2991 } }, { 8492, 8519, 1938, 438, 370, 447, 457, 465, 468, { 8537, 8543, 8553, 8559, 8570, 8580, 8585 }, { 8595, 8599, 8603, 8607, 8612, 8616, 8620 }, { 8624, 8629, 8636, 8641, 8647, 8654, 8662, 8669, 8678, 8685, 8690, 8697, 343 }, { 8705, 8709, 2909, 8714, 2878, 8718, 8722, 8726, 8731, 8735, 8739, 8743, 343 }, 0, 1, 344, 346, { 348, 1938 }, { 357, 8519 }, { 370 }, { 376, 438 } }, { 16486, 409, 2674, 2991, 1409, 447, 457, 465, 468, { 8747, 8754, 8760, 8767, 8772, 8778, 8784 }, { 8790, 8794, 8798, 8802, 8806, 8810, 8814 }, { 8818, 8826, 8835, 2064, 8841, 2074, 2079, 8845, 2091, 2101, 2109, 8853, 343 }, { 2127, 2131, 2909, 2139, 8841, 2143, 2147, 8862, 2155, 2159, 2163, 8866, 343 }, 0, 0, 344, 346, { 348, 888, 2674 }, { 357, 409 }, { 370, 1409 }, { 376, 2991 } }, { 8870, 876, 1938, 2991, 370, 8890, 74, 465, 468, { 8906, 8919, 8938, 8955, 8968, 8981, 8997 }, { 9010, 6757, 6762, 6767, 6772, 6777, 6782 }, { 9015, 9026, 9039, 9054, 9067, 9080, 9093, 9104, 9117, 9132, 9145, 9164, 343 }, { 9177, 9184, 9191, 9198, 9207, 9216, 9225, 9232, 9241, 9248, 9257, 9266, 343 }, 0, 1, 344, 346, { 348, 844, 1938 }, { 357, 876 }, { 370 }, { 376, 2991 } }, { 8870, 876, 1938, 2991, 5964, 447, 74, 465, 468, { 9298, 9313, 9334, 9349, 9362, 9375, 9390 }, { 9403, 9408, 9413, 9418, 9423, 9428, 9433 }, { 9438, 9455, 9464, 9479, 678, 9496, 9511, 9524, 9539, 9556, 9577, 9594, 343 }, { 9609, 9184, 9616, 9623, 678, 9630, 9637, 9644, 9241, 9651, 9658, 9665, 343 }, 0, 1, 344, 346, { 348, 1392, 1938 }, { 357, 876 }, { 370, 5964 }, { 376, 5953, 2991 } }, { 9672, 9694, 3323, 2991, 1409, 447, 1687, 465, 468, { 9708, 9716, 9727, 9733, 9739, 9748, 1482 }, { 7107, 7111, 1766, 9754, 7123, 7128, 9758 }, { 1779, 1786, 7381, 1800, 1806, 9762, 9768, 9774, 1827, 1837, 1845, 1854, 343 }, { 1863, 1867, 1871, 1875, 1806, 1879, 1883, 9781, 1891, 1895, 1899, 1903, 343 }, 0, 1, 344, 346, { 348, 9785, 3323 }, { 357, 9694 }, { 370, 1409 }, { 376, 1399, 2991 } }, { 8870, 876, 9792, 2991, 1409, 447, 9802, 465, 468, { 9810, 9821, 9832, 9843, 9854, 9865, 9871 }, { 4376, 9880, 9882, 4367, 6071, 9884, 6482 }, { 9886, 9894, 9903, 9910, 3781, 9917, 9923, 1820, 1827, 9929, 1845, 9938, 343 }, { 9948, 9953, 9903, 1875, 3781, 9917, 9923, 1887, 9959, 1895, 1899, 9964, 343 }, 0, 1, 344, 346, { 348, 844, 9792 }, { 357, 876 }, { 370, 1409 }, { 376, 1399, 2991 } }, { 9969, 9998, 4534, 2991, 370, 10019, 1414, 465, 468, { 10037, 10048, 10058, 10067, 10078, 10090, 10101 }, { 10111, 4376, 10114, 9882, 10116, 10118, 6489 }, { 10121, 10131, 1794, 10142, 10151, 10157, 10165, 10173, 10181, 10192, 10201, 10211, 343 }, { 2127, 2131, 2909, 2139, 2070, 10221, 10226, 2151, 2155, 2159, 2163, 2917, 343 }, 0, 1, 344, 346, { 348, 10231, 4534 }, { 357, 9998 }, { 370 }, { 376, 2991 } }, { 16507, 10271, 7265, 438, 370, 10293, 10308, 465, 468, { 10320, 10332, 10344, 10356, 10370, 10385, 10398 }, { 10412, 10415, 10418, 10421, 10424, 6073, 7374 }, { 10427, 10434, 10442, 10447, 10458, 10468, 10478, 10485, 10497, 10506, 10513, 10524, 343 }, { 10534, 10538, 10542, 10546, 10550, 10554, 10558, 10562, 10566, 10570, 10574, 10578, 343 }, 0, 1, 344, 346, { 348, 7265 }, { 357, 10271 }, { 370 }, { 376, 438 } }, { 10582, 876, 10606, 2979, 370, 447, 74, 10615, 10622, { 10629, 10645, 10658, 10674, 10691, 10709, 10718 }, { 10727, 10731, 10735, 10739, 10743, 10747, 10751 }, { 10755, 10768, 229, 10779, 10790, 10795, 10804, 10815, 10822, 10837, 10848, 10861, 343 }, { 10874, 10881, 10888, 10895, 10902, 10909, 10916, 10815, 10923, 10930, 10937, 10944, 343 }, 0, 6, 344, 346, { 348, 10951, 10606 }, { 357, 876 }, { 370 }, { 376, 10961, 2979 } }, { 10974, 409, 2674, 2195, 370, 447, 457, 10998, 11001, { 11004, 11017, 11027, 11036, 11046, 11057, 11068 }, { 11080, 11083, 11088, 11093, 11098, 11103, 11108 }, { 11113, 11126, 11137, 11147, 11158, 11170, 11182, 11195, 11207, 11220, 11235, 11256, 343 }, { 11275, 11281, 11287, 11293, 11299, 11305, 11311, 11317, 11323, 11329, 11336, 11343, 343 }, 0, 1, 344, 346, { 348, 2674 }, { 357, 409 }, { 370 }, { 376, 2195 } }, { 11350, 2921, 1938, 2991, 370, 447, 2763, 11372, 16538, { 11388, 11401, 11422, 11441, 11462, 11481, 11494 }, { 11505, 11512, 11519, 11526, 11533, 11540, 11547 }, { 16546, 16561, 11588, 11597, 11608, 16576, 16589, 11645, 11660, 11679, 11698, 11715, 343 }, { 16602, 16609, 11748, 11755, 11762, 16616, 16623, 11783, 11790, 11797, 11804, 11811, 343 }, 0, 1, 344, 346, { 348, 11818, 1938 }, { 357, 2921 }, { 370 }, { 376, 2991 } }, { 16630, 16669, 5015, 438, 370, 16699, 1146, 465, 468, { 11827, 11835, 11846, 11856, 11867, 11876, 11885 }, { 11895, 11898, 11901, 11904, 11907, 11910, 11913 }, { 11916, 11926, 11934, 11942, 11950, 11958, 11965, 11973, 11981, 11988, 11994, 12001, 343 }, { 12009, 12013, 1871, 12017, 3781, 12021, 12025, 12029, 12033, 12037, 12041, 12045, 343 }, 0, 1, 344, 346, { 348, 16714, 5015 }, { 357, 16669 }, { 370 }, { 376, 438 } }, { 387, 409, 1938, 438, 370, 447, 457, 465, 468, { 12049, 484, 505, 6696, 12062, 12079, 12090 }, { 574, 582, 590, 12103, 12111, 612, 12119 }, { 12127, 641, 658, 667, 12142, 12149, 12158, 699, 712, 731, 748, 763, 343 }, { 12167, 786, 12175, 794, 12183, 12191, 12199, 802, 12207, 818, 826, 12217, 343 }, 0, 1, 344, 346, { 348, 12229, 1938 }, { 357, 409 }, { 370 }, { 376, 438 } }, { 16727, 409, 5015, 2979, 56, 447, 457, 343, 343, { 12243, 12250, 12258, 12266, 12275, 12285, 12292 }, { 2022, 6484, 2028, 12301, 2034, 12304, 2040 }, { 12307, 12316, 12326, 2064, 8841, 12332, 12338, 12344, 2091, 2101, 2109, 8853, 343 }, { 2127, 2131, 2909, 2139, 8841, 2143, 2147, 2151, 2155, 2159, 2163, 8866, 343 }, 0, 0, 344, 346, { 348, 5015 }, { 357, 409 }, { 370, 56 }, { 376, 46, 2979 } }, { 16752, 16792, 1938, 2991, 1409, 12382, 1146, 12389, 12405, { 5226, 5228, 5230, 5232, 5234, 5236, 5238 }, { 5226, 5228, 5230, 5232, 5234, 5236, 5238 }, { 5226, 5228, 5230, 5232, 5234, 5236, 5238, 5240, 5242, 5244, 5247, 5250, 343 }, { 5226, 5228, 5230, 5232, 5234, 5236, 5238, 5240, 5242, 5244, 5247, 5250, 343 }, 0, 0, 344, 346, { 348, 1938 }, { 357, 12373, 16792 }, { 370, 1409 }, { 376, 2991 } }, { 16824, 1664, 1676, 16845, 370, 447, 457, 465, 468, { 4546, 12450, 12461, 12471, 12481, 12491, 12505 }, { 4632, 4636, 12517, 12522, 12526, 12531, 12536 }, { 1779, 1786, 3770, 4681, 3781, 1810, 1815, 1820, 1827, 1837, 1845, 4725, 343 }, { 1863, 1867, 1871, 1875, 3781, 1879, 1883, 1887, 1891, 1895, 1899, 4755, 343 }, 0, 0, 344, 346, { 348, 1907, 1676 }, { 357, 1664 }, { 370 }, { 376, 16845 } }, { 5984, 876, 1676, 438, 56, 447, 74, 12540, 12568, { 12590, 12609, 12628, 12650, 12669, 12691, 12716 }, { 12735, 12745, 12755, 12768, 12778, 12791, 12807 }, { 12817, 12833, 12849, 12865, 12884, 12891, 12901, 12917, 12933, 12955, 12977, 12996, 343 }, { 12817, 12833, 12849, 12865, 12884, 12891, 12901, 12917, 12933, 12955, 12977, 12996, 343 }, 0, 0, 344, 346, { 348, 5805, 1676 }, { 357, 876 }, { 370, 56 }, { 376, 2685, 438 } }, { 16854, 357, 10606, 16878, 370, 1136, 1146, 465, 468, { 13018, 13027, 13036, 13044, 13053, 13062, 13069 }, { 13078, 13082, 13086, 13090, 13094, 13098, 13102 }, { 8818, 8826, 13106, 13112, 8841, 2074, 13119, 13125, 13132, 13141, 13148, 13156, 343 }, { 2127, 2131, 2909, 2139, 8841, 2143, 2147, 13164, 2155, 2159, 2163, 8866, 343 }, 0, 6, 344, 346, { 348, 10606 }, { 357 }, { 370 }, { 376, 16878 } }, { 16889, 876, 16914, 16922, 16935, 447, 74, 13168, 13210, { 13252, 13271, 13290, 13312, 13331, 13353, 13378 }, { 13397, 13407, 13417, 13430, 13440, 13453, 13469 }, { 13479, 13507, 13535, 13551, 13570, 13577, 13587, 13603, 13619, 13647, 13669, 13691, 343 }, { 13716, 13735, 13535, 13551, 13570, 13577, 13587, 13603, 13754, 13770, 13786, 13796, 343 }, 0, 0, 344, 346, { 348, 16914 }, { 357, 876 }, { 370, 16935 }, { 376, 16922 } }, { 16943, 876, 5805, 2685, 56, 447, 74, 13809, 13822, { 13835, 13854, 13876, 13901, 13917, 13939, 13958 }, { 13968, 13975, 13982, 13989, 13996, 14003, 14010 }, { 14014, 14030, 14055, 14074, 14093, 14100, 14113, 14126, 14145, 14176, 14201, 14223, 343 }, { 14248, 14256, 14270, 14284, 14093, 14100, 14113, 14295, 14303, 14317, 14328, 14336, 343 }, 0, 0, 344, 346, { 348, 5805 }, { 357, 876 }, { 370, 56 }, { 376, 2685 } }, { 16943, 876, 1907, 2685, 56, 447, 74, 14347, 14375, { 14397, 14419, 14441, 14466, 14488, 14513, 14541 }, { 14563, 14573, 14583, 14596, 14606, 14619, 14635 }, { 14645, 14661, 14686, 14705, 14727, 14734, 14747, 14760, 14779, 14810, 14835, 14854, 343 }, { 14645, 14661, 14686, 14705, 14727, 14734, 14747, 14760, 14779, 14810, 14835, 14854, 343 }, 0, 0, 344, 346, { 348, 1907 }, { 357, 876 }, { 370, 56 }, { 376, 2685 } }, { 16889, 876, 5805, 16922, 16935, 447, 74, 14879, 14907, { 14929, 14948, 14967, 14989, 15008, 15030, 15055 }, { 15074, 15079, 15087, 15095, 15103, 15111, 15119 }, { 15130, 15146, 15171, 15190, 15212, 15219, 15232, 15245, 15264, 15292, 15317, 15339, 343 }, { 15130, 15146, 15171, 15190, 15212, 15219, 15232, 15245, 15264, 15292, 15317, 15339, 343 }, 0, 0, 344, 346, { 348, 5805 }, { 357, 876 }, { 370, 16935 }, { 376, 16922 } }, { 16943, 876, 5805, 2685, 56, 447, 74, 15364, 15376, { 12590, 12609, 15388, 12650, 12669, 12691, 12716 }, { 12735, 12745, 15410, 12768, 12778, 12791, 12807 }, { 15423, 15448, 12849, 15473, 15492, 12891, 15499, 15512, 15528, 15556, 15578, 15606, 343 }, { 15423, 15448, 12849, 15473, 15492, 12891, 15499, 15512, 15528, 15556, 15578, 15606, 343 }, 0, 0, 344, 346, { 348, 5805 }, { 357, 876 }, { 370, 56 }, { 376, 2685 } }, { 4759, 409, 888, 376, 370, 447, 457, 465, 468, { 15628, 15636, 15641, 15648, 15658, 15664, 15671 }, { 15679, 15683, 2909, 15687, 15692, 15696, 15700 }, { 15705, 15713, 15722, 15728, 15734, 15739, 15745, 15751, 15758, 15767, 15775, 15784, 343 }, { 15793, 2131, 2909, 15797, 2070, 15801, 15806, 13164, 15810, 15814, 2163, 2917, 343 }, 0, 1, 344, 346, { 348, 888 }, { 357, 409 }, { 370 }, { 376 } }, { 16943, 876, 5805, 2685, 56, 447, 74, 15364, 15376, { 15818, 12609, 15846, 12650, 12669, 12691, 12716 }, { 12735, 12745, 15410, 12768, 12778, 12791, 12807 }, { 15423, 15865, 12849, 15473, 15492, 12891, 15499, 15512, 15528, 15556, 15578, 15606, 343 }, { 15423, 15448, 12849, 15473, 15492, 12891, 15499, 15512, 15528, 15556, 15578, 15606, 343 }, 0, 0, 344, 346, { 348, 5805 }, { 357, 876 }, { 370, 56 }, { 376, 2685 } }, { 1, 24, 37, 46, 56, 63, 74, 81, 84, { 87, 98, 113, 130, 147, 160, 173 }, { 184, 187, 190, 193, 196, 199, 202 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, 0, 6, 344, 346, { 348, 37 }, { 357, 24 }, { 370, 56 }, { 376, 46 } }, { 16967, 4993, 17012, 17019, 17042, 5026, 5042, 1154, 1161, { 1168, 1178, 1188, 1198, 1208, 1218, 1228 }, { 1238, 1242, 1246, 1250, 1254, 1258, 1262 }, { 1266, 1273, 1280, 1287, 1294, 1301, 1308, 1315, 1322, 1329, 1336, 1346, 343 }, { 1266, 1273, 1280, 1287, 1294, 1301, 1308, 1315, 1322, 1329, 1336, 1346, 343 }, 0, 0, 344, 346, { 348, 17012 }, { 357, 4993 }, { 370, 17042 }, { 376, 17019 } }, { 1916, 1379, 1938, 438, 370, 447, 1414, 1949, 1955, { 1962, 1970, 1977, 1986, 1995, 2006, 2014 }, { 2022, 2025, 2028, 2031, 2034, 2037, 2040 }, { 2043, 2050, 2058, 2064, 2070, 2074, 2079, 2084, 2091, 2101, 2109, 2118, 343 }, { 2127, 2131, 2135, 2139, 2070, 2143, 2147, 2151, 2155, 2159, 2163, 2167, 343 }, 0, 1, 344, 346, { 348, 844, 1938 }, { 357, 1379 }, { 370 }, { 376, 438 } }, { 5984, 876, 2674, 438, 370, 447, 74, 465, 468, { 2770, 2777, 2784, 2792, 2802, 2811, 2818 }, { 2827, 2831, 2835, 2839, 2843, 2847, 2851 }, { 2855, 2863, 2872, 2064, 2878, 2882, 2887, 2084, 2091, 2892, 2109, 2900, 343 }, { 2127, 2131, 2909, 2139, 2878, 2143, 2147, 2151, 2155, 2913, 2163, 2917, 343 }, 0, 1, 344, 346, { 348, 2748, 2674 }, { 2728, 2728, 2921, 2935, 2955, 876 }, { 2755, 2755, 2970, 1409, 370 }, { 2195, 2195, 2979, 2991, 438, 376 } }, { 2999, 3033, 2674, 2979, 16935, 3066, 3071, 3083, 3088, { 3093, 3101, 3107, 3114, 3125, 3132, 3140 }, { 3148, 3152, 1871, 3156, 3161, 3165, 3169 }, { 3174, 3180, 3188, 1004, 3194, 3199, 3205, 3211, 3218, 1042, 3229, 3239, 343 }, { 3249, 1867, 1871, 3253, 3257, 1879, 1883, 3261, 1891, 3265, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 3273, 3055, 888, 2674 }, { 357, 3033 }, { 370, 16935 }, { 376, 2979, 16922 } }, { 8870, 876, 3868, 2991, 370, 447, 74, 465, 468, { 3666, 3675, 3681, 3687, 3696, 3702, 3711 }, { 3718, 3723, 3728, 3733, 3738, 3743, 3748 }, { 3753, 3761, 3770, 3775, 3781, 3785, 3790, 3798, 3804, 3814, 1050, 3822, 343 }, { 3832, 3838, 3770, 3845, 3781, 3785, 3850, 3798, 3856, 1097, 1102, 3862, 343 }, 0, 1, 344, 346, { 888, 3868, 3273 }, { 357, 876, 3649 }, { 370 }, { 376, 438, 2991 } }, { 5984, 876, 1938, 438, 370, 447, 74, 4783, 4786, { 4789, 4798, 4806, 4815, 4826, 4835, 4844 }, { 3148, 3152, 1871, 4851, 4855, 4859, 4863 }, { 4867, 4875, 3188, 4884, 4891, 4898, 4905, 3211, 4912, 4922, 1050, 4930, 343 }, { 4939, 1867, 1871, 1875, 4943, 4947, 4951, 3261, 4955, 4959, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 888, 844, 1938 }, { 357, 409, 876 }, { 370 }, { 376, 438 } }, { 8870, 876, 3868, 2991, 370, 447, 74, 465, 468, { 5812, 5819, 5827, 5835, 5844, 5854, 5862 }, { 5871, 3427, 5874, 5877, 5880, 5883, 5886 }, { 5889, 5897, 5906, 1800, 5912, 1810, 1815, 5916, 1827, 1837, 1845, 1854, 343 }, { 1863, 1867, 5925, 1875, 5912, 1879, 1883, 1887, 1891, 1895, 1899, 1903, 343 }, 0, 1, 344, 346, { 348, 5805, 3273, 3868 }, { 357, 876 }, { 370, 1409 }, { 376, 1399, 2991 } }, { 5929, 1379, 844, 5953, 5964, 447, 1414, 465, 468, { 1696, 1704, 1711, 1719, 1726, 1734, 1741 }, { 5970, 3427, 3430, 5974, 3436, 5977, 5980 }, { 1779, 1786, 3770, 1800, 3781, 1810, 1815, 1820, 1827, 1837, 1845, 4725, 343 }, { 1863, 1867, 1871, 1875, 3781, 1879, 1883, 1887, 1891, 1895, 1899, 4755, 343 }, 0, 1, 344, 346, { 348, 844 }, { 357, 1379 }, { 370, 5964 }, { 376, 5953 } }, { 17048, 3033, 1676, 2991, 370, 3066, 3071, 465, 468, { 3093, 6253, 6267, 6280, 6293, 6306, 3140 }, { 3148, 6318, 6322, 6326, 6330, 6334, 3169 }, { 6338, 6346, 6356, 1004, 6363, 6368, 6374, 3211, 6380, 6389, 6397, 6406, 343 }, { 1863, 6415, 1871, 3253, 3781, 1879, 1883, 3261, 4955, 6419, 1899, 6423, 343 }, 0, 1, 344, 346, { 348, 1676 }, { 357, 3033 }, { 370 }, { 376, 2991 } }, { 16460, 7677, 3323, 438, 5964, 447, 74, 7694, 7697, { 7700, 7708, 7716, 1719, 1726, 1734, 7723 }, { 7731, 7735, 3430, 5974, 3436, 5977, 7739 }, { 5889, 5897, 3770, 1800, 1806, 1810, 1815, 7743, 1827, 1837, 1845, 1854, 343 }, { 1863, 1867, 1871, 1875, 1806, 1879, 1883, 1887, 1891, 1895, 1899, 1903, 343 }, 0, 1, 344, 346, { 348, 6005, 3323 }, { 357, 7677 }, { 370, 5964 }, { 376, 5953, 438 } }, { 17078, 24, 2674, 2979, 56, 63, 74, 81, 84, { 87, 98, 113, 130, 147, 160, 173 }, { 184, 187, 190, 193, 196, 199, 202 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, 0, 6, 344, 346, { 348, 37, 2674 }, { 357, 24 }, { 370, 56 }, { 376, 46, 2979 } }, { 17103, 5324, 17150, 15941, 17042, 17170, 17187, 1154, 1161, { 1168, 1178, 1188, 1198, 1208, 1218, 1228 }, { 1238, 1242, 1246, 1250, 1254, 1258, 1262 }, { 1266, 1273, 1280, 1287, 1294, 1301, 1308, 1315, 1322, 1329, 1336, 1346, 343 }, { 5163, 5168, 5173, 5178, 5183, 5188, 5193, 5198, 5203, 5208, 5214, 5220, 343 }, 0, 0, 344, 346, { 348, 17150 }, { 357, 5324 }, { 370, 17042 }, { 376, 15941 } }, { 17202, 9694, 1938, 438, 370, 447, 1687, 1949, 1955, { 1962, 1970, 1977, 1986, 1995, 2006, 2014 }, { 2022, 2025, 2028, 2031, 2034, 2037, 2040 }, { 17225, 2050, 2058, 2064, 2070, 2074, 2079, 2084, 2091, 2101, 2109, 2118, 343 }, { 17233, 2131, 17238, 2139, 2070, 2143, 2147, 2151, 2155, 2159, 2163, 2167, 343 }, 0, 1, 344, 346, { 348, 844, 1938 }, { 357, 1379, 9694 }, { 370 }, { 376, 438 } }, { 17243, 876, 3868, 2195, 56, 447, 74, 465, 468, { 2770, 2777, 2784, 2792, 2802, 2811, 2818 }, { 2827, 2831, 2835, 2839, 2843, 2847, 2851 }, { 2855, 2863, 2872, 2064, 2878, 2882, 2887, 2084, 2091, 2892, 2109, 2900, 343 }, { 2127, 2131, 2909, 2139, 2878, 2143, 2147, 2151, 2155, 2913, 2163, 2917, 343 }, 0, 0, 344, 346, { 348, 2748, 3273, 3868 }, { 2728, 2728, 2921, 2935, 2955, 876 }, { 2755, 2755, 2970, 1409, 370, 56 }, { 2195, 2195, 2979, 2991, 438, 46 } }, { 17266, 17303, 2674, 2991, 1409, 17332, 457, 3083, 3088, { 3093, 3101, 3107, 3114, 3125, 3132, 3140 }, { 3148, 3152, 1871, 3156, 3161, 3165, 3169 }, { 3174, 3180, 3188, 1004, 3194, 3199, 3205, 3211, 3218, 1042, 3229, 3239, 343 }, { 3249, 1867, 1871, 3253, 3257, 1879, 1883, 3261, 1891, 3265, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 3273, 3055, 888, 2674 }, { 357, 3033, 17303 }, { 370, 1409 }, { 376, 2979, 2991 } }, { 5984, 876, 6005, 438, 370, 447, 74, 465, 468, { 3666, 3675, 3681, 3687, 3696, 3702, 3711 }, { 3718, 3723, 3728, 3733, 3738, 3743, 3748 }, { 3753, 3761, 3770, 3775, 3781, 3785, 3790, 3798, 3804, 3814, 1050, 3822, 343 }, { 3832, 3838, 3770, 3845, 3781, 3785, 3850, 3798, 3856, 1097, 1102, 3862, 343 }, 0, 0, 344, 346, { 888, 3868, 3273, 5524, 6005 }, { 357, 876, 3649 }, { 370 }, { 376, 438 } }, { 17078, 24, 2674, 2979, 56, 63, 74, 81, 84, { 87, 98, 113, 130, 147, 160, 173 }, { 184, 187, 190, 193, 196, 199, 202 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, 0, 6, 344, 346, { 348, 37, 2674 }, { 357, 24 }, { 370, 56 }, { 376, 46, 2979 } }, { 17347, 17370, 888, 17382, 17393, 447, 457, 1154, 1161, { 1168, 1178, 1188, 1198, 1208, 1218, 1228 }, { 1238, 1242, 1246, 1250, 1254, 1258, 1262 }, { 1266, 1273, 1280, 1287, 1294, 1301, 1308, 1315, 1322, 1329, 1336, 1346, 343 }, { 1266, 1273, 1280, 1287, 1294, 1301, 1308, 1315, 1322, 1329, 1336, 1346, 343 }, 0, 0, 344, 346, { 348, 888 }, { 357, 17370 }, { 370, 17393 }, { 376, 17382 } }, { 1916, 1379, 1938, 438, 370, 447, 1414, 1949, 1955, { 1962, 1970, 1977, 1986, 1995, 2006, 2014 }, { 2022, 2025, 2028, 2031, 2034, 2037, 2040 }, { 2043, 2050, 2058, 2064, 2070, 2074, 2079, 2084, 2091, 2101, 2109, 2118, 343 }, { 2127, 2131, 2135, 2139, 2070, 2143, 2147, 2151, 2155, 2159, 2163, 2167, 343 }, 0, 1, 344, 346, { 348, 844, 1938 }, { 357, 1379 }, { 370 }, { 376, 438 } }, { 17401, 17425, 2674, 2195, 56, 447, 2763, 465, 468, { 2770, 2777, 2784, 2792, 2802, 2811, 2818 }, { 2827, 2831, 2835, 2839, 2843, 2847, 2851 }, { 2855, 2863, 2872, 2064, 2878, 2882, 2887, 2084, 2091, 2892, 2109, 2900, 343 }, { 2127, 2131, 2909, 2139, 2878, 2143, 2147, 2151, 2155, 2913, 2163, 2917, 343 }, 0, 0, 344, 346, { 348, 2748, 888, 2674 }, { 2728, 2728, 2921, 2935, 2955, 17425 }, { 2755, 2755, 2970, 1409, 370, 56 }, { 2195, 2195, 2979, 2991, 438, 2685 } }, { 2999, 3033, 2674, 2979, 16935, 3066, 3071, 3083, 3088, { 3093, 3101, 3107, 3114, 3125, 3132, 3140 }, { 3148, 3152, 1871, 3156, 3161, 3165, 3169 }, { 3174, 3180, 3188, 1004, 3194, 3199, 3205, 3211, 3218, 1042, 3229, 3239, 343 }, { 3249, 1867, 1871, 3253, 3257, 1879, 1883, 3261, 1891, 3265, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 3273, 3055, 2674 }, { 357, 3033 }, { 370, 16935 }, { 376, 2979, 16922 } }, { 5984, 876, 1938, 438, 370, 447, 74, 465, 468, { 3666, 3675, 3681, 3687, 3696, 3702, 3711 }, { 3718, 3723, 3728, 3733, 3738, 3743, 3748 }, { 3753, 3761, 3770, 3775, 3781, 3785, 3790, 3798, 3804, 3814, 1050, 3822, 343 }, { 3832, 3838, 3770, 3845, 3781, 3785, 3850, 3798, 3856, 1097, 1102, 3862, 343 }, 0, 1, 344, 346, { 888, 3868, 3273, 844, 1938 }, { 357, 876, 3649 }, { 370 }, { 376, 438 } }, { 17438, 24, 1676, 2991, 56, 63, 74, 81, 84, { 87, 98, 113, 130, 147, 160, 173 }, { 184, 187, 190, 193, 196, 199, 202 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, 0, 6, 344, 346, { 348, 37, 1676 }, { 357, 24 }, { 370, 56 }, { 376, 46, 2991 } }, { 17103, 5324, 17150, 15941, 17042, 17170, 17187, 1154, 1161, { 1168, 1178, 1188, 1198, 1208, 1218, 1228 }, { 1238, 1242, 1246, 1250, 1254, 1258, 1262 }, { 1266, 1273, 1280, 1287, 1294, 1301, 1308, 1315, 1322, 1329, 1336, 1346, 343 }, { 5163, 5168, 5173, 5178, 5183, 5188, 5193, 5198, 5203, 5208, 5214, 5220, 343 }, 0, 0, 344, 346, { 348, 17150 }, { 357, 5324 }, { 370, 17042 }, { 376, 15941 } }, { 17243, 876, 3868, 2195, 56, 447, 74, 3083, 3088, { 2770, 2777, 2784, 2792, 2802, 2811, 2818 }, { 2827, 2831, 2835, 2839, 2843, 2847, 2851 }, { 2855, 2863, 2872, 2064, 2878, 2882, 2887, 2084, 2091, 2892, 2109, 2900, 343 }, { 2127, 2131, 2909, 2139, 2878, 2143, 2147, 2151, 2155, 2913, 2163, 2917, 343 }, 0, 0, 344, 346, { 348, 2748, 3273, 3868 }, { 2728, 2728, 2921, 2935, 2955, 876 }, { 2755, 2755, 2970, 1409, 370, 56 }, { 2195, 2195, 2979, 2991, 438, 46 } }, { 2999, 3033, 2674, 2979, 16935, 3066, 3071, 3083, 3088, { 3093, 3101, 3107, 3114, 3125, 3132, 3140 }, { 3148, 3152, 1871, 3156, 3161, 3165, 3169 }, { 3174, 3180, 3188, 1004, 3194, 3199, 3205, 3211, 3218, 1042, 3229, 3239, 343 }, { 3249, 1867, 1871, 3253, 3257, 1879, 1883, 3261, 1891, 3265, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 3273, 3055, 888, 2674 }, { 357, 3033 }, { 370, 16935 }, { 376, 2979, 16922 } }, { 3623, 3649, 2674, 438, 370, 447, 74, 465, 468, { 3666, 3675, 3681, 3687, 3696, 3702, 3711 }, { 3718, 3723, 3728, 3733, 3738, 3743, 3748 }, { 3753, 3761, 3770, 3775, 3781, 3785, 3790, 3798, 3804, 3814, 1050, 3822, 343 }, { 3832, 3838, 3770, 3845, 3781, 3785, 3850, 3798, 3856, 1097, 1102, 3862, 343 }, 0, 1, 344, 346, { 888, 3868, 3273, 2674 }, { 357, 876, 3649 }, { 370 }, { 376, 438 } }, { 17438, 24, 1676, 2991, 56, 63, 74, 81, 84, { 87, 98, 113, 130, 147, 160, 173 }, { 184, 187, 190, 193, 196, 199, 202 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, 0, 6, 344, 346, { 348, 37, 1676 }, { 357, 24 }, { 370, 56 }, { 376, 46, 2991 } }, { 5984, 876, 2674, 438, 370, 447, 74, 3083, 3088, { 2770, 2777, 2784, 2792, 2802, 2811, 2818 }, { 2827, 2831, 2835, 2839, 2843, 2847, 2851 }, { 2855, 2863, 2872, 2064, 2878, 2882, 2887, 2084, 2091, 2892, 2109, 2900, 343 }, { 2127, 2131, 2909, 2139, 2878, 2143, 2147, 2151, 2155, 2913, 2163, 2917, 343 }, 0, 0, 344, 346, { 348, 2748, 2674 }, { 2728, 2728, 2921, 2935, 2955, 876 }, { 2755, 2755, 2970, 1409, 370 }, { 2195, 2195, 2979, 2991, 438, 376 } }, { 2999, 3033, 3055, 2979, 16935, 3066, 3071, 3083, 3088, { 3093, 3101, 3107, 3114, 3125, 3132, 3140 }, { 3148, 3152, 1871, 3156, 3161, 3165, 3169 }, { 3174, 3180, 3188, 1004, 3194, 3199, 3205, 3211, 3218, 1042, 3229, 3239, 343 }, { 3249, 1867, 1871, 3253, 3257, 1879, 1883, 3261, 1891, 3265, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 3273, 3055, 11818 }, { 357, 3033 }, { 370, 16935 }, { 376, 2979, 16922 } }, { 17438, 24, 1676, 2991, 56, 63, 74, 81, 84, { 87, 98, 113, 130, 147, 160, 173 }, { 87, 98, 113, 130, 147, 160, 173 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, 0, 6, 344, 346, { 348, 37, 1676 }, { 357, 24 }, { 370, 56 }, { 376, 46, 2991 } }, { 16727, 409, 5015, 2979, 56, 447, 457, 465, 468, { 2770, 2777, 2784, 2792, 2802, 2811, 2818 }, { 2827, 2831, 2835, 2839, 2843, 2847, 2851 }, { 2855, 2863, 2872, 2064, 2878, 2882, 2887, 2084, 2091, 2892, 2109, 2900, 343 }, { 2127, 2131, 2909, 2139, 2878, 2143, 2147, 2151, 2155, 2913, 2163, 2917, 343 }, 0, 0, 344, 346, { 348, 2748, 5015 }, { 2728, 2728, 2921, 2935, 2955, 409 }, { 2755, 2755, 2970, 1409, 370, 56 }, { 2195, 2195, 2979, 2991, 438, 46 } }, { 2999, 3033, 2674, 2979, 16935, 3066, 3071, 3083, 3088, { 3093, 3101, 3107, 3114, 3125, 3132, 3140 }, { 3148, 3152, 1871, 3156, 3161, 3165, 3169 }, { 3174, 3180, 3188, 1004, 3194, 3199, 3205, 3211, 3218, 1042, 3229, 3239, 343 }, { 3249, 1867, 1871, 3253, 3257, 1879, 1883, 3261, 1891, 3265, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 3273, 3055, 888, 2674 }, { 357, 3033 }, { 370, 16935 }, { 376, 2979, 16922 } }, { 17078, 24, 2674, 2979, 56, 63, 74, 81, 84, { 87, 98, 113, 130, 147, 160, 173 }, { 184, 187, 190, 193, 196, 199, 202 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, 0, 6, 344, 346, { 348, 37, 2674 }, { 357, 24 }, { 370, 56 }, { 376, 46, 2979 } }, { 2999, 3033, 2674, 2979, 16935, 3066, 3071, 3083, 3088, { 3093, 3101, 3107, 3114, 3125, 3132, 3140 }, { 3148, 3152, 1871, 3156, 3161, 3165, 3169 }, { 3174, 3180, 3188, 1004, 3194, 3199, 3205, 3211, 3218, 1042, 3229, 3239, 343 }, { 3249, 1867, 1871, 3253, 3257, 1879, 1883, 3261, 1891, 3265, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 3273, 3055, 888, 2674 }, { 357, 3033 }, { 370, 16935 }, { 376, 2979, 16922 } }, { 17078, 24, 2674, 2979, 56, 63, 74, 81, 84, { 87, 98, 113, 130, 147, 160, 173 }, { 87, 98, 113, 130, 147, 160, 173 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, 0, 6, 344, 346, { 348, 37, 2674 }, { 357, 24 }, { 370, 56 }, { 376, 46, 2979 } }, { 2999, 3033, 2674, 2979, 1409, 3066, 3071, 3083, 3088, { 3093, 3101, 3107, 3114, 3125, 3132, 3140 }, { 3148, 3152, 1871, 3156, 3161, 3165, 3169 }, { 3174, 3180, 3188, 1004, 3194, 3199, 3205, 3211, 3218, 1042, 3229, 3239, 343 }, { 3249, 1867, 1871, 3253, 3257, 1879, 1883, 3261, 1891, 3265, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 3273, 3055, 2674 }, { 357, 3033 }, { 370, 1409 }, { 376, 2979, 1399 } }, { 17078, 24, 2674, 2979, 56, 63, 74, 81, 84, { 87, 98, 113, 130, 147, 160, 173 }, { 87, 98, 113, 130, 147, 160, 173 }, { 17459, 17483, 17492, 17501, 17512, 17521, 17534, 17543, 17548, 17559, 17581, 17605, 343 }, { 17459, 17483, 17492, 17501, 17512, 17521, 17534, 17543, 17548, 17559, 17581, 17605, 343 }, 0, 4, 344, 346, { 348, 37, 2674 }, { 357, 24 }, { 370, 56 }, { 376, 46, 2979 } }, { 2999, 3033, 2674, 2979, 16935, 3066, 3071, 3083, 3088, { 3093, 3101, 3107, 3114, 3125, 3132, 3140 }, { 3148, 3152, 1871, 3156, 3161, 3165, 3169 }, { 3174, 3180, 3188, 1004, 3194, 3199, 3205, 3211, 3218, 1042, 3229, 3239, 343 }, { 3249, 1867, 1871, 3253, 3257, 1879, 1883, 3261, 1891, 3265, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 3273, 3055, 888, 2674 }, { 357, 3033 }, { 370, 16935 }, { 376, 2979, 16922 } }, { 17078, 24, 2674, 2979, 56, 63, 74, 81, 84, { 87, 98, 113, 130, 147, 160, 173 }, { 87, 98, 113, 130, 147, 160, 173 }, { 17459, 17483, 17492, 17501, 17627, 17521, 17534, 17543, 17548, 17559, 17581, 17605, 343 }, { 17459, 17483, 17492, 17501, 17627, 17521, 17534, 17543, 17548, 17559, 17581, 17605, 343 }, 0, 6, 344, 346, { 348, 37, 2674 }, { 357, 24 }, { 370, 56 }, { 376, 46, 2979 } }, { 17636, 17667, 2674, 2979, 2755, 447, 2763, 465, 468, { 2770, 2777, 2784, 2792, 2802, 2811, 2818 }, { 2827, 2831, 2835, 2839, 2843, 2847, 2851 }, { 2855, 2863, 2872, 2064, 2878, 2882, 2887, 2084, 2091, 2892, 2109, 2900, 343 }, { 2127, 2131, 2909, 2139, 2878, 2143, 2147, 2151, 2155, 2913, 2163, 2917, 343 }, 0, 0, 344, 346, { 2674, 6005 }, { 2728, 2728, 2921, 2935, 2955, 17667 }, { 2755, 2755, 2970, 1409, 370 }, { 2979, 438 } }, { 2999, 3033, 2674, 2979, 370, 3066, 3071, 3083, 3088, { 3093, 3101, 3107, 3114, 3125, 3132, 3140 }, { 3148, 3152, 1871, 3156, 3161, 3165, 3169 }, { 3174, 3180, 3188, 1004, 3194, 3199, 3205, 3211, 3218, 1042, 3229, 3239, 343 }, { 3249, 1867, 1871, 3253, 3257, 1879, 1883, 3261, 1891, 3265, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 3273, 3055, 888, 2674 }, { 357, 3033 }, { 370 }, { 376, 2979, 1399 } }, { 17078, 24, 2674, 2979, 56, 63, 74, 81, 84, { 87, 98, 113, 130, 147, 160, 173 }, { 87, 98, 113, 130, 147, 160, 173 }, { 17459, 17483, 17492, 17501, 17512, 17521, 17534, 17543, 17548, 17559, 17581, 17605, 343 }, { 17459, 17483, 17492, 17501, 17512, 17521, 17534, 17543, 17548, 17559, 17581, 17605, 343 }, 0, 6, 344, 346, { 348, 37, 2674 }, { 357, 24 }, { 370, 56 }, { 376, 46, 2979 } }, { 2171, 409, 10606, 2195, 56, 447, 457, 465, 468, { 2770, 2777, 2784, 2792, 2802, 2811, 2818 }, { 2827, 2831, 2835, 2839, 2843, 2847, 2851 }, { 2855, 2863, 2872, 2064, 2878, 2882, 2887, 2084, 2091, 2892, 2109, 2900, 343 }, { 2127, 2131, 2909, 2139, 2878, 2143, 2147, 2151, 2155, 2913, 2163, 2917, 343 }, 0, 0, 344, 346, { 348, 2748, 37, 10606 }, { 2728, 2728, 2921, 2935, 2955, 409 }, { 2755, 2755, 2970, 1409, 370, 56 }, { 2195, 2195, 2979, 2991, 438, 46 } }, { 17048, 3033, 2674, 2991, 1409, 3066, 3071, 3083, 3088, { 3093, 3101, 3107, 3114, 3125, 3132, 3140 }, { 3148, 3152, 1871, 3156, 3161, 3165, 3169 }, { 3174, 3180, 3188, 1004, 3194, 3199, 3205, 3211, 3218, 1042, 3229, 3239, 343 }, { 3249, 1867, 1871, 3253, 3257, 1879, 1883, 3261, 1891, 3265, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 3273, 3055, 888, 2674 }, { 357, 3033 }, { 370, 1409 }, { 376, 2979, 1399, 2991 } }, { 17078, 24, 2674, 2979, 56, 63, 74, 81, 84, { 87, 98, 113, 130, 147, 160, 173 }, { 184, 187, 190, 193, 196, 199, 202 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, 0, 6, 344, 346, { 348, 37, 2674 }, { 357, 24 }, { 370, 56 }, { 376, 46, 2979 } }, { 17401, 17425, 10606, 2195, 56, 447, 2763, 465, 468, { 2770, 2777, 2784, 2792, 2802, 2811, 2818 }, { 2827, 2831, 2835, 2839, 2843, 2847, 2851 }, { 2855, 2863, 2872, 2064, 2878, 2882, 2887, 2084, 2091, 2892, 2109, 2900, 343 }, { 2127, 2131, 2909, 2139, 2878, 2143, 2147, 2151, 2155, 2913, 2163, 2917, 343 }, 0, 0, 344, 346, { 348, 2748, 10606 }, { 2728, 2728, 2921, 2935, 2955, 17425 }, { 2755, 2755, 2970, 1409, 370, 56 }, { 2195, 2195, 2979, 2991, 438, 2685 } }, { 17048, 3033, 1676, 2991, 1409, 3066, 3071, 3083, 3088, { 3093, 3101, 3107, 3114, 3125, 3132, 3140 }, { 3148, 3152, 1871, 3156, 3161, 3165, 3169 }, { 3174, 3180, 3188, 1004, 3194, 3199, 3205, 3211, 3218, 1042, 3229, 3239, 343 }, { 3249, 1867, 1871, 3253, 3257, 1879, 1883, 3261, 1891, 3265, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 3273, 3055, 1907, 1676 }, { 357, 3033 }, { 370, 1409 }, { 376, 2979, 1399, 2991 } }, { 17078, 24, 2674, 2979, 56, 63, 74, 81, 84, { 87, 98, 113, 130, 147, 160, 173 }, { 184, 187, 190, 193, 196, 199, 202 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, 0, 6, 344, 346, { 348, 37, 2674 }, { 357, 24 }, { 370, 56 }, { 376, 46, 2979 } }, { 2999, 3033, 2674, 2979, 16935, 3066, 3071, 3083, 3088, { 3093, 3101, 3107, 3114, 3125, 3132, 3140 }, { 3148, 3152, 1871, 3156, 3161, 3165, 3169 }, { 3174, 3180, 3188, 1004, 3194, 3199, 3205, 3211, 3218, 1042, 3229, 3239, 343 }, { 3249, 1867, 1871, 3253, 3257, 1879, 1883, 3261, 1891, 3265, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 3273, 3055, 888, 2674 }, { 357, 3033 }, { 370, 16935 }, { 376, 2979, 16922 } }, { 17078, 24, 2674, 2979, 56, 63, 74, 81, 84, { 87, 98, 113, 130, 147, 160, 173 }, { 184, 187, 190, 193, 196, 199, 202 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, 0, 6, 344, 346, { 348, 37, 2674 }, { 357, 24 }, { 370, 56 }, { 376, 46, 2979 } }, { 2999, 3033, 2674, 2979, 16935, 3066, 3071, 3083, 3088, { 3093, 3101, 3107, 3114, 3125, 3132, 3140 }, { 3148, 3152, 1871, 3156, 3161, 3165, 3169 }, { 3174, 3180, 3188, 1004, 3194, 3199, 3205, 3211, 3218, 1042, 3229, 3239, 343 }, { 3249, 1867, 1871, 3253, 3257, 1879, 1883, 3261, 1891, 3265, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 3273, 3055, 888, 2674 }, { 357, 3033 }, { 370, 16935 }, { 376, 2979, 16922 } }, { 17078, 24, 2674, 2979, 56, 63, 74, 81, 84, { 87, 98, 113, 130, 147, 160, 173 }, { 87, 98, 113, 130, 147, 160, 173 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, { 205, 216, 229, 238, 249, 258, 269, 280, 291, 304, 317, 330, 343 }, 0, 6, 344, 346, { 348, 37, 2674 }, { 357, 24 }, { 370, 56 }, { 376, 46, 2979 } }, { 2999, 3033, 2674, 2979, 16935, 3066, 3071, 3083, 3088, { 3093, 3101, 3107, 3114, 3125, 3132, 3140 }, { 3148, 3152, 1871, 3156, 3161, 3165, 3169 }, { 3174, 3180, 3188, 1004, 3194, 3199, 3205, 3211, 3218, 1042, 3229, 3239, 343 }, { 3249, 1867, 1871, 3253, 3257, 1879, 1883, 3261, 1891, 3265, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 3273, 3055, 888, 2674 }, { 357, 3033 }, { 370, 16935 }, { 376, 2979, 16922 } }, { 2999, 3033, 2674, 2979, 16935, 3066, 3071, 3083, 3088, { 3093, 3101, 3107, 3114, 3125, 3132, 3140 }, { 3148, 3152, 1871, 3156, 3161, 3165, 3169 }, { 3174, 3180, 3188, 1004, 3194, 3199, 3205, 3211, 3218, 1042, 3229, 3239, 343 }, { 3249, 1867, 1871, 3253, 3257, 1879, 1883, 3261, 1891, 3265, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 3273, 3055, 888, 2674 }, { 357, 3033 }, { 370, 16935 }, { 376, 2979, 16922 } }, { 17686, 17721, 2674, 2979, 16935, 3066, 17744, 3083, 3088, { 3093, 3101, 3107, 3114, 3125, 3132, 3140 }, { 3148, 3152, 1871, 3156, 3161, 3165, 3169 }, { 3174, 3180, 3188, 1004, 3194, 3199, 3205, 3211, 3218, 1042, 3229, 3239, 343 }, { 3249, 1867, 1871, 3253, 3257, 1879, 1883, 3261, 1891, 3265, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 3273, 3055, 888, 2674 }, { 357, 3033, 17721 }, { 370, 16935 }, { 376, 2979, 16922 } }, { 2999, 3033, 2674, 2979, 16935, 3066, 3071, 3083, 3088, { 3093, 3101, 3107, 3114, 3125, 3132, 3140 }, { 3148, 3152, 1871, 3156, 3161, 3165, 3169 }, { 3174, 3180, 3188, 1004, 3194, 3199, 3205, 3211, 3218, 1042, 3229, 3239, 343 }, { 3249, 1867, 1871, 3253, 3257, 1879, 1883, 3261, 1891, 3265, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 3273, 3055, 888, 2674 }, { 357, 3033 }, { 370, 16935 }, { 376, 2979, 16922 } }, { 2999, 3033, 2674, 2979, 16935, 3066, 3071, 3083, 3088, { 3093, 3101, 3107, 3114, 3125, 3132, 3140 }, { 3148, 3152, 1871, 3156, 3161, 3165, 3169 }, { 3174, 3180, 3188, 1004, 3194, 3199, 3205, 3211, 3218, 1042, 3229, 3239, 343 }, { 3249, 1867, 1871, 3253, 3257, 1879, 1883, 3261, 1891, 3265, 1899, 3269, 343 }, 0, 1, 344, 346, { 348, 3273, 3055, 11818, 2674 }, { 357, 3033 }, { 370, 16935 }, { 376, 2979, 16922 } }, { 1112, 357, 348, 376, 370, 1136, 1146, 1154, 1161, { 1168, 1178, 1188, 1198, 1208, 1218, 1228 }, { 1238, 1242, 1246, 1250, 1254, 1258, 1262 }, { 1266, 1273, 1280, 1287, 1294, 1301, 1308, 1315, 1322, 1329, 1336, 1346, 343 }, { 1266, 1273, 1280, 1287, 1294, 1301, 1308, 1315, 1322, 1329, 1336, 1346, 343 }, 0, 0, 344, 346, { 348 }, { 357 }, { 370 }, { 376 } } }; static const NumberFormatEntry number_format_entries[] = { { 17757, 17760, 17757, 17760, 17757, 17760, 0, 17763, 17766, 17770, 17774, 17779, 17783, 17785, 11, 2, 1, 1, 3, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 0, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 0, 0, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 0, 0, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 0, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 1, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 0, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 0, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 0, 0, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 0, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 9, 2, 2, 2, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 0, 0, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 0, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 0, 0, 1, 1, 1, 0, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 0, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 0, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 0, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 1, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 0, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 0, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17796, 17770, 17774, 17779, 17783, 17785, 0, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 0, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 0, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 2, 2, -1, -1, -1 }, { 2, 2, -1, -1, -1 }, { 2, 2, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 0, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 0, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 0, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17757, 17760, 17757, 17760, 17757, 17760, 17819, 17763, 17766, 17770, 17774, 17779, 17783, 17785, 1, 0, 1, 1, 3, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 17829, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17835, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 0, 0, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17839, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 1, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 17843, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17847, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 12, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17835, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17835, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 1, 1, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17850, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 0, 0, 0, 0, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 17835, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 17835, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 0, 0, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17852, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 17856, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17859, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17835, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17863, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 1, 0, 1, 1, 1, 0, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17865, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 0, 0, 0, 0, 1, 0, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17835, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 11, 2, 0, 0, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 17847, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 0, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 17869, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17873, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 0, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17877, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 17881, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 5, 1, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17885, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 10412, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17888, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 1, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 17847, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17892, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 2, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17896, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17899, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 0, 0, 1, 1, 1, 0, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 17902, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 1, 0, 1, 1, 1, 0, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17910, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 17847, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 17914, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17917, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 2, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17757, 17760, 17757, 17760, 17757, 17760, 17920, 17763, 17766, 17770, 17774, 17779, 17783, 17785, 0, 3, 2, 2, 1, 0, 2, 2, { 5, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17924, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17835, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17927, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 0, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 9884, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 1, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 0, 17792, 17796, 17770, 17774, 17779, 17783, 17785, 0, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17847, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 12, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17931, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 2, 2, -1, -1, -1 }, { 2, 2, -1, -1, -1 }, { 2, 2, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17938, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 1, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17942, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 2, 2, -1, -1, -1 }, { 2, 2, -1, -1, -1 }, { 2, 2, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17949, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 2, 2, -1, -1, -1 }, { 2, 2, -1, -1, -1 }, { 2, 2, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17956, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 2, 2, -1, -1, -1 }, { 2, 2, -1, -1, -1 }, { 2, 2, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17931, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 2, 2, -1, -1, -1 }, { 2, 2, -1, -1, -1 }, { 2, 2, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17931, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 2, 2, -1, -1, -1 }, { 2, 2, -1, -1, -1 }, { 2, 2, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17835, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17931, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 2, 2, -1, -1, -1 }, { 2, 2, -1, -1, -1 }, { 2, 2, -1, -1, -1 } }, { 17757, 17760, 17757, 17760, 17757, 17760, 17964, 17763, 17766, 17770, 17774, 17779, 17783, 17785, 11, 2, 1, 1, 3, 3, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17974, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 1, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17978, 17794, 17978, 17794, 17978, 17980, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 2, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17985, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 1, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17850, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 0, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17835, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17978, 17794, 17978, 17794, 17978, 17980, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 2, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17835, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 17847, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 0, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17835, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 17835, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17757, 17760, 17757, 17760, 17757, 17760, 17988, 17763, 17766, 17770, 17774, 17779, 17783, 17785, 11, 2, 1, 1, 3, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17998, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 0, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17835, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17850, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 1, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17835, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17789, 17787, 17789, 17787, 17789, 17850, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 0, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17757, 17760, 17757, 17760, 17757, 17760, 18002, 17763, 17766, 17770, 17774, 17779, 17783, 17785, 11, 2, 1, 1, 3, 3, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 18012, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 1, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17835, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17850, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 0, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 18015, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 0, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17978, 17794, 17978, 17794, 17978, 18017, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 2, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17757, 17760, 17757, 17760, 17757, 17760, 18022, 17763, 17766, 17770, 17774, 17779, 17783, 17785, 11, 2, 1, 1, 3, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 4376, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 0, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17850, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 1, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 18032, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 0, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17835, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 8, 3, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17757, 17760, 17757, 17760, 17757, 17760, 18036, 17763, 17766, 17770, 17774, 17779, 17783, 17785, 11, 2, 1, 1, 3, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17835, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 1, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 18046, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 0, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17757, 17760, 17757, 17760, 17757, 17760, 18049, 17763, 17766, 17770, 17774, 17779, 17783, 17785, 1, 0, 1, 1, 3, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 9884, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 1, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 18059, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 0, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17757, 17760, 17757, 17760, 17757, 17760, 18063, 17763, 17766, 17770, 17774, 17779, 17783, 17785, 11, 2, 1, 1, 3, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 18073, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 12, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17757, 17760, 17757, 17760, 17757, 17760, 18076, 17763, 17766, 17770, 17774, 17779, 17783, 17785, 1, 0, 1, 1, 3, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17850, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 0, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17757, 17760, 17757, 17760, 17757, 17760, 18086, 17763, 17766, 17770, 17774, 17779, 17783, 17785, 1, 0, 1, 1, 3, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 18096, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 2, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17757, 17760, 17757, 17760, 17757, 17760, 18099, 17763, 17766, 17770, 17774, 17779, 17783, 17785, 11, 2, 1, 1, 3, 3, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17850, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 0, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17850, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 0, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17757, 17760, 17757, 17760, 17757, 17760, 18109, 17763, 17766, 17770, 17774, 17779, 17783, 17785, 11, 2, 1, 1, 3, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 18119, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 1, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 18122, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 2, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17757, 17760, 17757, 17760, 17757, 17760, 18126, 17763, 17766, 17770, 17774, 17779, 17783, 17785, 11, 2, 1, 1, 3, 3, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 18136, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 0, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 17850, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 2, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17757, 17760, 17757, 17760, 17757, 17760, 18140, 17763, 17766, 17770, 17774, 17779, 17783, 17785, 11, 2, 1, 1, 3, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 18150, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 0, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17757, 17760, 17757, 17760, 17757, 17760, 18154, 17763, 17766, 17770, 17774, 17779, 17783, 17785, 11, 2, 1, 1, 3, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 18164, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 12, 2, 1, 1, 1, 0, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17757, 17760, 17757, 17760, 17757, 17760, 18167, 17763, 17766, 17770, 17774, 17779, 17783, 17785, 1, 0, 1, 1, 3, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17787, 17794, 17787, 17794, 17787, 17794, 18177, 17792, 17766, 17770, 17774, 17779, 17783, 17785, 0, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 18180, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 0, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 18184, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 0, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 18187, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 0, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 17850, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 0, 0, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } }, { 17794, 17787, 17794, 17787, 17794, 17787, 0, 17792, 17796, 17770, 17800, 17810, 17783, 17785, 9, 2, 1, 1, 1, 2, 2, 2, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 }, { 3, -1, -1, -1, -1 } } }; static const CultureInfoEntry culture_entries[] = { { 0x0001, 0x007F, 0x0401, -1, 18190, 18193, 18193, 18193, 18200, 18215, 18219, 18190, 0, { 16777216, 0, 0, 0, 0 }, 0, 0, { 1256, 20420, 10004, 720, ';' } }, { 0x0002, 0x007F, 0x0402, -1, 18223, 18226, 18226, 18226, 18236, 18255, 18259, 18223, 0, { 0, 0, 0, 0, 0 }, 1, 1, { 1251, 20420, 10007, 866, ';' } }, { 0x0003, 0x007F, 0x0403, -1, 18263, 18266, 18266, 18266, 18274, 18282, 18286, 18263, 0, { 0, 0, 0, 0, 0 }, 2, 2, { 1252, 500, 10000, 850, ';' } }, { 0x0004, 0x007F, 0x0000, -1, 18290, 18297, 18297, 18297, 18305, 18312, 18316, 18320, 0, { 0, 0, 0, 0, 0 }, 166, 166, { 936, 500, 10008, 936, ',' } }, { 0x0005, 0x007F, 0x0405, -1, 18323, 18326, 18326, 18326, 18332, 18342, 18346, 18323, 0, { 0, 0, 0, 0, 0 }, 4, 4, { 1250, 500, 10029, 852, ';' } }, { 0x0006, 0x007F, 0x0406, -1, 18350, 18353, 18353, 18353, 18360, 18366, 18370, 18350, 0, { 0, 0, 0, 0, 0 }, 5, 5, { 1252, 20277, 10000, 850, ';' } }, { 0x0007, 0x007F, 0x0407, -1, 18374, 18377, 18377, 18377, 18384, 18392, 18396, 18374, 0, { 0, 0, 0, 0, 0 }, 6, 6, { 1252, 20273, 10000, 850, ';' } }, { 0x0008, 0x007F, 0x0408, -1, 18400, 18403, 18403, 18403, 18409, 18426, 18430, 18400, 0, { 0, 0, 0, 0, 0 }, 7, 7, { 1253, 20273, 10006, 737, ';' } }, { 0x0009, 0x007F, 0x0409, -1, 18434, 18437, 18437, 18437, 18437, 18445, 18449, 18434, 0, { 0, 0, 0, 0, 0 }, 8, 8, { 1252, 37, 10000, 437, ',' } }, { 0x000A, 0x007F, 0x0C0A, -1, 18453, 18456, 18456, 18456, 18464, 18473, 18477, 18453, 0, { 0, 0, 0, 0, 0 }, 9, 9, { 1252, 20284, 10000, 850, ';' } }, { 0x000B, 0x007F, 0x040B, -1, 18481, 18484, 18484, 18484, 18492, 18498, 18502, 18481, 0, { 0, 0, 0, 0, 0 }, 10, 10, { 1252, 20278, 10000, 850, ';' } }, { 0x000C, 0x007F, 0x040C, -1, 5977, 18506, 18506, 18506, 18513, 18523, 18527, 5977, 0, { 0, 0, 0, 0, 0 }, 11, 11, { 1252, 20297, 10000, 850, ';' } }, { 0x000D, 0x007F, 0x040D, -1, 18531, 18534, 18534, 18534, 18541, 18552, 18556, 18531, 0, { 0, 0, 0, 0, 0 }, 12, 12, { 1255, 500, 10005, 862, ',' } }, { 0x000E, 0x007F, 0x040E, -1, 18560, 18563, 18563, 18563, 18573, 18580, 18584, 18560, 0, { 0, 0, 0, 0, 0 }, 13, 13, { 1250, 500, 10029, 852, ';' } }, { 0x000F, 0x007F, 0x040F, -1, 18588, 18591, 18591, 18591, 18601, 18611, 18615, 18588, 0, { 0, 0, 0, 0, 0 }, 14, 14, { 1252, 20871, 10079, 850, ';' } }, { 0x0010, 0x007F, 0x0410, -1, 18619, 18622, 18622, 18622, 18630, 18639, 18643, 18619, 0, { 0, 0, 0, 0, 0 }, 15, 15, { 1252, 20280, 10000, 850, ';' } }, { 0x0011, 0x007F, 0x0411, -1, 18647, 18650, 18650, 18650, 18659, 18669, 18673, 18647, 0, { 0, 0, 0, 0, 0 }, 16, 16, { 932, 20290, 10001, 932, ',' } }, { 0x0012, 0x007F, 0x0412, -1, 18677, 18680, 18680, 18680, 18687, 18697, 18701, 18677, 0, { 0, 0, 0, 0, 0 }, 17, 17, { 949, 20833, 10003, 949, ',' } }, { 0x0013, 0x007F, 0x0413, -1, 18705, 18708, 18708, 18708, 18714, 18725, 18729, 18705, 0, { 0, 0, 0, 0, 0 }, 18, 18, { 1252, 500, 10000, 850, ';' } }, { 0x0014, 0x007F, 0x0414, -1, 18733, 18736, 18736, 18736, 18746, 18752, 18756, 18733, 0, { 0, 0, 0, 0, 0 }, 19, 19, { 1252, 20277, 10000, 850, ';' } }, { 0x0015, 0x007F, 0x0415, -1, 18760, 18763, 18763, 18763, 18770, 18777, 18781, 18760, 0, { 0, 0, 0, 0, 0 }, 20, 20, { 1250, 20880, 10029, 852, ';' } }, { 0x0016, 0x007F, 0x0416, -1, 18785, 18788, 18788, 18788, 18799, 18810, 18814, 18785, 0, { 0, 0, 0, 0, 0 }, 21, 21, { 1252, 500, 10000, 850, ';' } }, { 0x0018, 0x007F, 0x0418, -1, 18818, 18821, 18821, 18821, 18830, 18839, 18843, 18818, 0, { 0, 0, 0, 0, 0 }, 22, 22, { 1250, 20880, 10029, 852, ';' } }, { 0x0019, 0x007F, 0x0419, -1, 18847, 18850, 18850, 18850, 18858, 18873, 18877, 18847, 0, { 0, 0, 0, 0, 0 }, 23, 23, { 1251, 20880, 10007, 866, ';' } }, { 0x001A, 0x007F, 0x041A, -1, 18881, 18884, 18884, 18884, 18893, 18902, 18906, 18881, 0, { 0, 0, 0, 0, 0 }, 24, 24, { 1250, 500, 10082, 852, ';' } }, { 0x001B, 0x007F, 0x041B, -1, 18910, 18913, 18913, 18913, 18920, 18931, 18935, 18910, 0, { 0, 0, 0, 0, 0 }, 25, 25, { 1250, 20880, 10029, 852, ';' } }, { 0x001C, 0x007F, 0x041C, -1, 18939, 18942, 18942, 18942, 18951, 18958, 18962, 18939, 0, { 0, 0, 0, 0, 0 }, 26, 26, { 1250, 20880, 10029, 852, ';' } }, { 0x001D, 0x007F, 0x041D, -1, 18966, 18969, 18969, 18969, 18977, 18985, 18989, 18966, 0, { 0, 0, 0, 0, 0 }, 27, 27, { 1252, 20278, 10000, 850, ';' } }, { 0x001E, 0x007F, 0x041E, -1, 18993, 18996, 18996, 18996, 19001, 19011, 19015, 18993, 0, { 0, 0, 0, 0, 0 }, 28, 28, { 874, 20838, 10021, 874, ',' } }, { 0x001F, 0x007F, 0x041F, -1, 19019, 19022, 19022, 19022, 19030, 19039, 19043, 19019, 0, { 0, 0, 0, 0, 0 }, 29, 29, { 1254, 20905, 10081, 857, ';' } }, { 0x0021, 0x007F, 0x0421, -1, 19047, 19050, 19050, 19050, 19061, 19078, 19082, 19047, 0, { 0, 0, 0, 0, 0 }, 30, 30, { 1252, 500, 10000, 850, ';' } }, { 0x0022, 0x007F, 0x0422, -1, 19086, 19089, 19089, 19089, 19099, 19120, 19124, 19086, 0, { 0, 0, 0, 0, 0 }, 31, 31, { 1251, 500, 10017, 866, ';' } }, { 0x0023, 0x007F, 0x0423, -1, 19128, 19131, 19131, 19131, 19142, 19161, 19165, 19128, 0, { 0, 0, 0, 0, 0 }, 32, 32, { 1251, 500, 10007, 866, ';' } }, { 0x0024, 0x007F, 0x0424, -1, 19169, 19172, 19172, 19172, 19182, 19196, 19200, 19169, 0, { 0, 0, 0, 0, 0 }, 33, 33, { 1250, 20880, 10029, 852, ';' } }, { 0x0025, 0x007F, 0x0425, -1, 19204, 19207, 19207, 19207, 19216, 19222, 19226, 19204, 0, { 0, 0, 0, 0, 0 }, 34, 34, { 1257, 500, 10029, 775, ';' } }, { 0x0026, 0x007F, 0x0426, -1, 19230, 19233, 19233, 19233, 19241, 19251, 19255, 19230, 0, { 0, 0, 0, 0, 0 }, 35, 35, { 1257, 500, 10029, 775, ';' } }, { 0x0027, 0x007F, 0x0427, -1, 19259, 19262, 19262, 19262, 19273, 19283, 19287, 19259, 0, { 0, 0, 0, 0, 0 }, 36, 36, { 1257, 500, 10029, 775, ';' } }, { 0x0029, 0x007F, 0x0429, -1, 19291, 19294, 19294, 19294, 19302, 19313, 19317, 19291, 0, { 0, 0, 0, 0, 0 }, 37, 37, { 1256, 20420, 10004, 720, ';' } }, { 0x002A, 0x007F, 0x042A, -1, 19321, 19324, 19324, 19324, 19335, 19350, 3165, 19321, 0, { 0, 0, 0, 0, 0 }, 38, 38, { 1258, 500, 10000, 1258, ',' } }, { 0x002B, 0x007F, 0x042B, -1, 19354, 19357, 19357, 19357, 19366, 19381, 19385, 19354, 0, { 0, 0, 0, 0, 0 }, 39, 39, { 0, 500, 2, 1, ',' } }, { 0x002D, 0x007F, 0x042D, -1, 19389, 19392, 19392, 19392, 19399, 19407, 19411, 19389, 0, { 0, 0, 0, 0, 0 }, 40, 40, { 1252, 500, 10000, 850, ';' } }, { 0x002F, 0x007F, 0x042F, -1, 19415, 19418, 19418, 19418, 19429, 19450, 19454, 19415, 0, { 0, 0, 0, 0, 0 }, 41, 41, { 1251, 500, 10007, 866, ';' } }, { 0x0036, 0x007F, 0x0436, -1, 19458, 19461, 19461, 19461, 19471, 19482, 19486, 19458, 0, { 0, 0, 0, 0, 0 }, 42, 42, { 1252, 500, 10000, 850, ',' } }, { 0x0037, 0x007F, 0x0437, -1, 19490, 19493, 19493, 19493, 19502, 19524, 19528, 19490, 0, { 0, 0, 0, 0, 0 }, 43, 43, { 0, 500, 2, 1, ';' } }, { 0x0038, 0x007F, 0x0438, -1, 19532, 19535, 19535, 19535, 19543, 19553, 19557, 19532, 0, { 0, 0, 0, 0, 0 }, 44, 44, { 1252, 20277, 10079, 850, ';' } }, { 0x0039, 0x007F, 0x0439, -1, 19561, 19564, 19564, 19564, 19570, 19586, 19590, 19561, 0, { 0, 0, 0, 0, 0 }, 45, 45, { 0, 500, 2, 1, ',' } }, { 0x0041, 0x007F, 0x0441, -1, 19594, 19597, 19597, 19597, 19605, 19615, 19619, 19594, 0, { 0, 0, 0, 0, 0 }, 46, 46, { 1252, 500, 10000, 437, ',' } }, { 0x0047, 0x007F, 0x0447, -1, 19623, 19626, 19626, 19626, 19635, 19657, 19661, 19623, 0, { 0, 0, 0, 0, 0 }, 47, 47, { 0, 500, 2, 1, ',' } }, { 0x0049, 0x007F, 0x0449, -1, 19665, 19668, 19668, 19668, 19674, 19690, 19694, 19665, 0, { 0, 0, 0, 0, 0 }, 48, 48, { 0, 500, 2, 1, ',' } }, { 0x004A, 0x007F, 0x044A, -1, 19698, 19701, 19701, 19701, 19708, 19727, 19731, 19698, 0, { 0, 0, 0, 0, 0 }, 49, 49, { 0, 500, 2, 1, ',' } }, { 0x004B, 0x007F, 0x044B, -1, 19735, 19738, 19738, 19738, 19746, 19762, 19766, 19735, 0, { 0, 0, 0, 0, 0 }, 50, 50, { 0, 500, 2, 1, ',' } }, { 0x004E, 0x007F, 0x044E, -1, 19770, 19773, 19773, 19773, 19781, 19797, 1871, 19770, 0, { 0, 0, 0, 0, 0 }, 51, 51, { 0, 500, 2, 1, ',' } }, { 0x0056, 0x007F, 0x0456, -1, 19801, 19804, 19804, 19804, 19813, 19820, 19824, 19801, 0, { 0, 0, 0, 0, 0 }, 52, 52, { 1252, 500, 10000, 850, ',' } }, { 0x0057, 0x007F, 0x0457, -1, 19828, 19832, 19832, 19832, 19840, 19859, 19828, 19561, 0, { 0, 0, 0, 0, 0 }, 53, 53, { 0, 500, 2, 1, ',' } }, { 0x0401, 0x0001, 0x0401, 174, 19863, 19869, 19869, 19869, 19891, 18215, 18219, 18190, 10998, { 16777216, 0, 0, 0, 0 }, 54, 54, { 1256, 20420, 10004, 720, ';' } }, { 0x0402, 0x0002, 0x0402, 19, 19940, 19946, 19946, 19946, 19967, 18255, 18259, 18223, 20005, { 0, 0, 0, 0, 0 }, 55, 55, { 1251, 20420, 10007, 866, ';' } }, { 0x0403, 0x0003, 0x0403, 61, 20008, 20014, 20014, 20014, 20030, 18282, 18286, 18263, 20048, { 0, 0, 0, 0, 0 }, 56, 56, { 1252, 500, 10000, 850, ';' } }, { 0x0404, 0x7C04, 0x0404, 207, 20051, 20057, 20057, 20057, 20074, 20090, 18316, 18320, 20094, { 0, 0, 0, 0, 0 }, 57, 57, { 950, 500, 10002, 950, ',' } }, { 0x0405, 0x0005, 0x0405, 49, 20097, 20103, 20103, 20103, 20126, 18342, 18346, 18323, 20156, { 0, 0, 0, 0, 0 }, 58, 58, { 1250, 500, 10029, 852, ';' } }, { 0x0406, 0x0006, 0x0406, 52, 20159, 20165, 20165, 20165, 20182, 18366, 18370, 18350, 20198, { 0, 0, 0, 0, 0 }, 59, 59, { 1252, 20277, 10000, 850, ';' } }, { 0x0407, 0x0007, 0x0407, 50, 20201, 20207, 20207, 20207, 20224, 18392, 18396, 18374, 4300, { 0, 0, 0, 0, 0 }, 60, 60, { 1252, 20273, 10000, 850, ';' } }, { 0x0408, 0x0008, 0x0408, 81, 20246, 20252, 20252, 20252, 20267, 18426, 18430, 18400, 20299, { 0, 0, 0, 0, 0 }, 61, 61, { 1253, 20273, 10006, 737, ';' } }, { 0x0409, 0x0009, 0x0409, 212, 20302, 20308, 20308, 20308, 20308, 18445, 18449, 18434, 20332, { 0, 0, 0, 0, 0 }, 62, 62, { 1252, 37, 10000, 437, ',' } }, { 0x040B, 0x000B, 0x040B, 63, 20335, 20341, 20341, 20341, 20359, 18498, 18502, 18481, 20373, { 0, 0, 0, 0, 0 }, 63, 63, { 1252, 20278, 10000, 850, ';' } }, { 0x040C, 0x000C, 0x040C, 68, 20376, 20382, 20382, 20382, 20398, 18523, 18527, 5977, 20417, { 0, 0, 0, 0, 0 }, 64, 64, { 1252, 20297, 10000, 850, ';' } }, { 0x040D, 0x000D, 0x040D, 92, 20420, 20426, 20426, 20426, 20442, 18552, 18556, 18531, 20466, { 0, 0, 0, 0, 0 }, 65, 65, { 1255, 500, 10005, 862, ',' } }, { 0x040E, 0x000E, 0x040E, 89, 20469, 20475, 20475, 20475, 20495, 18580, 18584, 18560, 20518, { 0, 0, 0, 0, 0 }, 66, 66, { 1250, 500, 10029, 852, ';' } }, { 0x040F, 0x000F, 0x040F, 97, 20521, 20527, 20527, 20527, 20547, 18611, 18615, 18588, 20567, { 0, 0, 0, 0, 0 }, 67, 67, { 1252, 20871, 10079, 850, ';' } }, { 0x0410, 0x0010, 0x0410, 98, 20570, 20576, 20576, 20576, 20592, 18639, 18643, 18619, 20610, { 0, 0, 0, 0, 0 }, 68, 68, { 1252, 20280, 10000, 850, ';' } }, { 0x0411, 0x0011, 0x0411, 101, 20613, 20619, 20619, 20619, 20636, 18669, 18673, 18647, 20655, { 0, 0, 0, 0, 0 }, 69, 69, { 932, 20290, 10001, 932, ',' } }, { 0x0412, 0x0012, 0x0412, 109, 20658, 20664, 20664, 20664, 20685, 18697, 18701, 18677, 20710, { 0, 0, 0, 0, 0 }, 70, 70, { 949, 20833, 10003, 949, ',' } }, { 0x0413, 0x0013, 0x0413, 149, 20713, 20719, 20719, 20719, 20739, 18725, 18729, 18705, 20762, { 0, 0, 0, 0, 0 }, 71, 71, { 1252, 500, 10000, 850, ';' } }, { 0x0414, 0x0014, 0x0414, 150, 20765, 20771, 20797, 20797, 20824, 18752, 20846, 20850, 20853, { 0, 0, 0, 0, 0 }, 72, 72, { 1252, 20277, 10000, 850, ';' } }, { 0x0415, 0x0015, 0x0415, 162, 20856, 20862, 20862, 20862, 20878, 18777, 18781, 18760, 20894, { 0, 0, 0, 0, 0 }, 73, 73, { 1250, 20880, 10029, 852, ';' } }, { 0x0416, 0x0016, 0x0416, 26, 20897, 20903, 20903, 20903, 20923, 18810, 18814, 18785, 20943, { 0, 0, 0, 0, 0 }, 74, 74, { 1252, 500, 10000, 850, ';' } }, { 0x0418, 0x0018, 0x0418, 171, 20946, 20952, 20952, 20952, 20971, 18839, 18843, 18818, 20991, { 0, 0, 0, 0, 0 }, 75, 75, { 1250, 20880, 10029, 852, ';' } }, { 0x0419, 0x0019, 0x0419, 172, 20994, 21000, 21000, 21000, 21017, 18873, 18877, 18847, 21047, { 0, 0, 0, 0, 0 }, 76, 76, { 1251, 20880, 10007, 866, ';' } }, { 0x041A, 0x001A, 0x041A, 88, 21050, 21056, 21056, 21056, 21075, 18902, 18906, 18881, 21095, { 0, 0, 0, 0, 0 }, 77, 77, { 1250, 500, 10082, 852, ';' } }, { 0x041B, 0x001B, 0x041B, 183, 21098, 21104, 21104, 21104, 21122, 18931, 18935, 18910, 21156, { 0, 0, 0, 0, 0 }, 78, 78, { 1250, 20880, 10029, 852, ';' } }, { 0x041C, 0x001C, 0x041C, 4, 21159, 21165, 21165, 21165, 21184, 18958, 18962, 18939, 21204, { 0, 0, 0, 0, 0 }, 79, 79, { 1250, 20880, 10029, 852, ';' } }, { 0x041D, 0x001D, 0x041D, 178, 21207, 21213, 21213, 21213, 21230, 18985, 18989, 18966, 21248, { 0, 0, 0, 0, 0 }, 80, 80, { 1252, 20278, 10000, 850, ';' } }, { 0x041E, 0x001E, 0x041E, 197, 21251, 21257, 21257, 21257, 21273, 19011, 19015, 18993, 21313, { 0, 0, 0, 0, 0 }, 81, 81, { 874, 20838, 10021, 874, ',' } }, { 0x041F, 0x001F, 0x041F, 204, 21316, 21322, 21322, 21322, 21339, 19039, 19043, 19019, 21359, { 0, 0, 0, 0, 0 }, 82, 82, { 1254, 20905, 10081, 857, ';' } }, { 0x0421, 0x0021, 0x0421, 90, 21362, 21368, 21368, 21368, 21391, 19078, 19082, 19047, 21420, { 0, 0, 0, 0, 0 }, 83, 83, { 1252, 500, 10000, 850, ';' } }, { 0x0422, 0x0022, 0x0422, 209, 21423, 21429, 21429, 21429, 21449, 19120, 19124, 19086, 21487, { 0, 0, 0, 0, 0 }, 84, 84, { 1251, 500, 10017, 866, ';' } }, { 0x0423, 0x0023, 0x0423, 30, 21490, 21496, 21496, 21496, 21517, 19161, 19165, 19128, 21555, { 0, 0, 0, 0, 0 }, 85, 85, { 1251, 500, 10007, 866, ';' } }, { 0x0424, 0x0024, 0x0424, 181, 21558, 21564, 21564, 21564, 21585, 19196, 19200, 19169, 21611, { 0, 0, 0, 0, 0 }, 86, 86, { 1250, 20880, 10029, 852, ';' } }, { 0x0425, 0x0025, 0x0425, 57, 21614, 21620, 21620, 21620, 21639, 19222, 19226, 19204, 21653, { 0, 0, 0, 0, 0 }, 87, 87, { 1257, 500, 10029, 775, ';' } }, { 0x0426, 0x0026, 0x0426, 121, 21656, 21662, 21662, 21662, 21679, 19251, 19255, 19230, 21699, { 0, 0, 0, 0, 0 }, 88, 88, { 1257, 500, 10029, 775, ';' } }, { 0x0427, 0x0027, 0x0427, 119, 21702, 21708, 21708, 21708, 21731, 19283, 19287, 19259, 21751, { 0, 0, 0, 0, 0 }, 89, 89, { 1257, 500, 10029, 775, ';' } }, { 0x0429, 0x0029, 0x0429, 96, 21754, 21760, 21760, 21760, 21775, 19313, 19317, 19291, 21799, { 0, 0, 0, 0, 0 }, 90, 90, { 1256, 20420, 10004, 720, ';' } }, { 0x042A, 0x002A, 0x042A, 220, 21802, 21808, 21808, 21808, 21829, 19350, 3165, 19321, 21857, { 0, 0, 0, 0, 0 }, 91, 91, { 1258, 500, 10000, 1258, ',' } }, { 0x042B, 0x002B, 0x042B, 5, 21860, 21866, 21866, 21866, 21885, 19381, 19385, 19354, 465, { 0, 0, 0, 0, 0 }, 92, 92, { 0, 500, 2, 1, ',' } }, { 0x042D, 0x002D, 0x042D, 61, 21950, 21956, 21956, 21956, 21971, 19407, 19411, 19389, 20048, { 0, 0, 0, 0, 0 }, 93, 93, { 1252, 500, 10000, 850, ';' } }, { 0x042F, 0x002F, 0x042F, 128, 21990, 21996, 21996, 21996, 22019, 19450, 19454, 19415, 22063, { 0, 0, 0, 0, 0 }, 94, 94, { 1251, 500, 10007, 866, ';' } }, { 0x0436, 0x0036, 0x0436, 227, 22066, 22072, 22072, 22072, 22097, 19482, 19486, 19458, 22122, { 0, 0, 0, 0, 0 }, 95, 95, { 1252, 500, 10000, 850, ',' } }, { 0x0437, 0x0037, 0x0437, 72, 22125, 22131, 22131, 22131, 22150, 19524, 19528, 19490, 22205, { 0, 0, 0, 0, 0 }, 96, 96, { 0, 500, 2, 1, ';' } }, { 0x0438, 0x0038, 0x0438, 67, 22208, 22214, 22214, 22214, 22238, 19553, 19557, 19532, 22259, { 0, 0, 0, 0, 0 }, 97, 97, { 1252, 20277, 10079, 850, ';' } }, { 0x0439, 0x0039, 0x0439, 93, 22262, 22268, 22268, 22268, 22282, 19586, 19590, 19561, 22313, { 0, 0, 0, 0, 0 }, 98, 98, { 0, 500, 2, 1, ',' } }, { 0x0441, 0x0041, 0x0441, 102, 22316, 22322, 22322, 22322, 22338, 19615, 19619, 19594, 22356, { 0, 0, 0, 0, 0 }, 99, 99, { 1252, 500, 10000, 437, ',' } }, { 0x0447, 0x0047, 0x0447, 93, 22359, 22365, 22365, 22365, 22382, 19657, 19661, 19623, 22313, { 0, 0, 0, 0, 0 }, 100, 100, { 0, 500, 2, 1, ',' } }, { 0x0449, 0x0049, 0x0449, 93, 22419, 22425, 22425, 22425, 22439, 19690, 19694, 19665, 22313, { 0, 0, 0, 0, 0 }, 101, 101, { 0, 500, 2, 1, ',' } }, { 0x044A, 0x004A, 0x044A, 93, 22479, 22485, 22485, 22485, 22500, 19727, 19731, 19698, 22313, { 0, 0, 0, 0, 0 }, 102, 102, { 0, 500, 2, 1, ',' } }, { 0x044B, 0x004B, 0x044B, 93, 22547, 22553, 22553, 22553, 22569, 19762, 19766, 19735, 22313, { 0, 0, 0, 0, 0 }, 103, 103, { 0, 500, 2, 1, ',' } }, { 0x044E, 0x004E, 0x044E, 93, 22600, 22606, 22606, 22606, 22622, 19797, 1871, 19770, 22313, { 0, 0, 0, 0, 0 }, 104, 104, { 0, 500, 2, 1, ',' } }, { 0x0456, 0x0056, 0x0456, 61, 22653, 22659, 22659, 22659, 22676, 19820, 19824, 19801, 20048, { 0, 0, 0, 0, 0 }, 105, 105, { 1252, 500, 10000, 850, ',' } }, { 0x0457, 0x0057, 0x0457, 93, 22693, 22700, 22700, 22700, 22716, 19859, 19828, 19828, 22313, { 0, 0, 0, 0, 0 }, 106, 106, { 0, 500, 2, 1, ',' } }, { 0x0801, 0x0001, 0x0801, 95, 22750, 22756, 22756, 22756, 22770, 22800, 18219, 18190, 22804, { 2, 1, 0, 0, 0 }, 107, 107, { 1256, 20420, 10004, 720, ';' } }, { 0x0804, 0x0004, 0x0804, 42, 22807, 22813, 22813, 22813, 22829, 18312, 18316, 18320, 11080, { 0, 0, 0, 0, 0 }, 108, 108, { 936, 500, 10008, 936, ',' } }, { 0x0807, 0x0007, 0x0807, 37, 22845, 22851, 22851, 22851, 22872, 22890, 18396, 18374, 11001, { 0, 0, 0, 0, 0 }, 109, 109, { 1252, 20273, 10000, 850, ';' } }, { 0x0809, 0x0009, 0x0809, 70, 22894, 22900, 22900, 22900, 22900, 22925, 18449, 18434, 22929, { 0, 0, 0, 0, 0 }, 110, 110, { 1252, 20285, 10000, 850, ',' } }, { 0x080A, 0x000A, 0x080A, 141, 22932, 22938, 22938, 22938, 22955, 22974, 18477, 18453, 22978, { 0, 0, 0, 0, 0 }, 111, 111, { 1252, 20284, 10000, 850, ',' } }, { 0x080C, 0x000C, 0x080C, 17, 22981, 22987, 22987, 22987, 23004, 23025, 18527, 5977, 23029, { 0, 0, 0, 0, 0 }, 112, 112, { 1252, 20297, 10000, 850, ';' } }, { 0x0810, 0x0010, 0x0810, 37, 23032, 23038, 23038, 23038, 23060, 23080, 18643, 18619, 11001, { 0, 0, 0, 0, 0 }, 113, 113, { 1252, 500, 10000, 850, ';' } }, { 0x0813, 0x0013, 0x0813, 17, 23084, 23090, 23090, 23090, 23106, 23127, 18729, 18705, 23029, { 0, 0, 0, 0, 0 }, 114, 114, { 1252, 500, 10000, 850, ';' } }, { 0x0814, 0x0014, 0x0814, 150, 23131, 23137, 23137, 23137, 23164, 23186, 23190, 23194, 20853, { 0, 0, 0, 0, 0 }, 115, 115, { 1252, 20277, 10000, 850, ';' } }, { 0x0816, 0x0016, 0x0816, 166, 23197, 23203, 23203, 23203, 23225, 23247, 18814, 18785, 23251, { 0, 0, 0, 0, 0 }, 116, 116, { 1252, 500, 10000, 850, ';' } }, { 0x081D, 0x001D, 0x081D, 63, 23254, 23260, 23260, 23260, 23278, 23296, 18989, 18966, 20373, { 0, 0, 0, 0, 0 }, 117, 117, { 1252, 20278, 10000, 850, ';' } }, { 0x0C01, 0x0001, 0x0C01, 58, 23300, 23306, 23306, 23306, 23321, 23345, 18219, 18190, 23349, { 16777216, 0, 0, 0, 0 }, 118, 118, { 1256, 20420, 10004, 720, ';' } }, { 0x0C04, 0x7C04, 0x0C04, 85, 23352, 23358, 23358, 23358, 23392, 23429, 18316, 18320, 23433, { 0, 0, 0, 0, 0 }, 119, 119, { 950, 500, 10002, 950, ',' } }, { 0x0C07, 0x0007, 0x0C07, 10, 23436, 23442, 23442, 23442, 23459, 23481, 18396, 18374, 23485, { 0, 0, 0, 0, 0 }, 120, 120, { 1252, 20273, 10000, 850, ';' } }, { 0x0C09, 0x0009, 0x0C09, 11, 23488, 23494, 23494, 23494, 23494, 23514, 18449, 18434, 23518, { 0, 0, 0, 0, 0 }, 121, 121, { 1252, 500, 10000, 850, ',' } }, { 0x0C0A, 0x000A, 0x0C0A, 61, 23521, 23527, 23527, 23527, 23543, 23562, 18477, 18453, 20048, { 0, 0, 0, 0, 0 }, 122, 122, { 1252, 20284, 10000, 850, ';' } }, { 0x0C0C, 0x000C, 0x0C0C, 32, 23566, 23572, 23572, 23572, 23588, 23607, 18527, 5977, 23611, { 0, 0, 0, 0, 0 }, 123, 123, { 1252, 20297, 10000, 850, ';' } }, { 0x1001, 0x0001, 0x1001, 122, 23614, 23620, 23620, 23620, 23635, 23663, 18219, 18190, 23667, { 16777216, 0, 0, 0, 0 }, 124, 124, { 1256, 20420, 10004, 720, ';' } }, { 0x1004, 0x0004, 0x1004, 179, 23670, 23676, 23676, 23676, 23696, 23715, 18316, 18320, 23719, { 0, 0, 0, 0, 0 }, 125, 125, { 936, 500, 10008, 936, ',' } }, { 0x1007, 0x0007, 0x1007, 120, 23722, 23728, 23728, 23728, 23748, 23768, 18396, 18374, 23772, { 0, 0, 0, 0, 0 }, 126, 126, { 1252, 20273, 10000, 850, ';' } }, { 0x1009, 0x0009, 0x1009, 32, 23775, 23781, 23781, 23781, 23781, 23798, 18449, 18434, 23611, { 0, 0, 0, 0, 0 }, 127, 127, { 1252, 37, 10000, 850, ',' } }, { 0x100A, 0x000A, 0x100A, 82, 23802, 23808, 23808, 23808, 23828, 23849, 18477, 18453, 23853, { 0, 0, 0, 0, 0 }, 128, 128, { 1252, 20284, 10000, 850, ',' } }, { 0x100C, 0x000C, 0x100C, 37, 23856, 23862, 23862, 23862, 23883, 23902, 18527, 5977, 11001, { 0, 0, 0, 0, 0 }, 129, 129, { 1252, 20297, 10000, 850, ';' } }, { 0x1401, 0x0001, 0x1401, 55, 23906, 23912, 23912, 23912, 23929, 23961, 18219, 18190, 23965, { 16777216, 0, 0, 0, 0 }, 130, 130, { 1256, 20420, 10004, 720, ';' } }, { 0x1404, 0x0004, 0x1404, 132, 23968, 23974, 23974, 23974, 24003, 24040, 18316, 18320, 24044, { 0, 0, 0, 0, 0 }, 131, 131, { 950, 500, 10002, 950, ',' } }, { 0x1409, 0x0009, 0x1409, 154, 24047, 24053, 24053, 24053, 24053, 24075, 18449, 18434, 24079, { 0, 0, 0, 0, 0 }, 132, 132, { 1252, 500, 10000, 850, ',' } }, { 0x140A, 0x000A, 0x140A, 44, 24082, 24088, 24088, 24088, 24109, 24131, 18477, 18453, 24135, { 0, 0, 0, 0, 0 }, 133, 133, { 1252, 20284, 10000, 850, ',' } }, { 0x140C, 0x000C, 0x140C, 120, 24138, 24144, 24144, 24144, 24164, 24187, 18527, 5977, 23772, { 0, 0, 0, 0, 0 }, 134, 134, { 1252, 20297, 10000, 850, ';' } }, { 0x1801, 0x0001, 0x1801, 123, 24191, 24197, 24197, 24197, 24214, 24244, 18219, 18190, 24248, { 16777216, 0, 0, 0, 0 }, 135, 135, { 1256, 20420, 10004, 720, ';' } }, { 0x1809, 0x0009, 0x1809, 91, 24251, 24257, 24257, 24257, 24257, 24275, 18449, 18434, 24279, { 0, 0, 0, 0, 0 }, 136, 136, { 1252, 500, 10000, 850, ',' } }, { 0x180A, 0x000A, 0x180A, 156, 24282, 24288, 24288, 24288, 24305, 24324, 18477, 18453, 24328, { 0, 0, 0, 0, 0 }, 137, 137, { 1252, 20284, 10000, 850, ',' } }, { 0x1C01, 0x0001, 0x1C01, 202, 24331, 24337, 24337, 24337, 24354, 24380, 18219, 18190, 24384, { 16777216, 0, 0, 0, 0 }, 138, 138, { 1256, 20420, 10004, 720, ';' } }, { 0x1C09, 0x0009, 0x1C09, 227, 24387, 24393, 24393, 24393, 24393, 24416, 18449, 18434, 22122, { 0, 0, 0, 0, 0 }, 139, 139, { 1252, 500, 10000, 437, ',' } }, { 0x1C0A, 0x000A, 0x1C0A, 54, 24420, 24426, 24426, 24426, 24455, 24488, 18477, 18453, 24492, { 0, 0, 0, 0, 0 }, 140, 140, { 1252, 20284, 10000, 850, ',' } }, { 0x2001, 0x0001, 0x2001, 155, 24495, 24501, 24501, 24501, 24515, 24541, 18219, 18190, 24545, { 16777216, 0, 0, 0, 0 }, 141, 141, { 1256, 20420, 10004, 720, ';' } }, { 0x200A, 0x000A, 0x200A, 217, 24548, 24554, 24554, 24554, 24574, 24595, 18477, 18453, 24599, { 0, 0, 0, 0, 0 }, 142, 142, { 1252, 20284, 10000, 850, ',' } }, { 0x2401, 0x0001, 0x2401, 224, 24602, 24608, 24608, 24608, 24623, 24651, 18219, 18190, 24655, { 16777216, 0, 0, 0, 0 }, 143, 143, { 1256, 20420, 10004, 720, ';' } }, { 0x240A, 0x000A, 0x240A, 43, 24658, 24664, 24664, 24664, 24683, 24703, 18477, 18453, 24707, { 0, 0, 0, 0, 0 }, 144, 144, { 1252, 20284, 10000, 850, ',' } }, { 0x2801, 0x0001, 0x2801, 191, 24710, 24716, 24716, 24716, 24731, 24759, 18219, 18190, 24763, { 16777216, 0, 0, 0, 0 }, 145, 145, { 1256, 20420, 10004, 720, ';' } }, { 0x280A, 0x000A, 0x280A, 157, 24766, 24772, 24772, 24772, 24787, 24804, 18477, 18453, 24808, { 0, 0, 0, 0, 0 }, 146, 146, { 1252, 20284, 10000, 850, ',' } }, { 0x2C01, 0x0001, 0x2C01, 100, 24811, 24817, 24817, 24817, 24833, 24863, 18219, 18190, 24867, { 16777216, 0, 0, 0, 0 }, 147, 147, { 1256, 20420, 10004, 720, ';' } }, { 0x2C09, 0x0009, 0x2C09, 205, 24870, 24876, 24876, 24876, 24876, 24906, 18449, 18434, 24910, { 0, 0, 0, 0, 0 }, 148, 148, { 1252, 500, 10000, 850, ';' } }, { 0x2C0A, 0x000A, 0x2C0A, 8, 24913, 24919, 24919, 24919, 24939, 24960, 18477, 18453, 24964, { 0, 0, 0, 0, 0 }, 149, 149, { 1252, 20284, 10000, 850, ',' } }, { 0x3001, 0x0001, 0x3001, 114, 24967, 24973, 24973, 24973, 24990, 25018, 18219, 18190, 25022, { 16777216, 0, 0, 0, 0 }, 150, 150, { 1256, 20420, 10004, 720, ';' } }, { 0x3009, 0x0009, 0x3009, 229, 25025, 25031, 25031, 25031, 25031, 25050, 18449, 18434, 25054, { 0, 0, 0, 0, 0 }, 151, 151, { 1252, 500, 10000, 437, ',' } }, { 0x300A, 0x000A, 0x300A, 56, 25057, 25063, 25063, 25063, 25081, 25100, 18477, 18453, 25104, { 0, 0, 0, 0, 0 }, 152, 152, { 1252, 20284, 10000, 850, ',' } }, { 0x3401, 0x0001, 0x3401, 110, 25107, 25113, 25113, 25113, 25129, 25159, 18219, 18190, 25163, { 16777216, 0, 0, 0, 0 }, 153, 153, { 1256, 20420, 10004, 720, ';' } }, { 0x3409, 0x0009, 0x3409, 160, 25166, 25172, 25172, 25172, 25172, 25194, 18449, 18434, 25198, { 0, 0, 0, 0, 0 }, 154, 154, { 1252, 500, 10000, 437, ',' } }, { 0x340A, 0x000A, 0x340A, 40, 25201, 25207, 25207, 25207, 25223, 25240, 18477, 18453, 25244, { 0, 0, 0, 0, 0 }, 155, 155, { 1252, 20284, 10000, 850, ',' } }, { 0x3801, 0x0001, 0x3801, 0, 25247, 25253, 25253, 25253, 25283, 25347, 18219, 18190, 25351, { 16777216, 0, 0, 0, 0 }, 156, 156, { 1256, 20420, 10004, 720, ';' } }, { 0x380A, 0x000A, 0x380A, 213, 25354, 25360, 25360, 25360, 25378, 25397, 18477, 18453, 25401, { 0, 0, 0, 0, 0 }, 157, 157, { 1252, 20284, 10000, 850, ',' } }, { 0x3C01, 0x0001, 0x3C01, 20, 25404, 25410, 25410, 25410, 25427, 25459, 18219, 18190, 25463, { 16777216, 0, 0, 0, 0 }, 158, 158, { 1256, 20420, 10004, 720, ';' } }, { 0x3C0A, 0x000A, 0x3C0A, 168, 25466, 25472, 25472, 25472, 25491, 25511, 18477, 18453, 25515, { 0, 0, 0, 0, 0 }, 159, 159, { 1252, 20284, 10000, 850, ',' } }, { 0x4001, 0x0001, 0x4001, 169, 25518, 25524, 25524, 25524, 25539, 25563, 18219, 18190, 25567, { 16777216, 0, 0, 0, 0 }, 160, 160, { 1256, 20420, 10004, 720, ';' } }, { 0x400A, 0x000A, 0x400A, 25, 25570, 25576, 25576, 25576, 25594, 25613, 18477, 18453, 25617, { 0, 0, 0, 0, 0 }, 161, 161, { 1252, 20284, 10000, 850, ',' } }, { 0x440A, 0x000A, 0x440A, 190, 25620, 25626, 25626, 25626, 25648, 25671, 18477, 18453, 25675, { 0, 0, 0, 0, 0 }, 162, 162, { 1252, 20284, 10000, 850, ',' } }, { 0x480A, 0x000A, 0x480A, 87, 25678, 25684, 25684, 25684, 25703, 25723, 18477, 18453, 25727, { 0, 0, 0, 0, 0 }, 163, 163, { 1252, 20284, 10000, 850, ',' } }, { 0x4C0A, 0x000A, 0x4C0A, 148, 25730, 25736, 25736, 25736, 25756, 25777, 18477, 18453, 25781, { 0, 0, 0, 0, 0 }, 164, 164, { 1252, 20284, 10000, 850, ',' } }, { 0x500A, 0x000A, 0x500A, 165, 25784, 25790, 25790, 25790, 25812, 25835, 18477, 18453, 25839, { 0, 0, 0, 0, 0 }, 165, 165, { 1252, 20284, 10000, 850, ',' } }, { 0x7C04, 0x007F, 0x0000, -1, 25842, 20057, 18297, 18297, 18305, 20090, 18316, 18320, 0, { 0, 0, 0, 0, 0 }, 166, 166, { 950, 500, 10002, 950, ',' } } }; static const CultureInfoNameEntry culture_name_entries[] = { { 19458, 42 }, { 25849, 95 }, { 18190, 0 }, { 25855, 156 }, { 25861, 158 }, { 25867, 130 }, { 25873, 118 }, { 25879, 107 }, { 25885, 147 }, { 25891, 153 }, { 25897, 150 }, { 25903, 124 }, { 25909, 135 }, { 25915, 141 }, { 25921, 160 }, { 25927, 54 }, { 25933, 145 }, { 25939, 138 }, { 25945, 143 }, { 19128, 32 }, { 25951, 85 }, { 18223, 1 }, { 25957, 55 }, { 18263, 2 }, { 25963, 56 }, { 18323, 4 }, { 25969, 58 }, { 18350, 5 }, { 25975, 59 }, { 18374, 6 }, { 25981, 120 }, { 25987, 109 }, { 25993, 60 }, { 25999, 126 }, { 18400, 7 }, { 26005, 61 }, { 18434, 8 }, { 26011, 121 }, { 26017, 127 }, { 26023, 110 }, { 26029, 136 }, { 26035, 132 }, { 26041, 154 }, { 26047, 148 }, { 26053, 62 }, { 26059, 139 }, { 26065, 151 }, { 18453, 9 }, { 26071, 149 }, { 26077, 161 }, { 26083, 155 }, { 26089, 144 }, { 26095, 133 }, { 26101, 140 }, { 26107, 152 }, { 26113, 122 }, { 26119, 128 }, { 26125, 163 }, { 26131, 111 }, { 26137, 164 }, { 26143, 137 }, { 26149, 146 }, { 26155, 165 }, { 26161, 159 }, { 26167, 162 }, { 26173, 157 }, { 26179, 142 }, { 19204, 34 }, { 26185, 87 }, { 19389, 40 }, { 26191, 93 }, { 19291, 37 }, { 26197, 90 }, { 18481, 10 }, { 26203, 63 }, { 19532, 44 }, { 26209, 97 }, { 5977, 11 }, { 26215, 112 }, { 26221, 123 }, { 26227, 129 }, { 26233, 64 }, { 26239, 134 }, { 19801, 52 }, { 26245, 105 }, { 19623, 47 }, { 26251, 100 }, { 18531, 12 }, { 26257, 65 }, { 19561, 45 }, { 26263, 98 }, { 18881, 24 }, { 26269, 77 }, { 18560, 13 }, { 26275, 66 }, { 19354, 39 }, { 26281, 92 }, { 19047, 30 }, { 26287, 83 }, { 18588, 14 }, { 26293, 67 }, { 18619, 15 }, { 26299, 113 }, { 26305, 68 }, { 18647, 16 }, { 26311, 69 }, { 19490, 43 }, { 26317, 96 }, { 19735, 50 }, { 26323, 103 }, { 18677, 17 }, { 26329, 70 }, { 19828, 53 }, { 26335, 106 }, { 19259, 36 }, { 26342, 89 }, { 19230, 35 }, { 26348, 88 }, { 19415, 41 }, { 26354, 94 }, { 19770, 51 }, { 26360, 104 }, { 26366, 72 }, { 18705, 18 }, { 26372, 114 }, { 26378, 71 }, { 26384, 115 }, { 18733, 19 }, { 18760, 20 }, { 26390, 73 }, { 18785, 21 }, { 26396, 74 }, { 26402, 116 }, { 18818, 22 }, { 26408, 75 }, { 18847, 23 }, { 26414, 76 }, { 18910, 25 }, { 26420, 78 }, { 19169, 33 }, { 26426, 86 }, { 18939, 26 }, { 26432, 79 }, { 18966, 27 }, { 26438, 117 }, { 26444, 80 }, { 19594, 46 }, { 26450, 99 }, { 19665, 48 }, { 26456, 101 }, { 19698, 49 }, { 26462, 102 }, { 18993, 28 }, { 26468, 81 }, { 19019, 29 }, { 26474, 82 }, { 19086, 31 }, { 26480, 84 }, { 19321, 38 }, { 26486, 91 }, { 26492, 3 }, { 26499, 166 }, { 26506, 108 }, { 26512, 119 }, { 26518, 131 }, { 26524, 125 }, { 26530, 57 } }; static const RegionInfoEntry region_entries[] = { { 0, 0, 25351, 343, 343, 26536, 343, 26557, 26561 }, { 0, 1, 26589, 343, 343, 26592, 343, 26604, 26608 }, { 0, 2, 26616, 343, 343, 26619, 343, 26639, 26643 }, { 0, 3, 26665, 343, 343, 26668, 343, 26639, 26643 }, { 0, 4, 21204, 343, 343, 26677, 343, 26685, 26689 }, { 0, 5, 465, 343, 343, 26702, 343, 26710, 26714 }, { 0, 6, 26728, 343, 343, 26731, 343, 26752, 26756 }, { 0, 7, 26785, 343, 343, 26788, 343, 26795, 26799 }, { 0, 8, 24964, 343, 343, 26814, 343, 24759, 26824 }, { 0, 9, 26839, 343, 343, 26842, 343, 26857, 26861 }, { 0, 10, 23485, 343, 343, 26871, 343, 26879, 26883 }, { 0, 11, 23518, 343, 343, 26888, 343, 26898, 26902 }, { 0, 12, 26920, 343, 343, 26923, 343, 26929, 26933 }, { 0, 13, 26948, 343, 343, 26951, 343, 26962, 26966 }, { 0, 14, 26986, 343, 343, 26989, 343, 27012, 27016 }, { 0, 15, 27052, 343, 343, 27055, 343, 27064, 27068 }, { 0, 16, 27084, 343, 343, 27087, 343, 27098, 27102 }, { 0, 17, 23029, 343, 343, 27118, 343, 26879, 26883 }, { 0, 18, 27126, 343, 343, 27129, 343, 27142, 27146 }, { 0, 19, 20005, 343, 343, 27162, 343, 27171, 27175 }, { 0, 20, 25463, 343, 343, 27193, 343, 27201, 27205 }, { 0, 21, 27220, 343, 343, 27223, 343, 27231, 27235 }, { 0, 22, 27249, 343, 343, 27252, 343, 27142, 27146 }, { 0, 23, 27258, 343, 343, 27261, 343, 27269, 27273 }, { 0, 24, 27289, 343, 343, 27292, 343, 27299, 27303 }, { 0, 25, 25617, 343, 343, 27317, 343, 27325, 27329 }, { 0, 26, 20943, 343, 343, 27339, 343, 27346, 27350 }, { 0, 27, 27365, 343, 343, 27368, 343, 27376, 27380 }, { 0, 28, 27396, 343, 343, 27399, 343, 27413, 27417 }, { 0, 29, 27433, 343, 343, 27436, 343, 27445, 27449 }, { 0, 30, 21555, 343, 343, 27464, 343, 27472, 27476 }, { 0, 31, 27494, 343, 343, 27497, 343, 27504, 27508 }, { 0, 32, 23611, 343, 343, 27522, 343, 27529, 27533 }, { 0, 33, 27549, 343, 343, 27552, 343, 26898, 26902 }, { 0, 34, 27566, 343, 343, 27569, 343, 27602, 27606 }, { 0, 35, 27632, 343, 343, 27635, 343, 27660, 27664 }, { 0, 36, 27679, 343, 343, 27682, 343, 27660, 27664 }, { 0, 37, 11001, 343, 343, 27688, 343, 27700, 27704 }, { 0, 38, 27716, 343, 343, 27719, 343, 27142, 27146 }, { 0, 39, 27734, 343, 343, 27737, 343, 27750, 27754 }, { 0, 40, 25244, 343, 343, 27773, 343, 27779, 27783 }, { 0, 41, 27796, 343, 343, 27799, 343, 27660, 27664 }, { 0, 42, 11080, 343, 343, 27808, 343, 27814, 27818 }, { 0, 43, 24707, 343, 343, 27840, 343, 27849, 27853 }, { 0, 44, 24135, 343, 343, 27868, 343, 18032, 27879 }, { 0, 45, 27897, 343, 343, 27900, 343, 27905, 27909 }, { 0, 46, 27920, 343, 343, 27923, 343, 27934, 27938 }, { 0, 47, 27956, 343, 343, 27959, 343, 26898, 26902 }, { 0, 48, 27976, 343, 343, 27979, 343, 27986, 27990 }, { 0, 49, 20156, 343, 343, 28003, 343, 28018, 28022 }, { 0, 50, 4300, 343, 343, 28044, 343, 26879, 26883 }, { 0, 51, 28052, 343, 343, 28055, 343, 28064, 28068 }, { 0, 52, 20198, 343, 343, 28083, 343, 28091, 28095 }, { 0, 53, 28108, 343, 343, 28111, 343, 26639, 26643 }, { 0, 54, 24492, 343, 343, 28120, 343, 28139, 28143 }, { 0, 55, 23965, 343, 343, 28158, 343, 28166, 28170 }, { 0, 56, 25104, 343, 343, 28185, 343, 28193, 28197 }, { 0, 57, 21653, 343, 343, 28211, 343, 28219, 28223 }, { 0, 58, 23349, 343, 343, 28238, 343, 28244, 28248 }, { 0, 59, 28263, 343, 343, 28266, 343, 28281, 28285 }, { 0, 60, 28301, 343, 343, 28304, 343, 28312, 28316 }, { 0, 61, 20048, 343, 343, 28331, 343, 26879, 26883 }, { 0, 62, 28337, 343, 343, 28340, 343, 28349, 28353 }, { 0, 63, 20373, 343, 343, 28368, 343, 26879, 26883 }, { 0, 64, 28376, 343, 343, 28379, 343, 28384, 28388 }, { 0, 65, 28400, 343, 343, 28403, 343, 28420, 28424 }, { 0, 66, 28447, 343, 343, 28450, 343, 26857, 26861 }, { 0, 67, 22259, 343, 343, 28461, 343, 28091, 28095 }, { 0, 68, 20417, 343, 343, 28475, 343, 26879, 26883 }, { 0, 69, 28482, 343, 343, 28485, 343, 27660, 27664 }, { 0, 70, 22929, 343, 343, 28491, 343, 28506, 28510 }, { 0, 71, 28533, 343, 343, 28536, 343, 26639, 26643 }, { 0, 72, 22205, 343, 343, 28544, 343, 28552, 28556 }, { 0, 73, 28570, 343, 343, 28573, 343, 26879, 26883 }, { 0, 74, 28587, 343, 343, 28590, 343, 28596, 28600 }, { 0, 75, 28611, 343, 343, 28614, 343, 28624, 28628 }, { 0, 76, 28644, 343, 343, 28647, 343, 28091, 28095 }, { 0, 77, 28657, 343, 343, 28660, 343, 28667, 28671 }, { 0, 78, 28685, 343, 343, 28688, 343, 28695, 28699 }, { 0, 79, 28712, 343, 343, 28715, 343, 26879, 26883 }, { 0, 80, 28726, 343, 343, 28729, 343, 27660, 27664 }, { 0, 81, 20299, 343, 343, 28747, 343, 26879, 26883 }, { 0, 82, 23853, 343, 343, 28754, 343, 28764, 28768 }, { 0, 83, 28786, 343, 343, 28789, 343, 26857, 26861 }, { 0, 84, 28794, 343, 343, 28797, 343, 28804, 28808 }, { 0, 85, 23433, 343, 343, 28822, 343, 28846, 28850 }, { 0, 86, 28867, 343, 343, 28870, 343, 26898, 26902 }, { 0, 87, 25727, 343, 343, 28904, 343, 28913, 28917 }, { 0, 88, 21095, 343, 343, 28933, 343, 28941, 28945 }, { 0, 89, 20518, 343, 343, 28959, 343, 28967, 28971 }, { 0, 90, 21420, 343, 343, 28988, 343, 28998, 29002 }, { 0, 91, 24279, 343, 343, 29020, 343, 26879, 26883 }, { 0, 92, 20466, 343, 343, 29028, 343, 29035, 29039 }, { 0, 93, 22313, 343, 343, 29058, 343, 29064, 29068 }, { 0, 94, 29081, 343, 343, 29084, 343, 26857, 26861 }, { 0, 95, 22804, 343, 343, 29115, 343, 29120, 29124 }, { 0, 96, 21799, 343, 343, 29136, 343, 29141, 29145 }, { 0, 97, 20567, 343, 343, 29158, 343, 29166, 29170 }, { 0, 98, 20610, 343, 343, 29186, 343, 26879, 26883 }, { 0, 99, 29192, 343, 343, 29195, 343, 29203, 29207 }, { 0, 100, 24867, 343, 343, 29223, 343, 29230, 29234 }, { 0, 101, 20655, 343, 343, 29250, 343, 29256, 29260 }, { 0, 102, 22356, 343, 343, 29273, 343, 29279, 29283 }, { 0, 103, 29299, 343, 343, 29302, 343, 29313, 29317 }, { 0, 104, 29331, 343, 343, 29334, 343, 29343, 29347 }, { 0, 105, 29362, 343, 343, 29365, 343, 26898, 26902 }, { 0, 106, 29374, 343, 343, 29377, 343, 29385, 29389 }, { 0, 107, 29402, 343, 343, 29405, 343, 26639, 26643 }, { 0, 108, 29427, 343, 343, 29430, 343, 29442, 29446 }, { 0, 109, 20710, 343, 343, 29463, 343, 29475, 29479 }, { 0, 110, 25163, 343, 343, 29496, 343, 29503, 29507 }, { 0, 111, 29521, 343, 343, 29524, 343, 29539, 29543 }, { 0, 112, 29565, 343, 343, 29568, 343, 29579, 29583 }, { 0, 113, 29600, 343, 343, 29603, 343, 29608, 29612 }, { 0, 114, 25022, 343, 343, 29624, 343, 29632, 29636 }, { 0, 115, 29651, 343, 343, 29654, 343, 26639, 26643 }, { 0, 116, 29666, 343, 343, 29669, 343, 27700, 27704 }, { 0, 117, 29683, 343, 343, 29686, 343, 29696, 29700 }, { 0, 118, 29716, 343, 343, 29719, 343, 29727, 29731 }, { 0, 119, 21751, 343, 343, 29747, 343, 29757, 29761 }, { 0, 120, 23772, 343, 343, 29777, 343, 26879, 26883 }, { 0, 121, 21699, 343, 343, 29788, 343, 29795, 29799 }, { 0, 122, 23667, 343, 343, 29812, 343, 29818, 29822 }, { 0, 123, 24248, 343, 343, 29835, 343, 28281, 28285 }, { 0, 124, 29843, 343, 343, 29846, 343, 26879, 26883 }, { 0, 125, 7437, 343, 343, 29853, 343, 29861, 29865 }, { 0, 126, 29878, 343, 343, 29881, 343, 29892, 29896 }, { 0, 127, 29913, 343, 343, 29916, 343, 26857, 26861 }, { 0, 128, 22063, 343, 343, 29933, 343, 29943, 29947 }, { 0, 129, 29964, 343, 343, 29967, 343, 27142, 27146 }, { 0, 130, 29972, 343, 343, 29975, 343, 29983, 29987 }, { 0, 131, 30000, 343, 343, 30003, 343, 30012, 30016 }, { 0, 132, 24044, 343, 343, 30033, 343, 30052, 30056 }, { 0, 133, 30069, 343, 343, 30072, 343, 26857, 26861 }, { 0, 134, 30097, 343, 343, 30100, 343, 26879, 26883 }, { 0, 135, 30111, 343, 343, 30114, 343, 30125, 30129 }, { 0, 136, 30148, 343, 343, 30151, 343, 26639, 26643 }, { 0, 137, 30162, 343, 343, 30165, 343, 30171, 30175 }, { 0, 138, 30188, 343, 343, 30191, 343, 30201, 30205 }, { 0, 139, 30221, 343, 343, 30224, 343, 30233, 30237 }, { 0, 140, 30261, 343, 343, 30264, 343, 30271, 30275 }, { 0, 141, 22978, 343, 343, 30289, 343, 30296, 30300 }, { 0, 142, 30313, 343, 343, 30316, 343, 30325, 30329 }, { 0, 143, 30347, 343, 343, 30350, 343, 30361, 30365 }, { 0, 144, 30384, 343, 343, 30387, 343, 30401, 30405 }, { 0, 145, 30415, 343, 343, 30418, 343, 27142, 27146 }, { 0, 146, 30424, 343, 343, 30427, 343, 26898, 26902 }, { 0, 147, 30442, 343, 343, 30445, 343, 30453, 30457 }, { 0, 148, 25781, 343, 343, 30472, 343, 30482, 30486 }, { 0, 149, 20762, 343, 343, 30509, 343, 26879, 26883 }, { 0, 150, 20853, 343, 343, 30521, 343, 27413, 27417 }, { 0, 151, 30528, 343, 343, 30531, 343, 30537, 30541 }, { 0, 152, 30556, 343, 343, 30559, 343, 26898, 26902 }, { 0, 153, 30565, 343, 343, 30568, 343, 27750, 27754 }, { 0, 154, 24079, 343, 343, 30573, 343, 27750, 27754 }, { 0, 155, 24545, 343, 343, 30585, 343, 30590, 30594 }, { 0, 156, 24328, 343, 343, 30604, 343, 30611, 30615 }, { 0, 157, 24808, 343, 343, 30633, 343, 30638, 30642 }, { 0, 158, 30661, 343, 343, 30664, 343, 30401, 30405 }, { 0, 159, 30681, 343, 343, 30684, 343, 30701, 30705 }, { 0, 160, 25198, 343, 343, 30727, 343, 18136, 30739 }, { 0, 161, 30755, 343, 343, 30758, 343, 30767, 30771 }, { 0, 162, 20894, 343, 343, 30786, 343, 30793, 30797 }, { 0, 163, 468, 343, 343, 30810, 343, 26879, 26883 }, { 0, 164, 30836, 343, 343, 30839, 343, 27750, 27754 }, { 0, 165, 25839, 343, 343, 30848, 343, 26857, 26861 }, { 0, 166, 23251, 343, 343, 30860, 343, 26879, 26883 }, { 0, 167, 30869, 343, 343, 30872, 343, 26857, 26861 }, { 0, 168, 25515, 343, 343, 30878, 343, 30887, 30891 }, { 0, 169, 25567, 343, 343, 30908, 343, 30914, 30918 }, { 0, 170, 30930, 343, 343, 30933, 343, 26879, 26883 }, { 0, 171, 20991, 343, 343, 30942, 343, 30950, 30954 }, { 0, 172, 21047, 343, 343, 30967, 343, 30974, 30978 }, { 0, 173, 31004, 343, 343, 31007, 343, 31014, 31018 }, { 0, 174, 10998, 343, 343, 31032, 343, 31045, 31049 }, { 0, 175, 31061, 343, 343, 31064, 343, 31080, 31084 }, { 0, 176, 31107, 343, 343, 31110, 343, 31121, 31125 }, { 0, 177, 31142, 343, 343, 31145, 343, 31151, 31155 }, { 0, 178, 21248, 343, 343, 31170, 343, 31177, 31181 }, { 0, 179, 23719, 343, 343, 31195, 343, 31205, 31209 }, { 0, 180, 31226, 343, 343, 31229, 343, 31242, 31246 }, { 0, 181, 21611, 343, 343, 31265, 343, 17910, 31274 }, { 0, 182, 31289, 343, 343, 31292, 343, 27413, 27417 }, { 0, 183, 21156, 343, 343, 31315, 343, 31324, 31328 }, { 0, 184, 31342, 343, 343, 31345, 343, 31358, 31362 }, { 0, 185, 31381, 343, 343, 31384, 343, 26879, 26883 }, { 0, 186, 31395, 343, 343, 31398, 343, 27142, 27146 }, { 0, 187, 31406, 343, 343, 31409, 343, 31417, 31421 }, { 0, 188, 31437, 343, 343, 31440, 343, 31449, 31453 }, { 0, 189, 31470, 343, 343, 31473, 343, 31495, 31499 }, { 0, 190, 25675, 343, 343, 31527, 343, 18180, 31539 }, { 0, 191, 24763, 343, 343, 31557, 343, 31563, 31567 }, { 0, 192, 31580, 343, 343, 31583, 343, 31593, 31597 }, { 0, 193, 31617, 343, 343, 31620, 343, 26857, 26861 }, { 0, 194, 31645, 343, 343, 31648, 343, 27660, 27664 }, { 0, 195, 31653, 343, 343, 31656, 343, 26879, 26883 }, { 0, 196, 31684, 343, 343, 31687, 343, 27142, 27146 }, { 0, 197, 21313, 343, 343, 31692, 343, 31701, 31705 }, { 0, 198, 31715, 343, 343, 31718, 343, 31729, 31733 }, { 0, 199, 31751, 343, 343, 31754, 343, 27750, 27754 }, { 0, 200, 17896, 343, 343, 31762, 343, 26857, 26861 }, { 0, 201, 31774, 343, 343, 31777, 343, 31790, 31794 }, { 0, 202, 24384, 343, 343, 31813, 343, 31821, 31825 }, { 0, 203, 31840, 343, 343, 31843, 343, 31849, 31853 }, { 0, 204, 21359, 343, 343, 31868, 343, 31875, 31879 }, { 0, 205, 24910, 343, 343, 31892, 343, 31912, 31916 }, { 0, 206, 31943, 343, 343, 31946, 343, 26898, 26902 }, { 0, 207, 20094, 343, 343, 31953, 343, 31960, 31964 }, { 0, 208, 31982, 343, 343, 31985, 343, 31994, 31998 }, { 0, 209, 21487, 343, 343, 32017, 343, 32025, 32029 }, { 0, 210, 32047, 343, 343, 32050, 343, 32057, 32061 }, { 0, 211, 32078, 343, 343, 32081, 343, 26857, 26861 }, { 0, 212, 20332, 343, 343, 32118, 343, 26857, 26861 }, { 0, 213, 25401, 343, 343, 32132, 343, 32140, 32144 }, { 0, 214, 32166, 343, 343, 32169, 343, 32180, 32184 }, { 0, 215, 32199, 343, 343, 32202, 343, 26879, 26883 }, { 0, 216, 32210, 343, 343, 32213, 343, 26639, 26643 }, { 0, 217, 24599, 343, 343, 32246, 343, 32256, 32260 }, { 0, 218, 32279, 343, 343, 32282, 343, 26857, 26861 }, { 0, 219, 1619, 343, 343, 32305, 343, 26857, 26861 }, { 0, 220, 21857, 343, 343, 32325, 343, 32333, 32337 }, { 0, 221, 32353, 343, 343, 32356, 343, 32364, 32368 }, { 0, 222, 32381, 343, 343, 32384, 343, 30401, 30405 }, { 0, 223, 32402, 343, 343, 32405, 343, 32411, 32415 }, { 0, 224, 24655, 343, 343, 32434, 343, 32440, 32444 }, { 0, 225, 32456, 343, 343, 32459, 343, 26879, 26883 }, { 0, 226, 32467, 343, 343, 32470, 343, 32481, 32485 }, { 0, 227, 22122, 343, 343, 32509, 343, 32522, 32526 }, { 0, 228, 32545, 343, 343, 32548, 343, 32555, 32559 }, { 0, 229, 25054, 343, 343, 32574, 343, 32583, 32587 } }; static const RegionInfoNameEntry region_name_entries[] = { { 25351, 0 }, { 26589, 1 }, { 26616, 2 }, { 26665, 3 }, { 21204, 4 }, { 465, 5 }, { 26728, 6 }, { 26785, 7 }, { 24964, 8 }, { 26839, 9 }, { 23485, 10 }, { 23518, 11 }, { 26920, 12 }, { 26948, 13 }, { 26986, 14 }, { 27052, 15 }, { 27084, 16 }, { 23029, 17 }, { 27126, 18 }, { 20005, 19 }, { 25463, 20 }, { 27220, 21 }, { 27249, 22 }, { 27258, 23 }, { 27289, 24 }, { 25617, 25 }, { 20943, 26 }, { 27365, 27 }, { 27396, 28 }, { 27433, 29 }, { 21555, 30 }, { 27494, 31 }, { 23611, 32 }, { 27549, 33 }, { 27566, 34 }, { 27632, 35 }, { 27679, 36 }, { 11001, 37 }, { 27716, 38 }, { 27734, 39 }, { 25244, 40 }, { 27796, 41 }, { 11080, 42 }, { 24707, 43 }, { 24135, 44 }, { 27897, 45 }, { 27920, 46 }, { 27956, 47 }, { 27976, 48 }, { 20156, 49 }, { 4300, 50 }, { 28052, 51 }, { 20198, 52 }, { 28108, 53 }, { 24492, 54 }, { 23965, 55 }, { 25104, 56 }, { 21653, 57 }, { 23349, 58 }, { 28263, 59 }, { 28301, 60 }, { 20048, 61 }, { 28337, 62 }, { 20373, 63 }, { 28376, 64 }, { 28400, 65 }, { 28447, 66 }, { 22259, 67 }, { 20417, 68 }, { 28482, 69 }, { 22929, 70 }, { 28533, 71 }, { 22205, 72 }, { 28570, 73 }, { 28587, 74 }, { 28611, 75 }, { 28644, 76 }, { 28657, 77 }, { 28685, 78 }, { 28712, 79 }, { 28726, 80 }, { 20299, 81 }, { 23853, 82 }, { 28786, 83 }, { 28794, 84 }, { 23433, 85 }, { 28867, 86 }, { 25727, 87 }, { 21095, 88 }, { 20518, 89 }, { 21420, 90 }, { 24279, 91 }, { 20466, 92 }, { 22313, 93 }, { 29081, 94 }, { 22804, 95 }, { 21799, 96 }, { 20567, 97 }, { 20610, 98 }, { 29192, 99 }, { 24867, 100 }, { 20655, 101 }, { 22356, 102 }, { 29299, 103 }, { 29331, 104 }, { 29362, 105 }, { 29374, 106 }, { 29402, 107 }, { 29427, 108 }, { 20710, 109 }, { 25163, 110 }, { 29521, 111 }, { 29565, 112 }, { 29600, 113 }, { 25022, 114 }, { 29651, 115 }, { 29666, 116 }, { 29683, 117 }, { 29716, 118 }, { 21751, 119 }, { 23772, 120 }, { 21699, 121 }, { 23667, 122 }, { 24248, 123 }, { 29843, 124 }, { 7437, 125 }, { 29878, 126 }, { 29913, 127 }, { 22063, 128 }, { 29964, 129 }, { 29972, 130 }, { 30000, 131 }, { 24044, 132 }, { 30069, 133 }, { 30097, 134 }, { 30111, 135 }, { 30148, 136 }, { 30162, 137 }, { 30188, 138 }, { 30221, 139 }, { 30261, 140 }, { 22978, 141 }, { 30313, 142 }, { 30347, 143 }, { 30384, 144 }, { 30415, 145 }, { 30424, 146 }, { 30442, 147 }, { 25781, 148 }, { 20762, 149 }, { 20853, 150 }, { 30528, 151 }, { 30556, 152 }, { 30565, 153 }, { 24079, 154 }, { 24545, 155 }, { 24328, 156 }, { 24808, 157 }, { 30661, 158 }, { 30681, 159 }, { 25198, 160 }, { 30755, 161 }, { 20894, 162 }, { 468, 163 }, { 30836, 164 }, { 25839, 165 }, { 23251, 166 }, { 30869, 167 }, { 25515, 168 }, { 25567, 169 }, { 30930, 170 }, { 20991, 171 }, { 21047, 172 }, { 31004, 173 }, { 10998, 174 }, { 31061, 175 }, { 31107, 176 }, { 31142, 177 }, { 21248, 178 }, { 23719, 179 }, { 31226, 180 }, { 21611, 181 }, { 31289, 182 }, { 21156, 183 }, { 31342, 184 }, { 31381, 185 }, { 31395, 186 }, { 31406, 187 }, { 31437, 188 }, { 31470, 189 }, { 25675, 190 }, { 24763, 191 }, { 31580, 192 }, { 31617, 193 }, { 31645, 194 }, { 31653, 195 }, { 31684, 196 }, { 21313, 197 }, { 31715, 198 }, { 31751, 199 }, { 17896, 200 }, { 31774, 201 }, { 24384, 202 }, { 31840, 203 }, { 21359, 204 }, { 24910, 205 }, { 31943, 206 }, { 20094, 207 }, { 31982, 208 }, { 21487, 209 }, { 32047, 210 }, { 32078, 211 }, { 20332, 212 }, { 25401, 213 }, { 32166, 214 }, { 32199, 215 }, { 32210, 216 }, { 24599, 217 }, { 32279, 218 }, { 1619, 219 }, { 21857, 220 }, { 32353, 221 }, { 32381, 222 }, { 32402, 223 }, { 24655, 224 }, { 32456, 225 }, { 32467, 226 }, { 22122, 227 }, { 32545, 228 }, { 25054, 229 } }; static const char locale_strings[] = { "\0" "d MMMM, yyyy h:mm:ss t\0" "d MMMM, yyyy\0" "d/M/yyyy\0" "h:mm:ss t\0" "h:mm t\0" "MMMM, yyyy\0" "d MMMM\0" "\xd8\xb5\0" "\xd9\x85\0" "\xd8\xa7\xd9\x84\xd8\xa3\xd8\xad\xd8\xaf\0" "\xd8\xa7\xd9\x84\xd8\xa7\xd8\xab\xd9\x86\xd9\x8a\xd9\x86\0" "\xd8\xa7\xd9\x84\xd8\xab\xd9\x84\xd8\xa7\xd8\xab\xd8\xa7\xd8\xa1\0" "\xd8\xa7\xd9\x84\xd8\xa3\xd8\xb1\xd8\xa8\xd8\xb9\xd8\xa7\xd8\xa1\0" "\xd8\xa7\xd9\x84\xd8\xae\xd9\x85\xd9\x8a\xd8\xb3\0" "\xd8\xa7\xd9\x84\xd8\xac\xd9\x85\xd8\xb9\xd8\xa9\0" "\xd8\xa7\xd9\x84\xd8\xb3\xd8\xa8\xd8\xaa\0" "\xd8\xad\0" "\xd9\x86\0" "\xd8\xab\0" "\xd8\xb1\0" "\xd8\xae\0" "\xd8\xac\0" "\xd8\xb3\0" "\xd9\x8a\xd9\x86\xd8\xa7\xd9\x8a\xd8\xb1\0" "\xd9\x81\xd8\xa8\xd8\xb1\xd8\xa7\xd9\x8a\xd8\xb1\0" "\xd9\x85\xd8\xa7\xd8\xb1\xd8\xb3\0" "\xd8\xa3\xd8\xa8\xd8\xb1\xd9\x8a\xd9\x84\0" "\xd9\x85\xd8\xa7\xd9\x8a\xd9\x88\0" "\xd9\x8a\xd9\x88\xd9\x86\xd9\x8a\xd9\x88\0" "\xd9\x8a\xd9\x88\xd9\x84\xd9\x8a\xd9\x88\0" "\xd8\xa3\xd8\xba\xd8\xb3\xd8\xb7\xd8\xb3\0" "\xd8\xb3\xd8\xa8\xd8\xaa\xd9\x85\xd8\xa8\xd8\xb1\0" "\xd8\xa3\xd9\x83\xd8\xaa\xd9\x88\xd8\xa8\xd8\xb1\0" "\xd9\x86\xd9\x88\xd9\x81\xd9\x85\xd8\xa8\xd8\xb1\0" "\xd8\xaf\xd9\x8a\xd8\xb3\xd9\x85\xd8\xa8\xd8\xb1\0" "\0" "/\0" ":\0" "yy/MM/dd\0" "yyyy MMMM d \0" "HH:mm\0" "HH:mm:ss z\0" "dd MMMM yyyy HH:mm:ss\0" "dd MMMM yyyy\0" "dd.M.yyyy '\xd0\xb3.'\0" "HH:mm:ss\0" "MMMM yyyy\0" "dd MMMM\0" "AM\0" "PM\0" "\xd0\xbd\xd0\xb5\xd0\xb4\xd0\xb5\xd0\xbb\xd1\x8f\0" "\xd0\xbf\xd0\xbe\xd0\xbd\xd0\xb5\xd0\xb4\xd0\xb5\xd0\xbb\xd0\xbd\xd0\xb8\xd0\xba\0" "\xd0\xb2\xd1\x82\xd0\xbe\xd1\x80\xd0\xbd\xd0\xb8\xd0\xba\0" "\xd1\x81\xd1\x80\xd1\x8f\xd0\xb4\xd0\xb0\0" "\xd1\x87\xd0\xb5\xd1\x82\xd0\xb2\xd1\x8a\xd1\x80\xd1\x82\xd1\x8a\xd0\xba\0" "\xd0\xbf\xd0\xb5\xd1\x82\xd1\x8a\xd0\xba\0" "\xd1\x81\xd1\x8a\xd0\xb1\xd0\xbe\xd1\x82\xd0\xb0\0" "\xd0\xbd\xd0\xb5\xd0\xb4.\0" "\xd0\xbf\xd0\xbe\xd0\xbd.\0" "\xd0\xb2\xd1\x82.\0" "\xd1\x81\xd1\x80.\0" "\xd1\x87\xd0\xb5\xd1\x82\xd0\xb2.\0" "\xd0\xbf\xd0\xb5\xd1\x82.\0" "\xd1\x81\xd1\x8a\xd0\xb1.\0" "\xd1\x8f\xd0\xbd\xd1\x83\xd0\xb0\xd1\x80\xd0\xb8\0" "\xd1\x84\xd0\xb5\xd0\xb2\xd1\x80\xd1\x83\xd0\xb0\xd1\x80\xd0\xb8\0" "\xd0\xbc\xd0\xb0\xd1\x80\xd1\x82\0" "\xd0\xb0\xd0\xbf\xd1\x80\xd0\xb8\xd0\xbb\0" "\xd0\xbc\xd0\xb0\xd0\xb9\0" "\xd1\x8e\xd0\xbd\xd0\xb8\0" "\xd1\x8e\xd0\xbb\xd0\xb8\0" "\xd0\xb0\xd0\xb2\xd0\xb3\xd1\x83\xd1\x81\xd1\x82\0" "\xd1\x81\xd0\xb5\xd0\xbf\xd1\x82\xd0\xb5\xd0\xbc\xd0\xb2\xd1\x80\xd0\xb8\0" "\xd0\xbe\xd0\xba\xd1\x82\xd0\xbe\xd0\xbc\xd0\xb2\xd1\x80\xd0\xb8\0" "\xd0\xbd\xd0\xbe\xd0\xb5\xd0\xbc\xd0\xb2\xd1\x80\xd0\xb8\0" "\xd0\xb4\xd0\xb5\xd0\xba\xd0\xb5\xd0\xbc\xd0\xb2\xd1\x80\xd0\xb8\0" "\xd1\x8f\xd0\xbd.\0" "\xd1\x84\xd0\xb5\xd0\xb2.\0" "\xd0\xb0\xd0\xbf\xd1\x80.\0" "\xd0\xb0\xd0\xb2\xd0\xb3.\0" "\xd1\x81\xd0\xb5\xd0\xbf.\0" "\xd0\xbe\xd0\xba\xd1\x82.\0" "\xd0\xbd\xd0\xbe\xd0\xb5\xd0\xbc.\0" "\xd0\xb4\xd0\xb5\xd0\xba.\0" "dd.MM.yy\0" "d MMMM yyyy HH:mm:ss z\0" "d MMMM yyyy\0" "dd/MM/yy\0" "diumenge\0" "dilluns\0" "dimarts\0" "dimecres\0" "dijous\0" "divendres\0" "dissabte\0" "dg.\0" "dl.\0" "dt.\0" "dc.\0" "dj.\0" "dv.\0" "ds.\0" "gener\0" "febrer\0" "mar\xc3\xa7\0" "abril\0" "maig\0" "juny\0" "juliol\0" "agost\0" "setembre\0" "octubre\0" "novembre\0" "desembre\0" "gen.\0" "feb.\0" "abr.\0" "jul.\0" "ag.\0" "set.\0" "oct.\0" "nov.\0" "des.\0" "yyyy MMMM d HH:mm:ss z\0" "yyyy MMMM\0" "MMMM dd\0" "\xe4\xb8\x8a\xe5\x8d\x88\0" "\xe4\xb8\x8b\xe5\x8d\x88\0" "\xe6\x98\x9f\xe6\x9c\x9f\xe6\x97\xa5\0" "\xe6\x98\x9f\xe6\x9c\x9f\xe4\xb8\x80\0" "\xe6\x98\x9f\xe6\x9c\x9f\xe4\xba\x8c\0" "\xe6\x98\x9f\xe6\x9c\x9f\xe4\xb8\x89\0" "\xe6\x98\x9f\xe6\x9c\x9f\xe5\x9b\x9b\0" "\xe6\x98\x9f\xe6\x9c\x9f\xe4\xba\x94\0" "\xe6\x98\x9f\xe6\x9c\x9f\xe5\x85\xad\0" "\xe6\x97\xa5\0" "\xe4\xb8\x80\0" "\xe4\xba\x8c\0" "\xe4\xb8\x89\0" "\xe5\x9b\x9b\0" "\xe4\xba\x94\0" "\xe5\x85\xad\0" "\xe4\xb8\x80\xe6\x9c\x88\0" "\xe4\xba\x8c\xe6\x9c\x88\0" "\xe4\xb8\x89\xe6\x9c\x88\0" "\xe5\x9b\x9b\xe6\x9c\x88\0" "\xe4\xba\x94\xe6\x9c\x88\0" "\xe5\x85\xad\xe6\x9c\x88\0" "\xe4\xb8\x83\xe6\x9c\x88\0" "\xe5\x85\xab\xe6\x9c\x88\0" "\xe4\xb9\x9d\xe6\x9c\x88\0" "\xe5\x8d\x81\xe6\x9c\x88\0" "\xe5\x8d\x81\xe4\xb8\x80\xe6\x9c\x88\0" "\xe5\x8d\x81\xe4\xba\x8c\xe6\x9c\x88\0" "d. MMMM yyyy H:mm:ss z\0" "d. MMMM yyyy\0" "d.M.yy\0" "H:mm:ss z\0" "H:mm\0" "d. MMMM\0" "dop.\0" "odp.\0" "ned\xc4\x9ble\0" "pond\xc4\x9bl\xc3\xad\0" "\xc3\xbater\xc3\xbd\0" "st\xc5\x99\x65\x64\x61\0" "\xc4\x8dtvrtek\0" "p\xc3\xa1tek\0" "sobota\0" "ne\0" "po\0" "\xc3\xbat\0" "st\0" "\xc4\x8dt\0" "p\xc3\xa1\0" "so\0" "leden\0" "\xc3\xbanor\0" "b\xc5\x99\x65zen\0" "duben\0" "kv\xc4\x9bten\0" "\xc4\x8d\x65rven\0" "\xc4\x8d\x65rvenec\0" "srpen\0" "z\xc3\xa1\xc5\x99\xc3\xad\0" "\xc5\x99\xc3\xadjen\0" "listopad\0" "prosinec\0" "I\0" "II\0" "III\0" "IV\0" "V\0" "VI\0" "VII\0" "VIII\0" "IX\0" "X\0" "XI\0" "XII\0" "d. MMM yyyy HH:mm:ss\0" "d. MMM yyyy\0" "dd-MM-yyyy\0" "dd. MMMM\0" "s\xc3\xb8ndag\0" "mandag\0" "tirsdag\0" "onsdag\0" "torsdag\0" "fredag\0" "l\xc3\xb8rdag\0" "s\xc3\xb8n\0" "man\0" "tir\0" "ons\0" "tor\0" "fre\0" "l\xc3\xb8r\0" "januar\0" "februar\0" "marts\0" "april\0" "maj\0" "juni\0" "juli\0" "august\0" "september\0" "oktober\0" "november\0" "december\0" "jan\0" "feb\0" "mar\0" "apr\0" "jun\0" "jul\0" "aug\0" "sep\0" "okt\0" "nov\0" "dec\0" "dd-MM-yy\0" "d. MMMM yyyy HH:mm:ss\0" "dd.MM.yyyy\0" "vorm.\0" "nachm.\0" "Sonntag\0" "Montag\0" "Dienstag\0" "Mittwoch\0" "Donnerstag\0" "Freitag\0" "Samstag\0" "So\0" "Mo\0" "Di\0" "Mi\0" "Do\0" "Fr\0" "Sa\0" "Januar\0" "Februar\0" "M\xc3\xa4rz\0" "April\0" "Mai\0" "Juni\0" "Juli\0" "August\0" "September\0" "Oktober\0" "November\0" "Dezember\0" "Jan\0" "Feb\0" "Mrz\0" "Apr\0" "Jun\0" "Jul\0" "Aug\0" "Sep\0" "Okt\0" "Nov\0" "Dez\0" "dd MMMM yyyy h:mm:ss tt\0" "h:mm:ss tt\0" "\xce\xa0\xce\x9c\0" "\xce\x9c\xce\x9c\0" "\xce\x9a\xcf\x85\xcf\x81\xce\xb9\xce\xb1\xce\xba\xce\xae\0" "\xce\x94\xce\xb5\xcf\x85\xcf\x84\xce\xad\xcf\x81\xce\xb1\0" "\xce\xa4\xcf\x81\xce\xaf\xcf\x84\xce\xb7\0" "\xce\xa4\xce\xb5\xcf\x84\xce\xac\xcf\x81\xcf\x84\xce\xb7\0" "\xce\xa0\xce\xad\xce\xbc\xcf\x80\xcf\x84\xce\xb7\0" "\xce\xa0\xce\xb1\xcf\x81\xce\xb1\xcf\x83\xce\xba\xce\xb5\xcf\x85\xce\xae\0" "\xce\xa3\xce\xac\xce\xb2\xce\xb2\xce\xb1\xcf\x84\xce\xbf\0" "\xce\x9a\xcf\x85\xcf\x81\0" "\xce\x94\xce\xb5\xcf\x85\0" "\xce\xa4\xcf\x81\xce\xb9\0" "\xce\xa4\xce\xb5\xcf\x84\0" "\xce\xa0\xce\xb5\xce\xbc\0" "\xce\xa0\xce\xb1\xcf\x81\0" "\xce\xa3\xce\xb1\xce\xb2\0" "\xce\x99\xce\xb1\xce\xbd\xce\xbf\xcf\x85\xce\xac\xcf\x81\xce\xb9\xce\xbf\xcf\x82\0" "\xce\xa6\xce\xb5\xce\xb2\xcf\x81\xce\xbf\xcf\x85\xce\xac\xcf\x81\xce\xb9\xce\xbf\xcf\x82\0" "\xce\x9c\xce\xac\xcf\x81\xcf\x84\xce\xb9\xce\xbf\xcf\x82\0" "\xce\x91\xcf\x80\xcf\x81\xce\xaf\xce\xbb\xce\xb9\xce\xbf\xcf\x82\0" "\xce\x9c\xce\xac\xce\xb9\xce\xbf\xcf\x82\0" "\xce\x99\xce\xbf\xcf\x8d\xce\xbd\xce\xb9\xce\xbf\xcf\x82\0" "\xce\x99\xce\xbf\xcf\x8d\xce\xbb\xce\xb9\xce\xbf\xcf\x82\0" "\xce\x91\xcf\x8d\xce\xb3\xce\xbf\xcf\x85\xcf\x83\xcf\x84\xce\xbf\xcf\x82\0" "\xce\xa3\xce\xb5\xcf\x80\xcf\x84\xce\xad\xce\xbc\xce\xb2\xcf\x81\xce\xb9\xce\xbf\xcf\x82\0" "\xce\x9f\xce\xba\xcf\x84\xcf\x8e\xce\xb2\xcf\x81\xce\xb9\xce\xbf\xcf\x82\0" "\xce\x9d\xce\xbf\xce\xad\xce\xbc\xce\xb2\xcf\x81\xce\xb9\xce\xbf\xcf\x82\0" "\xce\x94\xce\xb5\xce\xba\xce\xad\xce\xbc\xce\xb2\xcf\x81\xce\xb9\xce\xbf\xcf\x82\0" "\xce\x99\xce\xb1\xce\xbd\0" "\xce\xa6\xce\xb5\xce\xb2\0" "\xce\x9c\xce\xb1\xcf\x81\0" "\xce\x91\xcf\x80\xcf\x81\0" "\xce\x9c\xce\xb1\xcf\x8a\0" "\xce\x99\xce\xbf\xcf\x85\xce\xbd\0" "\xce\x99\xce\xbf\xcf\x85\xce\xbb\0" "\xce\x91\xcf\x85\xce\xb3\0" "\xce\xa3\xce\xb5\xcf\x80\0" "\xce\x9f\xce\xba\xcf\x84\0" "\xce\x9d\xce\xbf\xce\xb5\0" "\xce\x94\xce\xb5\xce\xba\0" "dd/MM/yyyy\0" "h:mm:ss t z\0" "dddd, MMMM dd, yyyy h:mm:ss tt\0" "dddd, MMMM dd, yyyy\0" "M/d/yy\0" "h:mm tt\0" "MMMM d\0" "Sunday\0" "Monday\0" "Tuesday\0" "Wednesday\0" "Thursday\0" "Friday\0" "Saturday\0" "Sun\0" "Mon\0" "Tue\0" "Wed\0" "Thu\0" "Fri\0" "Sat\0" "January\0" "February\0" "March\0" "May\0" "June\0" "July\0" "October\0" "December\0" "Mar\0" "Oct\0" "Dec\0" "MMMM dd, yyyy\0" "dddd, dd MMMM, yyyy\0" "dd, MMMM, yyyy\0" "hh:mm tt\0" "hh:mm:ss tt\0" "H:mm:ss\0" "d' de 'MMMM' de 'yyyy hh:mm:ss tt\0" "d' de 'MMMM' de 'yyyy\0" "MM/dd/yyyy\0" "MMMM\0" "d' de 'MMMM\0" "a.m.\0" "p.m.\0" "domingo\0" "lunes\0" "martes\0" "mi\xc3\xa9rcoles\0" "jueves\0" "viernes\0" "s\xc3\xa1\x62\x61\x64o\0" "dom\0" "lun\0" "mi\xc3\xa9\0" "jue\0" "vie\0" "s\xc3\xa1\x62\0" "enero\0" "febrero\0" "marzo\0" "mayo\0" "junio\0" "julio\0" "agosto\0" "septiembre\0" "noviembre\0" "diciembre\0" "ene\0" "abr\0" "may\0" "ago\0" "oct\0" "dic\0" "d/MM/yy\0" "d. MMMM'ta 'yyyy H:mm:ss\0" "d. MMMM'ta 'yyyy\0" "d.M.yyyy\0" "MMMM'ta'yyyy\0" "d. MMMM'ta'\0" "sunnuntai\0" "maanantai\0" "tiistai\0" "keskiviikko\0" "torstai\0" "perjantai\0" "lauantai\0" "su\0" "ma\0" "ti\0" "ke\0" "to\0" "pe\0" "la\0" "tammikuu\0" "helmikuu\0" "maaliskuu\0" "huhtikuu\0" "toukokuu\0" "kes\xc3\xa4kuu\0" "hein\xc3\xa4kuu\0" "elokuu\0" "syyskuu\0" "lokakuu\0" "marraskuu\0" "joulukuu\0" "tammi\0" "helmi\0" "maalis\0" "huhti\0" "touko\0" "kes\xc3\xa4\0" "hein\xc3\xa4\0" "elo\0" "syys\0" "loka\0" "marras\0" "joulu\0" "dddd d MMMM yyyy HH:mm:ss\0" "dddd d MMMM yyyy\0" "dimanche\0" "lundi\0" "mardi\0" "mercredi\0" "jeudi\0" "vendredi\0" "samedi\0" "dim.\0" "lun.\0" "mar.\0" "mer.\0" "jeu.\0" "ven.\0" "sam.\0" "janvier\0" "f\xc3\xa9vrier\0" "mars\0" "avril\0" "mai\0" "juin\0" "juillet\0" "ao\xc3\xbbt\0" "septembre\0" "octobre\0" "d\xc3\xa9\x63\x65mbre\0" "janv.\0" "f\xc3\xa9vr.\0" "avr.\0" "juil.\0" "sept.\0" "d\xc3\xa9\x63.\0" "d/MM/yyyy\0" "HH:mm:ss d MMMM yyyy\0" "\xd7\x99\xd7\x95\xd7\x9d \xd7\xa8\xd7\x90\xd7\xa9\xd7\x95\xd7\x9f\0" "\xd7\x99\xd7\x95\xd7\x9d \xd7\xa9\xd7\xa0\xd7\x99\0" "\xd7\x99\xd7\x95\xd7\x9d \xd7\xa9\xd7\x9c\xd7\x99\xd7\xa9\xd7\x99\0" "\xd7\x99\xd7\x95\xd7\x9d \xd7\xa8\xd7\x91\xd7\x99\xd7\xa2\xd7\x99\0" "\xd7\x99\xd7\x95\xd7\x9d \xd7\x97\xd7\x9e\xd7\x99\xd7\xa9\xd7\x99\0" "\xd7\x99\xd7\x95\xd7\x9d \xd7\xa9\xd7\x99\xd7\xa9\xd7\x99\0" "\xd7\xa9\xd7\x91\xd7\xaa\0" "\xd7\x90\0" "\xd7\x91\0" "\xd7\x92\0" "\xd7\x93\0" "\xd7\x94\0" "\xd7\x95\0" "\xd7\xa9\0" "\xd7\x99\xd7\xa0\xd7\x95\xd7\x90\xd7\xa8\0" "\xd7\xa4\xd7\x91\xd7\xa8\xd7\x95\xd7\x90\xd7\xa8\0" "\xd7\x9e\xd7\xa8\xd7\xa5\0" "\xd7\x90\xd7\xa4\xd7\xa8\xd7\x99\xd7\x9c\0" "\xd7\x9e\xd7\x90\xd7\x99\0" "\xd7\x99\xd7\x95\xd7\xa0\xd7\x99\0" "\xd7\x99\xd7\x95\xd7\x9c\xd7\x99\0" "\xd7\x90\xd7\x95\xd7\x92\xd7\x95\xd7\xa1\xd7\x98\0" "\xd7\xa1\xd7\xa4\xd7\x98\xd7\x9e\xd7\x91\xd7\xa8\0" "\xd7\x90\xd7\x95\xd7\xa7\xd7\x98\xd7\x95\xd7\x91\xd7\xa8\0" "\xd7\xa0\xd7\x95\xd7\x91\xd7\x9e\xd7\x91\xd7\xa8\0" "\xd7\x93\xd7\xa6\xd7\x9e\xd7\x91\xd7\xa8\0" "\xd7\x99\xd7\xa0\xd7\x95\0" "\xd7\xa4\xd7\x91\xd7\xa8\0" "\xd7\x90\xd7\xa4\xd7\xa8\0" "\xd7\x99\xd7\x95\xd7\xa0\0" "\xd7\x99\xd7\x95\xd7\x9c\0" "\xd7\x90\xd7\x95\xd7\x92\0" "\xd7\xa1\xd7\xa4\xd7\x98\0" "\xd7\x90\xd7\x95\xd7\xa7\0" "\xd7\xa0\xd7\x95\xd7\x91\0" "\xd7\x93\xd7\xa6\xd7\x9e\0" "yyyy. MMMM d. H:mm:ss\0" "yyyy. MMMM d.\0" "yyyy. MM. dd.\0" "yyyy. MMMM\0" "MMMM d.\0" "DE\0" "DU\0" "vas\xc3\xa1rnap\0" "h\xc3\xa9tf\xc5\x91\0" "kedd\0" "szerda\0" "cs\xc3\xbct\xc3\xb6rt\xc3\xb6k\0" "p\xc3\xa9ntek\0" "szombat\0" "H\0" "K\0" "Sze\0" "Cs\0" "P\0" "Szo\0" "janu\xc3\xa1r\0" "febru\xc3\xa1r\0" "m\xc3\xa1rcius\0" "\xc3\xa1prilis\0" "m\xc3\xa1jus\0" "j\xc3\xbanius\0" "j\xc3\xbalius\0" "augusztus\0" "szeptember\0" "okt\xc3\xb3\x62\x65r\0" "jan.\0" "febr.\0" "m\xc3\xa1rc.\0" "\xc3\xa1pr.\0" "m\xc3\xa1j.\0" "j\xc3\xban.\0" "j\xc3\xbal.\0" "aug.\0" "szept.\0" "okt.\0" "dec.\0" "yyyy.MM.dd.\0" "sunnudagur\0" "m\xc3\xa1nudagur\0" "\xc3\xberi\xc3\xb0judagur\0" "mi\xc3\xb0vikudagur\0" "fimmtudagur\0" "f\xc3\xb6studagur\0" "laugardagur\0" "sun\0" "m\xc3\xa1n\0" "\xc3\xberi\0" "mi\xc3\xb0\0" "fim\0" "f\xc3\xb6s\0" "lau\0" "jan\xc3\xba\x61r\0" "febr\xc3\xba\x61r\0" "apr\xc3\xadl\0" "ma\xc3\xad\0" "j\xc3\xban\xc3\xad\0" "j\xc3\xbal\xc3\xad\0" "\xc3\xa1g\xc3\xbast\0" "n\xc3\xb3vember\0" "desember\0" "j\xc3\xban\0" "j\xc3\xbal\0" "\xc3\xa1g\xc3\xba\0" "n\xc3\xb3v\0" "des\0" "dd MMMM yyyy HH:mm:ss z\0" "m.\0" "p.\0" "domenica\0" "luned\xc3\xac\0" "marted\xc3\xac\0" "mercoled\xc3\xac\0" "gioved\xc3\xac\0" "venerd\xc3\xac\0" "sabato\0" "mer\0" "gio\0" "ven\0" "sab\0" "gennaio\0" "febbraio\0" "aprile\0" "maggio\0" "giugno\0" "luglio\0" "settembre\0" "ottobre\0" "dicembre\0" "gen\0" "mag\0" "giu\0" "lug\0" "set\0" "ott\0" "yyyy'\xe5\xb9\xb4'M'\xe6\x9c\x88'd'\xe6\x97\xa5' H:mm:ss\0" "yyyy'\xe5\xb9\xb4'M'\xe6\x9c\x88'd'\xe6\x97\xa5'\0" "yyyy/MM/dd\0" "yyyy'\xe5\xb9\xb4'M'\xe6\x9c\x88'\0" "M'\xe6\x9c\x88'd'\xe6\x97\xa5'\0" "\xe5\x8d\x88\xe5\x89\x8d\0" "\xe5\x8d\x88\xe5\xbe\x8c\0" "\xe6\x97\xa5\xe6\x9b\x9c\xe6\x97\xa5\0" "\xe6\x9c\x88\xe6\x9b\x9c\xe6\x97\xa5\0" "\xe7\x81\xab\xe6\x9b\x9c\xe6\x97\xa5\0" "\xe6\xb0\xb4\xe6\x9b\x9c\xe6\x97\xa5\0" "\xe6\x9c\xa8\xe6\x9b\x9c\xe6\x97\xa5\0" "\xe9\x87\x91\xe6\x9b\x9c\xe6\x97\xa5\0" "\xe5\x9c\x9f\xe6\x9b\x9c\xe6\x97\xa5\0" "\xe6\x9c\x88\0" "\xe7\x81\xab\0" "\xe6\xb0\xb4\0" "\xe6\x9c\xa8\0" "\xe9\x87\x91\0" "\xe5\x9c\x9f\0" "1\xe6\x9c\x88\0" "2\xe6\x9c\x88\0" "3\xe6\x9c\x88\0" "4\xe6\x9c\x88\0" "5\xe6\x9c\x88\0" "6\xe6\x9c\x88\0" "7\xe6\x9c\x88\0" "8\xe6\x9c\x88\0" "9\xe6\x9c\x88\0" "10\xe6\x9c\x88\0" "11\xe6\x9c\x88\0" "12\xe6\x9c\x88\0" "1\0" "2\0" "3\0" "4\0" "5\0" "6\0" "7\0" "8\0" "9\0" "10\0" "11\0" "12\0" "yy/M/d\0" "yyyy/M/d\0" "yy/MM/dd' ('ddd')'\0" "yy/M/d' ('ddd')'\0" "yyyy/M/d' ('ddd')'\0" "yyyy'\xe5\xb9\xb4'MM'\xe6\x9c\x88'dd'\xe6\x97\xa5'\0" "yyyy'\xe5\xb9\xb4'M'\xe6\x9c\x88'd'\xe6\x97\xa5' dddd\0" "yyyy'\xe5\xb9\xb4'MM'\xe6\x9c\x88'dd'\xe6\x97\xa5' dddd\0" "tt h:mm\0" "tt hh:mm\0" "tt h:mm:ss\0" "tt hh:mm:ss\0" "yyyy'\xeb\x85\x84' M'\xec\x9b\x94' d'\xec\x9d\xbc' EE t hh'\xec\x8b\x9c' mm'\xeb\xb6\x84' ss'\xec\xb4\x88'\0" "yyyy'\xeb\x85\x84' M'\xec\x9b\x94' d'\xec\x9d\xbc' EE\0" "yy-MM-dd\0" "t hh'\xec\x8b\x9c' mm'\xeb\xb6\x84' ss'\xec\xb4\x88'\0" "t hh'\xec\x8b\x9c' mm'\xeb\xb6\x84'\0" "yyyy'\xeb\x85\x84' M'\xec\x9b\x94'\0" "M'\xec\x9b\x94' d'\xec\x9d\xbc'\0" "\xec\x98\xa4\xec\xa0\x84\0" "\xec\x98\xa4\xed\x9b\x84\0" "\xec\x9d\xbc\xec\x9a\x94\xec\x9d\xbc\0" "\xec\x9b\x94\xec\x9a\x94\xec\x9d\xbc\0" "\xed\x99\x94\xec\x9a\x94\xec\x9d\xbc\0" "\xec\x88\x98\xec\x9a\x94\xec\x9d\xbc\0" "\xeb\xaa\xa9\xec\x9a\x94\xec\x9d\xbc\0" "\xea\xb8\x88\xec\x9a\x94\xec\x9d\xbc\0" "\xed\x86\xa0\xec\x9a\x94\xec\x9d\xbc\0" "\xec\x9d\xbc\0" "\xec\x9b\x94\0" "\xed\x99\x94\0" "\xec\x88\x98\0" "\xeb\xaa\xa9\0" "\xea\xb8\x88\0" "\xed\x86\xa0\0" "1\xec\x9b\x94\0" "2\xec\x9b\x94\0" "3\xec\x9b\x94\0" "4\xec\x9b\x94\0" "5\xec\x9b\x94\0" "6\xec\x9b\x94\0" "7\xec\x9b\x94\0" "8\xec\x9b\x94\0" "9\xec\x9b\x94\0" "10\xec\x9b\x94\0" "11\xec\x9b\x94\0" "12\xec\x9b\x94\0" "d MMMM yyyy H:mm:ss z\0" "d-M-yy\0" "zondag\0" "maandag\0" "dinsdag\0" "woensdag\0" "donderdag\0" "vrijdag\0" "zaterdag\0" "zo\0" "di\0" "wo\0" "do\0" "vr\0" "za\0" "januari\0" "februari\0" "maart\0" "mei\0" "augustus\0" "mrt\0" "d. MMMM yyyy HH.mm.ss z\0" "HH.mm.ss z\0" "HH.mm\0" "s\xc3\xb8\0" "on\0" "fr\0" "l\xc3\xb8\0" "d MMMM yyyy HH:mm:ss\0" "yyyy-MM-dd\0" "niedziela\0" "poniedzia\xc5\x82\x65k\0" "wtorek\0" "\xc5\x9broda\0" "czwartek\0" "pi\xc4\x85tek\0" "N\0" "Pn\0" "Wt\0" "\xc5\x9ar\0" "Cz\0" "Pt\0" "stycze\xc5\x84\0" "luty\0" "marzec\0" "kwiecie\xc5\x84\0" "czerwiec\0" "lipiec\0" "sierpie\xc5\x84\0" "wrzesie\xc5\x84\0" "pa\xc5\xba\x64ziernik\0" "grudzie\xc5\x84\0" "sty\0" "lut\0" "kwi\0" "cze\0" "lip\0" "sie\0" "wrz\0" "pa\xc5\xba\0" "lis\0" "gru\0" "d' de 'MMMM' de 'yyyy HH:mm:ss z\0" "segunda-feira\0" "ter\xc3\xa7\x61-feira\0" "quarta-feira\0" "quinta-feira\0" "sexta-feira\0" "seg\0" "ter\0" "qua\0" "qui\0" "sex\0" "janeiro\0" "fevereiro\0" "mar\xc3\xa7o\0" "maio\0" "junho\0" "julho\0" "setembro\0" "outubro\0" "novembro\0" "dezembro\0" "fev\0" "out\0" "dez\0" "duminic\xc4\x83\0" "luni\0" "mar\xc5\xa3i\0" "miercuri\0" "joi\0" "vineri\0" "s\xc3\xaemb\xc4\x83t\xc4\x83\0" "D\0" "L\0" "Ma\0" "J\0" "S\0" "ianuarie\0" "februarie\0" "martie\0" "aprilie\0" "iunie\0" "iulie\0" "septembrie\0" "octombrie\0" "noiembrie\0" "decembrie\0" "Ian\0" "Iun\0" "Iul\0" "d MMMM yyyy '\xd0\xb3.' H:mm:ss\0" "d MMMM yyyy '\xd0\xb3.'\0" "MMMM yyyy '\xd0\xb3.'\0" "\xd0\xb2\xd0\xbe\xd1\x81\xd0\xba\xd1\x80\xd0\xb5\xd1\x81\xd0\xb5\xd0\xbd\xd1\x8c\xd0\xb5\0" "\xd0\xbf\xd0\xbe\xd0\xbd\xd0\xb5\xd0\xb4\xd0\xb5\xd0\xbb\xd1\x8c\xd0\xbd\xd0\xb8\xd0\xba\0" "\xd1\x81\xd1\x80\xd0\xb5\xd0\xb4\xd0\xb0\0" "\xd1\x87\xd0\xb5\xd1\x82\xd0\xb2\xd0\xb5\xd1\x80\xd0\xb3\0" "\xd0\xbf\xd1\x8f\xd1\x82\xd0\xbd\xd0\xb8\xd1\x86\xd0\xb0\0" "\xd1\x81\xd1\x83\xd0\xb1\xd0\xb1\xd0\xbe\xd1\x82\xd0\xb0\0" "\xd0\x92\xd1\x81\0" "\xd0\x9f\xd0\xbd\0" "\xd0\x92\xd1\x82\0" "\xd0\xa1\xd1\x80\0" "\xd0\xa7\xd1\x82\0" "\xd0\x9f\xd1\x82\0" "\xd0\xa1\xd0\xb1\0" "\xd0\xaf\xd0\xbd\xd0\xb2\xd0\xb0\xd1\x80\xd1\x8c\0" "\xd0\xa4\xd0\xb5\xd0\xb2\xd1\x80\xd0\xb0\xd0\xbb\xd1\x8c\0" "\xd0\x9c\xd0\xb0\xd1\x80\xd1\x82\0" "\xd0\x90\xd0\xbf\xd1\x80\xd0\xb5\xd0\xbb\xd1\x8c\0" "\xd0\x9c\xd0\xb0\xd0\xb9\0" "\xd0\x98\xd1\x8e\xd0\xbd\xd1\x8c\0" "\xd0\x98\xd1\x8e\xd0\xbb\xd1\x8c\0" "\xd0\x90\xd0\xb2\xd0\xb3\xd1\x83\xd1\x81\xd1\x82\0" "\xd0\xa1\xd0\xb5\xd0\xbd\xd1\x82\xd1\x8f\xd0\xb1\xd1\x80\xd1\x8c\0" "\xd0\x9e\xd0\xba\xd1\x82\xd1\x8f\xd0\xb1\xd1\x80\xd1\x8c\0" "\xd0\x9d\xd0\xbe\xd1\x8f\xd0\xb1\xd1\x80\xd1\x8c\0" "\xd0\x94\xd0\xb5\xd0\xba\xd0\xb0\xd0\xb1\xd1\x80\xd1\x8c\0" "\xd1\x8f\xd0\xbd\xd0\xb2\0" "\xd1\x84\xd0\xb5\xd0\xb2\0" "\xd0\xbc\xd0\xb0\xd1\x80\0" "\xd0\xb0\xd0\xbf\xd1\x80\0" "\xd0\xb8\xd1\x8e\xd0\xbd\0" "\xd0\xb8\xd1\x8e\xd0\xbb\0" "\xd0\xb0\xd0\xb2\xd0\xb3\0" "\xd1\x81\xd0\xb5\xd0\xbd\0" "\xd0\xbe\xd0\xba\xd1\x82\0" "\xd0\xbd\xd0\xbe\xd1\x8f\0" "\xd0\xb4\xd0\xb5\xd0\xba\0" "yyyy. MMMM dd H:mm:ss\0" "yyyy. MMMM dd\0" "nedjelja\0" "ponedjeljak\0" "utorak\0" "srijeda\0" "\xc4\x8d\x65tvrtak\0" "petak\0" "subota\0" "ned\0" "pon\0" "uto\0" "sri\0" "\xc4\x8d\x65t\0" "pet\0" "sub\0" "sije\xc4\x8d\x61nj\0" "velja\xc4\x8d\x61\0" "o\xc5\xbeujak\0" "travanj\0" "svibanj\0" "lipanj\0" "srpanj\0" "kolovoz\0" "rujan\0" "studeni\0" "prosinac\0" "sij\0" "vel\0" "o\xc5\xbeu\0" "tra\0" "svi\0" "srp\0" "kol\0" "ruj\0" "stu\0" "pro\0" "yyyy.MM.dd\0" "d. MMMM yyyy H:mm:ss\0" "d. M. yyyy\0" "Nede\xc4\xbe\x61\0" "Pondelok\0" "Utorok\0" "Streda\0" "\xc5\xa0tvrtok\0" "Piatok\0" "Sobota\0" "Ne\0" "Po\0" "Ut\0" "St\0" "\xc5\xa0t\0" "Pi\0" "marec\0" "m\xc3\xa1j\0" "dd MMMM yyyy h:mm:ss.tt\0" "h:mm:ss.tt\0" "h.mm.t\0" "PD\0" "MD\0" "e diel\0" "e h\xc3\xabn\xc3\xab\0" "e mart\xc3\xab\0" "e m\xc3\xabrkur\xc3\xab\0" "e enjte\0" "e premte\0" "e shtun\xc3\xab\0" "Die\0" "H\xc3\xabn\0" "M\xc3\xabr\0" "Enj\0" "Pre\0" "Sht\0" "janar\0" "shkurt\0" "prill\0" "qershor\0" "korrik\0" "gusht\0" "shtator\0" "tetor\0" "n\xc3\xabntor\0" "dhjetor\0" "Shk\0" "Pri\0" "Maj\0" "Qer\0" "Kor\0" "Gsh\0" "Tet\0" "N\xc3\xabn\0" "Dhj\0" "h.mm.ss.t z\0" "'den 'd MMM yyyy HH.mm.ss z\0" "'den 'd MMM yyyy\0" "fm\0" "em\0" "s\xc3\xb6ndag\0" "m\xc3\xa5ndag\0" "tisdag\0" "l\xc3\xb6rdag\0" "s\xc3\xb6\0" "m\xc3\xa5\0" "l\xc3\xb6\0" "augusti\0" "d MMMM yyyy, H:mm:ss\0" "\xe0\xb8\x81\xe0\xb9\x88\xe0\xb8\xad\xe0\xb8\x99\xe0\xb9\x80\xe0\xb8\x97\xe0\xb8\xb5\xe0\xb9\x88\xe0\xb8\xa2\xe0\xb8\x87\0" "\xe0\xb8\xab\xe0\xb8\xa5\xe0\xb8\xb1\xe0\xb8\x87\xe0\xb9\x80\xe0\xb8\x97\xe0\xb8\xb5\xe0\xb9\x88\xe0\xb8\xa2\xe0\xb8\x87\0" "\xe0\xb8\xa7\xe0\xb8\xb1\xe0\xb8\x99\xe0\xb8\xad\xe0\xb8\xb2\xe0\xb8\x97\xe0\xb8\xb4\xe0\xb8\x95\xe0\xb8\xa2\xe0\xb9\x8c\0" "\xe0\xb8\xa7\xe0\xb8\xb1\xe0\xb8\x99\xe0\xb8\x88\xe0\xb8\xb1\xe0\xb8\x99\xe0\xb8\x97\xe0\xb8\xa3\xe0\xb9\x8c\0" "\xe0\xb8\xa7\xe0\xb8\xb1\xe0\xb8\x99\xe0\xb8\xad\xe0\xb8\xb1\xe0\xb8\x87\xe0\xb8\x84\xe0\xb8\xb2\xe0\xb8\xa3\0" "\xe0\xb8\xa7\xe0\xb8\xb1\xe0\xb8\x99\xe0\xb8\x9e\xe0\xb8\xb8\xe0\xb8\x98\0" "\xe0\xb8\xa7\xe0\xb8\xb1\xe0\xb8\x99\xe0\xb8\x9e\xe0\xb8\xa4\xe0\xb8\xab\xe0\xb8\xb1\xe0\xb8\xaa\xe0\xb8\x9a\xe0\xb8\x94\xe0\xb8\xb5\0" "\xe0\xb8\xa7\xe0\xb8\xb1\xe0\xb8\x99\xe0\xb8\xa8\xe0\xb8\xb8\xe0\xb8\x81\xe0\xb8\xa3\xe0\xb9\x8c\0" "\xe0\xb8\xa7\xe0\xb8\xb1\xe0\xb8\x99\xe0\xb9\x80\xe0\xb8\xaa\xe0\xb8\xb2\xe0\xb8\xa3\xe0\xb9\x8c\0" "\xe0\xb8\xad\xe0\xb8\xb2.\0" "\xe0\xb8\x88.\0" "\xe0\xb8\xad.\0" "\xe0\xb8\x9e.\0" "\xe0\xb8\x9e\xe0\xb8\xa4.\0" "\xe0\xb8\xa8.\0" "\xe0\xb8\xaa.\0" "\xe0\xb8\xa1\xe0\xb8\x81\xe0\xb8\xa3\xe0\xb8\xb2\xe0\xb8\x84\xe0\xb8\xa1\0" "\xe0\xb8\x81\xe0\xb8\xb8\xe0\xb8\xa1\xe0\xb8\xa0\xe0\xb8\xb2\xe0\xb8\x9e\xe0\xb8\xb1\xe0\xb8\x99\xe0\xb8\x98\xe0\xb9\x8c\0" "\xe0\xb8\xa1\xe0\xb8\xb5\xe0\xb8\x99\xe0\xb8\xb2\xe0\xb8\x84\xe0\xb8\xa1\0" "\xe0\xb9\x80\xe0\xb8\xa1\xe0\xb8\xa9\xe0\xb8\xb2\xe0\xb8\xa2\xe0\xb8\x99\0" "\xe0\xb8\x9e\xe0\xb8\xa4\xe0\xb8\xa9\xe0\xb8\xa0\xe0\xb8\xb2\xe0\xb8\x84\xe0\xb8\xa1\0" "\xe0\xb8\xa1\xe0\xb8\xb4\xe0\xb8\x96\xe0\xb8\xb8\xe0\xb8\x99\xe0\xb8\xb2\xe0\xb8\xa2\xe0\xb8\x99\0" "\xe0\xb8\x81\xe0\xb8\xa3\xe0\xb8\x81\xe0\xb8\x8e\xe0\xb8\xb2\xe0\xb8\x84\xe0\xb8\xa1\0" "\xe0\xb8\xaa\xe0\xb8\xb4\xe0\xb8\x87\xe0\xb8\xab\xe0\xb8\xb2\xe0\xb8\x84\xe0\xb8\xa1\0" "\xe0\xb8\x81\xe0\xb8\xb1\xe0\xb8\x99\xe0\xb8\xa2\xe0\xb8\xb2\xe0\xb8\xa2\xe0\xb8\x99\0" "\xe0\xb8\x95\xe0\xb8\xb8\xe0\xb8\xa5\xe0\xb8\xb2\xe0\xb8\x84\xe0\xb8\xa1\0" "\xe0\xb8\x9e\xe0\xb8\xa4\xe0\xb8\xa8\xe0\xb8\x88\xe0\xb8\xb4\xe0\xb8\x81\xe0\xb8\xb2\xe0\xb8\xa2\xe0\xb8\x99\0" "\xe0\xb8\x98\xe0\xb8\xb1\xe0\xb8\x99\xe0\xb8\xa7\xe0\xb8\xb2\xe0\xb8\x84\xe0\xb8\xa1\0" "\xe0\xb8\xa1.\xe0\xb8\x84.\0" "\xe0\xb8\x81.\xe0\xb8\x9e.\0" "\xe0\xb8\xa1\xe0\xb8\xb5.\xe0\xb8\x84.\0" "\xe0\xb9\x80\xe0\xb8\xa1.\xe0\xb8\xa2.\0" "\xe0\xb8\x9e.\xe0\xb8\x84.\0" "\xe0\xb8\xa1\xe0\xb8\xb4.\xe0\xb8\xa2.\0" "\xe0\xb8\x81.\xe0\xb8\x84.\0" "\xe0\xb8\xaa.\xe0\xb8\x84.\0" "\xe0\xb8\x81.\xe0\xb8\xa2.\0" "\xe0\xb8\x95.\xe0\xb8\x84.\0" "\xe0\xb8\x9e.\xe0\xb8\xa2.\0" "\xe0\xb8\x98.\xe0\xb8\x84.\0" "H' \xe0\xb8\x99\xe0\xb8\xb2\xe0\xb8\xac\xe0\xb8\xb4\xe0\xb8\x81\xe0\xb8\xb2 'm' \xe0\xb8\x99\xe0\xb8\xb2\xe0\xb8\x97\xe0\xb8\xb5'\0" "dd MMMM yyyy EEEE HH:mm:ss\0" "dd MMMM yyyy EEEE\0" "Pazar\0" "Pazartesi\0" "Sal\xc4\xb1\0" "\xc3\x87\x61r\xc5\x9f\x61mba\0" "Per\xc5\x9f\x65mbe\0" "Cuma\0" "Cumartesi\0" "Paz\0" "Pzt\0" "Sal\0" "\xc3\x87\x61r\0" "Per\0" "Cum\0" "Cmt\0" "Ocak\0" "\xc5\x9eubat\0" "Mart\0" "Nisan\0" "May\xc4\xb1s\0" "Haziran\0" "Temmuz\0" "A\xc4\x9fustos\0" "Eyl\xc3\xbcl\0" "Ekim\0" "Kas\xc4\xb1m\0" "Aral\xc4\xb1k\0" "Oca\0" "\xc5\x9eub\0" "Nis\0" "Haz\0" "Tem\0" "A\xc4\x9fu\0" "Eyl\0" "Eki\0" "Kas\0" "Ara\0" "Minggu\0" "Senin\0" "Selasa\0" "Rabu\0" "Kamis\0" "Jumat\0" "Sabtu\0" "Min\0" "Sen\0" "Sel\0" "Rab\0" "Kam\0" "Jum\0" "Sab\0" "Januari\0" "Februari\0" "Maret\0" "Mei\0" "Agustus\0" "Desember\0" "Agu\0" "Des\0" "d MMMM yyyy H:mm:ss\0" "MMMM yyyy '\xd1\x80.'\0" "\xd0\x9d\xd0\xb5\xd0\xb4\xd1\x96\xd0\xbb\xd1\x8f\0" "\xd0\x9f\xd0\xbe\xd0\xbd\xd0\xb5\xd0\xb4\xd1\x96\xd0\xbb\xd0\xbe\xd0\xba\0" "\xd0\x92\xd1\x96\xd0\xb2\xd1\x82\xd0\xbe\xd1\x80\xd0\xbe\xd0\xba\0" "\xd0\xa1\xd0\xb5\xd1\x80\xd0\xb5\xd0\xb4\xd0\xb0\0" "\xd0\xa7\xd0\xb5\xd1\x82\xd0\xb2\xd0\xb5\xd1\x80\0" "\xd0\x9f'\xd1\x8f\xd1\x82\xd0\xbd\xd0\xb8\xd1\x86\xd1\x8f\0" "\xd0\xa1\xd1\x83\xd0\xb1\xd0\xbe\xd1\x82\xd0\xb0\0" "\xd0\x9d\xd0\xb4\0" "\xd1\x81\xd1\x96\xd1\x87\xd0\xbd\xd1\x8f\0" "\xd0\xbb\xd1\x8e\xd1\x82\xd0\xbe\xd0\xb3\xd0\xbe\0" "\xd0\xb1\xd0\xb5\xd1\x80\xd0\xb5\xd0\xb7\xd0\xbd\xd1\x8f\0" "\xd0\xba\xd0\xb2\xd1\x96\xd1\x82\xd0\xbd\xd1\x8f\0" "\xd1\x82\xd1\x80\xd0\xb0\xd0\xb2\xd0\xbd\xd1\x8f\0" "\xd1\x87\xd0\xb5\xd1\x80\xd0\xb2\xd0\xbd\xd1\x8f\0" "\xd0\xbb\xd0\xb8\xd0\xbf\xd0\xbd\xd1\x8f\0" "\xd1\x81\xd0\xb5\xd1\x80\xd0\xbf\xd0\xbd\xd1\x8f\0" "\xd0\xb2\xd0\xb5\xd1\x80\xd0\xb5\xd1\x81\xd0\xbd\xd1\x8f\0" "\xd0\xb6\xd0\xbe\xd0\xb2\xd1\x82\xd0\xbd\xd1\x8f\0" "\xd0\xbb\xd0\xb8\xd1\x81\xd1\x82\xd0\xbe\xd0\xbf\xd0\xb0\xd0\xb4\xd0\xb0\0" "\xd0\xb3\xd1\x80\xd1\x83\xd0\xb4\xd0\xbd\xd1\x8f\0" "\xd1\x81\xd1\x96\xd1\x87\0" "\xd0\xbb\xd1\x8e\xd1\x82\0" "\xd0\xb1\xd0\xb5\xd1\x80\0" "\xd0\xba\xd0\xb2\xd1\x96\xd1\x82\0" "\xd1\x82\xd1\x80\xd0\xb0\xd0\xb2\0" "\xd1\x87\xd0\xb5\xd1\x80\xd0\xb2\0" "\xd0\xbb\xd0\xb8\xd0\xbf\0" "\xd1\x81\xd0\xb5\xd1\x80\xd0\xbf\0" "\xd0\xb2\xd0\xb5\xd1\x80\0" "\xd0\xb6\xd0\xbe\xd0\xb2\xd1\x82\0" "\xd0\xbb\xd0\xb8\xd1\x81\xd1\x82\0" "\xd0\xb3\xd1\x80\xd1\x83\xd0\xb4\0" "d MMMM yyyy HH.mm.ss z\0" "\xd0\xbd\xd1\x8f\xd0\xb4\xd0\xb7\xd0\xb5\xd0\xbb\xd1\x8f\0" "\xd0\xbf\xd0\xb0\xd0\xbd\xd1\x8f\xd0\xb4\xd0\xb7\xd0\xb5\xd0\xbb\xd0\xb0\xd0\xba\0" "\xd0\xb0\xd1\x9e\xd1\x82\xd0\xbe\xd1\x80\xd0\xb0\xd0\xba\0" "\xd1\x81\xd0\xb5\xd1\x80\xd0\xb0\xd0\xb4\xd0\xb0\0" "\xd1\x87\xd0\xb0\xd1\x86\xd0\xb2\xd0\xb5\xd1\x80\0" "\xd0\xbf\xd1\x8f\xd1\x82\xd0\xbd\xd1\x96\xd1\x86\xd0\xb0\0" "\xd1\x81\xd1\x83\xd0\xb1\xd0\xbe\xd1\x82\xd0\xb0\0" "\xd0\xbd\xd0\xb4\0" "\xd0\xbf\xd0\xbd\0" "\xd0\xb0\xd1\x9e\0" "\xd1\x81\xd1\x80\0" "\xd1\x87\xd1\x86\0" "\xd0\xbf\xd1\x82\0" "\xd1\x81\xd0\xb1\0" "\xd1\x81\xd1\x82\xd1\x83\xd0\xb4\xd0\xb7\xd0\xb5\xd0\xbd\xd1\x8c\0" "\xd0\xbb\xd1\x8e\xd1\x82\xd1\x8b\0" "\xd1\x81\xd0\xb0\xd0\xba\xd0\xb0\xd0\xb2\xd1\x96\xd0\xba\0" "\xd0\xba\xd1\x80\xd0\xb0\xd1\x81\xd0\xb0\xd0\xb2\xd1\x96\xd0\xba\0" "\xd1\x87\xd1\x8d\xd1\x80\xd0\xb2\xd0\xb5\xd0\xbd\xd1\x8c\0" "\xd0\xbb\xd1\x96\xd0\xbf\xd0\xb5\xd0\xbd\xd1\x8c\0" "\xd0\xb6\xd0\xbd\xd1\x96\xd0\xb2\xd0\xb5\xd0\xbd\xd1\x8c\0" "\xd0\xb2\xd0\xb5\xd1\x80\xd0\xb0\xd1\x81\xd0\xb5\xd0\xbd\xd1\x8c\0" "\xd0\xba\xd0\xb0\xd1\x81\xd1\x82\xd1\x80\xd1\x8b\xd1\x87\xd0\xbd\xd1\x96\xd0\xba\0" "\xd0\xbb\xd1\x96\xd1\x81\xd1\x82\xd0\xb0\xd0\xbf\xd0\xb0\xd0\xb4\0" "\xd1\x81\xd0\xbd\xd0\xb5\xd0\xb6\xd0\xb0\xd0\xbd\xd1\x8c\0" "\xd1\x81\xd1\x82\xd1\x83\0" "\xd1\x81\xd0\xb0\xd0\xba\0" "\xd0\xba\xd1\x80\xd0\xb0\0" "\xd1\x87\xd1\x8d\xd1\x80\0" "\xd0\xbb\xd1\x96\xd0\xbf\0" "\xd0\xb6\xd0\xbd\xd1\x96\0" "\xd0\xba\xd0\xb0\xd1\x81\0" "\xd0\xbb\xd1\x96\xd1\x81\0" "\xd1\x81\xd0\xbd\xd0\xb5\0" "dd. MMMM yyyy H:mm:ss\0" "dd. MMMM yyyy\0" "nedelja\0" "ponedeljek\0" "torek\0" "sreda\0" "\xc4\x8d\x65trtek\0" "petek\0" "sre\0" "sob\0" "junij\0" "julij\0" "avgust\0" "avg\0" "yy.M.d\0" "d.MM.yyyy\0" "d, MMMM\0" "p\xc3\xbchap\xc3\xa4\x65v\0" "esmasp\xc3\xa4\x65v\0" "teisip\xc3\xa4\x65v\0" "kolmap\xc3\xa4\x65v\0" "neljap\xc3\xa4\x65v\0" "reede\0" "laup\xc3\xa4\x65v\0" "E\0" "T\0" "R\0" "jaanuar\0" "veebruar\0" "m\xc3\xa4rts\0" "aprill\0" "juuni\0" "juuli\0" "oktoober\0" "detsember\0" "jaan\0" "veebr\0" "sept\0" "dets\0" "yyyy'. gada 'd. MMMM H:mm:ss\0" "yyyy'. gada 'd. MMMM\0" "yyyy'. gada 'MMMM\0" "sv\xc4\x93tdiena\0" "pirmdiena\0" "otrdiena\0" "tre\xc5\xa1\x64iena\0" "ceturtdiena\0" "piektdiena\0" "sestdiena\0" "Sv\0" "O\0" "C\0" "Pk\0" "janv\xc4\x81ris\0" "febru\xc4\x81ris\0" "apr\xc4\xablis\0" "maijs\0" "j\xc5\xabnijs\0" "j\xc5\xablijs\0" "augusts\0" "septembris\0" "oktobris\0" "novembris\0" "decembris\0" "J\xc5\xabn\0" "J\xc5\xabl\0" "yy.d.M\0" "yyyy 'm.' MMMM d 'd.' HH:mm:ss z\0" "yyyy 'm.' MMMM d 'd.'\0" "yyyy 'm.' MMMM\0" "MMMM d 'd.'\0" "Sekmadienis\0" "Pirmadienis\0" "Antradienis\0" "Tre\xc4\x8diadienis\0" "Ketvirtadienis\0" "Penktadienis\0" "\xc5\xa0\x65\xc5\xa1tadienis\0" "Sk\0" "Pr\0" "An\0" "Tr\0" "Kt\0" "Sausio\0" "Vasario\0" "Kovo\0" "Baland\xc5\xbeio\0" "Gegu\xc5\xbe\xc4\x97s\0" "Bir\xc5\xbe\x65lio\0" "Liepos\0" "Rugpj\xc5\xab\xc4\x8dio\0" "Rugs\xc4\x97jo\0" "Spalio\0" "Lapkri\xc4\x8dio\0" "Gruod\xc5\xbeio\0" "Sau\0" "Vas\0" "Kov\0" "Bal\0" "Geg\0" "Bir\0" "Lie\0" "Rgp\0" "Rgs\0" "Spa\0" "Lap\0" "Grd\0" "d MMMM yyyy hh:mm:ss tt\0" "M/d/yyyy\0" "\xd9\x82.\xd8\xb8.\0" "\xd8\xa8.\xd8\xb8.\0" "\xdb\x8c\xda\xa9\xe2\x80\x8c\xd8\xb4\xd9\x86\xd8\xa8\xd9\x87\0" "\xd8\xaf\xd9\x88\xd8\xb4\xd9\x86\xd8\xa8\xd9\x87\0" "\xd8\xb3\xd9\x87\xe2\x80\x8c\xd8\xb4\xd9\x86\xd8\xa8\xd9\x87\0" "\xda\x86\xd9\x87\xd8\xa7\xd8\xb1\xd8\xb4\xd9\x86\xd8\xa8\xd9\x87\0" "\xd9\xbe\xd9\x86\xd8\xac\xe2\x80\x8c\xd8\xb4\xd9\x86\xd8\xa8\xd9\x87\0" "\xd8\xac\xd9\x85\xd8\xb9\xd9\x87\0" "\xd8\xb4\xd9\x86\xd8\xa8\xd9\x87\0" "\xdb\x8c.\0" "\xd8\xaf.\0" "\xd8\xb3.\0" "\xda\x86.\0" "\xd9\xbe.\0" "\xd8\xac.\0" "\xd8\xb4.\0" "\xda\x98\xd8\xa7\xd9\x86\xd9\x88\xdb\x8c\xd9\x87\0" "\xd9\x81\xd9\x88\xd8\xb1\xdb\x8c\xd9\x87\0" "\xd8\xa2\xd9\x88\xd8\xb1\xdb\x8c\xd9\x84\0" "\xd9\x85\xd9\x87\0" "\xda\x98\xd9\x88\xd8\xa6\xd9\x86\0" "\xda\x98\xd9\x88\xd8\xa6\xdb\x8c\xd9\x87\0" "\xd8\xa7\xd9\x88\xd8\xaa\0" "\xd8\xb3\xd9\xbe\xd8\xaa\xd8\xa7\xd9\x85\xd8\xa8\xd8\xb1\0" "\xd8\xa7\xda\xa9\xd8\xaa\xd8\xa8\xd8\xb1\0" "\xd9\x86\xd9\x88\xd8\xa7\xd9\x85\xd8\xa8\xd8\xb1\0" "\xd8\xaf\xd8\xb3\xd8\xa7\xd9\x85\xd8\xa8\xd8\xb1\0" "\xda\x98\xd8\xa7\xd9\x86\0" "\xd9\x81\xd9\x88\xd8\xb1\0" "\xd9\x85\xd8\xa7\xd8\xb1\0" "\xd8\xa2\xd9\x88\xd8\xb1\0" "\xd9\x85\xd9\x80\xd9\x87\0" "\xda\x98\xd9\x88\xd9\x86\0" "\xda\x98\xd9\x88\xdb\x8c\0" "\xd8\xb3\xd9\xbe\xd8\xaa\0" "\xd8\xa7\xda\xa9\xd8\xaa\0" "\xd9\x86\xd9\x88\xd8\xa7\0" "\xd8\xaf\xd8\xb3\xd8\xa7\0" "yyyy/MM/d\0" "HH:mm:ss (z)\0" "h:mm:ss tt dd MMMM yyyy\0" "SA\0" "CH\0" "Ch\xe1\xbb\xa7 nh\xe1\xba\xadt\0" "Th\xe1\xbb\xa9 hai\0" "Th\xe1\xbb\xa9 ba\0" "Th\xe1\xbb\xa9 t\xc6\xb0\0" "Th\xe1\xbb\xa9 n\xc4\x83m\0" "Th\xe1\xbb\xa9 s\xc3\xa1u\0" "Th\xe1\xbb\xa9 b\xe1\xba\xa3y\0" "CN\0" "Th 2\0" "Th 3\0" "Th 4\0" "Th 5\0" "Th 6\0" "Th 7\0" "Th\xc3\xa1ng m\xe1\xbb\x99t\0" "Th\xc3\xa1ng hai\0" "Th\xc3\xa1ng ba\0" "Th\xc3\xa1ng t\xc6\xb0\0" "Th\xc3\xa1ng n\xc4\x83m\0" "Th\xc3\xa1ng s\xc3\xa1u\0" "Th\xc3\xa1ng b\xe1\xba\xa3y\0" "Th\xc3\xa1ng t\xc3\xa1m\0" "Th\xc3\xa1ng ch\xc3\xadn\0" "Th\xc3\xa1ng m\xc6\xb0\xe1\xbb\x9di\0" "Th\xc3\xa1ng m\xc6\xb0\xe1\xbb\x9di m\xe1\xbb\x99t\0" "Th\xc3\xa1ng m\xc6\xb0\xe1\xbb\x9di hai\0" "Thg 1\0" "Thg 2\0" "Thg 3\0" "Thg 4\0" "Thg 5\0" "Thg 6\0" "Thg 7\0" "Thg 8\0" "Thg 9\0" "Thg 10\0" "Thg 11\0" "Thg 12\0" "MMMM dd, yyyy H:mm:ss\0" "\xd4\xb1\xd5\xbc\xe2\x80\xa4\0" "\xd4\xb5\xd6\x80\xe2\x80\xa4\0" "\xd4\xbf\xd5\xab\xd6\x80\xd5\xa1\xd5\xaf\xd5\xab\0" "\xd4\xb5\xd6\x80\xd5\xaf\xd5\xb8\xd6\x82\xd5\xb7\xd5\xa1\xd5\xa2\xd5\xa9\xd5\xab\0" "\xd4\xb5\xd6\x80\xd5\xa5\xd6\x84\xd5\xb7\xd5\xa1\xd5\xa2\xd5\xa9\xd5\xab\0" "\xd5\x89\xd5\xb8\xd6\x80\xd5\xa5\xd6\x84\xd5\xb7\xd5\xa1\xd5\xa2\xd5\xa9\xd5\xab\0" "\xd5\x80\xd5\xab\xd5\xb6\xd5\xa3\xd5\xb7\xd5\xa1\xd5\xa2\xd5\xa9\xd5\xab\0" "\xd5\x88\xd6\x82\xd6\x80\xd5\xa2\xd5\xa1\xd5\xa9\0" "\xd5\x87\xd5\xa1\xd5\xa2\xd5\xa1\xd5\xa9\0" "\xd4\xbf\xd5\xab\xd6\x80\0" "\xd4\xb5\xd6\x80\xd5\xaf\0" "\xd4\xb5\xd6\x80\xd6\x84\0" "\xd5\x89\xd5\xb8\xd6\x80\0" "\xd5\x80\xd5\xb6\xd5\xa3\0" "\xd5\x88\xd6\x82\xd6\x80\0" "\xd5\x87\xd5\xa1\xd5\xa2\0" "\xd5\x85\xd5\xb8\xd6\x82\xd5\xb6\xd5\xb8\xd6\x82\xd5\xa1\xd6\x80\0" "\xd5\x93\xd5\xa5\xd5\xbf\xd6\x80\xd5\xb8\xd6\x82\xd5\xa1\xd6\x80\0" "\xd5\x84\xd5\xa1\xd6\x80\xd5\xbf\0" "\xd4\xb1\xd5\xba\xd6\x80\xd5\xab\xd5\xac\0" "\xd5\x84\xd5\xa1\xd5\xb5\xd5\xab\xd5\xbd\0" "\xd5\x85\xd5\xb8\xd6\x82\xd5\xb6\xd5\xab\xd5\xbd\0" "\xd5\x85\xd5\xb8\xd6\x82\xd5\xac\xd5\xab\xd5\xbd\0" "\xd5\x95\xd5\xa3\xd5\xb8\xd5\xbd\xd5\xbf\xd5\xb8\xd5\xbd\0" "\xd5\x8d\xd5\xa5\xd5\xba\xd5\xbf\xd5\xa5\xd5\xb4\xd5\xa2\xd5\xa5\xd6\x80\0" "\xd5\x80\xd5\xb8\xd5\xaf\xd5\xbf\xd5\xa5\xd5\xb4\xd5\xa2\xd5\xa5\xd6\x80\0" "\xd5\x86\xd5\xb8\xd5\xb5\xd5\xa5\xd5\xb4\xd5\xa2\xd5\xa5\xd6\x80\0" "\xd4\xb4\xd5\xa5\xd5\xaf\xd5\xbf\xd5\xa5\xd5\xb4\xd5\xa2\xd5\xa5\xd6\x80\0" "\xd5\x85\xd5\xb6\xd6\x80\0" "\xd5\x93\xd5\xbf\xd6\x80\0" "\xd5\x84\xd6\x80\xd5\xbf\0" "\xd4\xb1\xd5\xba\xd6\x80\0" "\xd5\x84\xd5\xb5\xd5\xbd\0" "\xd5\x85\xd5\xb6\xd5\xbd\0" "\xd5\x85\xd5\xac\xd5\xbd\0" "\xd5\x95\xd5\xa3\xd5\xbd\0" "\xd5\x8d\xd5\xa5\xd5\xba\0" "\xd5\x80\xd5\xb8\xd5\xaf\0" "\xd5\x86\xd5\xb8\xd5\xb5\0" "\xd4\xb4\xd5\xa5\xd5\xaf\0" "MM/dd/yy\0" "igandea\0" "astelehena\0" "asteartea\0" "asteazkena\0" "osteguna\0" "ostirala\0" "larunbata\0" "ig\0" "al\0" "as\0" "az\0" "og\0" "or\0" "lr\0" "urtarrila\0" "otsaila\0" "martxoa\0" "apirila\0" "maiatza\0" "ekaina\0" "uztaila\0" "abuztua\0" "iraila\0" "urria\0" "azaroa\0" "abendua\0" "urt\0" "ots\0" "api\0" "eka\0" "uzt\0" "abu\0" "ira\0" "urr\0" "aza\0" "abe\0" "\xd0\xbd\xd0\xb5\xd0\xb4\xd0\xb5\xd0\xbb\xd0\xb0\0" "\xd1\x87\xd0\xb5\xd1\x82\xd0\xb2\xd1\x80\xd1\x82\xd0\xbe\xd0\xba\0" "\xd0\xbf\xd0\xb5\xd1\x82\xd0\xbe\xd0\xba\0" "\xd1\x81\xd0\xb0\xd0\xb1\xd0\xbe\xd1\x82\xd0\xb0\0" "\xd1\x81\xd1\x80\xd0\xb5.\0" "\xd1\x87\xd0\xb5\xd1\x82.\0" "\xd1\x81\xd0\xb0\xd0\xb1.\0" "\xd1\x98\xd0\xb0\xd0\xbd\xd1\x83\xd0\xb0\xd1\x80\xd0\xb8\0" "\xd0\xbc\xd0\xb0\xd1\x98\0" "\xd1\x98\xd1\x83\xd0\xbd\xd0\xb8\0" "\xd1\x98\xd1\x83\xd0\xbb\xd0\xb8\0" "\xd1\x98\xd0\xb0\xd0\xbd.\0" "\xd0\xbc\xd0\xb0\xd1\x80.\0" "\xd0\xbc\xd0\xb0\xd1\x98.\0" "\xd1\x98\xd1\x83\xd0\xbd.\0" "\xd1\x98\xd1\x83\xd0\xbb.\0" "\xd1\x81\xd0\xb5\xd0\xbf\xd1\x82.\0" "\xd0\xb4\xd0\xb5\xd0\xba\xd0\xb5\xd0\xbc.\0" "dd.M.yy\0" "VM\0" "NM\0" "Sondag\0" "Maandag\0" "Dinsdag\0" "Woensdag\0" "Donderdag\0" "Vrydag\0" "Saterdag\0" "Wo\0" "Vr\0" "Januarie\0" "Februarie\0" "Maart\0" "Junie\0" "Julie\0" "Augustus\0" "y MMMM d HH:mm:ss z\0" "y MMMM d\0" "y MMMM\0" "\xe1\x83\x93\xe1\x83\x98\xe1\x83\x9a\xe1\x83\x98\xe1\x83\xa1\0" "\xe1\x83\xa1\xe1\x83\x90\xe1\x83\xa6\xe1\x83\x90\xe1\x83\x9b\xe1\x83\x9d\xe1\x83\xa1\0" "d. MMM yyyy HH:mm:ss z\0" "m\xc3\xa1nadagur\0" "t\xc3\xbdsdagur\0" "mikudagur\0" "h\xc3\xb3sdagur\0" "fr\xc3\xadggjadagur\0" "leygardagur\0" "t\xc3\xbds\0" "mik\0" "h\xc3\xb3s\0" "fr\xc3\xad\0" "ley\0" "\xe0\xa4\xaa\xe0\xa5\x82\xe0\xa4\xb0\xe0\xa5\x8d\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb9\xe0\xa5\x8d\xe0\xa4\xa8\0" "\xe0\xa4\x85\xe0\xa4\xaa\xe0\xa4\xb0\xe0\xa4\xbe\xe0\xa4\xb9\xe0\xa5\x8d\xe0\xa4\xa8\0" "\xe0\xa4\xb0\xe0\xa4\xb5\xe0\xa4\xbf\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xb8\xe0\xa5\x8b\xe0\xa4\xae\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xae\xe0\xa4\x82\xe0\xa4\x97\xe0\xa4\xb2\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xac\xe0\xa5\x81\xe0\xa4\xa7\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\x97\xe0\xa5\x81\xe0\xa4\xb0\xe0\xa5\x81\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xb6\xe0\xa5\x81\xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\xb0\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xb6\xe0\xa4\xa8\xe0\xa4\xbf\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xb0\xe0\xa4\xb5\xe0\xa4\xbf\0" "\xe0\xa4\xb8\xe0\xa5\x8b\xe0\xa4\xae\0" "\xe0\xa4\xae\xe0\xa4\x82\xe0\xa4\x97\xe0\xa4\xb2\0" "\xe0\xa4\xac\xe0\xa5\x81\xe0\xa4\xa7\0" "\xe0\xa4\x97\xe0\xa5\x81\xe0\xa4\xb0\xe0\xa5\x81\0" "\xe0\xa4\xb6\xe0\xa5\x81\xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\xb0\0" "\xe0\xa4\xb6\xe0\xa4\xa8\xe0\xa4\xbf\0" "\xe0\xa4\x9c\xe0\xa4\xa8\xe0\xa4\xb5\xe0\xa4\xb0\xe0\xa5\x80\0" "\xe0\xa4\xab\xe0\xa4\xb0\xe0\xa4\xb5\xe0\xa4\xb0\xe0\xa5\x80\0" "\xe0\xa4\xae\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa5\x8d\xe0\xa4\x9a\0" "\xe0\xa4\x85\xe0\xa4\xaa\xe0\xa5\x8d\xe0\xa4\xb0\xe0\xa5\x88\xe0\xa4\xb2\0" "\xe0\xa4\xae\xe0\xa4\x88\0" "\xe0\xa4\x9c\xe0\xa5\x82\xe0\xa4\xa8\0" "\xe0\xa4\x9c\xe0\xa5\x81\xe0\xa4\xb2\xe0\xa4\xbe\xe0\xa4\x88\0" "\xe0\xa4\x85\xe0\xa4\x97\xe0\xa4\xb8\xe0\xa5\x8d\xe0\xa4\xa4\0" "\xe0\xa4\xb8\xe0\xa4\xbf\xe0\xa4\xa4\xe0\xa4\xae\xe0\xa5\x8d\xe0\xa4\xac\xe0\xa4\xb0\0" "\xe0\xa4\x85\xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\xa4\xe0\xa5\x82\xe0\xa4\xac\xe0\xa4\xb0\0" "\xe0\xa4\xa8\xe0\xa4\xb5\xe0\xa4\xae\xe0\xa5\x8d\xe0\xa4\xac\xe0\xa4\xb0\0" "\xe0\xa4\xa6\xe0\xa4\xbf\xe0\xa4\xb8\xe0\xa4\xae\xe0\xa5\x8d\xe0\xa4\xac\xe0\xa4\xb0\0" "Jumapili\0" "Jumatatu\0" "Jumanne\0" "Jumatano\0" "Alhamisi\0" "Ijumaa\0" "Jumamosi\0" "Jpi\0" "Jtt\0" "Jnn\0" "Jtn\0" "Alh\0" "Iju\0" "Jmo\0" "Machi\0" "Aprili\0" "Julai\0" "Agosti\0" "Septemba\0" "Oktoba\0" "Novemba\0" "Desemba\0" "Ago\0" "\xe0\xaa\xaa\xe0\xab\x82\xe0\xaa\xb0\xe0\xab\x8d\xe0\xaa\xb5\xc2\xa0\xe0\xaa\xae\xe0\xaa\xa7\xe0\xab\x8d\xe0\xaa\xaf\xe0\xaa\xbe\xe0\xaa\xb9\xe0\xab\x8d\xe0\xaa\xa8\0" "\xe0\xaa\x89\xe0\xaa\xa4\xe0\xab\x8d\xe0\xaa\xa4\xe0\xaa\xb0\xc2\xa0\xe0\xaa\xae\xe0\xaa\xa7\xe0\xab\x8d\xe0\xaa\xaf\xe0\xaa\xbe\xe0\xaa\xb9\xe0\xab\x8d\xe0\xaa\xa8\0" "\xe0\xaa\xb0\xe0\xaa\xb5\xe0\xaa\xbf\xe0\xaa\xb5\xe0\xaa\xbe\xe0\xaa\xb0\0" "\xe0\xaa\xb8\xe0\xab\x8b\xe0\xaa\xae\xe0\xaa\xb5\xe0\xaa\xbe\xe0\xaa\xb0\0" "\xe0\xaa\xae\xe0\xaa\x82\xe0\xaa\x97\xe0\xaa\xb3\xe0\xaa\xb5\xe0\xaa\xbe\xe0\xaa\xb0\0" "\xe0\xaa\xac\xe0\xab\x81\xe0\xaa\xa7\xe0\xaa\xb5\xe0\xaa\xbe\xe0\xaa\xb0\0" "\xe0\xaa\x97\xe0\xab\x81\xe0\xaa\xb0\xe0\xab\x81\xe0\xaa\xb5\xe0\xaa\xbe\xe0\xaa\xb0\0" "\xe0\xaa\xb6\xe0\xab\x81\xe0\xaa\x95\xe0\xab\x8d\xe0\xaa\xb0\xe0\xaa\xb5\xe0\xaa\xbe\xe0\xaa\xb0\0" "\xe0\xaa\xb6\xe0\xaa\xa8\xe0\xaa\xbf\xe0\xaa\xb5\xe0\xaa\xbe\xe0\xaa\xb0\0" "\xe0\xaa\xb0\xe0\xaa\xb5\xe0\xaa\xbf\0" "\xe0\xaa\xb8\xe0\xab\x8b\xe0\xaa\xae\0" "\xe0\xaa\xae\xe0\xaa\x82\xe0\xaa\x97\xe0\xaa\xb3\0" "\xe0\xaa\xac\xe0\xab\x81\xe0\xaa\xa7\0" "\xe0\xaa\x97\xe0\xab\x81\xe0\xaa\xb0\xe0\xab\x81\0" "\xe0\xaa\xb6\xe0\xab\x81\xe0\xaa\x95\xe0\xab\x8d\xe0\xaa\xb0\0" "\xe0\xaa\xb6\xe0\xaa\xa8\xe0\xaa\xbf\0" "\xe0\xaa\x9c\xe0\xaa\xbe\xe0\xaa\xa8\xe0\xab\x8d\xe0\xaa\xaf\xe0\xab\x81\xe0\xaa\x86\xe0\xaa\xb0\xe0\xab\x80\0" "\xe0\xaa\xab\xe0\xab\x87\xe0\xaa\xac\xe0\xab\x8d\xe0\xaa\xb0\xe0\xab\x81\xe0\xaa\x86\xe0\xaa\xb0\xe0\xab\x80\0" "\xe0\xaa\xae\xe0\xaa\xbe\xe0\xaa\xb0\xe0\xab\x8d\xe0\xaa\x9a\0" "\xe0\xaa\x8f\xe0\xaa\xaa\xe0\xab\x8d\xe0\xaa\xb0\xe0\xaa\xbf\xe0\xaa\xb2\0" "\xe0\xaa\xae\xe0\xab\x87\0" "\xe0\xaa\x9c\xe0\xab\x82\xe0\xaa\xa8\0" "\xe0\xaa\x9c\xe0\xab\x81\xe0\xaa\xb2\xe0\xaa\xbe\xe0\xaa\x88\0" "\xe0\xaa\x91\xe0\xaa\x97\xe0\xaa\xb8\xe0\xab\x8d\xe0\xaa\x9f\0" "\xe0\xaa\xb8\xe0\xaa\xaa\xe0\xab\x8d\xe0\xaa\x9f\xe0\xab\x87\xe0\xaa\xae\xe0\xab\x8d\xe0\xaa\xac\xe0\xaa\xb0\0" "\xe0\xaa\x91\xe0\xaa\x95\xe0\xab\x8d\xe0\xaa\x9f\xe0\xab\x8d\xe0\xaa\xac\xe0\xaa\xb0\0" "\xe0\xaa\xa8\xe0\xaa\xb5\xe0\xab\x87\xe0\xaa\xae\xe0\xab\x8d\xe0\xaa\xac\xe0\xaa\xb0\0" "\xe0\xaa\xa1\xe0\xaa\xbf\xe0\xaa\xb8\xe0\xab\x87\xe0\xaa\xae\xe0\xab\x8d\xe0\xaa\xac\xe0\xaa\xb0\0" "\xe0\xaa\x9c\xe0\xaa\xbe\xe0\xaa\xa8\xe0\xab\x8d\xe0\xaa\xaf\xe0\xab\x81\0" "\xe0\xaa\xab\xe0\xab\x87\xe0\xaa\xac\xe0\xab\x8d\xe0\xaa\xb0\xe0\xab\x81\0" "\xe0\xaa\xb8\xe0\xaa\xaa\xe0\xab\x8d\xe0\xaa\x9f\xe0\xab\x87\0" "\xe0\xaa\x91\xe0\xaa\x95\xe0\xab\x8d\xe0\xaa\x9f\xe0\xab\x8b\0" "\xe0\xaa\xa8\xe0\xaa\xb5\xe0\xab\x87\0" "\xe0\xaa\xa1\xe0\xaa\xbf\xe0\xaa\xb8\xe0\xab\x87\0" "\xe0\xae\x95\xe0\xae\xbe\xe0\xae\xb2\xe0\xaf\x88\0" "\xe0\xae\xae\xe0\xae\xbe\xe0\xae\xb2\xe0\xaf\x88\0" "\xe0\xae\x9e\xe0\xae\xbe\xe0\xae\xaf\xe0\xae\xbf\xe0\xae\xb1\xe0\xaf\x81\0" "\xe0\xae\xa4\xe0\xae\xbf\xe0\xae\x99\xe0\xaf\x8d\xe0\xae\x95\xe0\xae\xb3\xe0\xaf\x8d\0" "\xe0\xae\x9a\xe0\xaf\x86\xe0\xae\xb5\xe0\xaf\x8d\xe0\xae\xb5\xe0\xae\xbe\xe0\xae\xaf\xe0\xaf\x8d\0" "\xe0\xae\xaa\xe0\xaf\x81\xe0\xae\xa4\xe0\xae\xa9\xe0\xaf\x8d\0" "\xe0\xae\xb5\xe0\xae\xbf\xe0\xae\xaf\xe0\xae\xbe\xe0\xae\xb4\xe0\xae\xa9\xe0\xaf\x8d\0" "\xe0\xae\xb5\xe0\xaf\x86\xe0\xae\xb3\xe0\xaf\x8d\xe0\xae\xb3\xe0\xae\xbf\0" "\xe0\xae\x9a\xe0\xae\xa9\xe0\xae\xbf\0" "\xe0\xae\x9e\xe0\xae\xbe\0" "\xe0\xae\xa4\xe0\xae\xbf\0" "\xe0\xae\x9a\xe0\xaf\x86\0" "\xe0\xae\xaa\xe0\xaf\x81\0" "\xe0\xae\xb5\xe0\xae\xbf\0" "\xe0\xae\xb5\xe0\xaf\x86\0" "\xe0\xae\x9a\0" "\xe0\xae\x9c\xe0\xae\xa9\xe0\xae\xb5\xe0\xae\xb0\xe0\xae\xbf\0" "\xe0\xae\xaa\xe0\xae\xbf\xe0\xae\xaa\xe0\xaf\x8d\xe0\xae\xb0\xe0\xae\xb5\xe0\xae\xb0\xe0\xae\xbf\0" "\xe0\xae\xae\xe0\xae\xbe\xe0\xae\xb0\xe0\xaf\x8d\xe0\xae\x9a\xe0\xaf\x8d\0" "\xe0\xae\x8f\xe0\xae\xaa\xe0\xaf\x8d\xe0\xae\xb0\xe0\xae\xb2\xe0\xaf\x8d\0" "\xe0\xae\xae\xe0\xaf\x87\0" "\xe0\xae\x9c\xe0\xaf\x82\xe0\xae\xa9\xe0\xaf\x8d\0" "\xe0\xae\x9c\xe0\xaf\x82\xe0\xae\xb2\xe0\xaf\x88\0" "\xe0\xae\x86\xe0\xae\x95\xe0\xae\xb8\xe0\xaf\x8d\xe0\xae\x9f\xe0\xaf\x8d\0" "\xe0\xae\x9a\xe0\xaf\x86\xe0\xae\xaa\xe0\xaf\x8d\xe0\xae\x9f\xe0\xae\xae\xe0\xaf\x8d\xe0\xae\xaa\xe0\xae\xb0\xe0\xaf\x8d\0" "\xe0\xae\x85\xe0\xae\x95\xe0\xaf\x8d\xe0\xae\x9f\xe0\xaf\x8b\xe0\xae\xaa\xe0\xae\xb0\xe0\xaf\x8d\0" "\xe0\xae\xa8\xe0\xae\xb5\xe0\xae\xae\xe0\xaf\x8d\xe0\xae\xaa\xe0\xae\xb0\xe0\xaf\x8d\0" "\xe0\xae\x9f\xe0\xae\xbf\xe0\xae\x9a\xe0\xae\xae\xe0\xaf\x8d\xe0\xae\xaa\xe0\xae\xb0\xe0\xaf\x8d\0" "\xe0\xae\x9c\xe0\xae\xa9.\0" "\xe0\xae\xaa\xe0\xae\xbf\xe0\xae\xaa\xe0\xaf\x8d.\0" "\xe0\xae\xae\xe0\xae\xbe\xe0\xae\xb0\xe0\xaf\x8d.\0" "\xe0\xae\x8f\xe0\xae\xaa\xe0\xaf\x8d.\0" "\xe0\xae\x86\xe0\xae\x95.\0" "\xe0\xae\x9a\xe0\xaf\x86\xe0\xae\xaa\xe0\xaf\x8d.\0" "\xe0\xae\x85\xe0\xae\x95\xe0\xaf\x8d.\0" "\xe0\xae\xa8\xe0\xae\xb5.\0" "\xe0\xae\x9f\xe0\xae\xbf\xe0\xae\x9a.\0" "\xe0\xb0\xaa\xe0\xb1\x82\xe0\xb0\xb0\xe0\xb1\x8d\xe0\xb0\xb5\xe0\xb0\xbe\xe0\xb0\xb9\xe0\xb1\x8d\xe0\xb0\xa8\0" "\xe0\xb0\x85\xe0\xb0\xaa\xe0\xb0\xb0\xe0\xb0\xbe\xe0\xb0\xb9\xe0\xb1\x8d\xe0\xb0\xa8\0" "\xe0\xb0\x86\xe0\xb0\xa6\xe0\xb0\xbf\xe0\xb0\xb5\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb0\x82\0" "\xe0\xb0\xb8\xe0\xb1\x8b\xe0\xb0\xae\xe0\xb0\xb5\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb0\x82\0" "\xe0\xb0\xae\xe0\xb0\x82\xe0\xb0\x97\xe0\xb0\xb3\xe0\xb0\xb5\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb0\x82\0" "\xe0\xb0\xac\xe0\xb1\x81\xe0\xb0\xa7\xe0\xb0\xb5\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb0\x82\0" "\xe0\xb0\x97\xe0\xb1\x81\xe0\xb0\xb0\xe0\xb1\x81\xe0\xb0\xb5\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb0\x82\0" "\xe0\xb0\xb6\xe0\xb1\x81\xe0\xb0\x95\xe0\xb1\x8d\xe0\xb0\xb0\xe0\xb0\xb5\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb0\x82\0" "\xe0\xb0\xb6\xe0\xb0\xa8\xe0\xb0\xbf\xe0\xb0\xb5\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb0\x82\0" "\xe0\xb0\x86\xe0\xb0\xa6\xe0\xb0\xbf\0" "\xe0\xb0\xb8\xe0\xb1\x8b\xe0\xb0\xae\0" "\xe0\xb0\xae\xe0\xb0\x82\xe0\xb0\x97\xe0\xb0\xb3\0" "\xe0\xb0\xac\xe0\xb1\x81\xe0\xb0\xa7\0" "\xe0\xb0\x97\xe0\xb1\x81\xe0\xb0\xb0\xe0\xb1\x81\0" "\xe0\xb0\xb6\xe0\xb1\x81\xe0\xb0\x95\xe0\xb1\x8d\xe0\xb0\xb0\0" "\xe0\xb0\xb6\xe0\xb0\xa8\xe0\xb0\xbf\0" "\xe0\xb0\x9c\xe0\xb0\xa8\xe0\xb0\xb5\xe0\xb0\xb0\xe0\xb0\xbf\0" "\xe0\xb0\xab\xe0\xb0\xbf\xe0\xb0\xac\xe0\xb1\x8d\xe0\xb0\xb0\xe0\xb0\xb5\xe0\xb0\xb0\xe0\xb0\xbf\0" "\xe0\xb0\xae\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb1\x8d\xe0\xb0\x9a\xe0\xb0\xbf\0" "\xe0\xb0\x8f\xe0\xb0\xaa\xe0\xb1\x8d\xe0\xb0\xb0\xe0\xb0\xbf\xe0\xb0\xb2\xe0\xb1\x8d\0" "\xe0\xb0\xae\xe0\xb1\x87\0" "\xe0\xb0\x9c\xe0\xb1\x82\xe0\xb0\xa8\xe0\xb1\x8d\0" "\xe0\xb0\x9c\xe0\xb1\x82\xe0\xb0\xb2\xe0\xb1\x88\0" "\xe0\xb0\x86\xe0\xb0\x97\xe0\xb0\xb8\xe0\xb1\x8d\xe0\xb0\x9f\xe0\xb1\x81\0" "\xe0\xb0\xb8\xe0\xb1\x86\xe0\xb0\xaa\xe0\xb1\x8d\xe0\xb0\x9f\xe0\xb1\x86\xe0\xb0\x82\xe0\xb0\xac\xe0\xb0\xb0\xe0\xb1\x8d\0" "\xe0\xb0\x85\xe0\xb0\x95\xe0\xb1\x8d\xe0\xb0\x9f\xe0\xb1\x8b\xe0\xb0\xac\xe0\xb0\xb0\xe0\xb1\x8d\0" "\xe0\xb0\xa8\xe0\xb0\xb5\xe0\xb0\x82\xe0\xb0\xac\xe0\xb0\xb0\xe0\xb1\x8d\0" "\xe0\xb0\xa1\xe0\xb0\xbf\xe0\xb0\xb8\xe0\xb1\x86\xe0\xb0\x82\xe0\xb0\xac\xe0\xb0\xb0\xe0\xb1\x8d\0" "\xe0\xb2\xaa\xe0\xb3\x82\xe0\xb2\xb0\xe0\xb3\x8d\xe0\xb2\xb5\xe0\xb2\xbe\xe0\xb2\xb9\xe0\xb3\x8d\xe0\xb2\xa8\0" "\xe0\xb2\x85\xe0\xb2\xaa\xe0\xb2\xb0\xe0\xb2\xbe\xe0\xb2\xb9\xe0\xb3\x8d\xe0\xb2\xa8\0" "\xe0\xb2\xb0\xe0\xb2\xb5\xe0\xb2\xbf\xe0\xb2\xb5\xe0\xb2\xbe\xe0\xb2\xb0\0" "\xe0\xb2\xb8\xe0\xb3\x8b\xe0\xb2\xae\xe0\xb2\xb5\xe0\xb2\xbe\xe0\xb2\xb0\0" "\xe0\xb2\xae\xe0\xb2\x82\xe0\xb2\x97\xe0\xb2\xb3\xe0\xb2\xb5\xe0\xb2\xbe\xe0\xb2\xb0\0" "\xe0\xb2\xac\xe0\xb3\x81\xe0\xb2\xa7\xe0\xb2\xb5\xe0\xb2\xbe\xe0\xb2\xb0\0" "\xe0\xb2\x97\xe0\xb3\x81\xe0\xb2\xb0\xe0\xb3\x81\xe0\xb2\xb5\xe0\xb2\xbe\xe0\xb2\xb0\0" "\xe0\xb2\xb6\xe0\xb3\x81\xe0\xb2\x95\xe0\xb3\x8d\xe0\xb2\xb0\xe0\xb2\xb5\xe0\xb2\xbe\xe0\xb2\xb0\0" "\xe0\xb2\xb6\xe0\xb2\xa8\xe0\xb2\xbf\xe0\xb2\xb5\xe0\xb2\xbe\xe0\xb2\xb0\0" "\xe0\xb2\xb0.\0" "\xe0\xb2\xb8\xe0\xb3\x8b.\0" "\xe0\xb2\xae\xe0\xb2\x82.\0" "\xe0\xb2\xac\xe0\xb3\x81.\0" "\xe0\xb2\x97\xe0\xb3\x81.\0" "\xe0\xb2\xb6\xe0\xb3\x81.\0" "\xe0\xb2\xb6\xe0\xb2\xa8\xe0\xb2\xbf.\0" "\xe0\xb2\x9c\xe0\xb2\xa8\xe0\xb2\xb5\xe0\xb2\xb0\xe0\xb3\x80\0" "\xe0\xb2\xab\xe0\xb3\x86\xe0\xb2\xac\xe0\xb3\x8d\xe0\xb2\xb0\xe0\xb2\xb5\xe0\xb2\xb0\xe0\xb3\x80\0" "\xe0\xb2\xae\xe0\xb2\xbe\xe0\xb2\xb0\xe0\xb3\x8d\xe0\xb2\x9a\xe0\xb3\x8d\0" "\xe0\xb2\x8e\xe0\xb2\xaa\xe0\xb3\x8d\xe0\xb2\xb0\xe0\xb2\xbf\xe0\xb2\xb2\xe0\xb3\x8d\0" "\xe0\xb2\xae\xe0\xb3\x86\0" "\xe0\xb2\x9c\xe0\xb3\x82\xe0\xb2\xa8\xe0\xb3\x8d\0" "\xe0\xb2\x9c\xe0\xb3\x81\xe0\xb2\xb2\xe0\xb3\x88\0" "\xe0\xb2\x86\xe0\xb2\x97\xe0\xb2\xb8\xe0\xb3\x8d\xe0\xb2\x9f\xe0\xb3\x8d\0" "\xe0\xb2\xb8\xe0\xb2\xaa\xe0\xb3\x8d\xe0\xb2\x9f\xe0\xb3\x86\xe0\xb2\x82\xe0\xb2\xac\xe0\xb2\xb0\xe0\xb3\x8d\0" "\xe0\xb2\x85\xe0\xb2\x95\xe0\xb3\x8d\xe0\xb2\x9f\xe0\xb3\x8b\xe0\xb2\xac\xe0\xb2\xb0\xe0\xb3\x8d\0" "\xe0\xb2\xa8\xe0\xb2\xb5\xe0\xb3\x86\xe0\xb2\x82\xe0\xb2\xac\xe0\xb2\xb0\xe0\xb3\x8d\0" "\xe0\xb2\xa1\xe0\xb2\xbf\xe0\xb2\xb8\xe0\xb3\x86\xe0\xb2\x82\xe0\xb2\xac\xe0\xb2\xb0\xe0\xb3\x8d\0" "\xe0\xa4\xae.\xe0\xa4\xaa\xe0\xa5\x82.\0" "\xe0\xa4\xae.\xe0\xa4\xa8\xe0\xa4\x82.\0" "\xe0\xa4\xae\xe0\xa4\x82\xe0\xa4\x97\xe0\xa4\xb3\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xae\xe0\xa4\x82\xe0\xa4\x97\xe0\xa4\xb3\0" "\xe0\xa4\x9c\xe0\xa4\xbe\xe0\xa4\xa8\xe0\xa5\x87\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa5\x80\0" "\xe0\xa4\xab\xe0\xa5\x87\xe0\xa4\xac\xe0\xa5\x83\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa5\x80\0" "\xe0\xa4\x8f\xe0\xa4\xaa\xe0\xa5\x8d\xe0\xa4\xb0\xe0\xa4\xbf\xe0\xa4\xb2\0" "\xe0\xa4\xae\xe0\xa5\x87\0" "\xe0\xa4\x9c\xe0\xa5\x81\xe0\xa4\xb2\xe0\xa5\x88\0" "\xe0\xa4\x93\xe0\xa4\x97\xe0\xa4\xb8\xe0\xa5\x8d\xe0\xa4\x9f\0" "\xe0\xa4\xb8\xe0\xa5\x87\xe0\xa4\xaa\xe0\xa5\x8d\xe0\xa4\x9f\xe0\xa5\x87\xe0\xa4\x82\xe0\xa4\xac\xe0\xa4\xb0\0" "\xe0\xa4\x93\xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\x9f\xe0\xa5\x8b\xe0\xa4\xac\xe0\xa4\xb0\0" "\xe0\xa4\xa8\xe0\xa5\x8b\xe0\xa4\xb5\xe0\xa5\x8d\xe0\xa4\xb9\xe0\xa5\x87\xe0\xa4\x82\xe0\xa4\xac\xe0\xa4\xb0\0" "\xe0\xa4\xa1\xe0\xa4\xbf\xe0\xa4\xb8\xe0\xa5\x87\xe0\xa4\x82\xe0\xa4\xac\xe0\xa4\xb0\0" "Domingo\0" "Luns\0" "Martes\0" "M\xc3\xa9rcores\0" "Xoves\0" "Venres\0" "S\xc3\xa1\x62\x61\x64o\0" "Dom\0" "Lun\0" "M\xc3\xa9r\0" "Xov\0" "Ven\0" "S\xc3\xa1\x62\0" "Xaneiro\0" "Febreiro\0" "Marzo\0" "Abril\0" "Maio\0" "Xu\xc3\xb1o\0" "Xullo\0" "Agosto\0" "Setembro\0" "Outubro\0" "Novembro\0" "Decembro\0" "Xan\0" "Abr\0" "Xu\xc3\xb1\0" "Xul\0" "Set\0" "Out\0" "\xe0\xa4\x86\xe0\xa4\xa6\xe0\xa4\xbf\xe0\xa4\xa4\xe0\xa5\x8d\xe0\xa4\xaf\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xae\xe0\xa4\x82\xe0\xa4\x97\xe0\xa4\xb3\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xab\xe0\xa5\x87\xe0\xa4\xac\xe0\xa5\x8d\xe0\xa4\xb0\xe0\xa5\x81\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa5\x80\0" "yyyy'\xe5\xb9\xb4'M'\xe6\x9c\x88'd'\xe6\x97\xa5' thh'\xe6\x99\x82'mm'\xe5\x88\x86'ss'\xe7\xa7\x92'\0" "thh'\xe6\x99\x82'mm'\xe5\x88\x86'ss'\xe7\xa7\x92'\0" "t h:mm\0" "dd-MMM-yy\0" "dd MMMM yyyy H.mm.ss\0" "H.mm.ss\0" "yyyy'\xeb\x85\x84' M'\xec\x9b\x94' d'\xec\x9d\xbc' tt h'\xec\x8b\x9c' mm'\xeb\xb6\x84' ss'\xec\xb4\x88'\0" "yyyy'\xeb\x85\x84' M'\xec\x9b\x94' d'\xec\x9d\xbc'\0" "tt h'\xec\x8b\x9c' mm'\xeb\xb6\x84' ss'\xec\xb4\x88'\0" "yyyy. MM. dd\0" "yy. MM. dd\0" "yyyy'\xeb\x85\x84' MM'\xec\x9b\x94' dd'\xec\x9d\xbc'\0" "yy'\xeb\x85\x84' M'\xec\x9b\x94' d'\xec\x9d\xbc'\0" "yy'\xeb\x85\x84' MM'\xec\x9b\x94' dd'\xec\x9d\xbc'\0" "H'\xec\x8b\x9c' m'\xeb\xb6\x84'\0" "H'\xec\x8b\x9c' mm'\xeb\xb6\x84'\0" "HH'\xec\x8b\x9c' mm'\xeb\xb6\x84'\0" "tt h'\xec\x8b\x9c' m'\xeb\xb6\x84'\0" "tt h'\xec\x8b\x9c' mm'\xeb\xb6\x84'\0" "tt hh'\xec\x8b\x9c' mm'\xeb\xb6\x84'\0" "H'\xec\x8b\x9c' m'\xeb\xb6\x84' ss'\xec\xb4\x88'\0" "HH'\xec\x8b\x9c' mm'\xeb\xb6\x84' ss'\xec\xb4\x88'\0" "tt h'\xec\x8b\x9c' m'\xeb\xb6\x84' ss'\xec\xb4\x88'\0" "tt hh'\xec\x8b\x9c' mm'\xeb\xb6\x84' ss'\xec\xb4\x88'\0" "d-M-yyyy\0" "d' de 'MMMM' de 'yyyy HH:mm:ss\0" "H'h'm'min's's' z\0" "'den 'd MMM yyyy HH:mm:ss\0" "dd MMMM yyyy H:mm:ss\0" "yyyy 'm.' MMMM d 'd.' HH:mm:ss\0" "\xd4\xbf\xd5\xa5\xe2\x80\xa4\0" "\xd5\x80\xd5\xb8\xd6\x82\xd5\xb6\xd5\xbe\xd5\xa1\xd6\x80\0" "\xd5\x93\xd5\xa5\xd5\xbf\xd6\x80\xd5\xbe\xd5\xa1\xd6\x80\0" "\xd5\x80\xd5\xb8\xd6\x82\xd5\xb6\xd5\xab\xd5\xbd\0" "\xd5\x80\xd5\xb8\xd6\x82\xd5\xac\xd5\xab\xd5\xbd\0" "\xd5\x80\xd5\xb6\xd5\xbe\0" "\xd5\x93\xd5\xbf\xd5\xbe\0" "\xd5\x80\xd5\xb6\xd5\xbd\0" "\xd5\x80\xd5\xac\xd5\xbd\0" "EEE, yyyy'eko' MMM'ren' dd'a' HH:mm:ss\0" "EEE, yyyy'eko' MMM'ren' dd'a'\0" "yyyy'eko' MMMM\0" "yy'-'MM'-'dd\0" "dd MMMM yyyy hh:mm:ss tt\0" "yyyy '\xe1\x83\xac\xe1\x83\x9a\xe1\x83\x98\xe1\x83\xa1' dd MM, dddd H:mm:ss\0" "yyyy '\xe1\x83\xac\xe1\x83\x9a\xe1\x83\x98\xe1\x83\xa1' dd MM, dddd\0" "d. MMM yyyy HH.mm.ss\0" "HH.mm.ss\0" "yyyy MMMM d h.mm.ss tt\0" "h.mm.ss tt\0" "d MMMM yyyy hh:mm:ss t z\0" "d-MM-yy\0" "hh:mm:ss t z\0" "hh:mm t\0" "d MMMM yyyy h:mm:ss t z\0" "yyyy'\xe5\xb9\xb4'M'\xe6\x9c\x88'd'\xe6\x97\xa5' thh'\xe6\x97\xb6'mm'\xe5\x88\x86'ss'\xe7\xa7\x92'\0" "yy-M-d\0" "thh'\xe6\x97\xb6'mm'\xe5\x88\x86'ss'\xe7\xa7\x92'\0" "th:mm\0" "d' de 'MMMM' de 'yyyy H:mm:ss\0" "d MMMM, yyyy hh:mm:ss tt\0" "yyyy'\xe5\xb9\xb4'MM'\xe6\x9c\x88'dd'\xe6\x97\xa5' thh'\xe6\x99\x82'mm'\xe5\x88\x86'ss'\xe7\xa7\x92'\0" "yy'\xe5\xb9\xb4'M'\xe6\x9c\x88'd'\xe6\x97\xa5'\0" "yyyy'\xe5\xb9\xb4'MM'\xe6\x9c\x88'\0" "MM'\xe6\x9c\x88'dd'\xe6\x97\xa5'\0" "dd. MMMM yyyy HH:mm:ss\0" "J\xc3\xa4nner\0" "J\xc3\xa4n\0" "M\xc3\xa4r\0" "d MMMM yyyy h:mm:ss tt\0" "dddd, dd' de 'MMMM' de 'yyyy H:mm:ss\0" "dddd, dd' de 'MMMM' de 'yyyy\0" "MMMM' de 'yyyy\0" "dd MMM yyyy t hh:mm:ss\0" "dd MMM yyyy\0" "t hh:mm:ss\0" "t hh:mm\0" "MMMM d, yyyy h:mm:ss tt\0" "MMMM d, yyyy\0" "d MMMM, yyyy H:mm:ss\0" "\xd9\x83\xd8\xa7\xd9\x86\xd9\x88\xd9\x86 \xd8\xa7\xd9\x84\xd8\xab\xd8\xa7\xd9\x86\xd9\x8a\0" "\xd8\xb4\xd8\xa8\xd8\xa7\xd8\xb7\0" "\xd8\xa2\xd8\xb0\xd8\xa7\xd8\xb1\0" "\xd9\x86\xd9\x8a\xd8\xb3\xd8\xa7\xd9\x86\0" "\xd9\x86\xd9\x88\xd8\xa7\xd8\xb1\0" "\xd8\xad\xd8\xb2\xd9\x8a\xd8\xb1\xd8\xa7\xd9\x86\0" "\xd8\xaa\xd9\x85\xd9\x88\xd8\xb2\0" "\xd8\xa2\xd8\xa8\0" "\xd8\xa3\xd9\x8a\xd9\x84\xd9\x88\xd9\x84\0" "\xd8\xaa\xd8\xb4\xd8\xb1\xd9\x8a\xd9\x86 \xd8\xa7\xd9\x84\xd8\xa3\xd9\x88\xd9\x84\0" "\xd8\xaa\xd8\xb4\xd8\xb1\xd9\x8a\xd9\x86 \xd8\xa7\xd9\x84\xd8\xab\xd8\xa7\xd9\x86\xd9\x8a\0" "\xd9\x83\xd8\xa7\xd9\x86\xd9\x88\xd9\x86 \xd8\xa7\xd9\x84\xd8\xa3\xd9\x88\xd9\x84\0" "\xd8\xa3\xd9\x8a\xd8\xa7\xd8\xb1\0" "dddd, dd MMMM yyyy hh:mm:ss tt\0" "dddd, dd MMMM yyyy\0" "dd' de 'MMMM' de 'yyyy hh:mm:ss tt\0" "dd' de 'MMMM' de 'yyyy\0" "dd' de 'MMMM\0" "\xd9\xab\0" "\xd9\xac\0" "\xd9\xaa\0" "\xef\xbf\xbd\0" "\xe2\x80\xb0\0" "-\xe2\x88\x9e\0" "\xe2\x88\x9e\0" "-\0" "+\0" ",\0" "\xc2\xa0\0" "%\0" ".\0" "NaN\0" "-Infinity\0" "Infinity\0" "\xd8\xb1.\xd8\xb3.\xe2\x80\x8f\0" "\xd0\xbb\xd0\xb2.\0" "\xe2\x82\xac\0" "NT$\0" "K\xc4\x8d\0" "kr\0" "$\0" "\xe2\x82\xaa\0" "Ft\0" "kr.\0" "\\\0" "\xef\xbf\xa6\0" "z\xc5\x82\0" "R$ \0" "lei\0" "\xd1\x80.\0" "Kn\0" "Lek\0" "\xe0\xb8\xbf\0" "TL\0" "Rp\0" "\xd0\xb3\xd1\x80\xd0\xbd.\0" "SIT\0" "Ls\0" "Lt\0" "\xef\xb7\xbc\0" "\xc4\x91\0" "Den\0" "\xe0\xa4\xb0\xe0\xa5\x81\0" "KSh\0" "\xe0\xaa\xb0\xe0\xab\x81\0" "\xe0\xae\xb0\xe0\xaf\x82\0" "\xe0\xb0\xb0\xe0\xb1\x82.\0" "\xd8\xaf.\xd8\xb9.\xe2\x80\x8f\0" "\xef\xbf\xa5\0" "'\0" "SFr.\0" "\xc2\xa3\0" "\xd8\xac.\xd9\x85.\xe2\x80\x8f\0" "HK$\0" "\xd8\xaf.\xd9\x84.\xe2\x80\x8f\0" "S$\0" "Q\0" "sFr.\0" "\xd8\xaf.\xd8\xac.\xe2\x80\x8f\0" "CRC\0" "\xd8\xaf.\xd9\x85.\xe2\x80\x8f\0" "B/\0" "\xd8\xaf.\xd8\xaa.\xe2\x80\x8f\0" "RD$\0" "\xd8\xb1.\xd8\xb9.\xe2\x80\x8f\0" "Bs\0" "\xd8\xb1.\xd9\x8a.\xe2\x80\x8f\0" "\xd9\x84.\xd8\xb3.\xe2\x80\x8f\0" "S/\0" "\xd8\xaf.\xd8\xa3.\xe2\x80\x8f\0" "\xd9\x84.\xd9\x84.\xe2\x80\x8f\0" "Z$\0" "S/.\0" "\xd8\xaf.\xd9\x83.\xe2\x80\x8f\0" "PHP\0" "\xd8\xaf.\xd8\xa5.\xe2\x80\x8f\0" "NU$\0" "\xd8\xaf.\xd8\xa8.\xe2\x80\x8f\0" "Gs\0" "\xd8\xb1.\xd9\x82.\xe2\x80\x8f\0" "$b\0" "SVC\0" "L.\0" "C$\0" "ar\0" "Arabic\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9\0" "ARA\0" "ara\0" "bg\0" "Bulgarian\0" "\xd0\x91\xd1\x8a\xd0\xbb\xd0\xb3\xd0\xb0\xd1\x80\xd1\x81\xd0\xba\xd0\xb8\0" "BGR\0" "bul\0" "ca\0" "Catalan\0" "catal\xc3\xa0\0" "CAT\0" "cat\0" "zh-CHS\0" "Chinese\0" "\xe4\xb8\xad\xe6\x96\x87\0" "CHS\0" "zho\0" "zh\0" "cs\0" "Czech\0" "\xc4\x8c\x65\xc5\xa1tina\0" "CSY\0" "ces\0" "da\0" "Danish\0" "Dansk\0" "DAN\0" "dan\0" "de\0" "German\0" "Deutsch\0" "DEU\0" "deu\0" "el\0" "Greek\0" "\xce\x95\xce\xbb\xce\xbb\xce\xb7\xce\xbd\xce\xb9\xce\xba\xce\xac\0" "ELL\0" "ell\0" "en\0" "English\0" "ENU\0" "eng\0" "es\0" "Spanish\0" "espa\xc3\xb1ol\0" "ESP\0" "spa\0" "fi\0" "Finnish\0" "suomi\0" "FIN\0" "fin\0" "French\0" "fran\xc3\xa7\x61is\0" "FRA\0" "fra\0" "he\0" "Hebrew\0" "\xd7\xa2\xd7\x91\xd7\xa8\xd7\x99\xd7\xaa\0" "HEB\0" "heb\0" "hu\0" "Hungarian\0" "magyar\0" "HUN\0" "hun\0" "is\0" "Icelandic\0" "\xc3\xadslenska\0" "ISL\0" "isl\0" "it\0" "Italian\0" "italiano\0" "ITA\0" "ita\0" "ja\0" "Japanese\0" "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e\0" "JPN\0" "jpn\0" "ko\0" "Korean\0" "\xed\x95\x9c\xea\xb5\xad\xec\x96\xb4\0" "KOR\0" "kor\0" "nl\0" "Dutch\0" "Nederlands\0" "NLD\0" "nld\0" "no\0" "Norwegian\0" "norsk\0" "NOR\0" "nor\0" "pl\0" "Polish\0" "polski\0" "PLK\0" "pol\0" "pt\0" "Portuguese\0" "portugu\xc3\xaas\0" "PTB\0" "por\0" "ro\0" "Romanian\0" "Rom\xc3\xa2n\xc4\x83\0" "ROM\0" "ron\0" "ru\0" "Russian\0" "\xd0\xa0\xd1\x83\xd1\x81\xd1\x81\xd0\xba\xd0\xb8\xd0\xb9\0" "RUS\0" "rus\0" "hr\0" "Croatian\0" "hrvatski\0" "HRV\0" "hrv\0" "sk\0" "Slovak\0" "slovensk\xc3\xbd\0" "SKY\0" "slk\0" "sq\0" "Albanian\0" "shqipe\0" "SQI\0" "sqi\0" "sv\0" "Swedish\0" "svenska\0" "SVE\0" "swe\0" "th\0" "Thai\0" "\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0" "THA\0" "tha\0" "tr\0" "Turkish\0" "T\xc3\xbcrk\xc3\xa7\x65\0" "TRK\0" "tur\0" "id\0" "Indonesian\0" "Bahasa Indonesia\0" "IND\0" "ind\0" "uk\0" "Ukrainian\0" "\xd0\xa3\xd0\xba\xd1\x80\xd0\xb0\xd1\x97\xd0\xbd\xd1\x81\xd1\x8c\xd0\xba\xd0\xb0\0" "UKR\0" "ukr\0" "be\0" "Belarusian\0" "\xd0\x91\xd0\xb5\xd0\xbb\xd0\xb0\xd1\x80\xd1\x83\xd1\x81\xd0\xba\xd1\x96\0" "BEL\0" "bel\0" "sl\0" "Slovenian\0" "Sloven\xc5\xa1\xc4\x8dina\0" "SLV\0" "slv\0" "et\0" "Estonian\0" "Eesti\0" "ETI\0" "est\0" "lv\0" "Latvian\0" "latvie\xc5\xa1u\0" "LVI\0" "lav\0" "lt\0" "Lithuanian\0" "Lietuvi\xc5\xb3\0" "LTH\0" "lit\0" "fa\0" "Persian\0" "\xd9\x81\xd8\xa7\xd8\xb1\xd8\xb3\xdb\x8c\0" "FAR\0" "fas\0" "vi\0" "Vietnamese\0" "Ti\xe1\xba\xbfng Vi\xe1\xbb\x87t\0" "VIT\0" "hy\0" "Armenian\0" "\xd5\x80\xd5\xa1\xd5\xb5\xd5\xa5\xd6\x80\xd5\xa7\xd5\xb6\0" "HYE\0" "hye\0" "eu\0" "Basque\0" "euskara\0" "EUQ\0" "eus\0" "mk\0" "Macedonian\0" "\xd0\xbc\xd0\xb0\xd0\xba\xd0\xb5\xd0\xb4\xd0\xbe\xd0\xbd\xd1\x81\xd0\xba\xd0\xb8\0" "MKI\0" "mkd\0" "af\0" "Afrikaans\0" "Afrikaanse\0" "AFK\0" "afr\0" "ka\0" "Georgian\0" "\xe1\x83\xa5\xe1\x83\x90\xe1\x83\xa0\xe1\x83\x97\xe1\x83\xa3\xe1\x83\x9a\xe1\x83\x98\0" "KAT\0" "kat\0" "fo\0" "Faroese\0" "f\xc3\xb8royskt\0" "FOS\0" "fao\0" "hi\0" "Hindi\0" "\xe0\xa4\xb9\xe0\xa4\xbf\xe0\xa4\x82\xe0\xa4\xa6\xe0\xa5\x80\0" "HIN\0" "hin\0" "sw\0" "Swahili\0" "Kiswahili\0" "SWK\0" "swa\0" "gu\0" "Gujarati\0" "\xe0\xaa\x97\xe0\xab\x81\xe0\xaa\x9c\xe0\xaa\xb0\xe0\xaa\xbe\xe0\xaa\xa4\xe0\xab\x80\0" "GUJ\0" "guj\0" "ta\0" "Tamil\0" "\xe0\xae\xa4\xe0\xae\xae\xe0\xae\xbf\xe0\xae\xb4\xe0\xaf\x8d\0" "TAM\0" "tam\0" "te\0" "Telugu\0" "\xe0\xb0\xa4\xe0\xb1\x86\xe0\xb0\xb2\xe0\xb1\x81\xe0\xb0\x97\xe0\xb1\x81\0" "TEL\0" "tel\0" "kn\0" "Kannada\0" "\xe0\xb2\x95\xe0\xb2\xa8\xe0\xb3\x8d\xe0\xb2\xa8\xe0\xb2\xa1\0" "KAN\0" "kan\0" "mr\0" "Marathi\0" "\xe0\xa4\xae\xe0\xa4\xb0\xe0\xa4\xbe\xe0\xa4\xa0\xe0\xa5\x80\0" "MAR\0" "gl\0" "Gallegan\0" "galego\0" "GLC\0" "glg\0" "kok\0" "Konkani\0" "\xe0\xa4\x95\xe0\xa5\x8b\xe0\xa4\x82\xe0\xa4\x95\xe0\xa4\xa3\xe0\xa5\x80\0" "KNK\0" "ar-SA\0" "Arabic (Saudi Arabia)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 \xd8\xa7\xd9\x84\xd8\xb3\xd8\xb9\xd9\x88\xd8\xaf\xd9\x8a\xd8\xa9)\0" "bg-BG\0" "Bulgarian (Bulgaria)\0" "\xd0\x91\xd1\x8a\xd0\xbb\xd0\xb3\xd0\xb0\xd1\x80\xd1\x81\xd0\xba\xd0\xb8 (\xd0\x91\xd1\x8a\xd0\xbb\xd0\xb3\xd0\xb0\xd1\x80\xd0\xb8\xd1\x8f)\0" "BG\0" "ca-ES\0" "Catalan (Spain)\0" "catal\xc3\xa0 (Espanya)\0" "ES\0" "zh-TW\0" "Chinese (Taiwan)\0" "\xe4\xb8\xad\xe6\x96\x87 (\xe5\x8f\xb0\xe6\xb9\xbe)\0" "CHT\0" "TW\0" "cs-CZ\0" "Czech (Czech Republic)\0" "\xc4\x8c\x65\xc5\xa1tina (\xc4\x8c\x65sk\xc3\xa1 republika)\0" "CZ\0" "da-DK\0" "Danish (Denmark)\0" "Dansk (Danmark)\0" "DK\0" "de-DE\0" "German (Germany)\0" "Deutsch (Deutschland)\0" "el-GR\0" "Greek (Greece)\0" "\xce\x95\xce\xbb\xce\xbb\xce\xb7\xce\xbd\xce\xb9\xce\xba\xce\xac (\xce\x95\xce\xbb\xce\xbb\xce\xac\xce\xb4\xce\xb1)\0" "GR\0" "en-US\0" "English (United States)\0" "US\0" "fi-FI\0" "Finnish (Finland)\0" "suomi (Suomi)\0" "FI\0" "fr-FR\0" "French (France)\0" "fran\xc3\xa7\x61is (France)\0" "FR\0" "he-IL\0" "Hebrew (Israel)\0" "\xd7\xa2\xd7\x91\xd7\xa8\xd7\x99\xd7\xaa (\xd7\x99\xd7\xa9\xd7\xa8\xd7\x90\xd7\x9c)\0" "IL\0" "hu-HU\0" "Hungarian (Hungary)\0" "magyar (Magyarorsz\xc3\xa1g)\0" "HU\0" "is-IS\0" "Icelandic (Iceland)\0" "\xc3\xadslenska (\xc3\x8dsland)\0" "IS\0" "it-IT\0" "Italian (Italy)\0" "italiano (Italia)\0" "IT\0" "ja-JP\0" "Japanese (Japan)\0" "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (\xe6\x97\xa5\xe6\x9c\xac)\0" "JP\0" "ko-KR\0" "Korean (South Korea)\0" "\xed\x95\x9c\xea\xb5\xad\xec\x96\xb4 (\xeb\x8c\x80\xed\x95\x9c\xeb\xaf\xbc\xea\xb5\xad)\0" "KR\0" "nl-NL\0" "Dutch (Netherlands)\0" "Nederlands (Nederland)\0" "NL\0" "nb-NO\0" "Norwegian Bokm?l (Norway)\0" "Norwegian Bokm\xc3\xa5l (Norway)\0" "norsk bokm\xc3\xa5l (Norge)\0" "nob\0" "nb\0" "NO\0" "pl-PL\0" "Polish (Poland)\0" "polski (Polska)\0" "PL\0" "pt-BR\0" "Portuguese (Brazil)\0" "portugu\xc3\xaas (Brasil)\0" "BR\0" "ro-RO\0" "Romanian (Romania)\0" "Rom\xc3\xa2n\xc4\x83 (Rom\xc3\xa2nia)\0" "RO\0" "ru-RU\0" "Russian (Russia)\0" "\xd0\xa0\xd1\x83\xd1\x81\xd1\x81\xd0\xba\xd0\xb8\xd0\xb9 (\xd0\xa0\xd0\xbe\xd1\x81\xd1\x81\xd0\xb8\xd1\x8f)\0" "RU\0" "hr-HR\0" "Croatian (Croatia)\0" "hrvatski (Hrvatska)\0" "HR\0" "sk-SK\0" "Slovak (Slovakia)\0" "slovensk\xc3\xbd (Slovensk\xc3\xa1 republika)\0" "SK\0" "sq-AL\0" "Albanian (Albania)\0" "shqipe (Shqip\xc3\xabria)\0" "AL\0" "sv-SE\0" "Swedish (Sweden)\0" "svenska (Sverige)\0" "SE\0" "th-TH\0" "Thai (Thailand)\0" "\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2 (\xe0\xb8\x9b\xe0\xb8\xa3\xe0\xb8\xb0\xe0\xb9\x80\xe0\xb8\x97\xe0\xb8\xa8\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2)\0" "TH\0" "tr-TR\0" "Turkish (Turkey)\0" "T\xc3\xbcrk\xc3\xa7\x65 (T\xc3\xbcrkiye)\0" "TR\0" "id-ID\0" "Indonesian (Indonesia)\0" "Bahasa Indonesia (Indonesia)\0" "ID\0" "uk-UA\0" "Ukrainian (Ukraine)\0" "\xd0\xa3\xd0\xba\xd1\x80\xd0\xb0\xd1\x97\xd0\xbd\xd1\x81\xd1\x8c\xd0\xba\xd0\xb0 (\xd0\xa3\xd0\xba\xd1\x80\xd0\xb0\xd1\x97\xd0\xbd\xd0\xb0)\0" "UA\0" "be-BY\0" "Belarusian (Belarus)\0" "\xd0\x91\xd0\xb5\xd0\xbb\xd0\xb0\xd1\x80\xd1\x83\xd1\x81\xd0\xba\xd1\x96 (\xd0\x91\xd0\xb5\xd0\xbb\xd0\xb0\xd1\x80\xd1\x83\xd1\x81\xd1\x8c)\0" "BY\0" "sl-SI\0" "Slovenian (Slovenia)\0" "Sloven\xc5\xa1\xc4\x8dina (Slovenija)\0" "SI\0" "et-EE\0" "Estonian (Estonia)\0" "Eesti (Eesti)\0" "EE\0" "lv-LV\0" "Latvian (Latvia)\0" "latvie\xc5\xa1u (Latvija)\0" "LV\0" "lt-LT\0" "Lithuanian (Lithuania)\0" "Lietuvi\xc5\xb3 (Lietuva)\0" "LT\0" "fa-IR\0" "Persian (Iran)\0" "\xd9\x81\xd8\xa7\xd8\xb1\xd8\xb3\xdb\x8c (\xd8\xa7\xdb\x8c\xd8\xb1\xd8\xa7\xd9\x86)\0" "IR\0" "vi-VN\0" "Vietnamese (Vietnam)\0" "Ti\xe1\xba\xbfng Vi\xe1\xbb\x87t (Vi\xe1\xbb\x87t Nam)\0" "VN\0" "hy-AM\0" "Armenian (Armenia)\0" "\xd5\x80\xd5\xa1\xd5\xb5\xd5\xa5\xd6\x80\xd5\xa7\xd5\xb6 (\xd5\x80\xd5\xa1\xd5\xb5\xd5\xa1\xd5\xbd\xd5\xbf\xd5\xa1\xd5\xb6\xd5\xab \xd5\x80\xd5\xa1\xd5\xb6\xd6\x80\xd5\xa1\xd5\xba\xd5\xa5\xd5\xbf\xd5\xb8\xd6\x82\xd5\xa9\xd5\xab\xd6\x82\xd5\xb6)\0" "eu-ES\0" "Basque (Spain)\0" "euskara (Espainia)\0" "mk-MK\0" "Macedonian (Macedonia)\0" "\xd0\xbc\xd0\xb0\xd0\xba\xd0\xb5\xd0\xb4\xd0\xbe\xd0\xbd\xd1\x81\xd0\xba\xd0\xb8 (\xd0\x9c\xd0\xb0\xd0\xba\xd0\xb5\xd0\xb4\xd0\xbe\xd0\xbd\xd0\xb8\xd1\x98\xd0\xb0)\0" "MK\0" "af-ZA\0" "Afrikaans (South Africa)\0" "Afrikaanse (Suid-Afrika)\0" "ZA\0" "ka-GE\0" "Georgian (Georgia)\0" "\xe1\x83\xa5\xe1\x83\x90\xe1\x83\xa0\xe1\x83\x97\xe1\x83\xa3\xe1\x83\x9a\xe1\x83\x98 (\xe1\x83\xa1\xe1\x83\x90\xe1\x83\xa5\xe1\x83\x90\xe1\x83\xa0\xe1\x83\x97\xe1\x83\x95\xe1\x83\x94\xe1\x83\x9a\xe1\x83\x9d)\0" "GE\0" "fo-FO\0" "Faroese (Faroe Islands)\0" "f\xc3\xb8royskt (F\xc3\xb8royar)\0" "FO\0" "hi-IN\0" "Hindi (India)\0" "\xe0\xa4\xb9\xe0\xa4\xbf\xe0\xa4\x82\xe0\xa4\xa6\xe0\xa5\x80 (\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa4\xa4)\0" "IN\0" "sw-KE\0" "Swahili (Kenya)\0" "Kiswahili (Kenya)\0" "KE\0" "gu-IN\0" "Gujarati (India)\0" "\xe0\xaa\x97\xe0\xab\x81\xe0\xaa\x9c\xe0\xaa\xb0\xe0\xaa\xbe\xe0\xaa\xa4\xe0\xab\x80 (\xe0\xaa\xad\xe0\xaa\xbe\xe0\xaa\xb0\xe0\xaa\xa4)\0" "ta-IN\0" "Tamil (India)\0" "\xe0\xae\xa4\xe0\xae\xae\xe0\xae\xbf\xe0\xae\xb4\xe0\xaf\x8d (\xe0\xae\x87\xe0\xae\xa8\xe0\xaf\x8d\xe0\xae\xa4\xe0\xae\xbf\xe0\xae\xaf\xe0\xae\xbe)\0" "te-IN\0" "Telugu (India)\0" "\xe0\xb0\xa4\xe0\xb1\x86\xe0\xb0\xb2\xe0\xb1\x81\xe0\xb0\x97\xe0\xb1\x81 (\xe0\xb0\xad\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb0\xa4 \xe0\xb0\xa6\xe0\xb1\x87\xe0\xb0\xb3\xe0\xb1\xa6)\0" "kn-IN\0" "Kannada (India)\0" "\xe0\xb2\x95\xe0\xb2\xa8\xe0\xb3\x8d\xe0\xb2\xa8\xe0\xb2\xa1 (\xe0\xb2\xad\xe0\xb2\xbe\xe0\xb2\xb0\xe0\xb2\xa4)\0" "mr-IN\0" "Marathi (India)\0" "\xe0\xa4\xae\xe0\xa4\xb0\xe0\xa4\xbe\xe0\xa4\xa0\xe0\xa5\x80 (\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa4\xa4)\0" "gl-ES\0" "Gallegan (Spain)\0" "galego (Espa\xc3\xb1\x61)\0" "kok-IN\0" "Konkani (India)\0" "\xe0\xa4\x95\xe0\xa5\x8b\xe0\xa4\x82\xe0\xa4\x95\xe0\xa4\xa3\xe0\xa5\x80 (\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa4\xa4)\0" "ar-IQ\0" "Arabic (Iraq)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa7\xd9\x82)\0" "ARI\0" "IQ\0" "zh-CN\0" "Chinese (China)\0" "\xe4\xb8\xad\xe6\x96\x87 (\xe4\xb8\xad\xe5\x9b\xbd)\0" "de-CH\0" "German (Switzerland)\0" "Deutsch (Schweiz)\0" "DES\0" "en-GB\0" "English (United Kingdom)\0" "ENG\0" "GB\0" "es-MX\0" "Spanish (Mexico)\0" "espa\xc3\xb1ol (M\xc3\xa9xico)\0" "ESM\0" "MX\0" "fr-BE\0" "French (Belgium)\0" "fran\xc3\xa7\x61is (Belgique)\0" "FRB\0" "BE\0" "it-CH\0" "Italian (Switzerland)\0" "italiano (Svizzera)\0" "ITS\0" "nl-BE\0" "Dutch (Belgium)\0" "Nederlands (Belgi\xc3\xab)\0" "NLB\0" "nn-NO\0" "Norwegian Nynorsk (Norway)\0" "norsk nynorsk (Noreg)\0" "NON\0" "nno\0" "nn\0" "pt-PT\0" "Portuguese (Portugal)\0" "portugu\xc3\xaas (Portugal)\0" "PTG\0" "PT\0" "sv-FI\0" "Swedish (Finland)\0" "svenska (Finland)\0" "SVF\0" "ar-EG\0" "Arabic (Egypt)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd9\x85\xd8\xb5\xd8\xb1)\0" "ARE\0" "EG\0" "zh-HK\0" "Chinese (Hong Kong S.A.R., China)\0" "\xe4\xb8\xad\xe6\x96\x87 (\xe4\xb8\xad\xe5\x9b\xbd\xe9\xa6\x99\xe6\xb8\xaf\xe7\x89\xb9\xe5\x88\xab\xe8\xa1\x8c\xe6\x94\xbf\xe5\x8c\xba)\0" "ZHH\0" "HK\0" "de-AT\0" "German (Austria)\0" "Deutsch (\xc3\x96sterreich)\0" "DEA\0" "AT\0" "en-AU\0" "English (Australia)\0" "ENA\0" "AU\0" "es-ES\0" "Spanish (Spain)\0" "espa\xc3\xb1ol (Espa\xc3\xb1\x61)\0" "ESN\0" "fr-CA\0" "French (Canada)\0" "fran\xc3\xa7\x61is (Canada)\0" "FRC\0" "CA\0" "ar-LY\0" "Arabic (Libya)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd9\x84\xd9\x8a\xd8\xa8\xd9\x8a\xd8\xa7)\0" "ARL\0" "LY\0" "zh-SG\0" "Chinese (Singapore)\0" "\xe4\xb8\xad\xe6\x96\x87 (\xe6\x96\xb0\xe5\x8a\xa0\xe5\x9d\xa1)\0" "ZHI\0" "SG\0" "de-LU\0" "German (Luxembourg)\0" "Deutsch (Luxemburg)\0" "DEL\0" "LU\0" "en-CA\0" "English (Canada)\0" "ENC\0" "es-GT\0" "Spanish (Guatemala)\0" "espa\xc3\xb1ol (Guatemala)\0" "ESG\0" "GT\0" "fr-CH\0" "French (Switzerland)\0" "fran\xc3\xa7\x61is (Suisse)\0" "FRS\0" "ar-DZ\0" "Arabic (Algeria)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd8\xac\xd8\xb2\xd8\xa7\xd8\xa6\xd8\xb1)\0" "ARG\0" "DZ\0" "zh-MO\0" "Chinese (Macao S.A.R. China)\0" "\xe4\xb8\xad\xe6\x96\x87 (\xe4\xb8\xad\xe5\x9b\xbd\xe6\xbe\xb3\xe9\x97\xa8\xe7\x89\xb9\xe5\x88\xab\xe8\xa1\x8c\xe6\x94\xbf\xe5\x8c\xba)\0" "ZHM\0" "MO\0" "en-NZ\0" "English (New Zealand)\0" "ENZ\0" "NZ\0" "es-CR\0" "Spanish (Costa Rica)\0" "espa\xc3\xb1ol (Costa Rica)\0" "ESC\0" "CR\0" "fr-LU\0" "French (Luxembourg)\0" "fran\xc3\xa7\x61is (Luxembourg)\0" "FRL\0" "ar-MA\0" "Arabic (Morocco)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd9\x85\xd8\xba\xd8\xb1\xd8\xa8)\0" "ARM\0" "MA\0" "en-IE\0" "English (Ireland)\0" "ENI\0" "IE\0" "es-PA\0" "Spanish (Panama)\0" "espa\xc3\xb1ol (Panam\xc3\xa1)\0" "ESA\0" "PA\0" "ar-TN\0" "Arabic (Tunisia)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xaa\xd9\x88\xd9\x86\xd8\xb3)\0" "ART\0" "TN\0" "en-ZA\0" "English (South Africa)\0" "ENS\0" "es-DO\0" "Spanish (Dominican Republic)\0" "espa\xc3\xb1ol (Rep\xc3\xba\x62lica Dominicana)\0" "ESD\0" "DO\0" "ar-OM\0" "Arabic (Oman)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xb9\xd9\x85\xd8\xa7\xd9\x86)\0" "ARO\0" "OM\0" "es-VE\0" "Spanish (Venezuela)\0" "espa\xc3\xb1ol (Venezuela)\0" "ESV\0" "VE\0" "ar-YE\0" "Arabic (Yemen)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd9\x8a\xd9\x85\xd9\x86)\0" "ARY\0" "YE\0" "es-CO\0" "Spanish (Colombia)\0" "espa\xc3\xb1ol (Colombia)\0" "ESO\0" "CO\0" "ar-SY\0" "Arabic (Syria)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xb3\xd9\x88\xd8\xb1\xd9\x8a\xd8\xa9)\0" "ARS\0" "SY\0" "es-PE\0" "Spanish (Peru)\0" "espa\xc3\xb1ol (Per\xc3\xba)\0" "ESR\0" "PE\0" "ar-JO\0" "Arabic (Jordan)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd8\xa7\xd8\xb1\xd8\xaf\xd9\x86)\0" "ARJ\0" "JO\0" "en-TT\0" "English (Trinidad and Tobago)\0" "ENT\0" "TT\0" "es-AR\0" "Spanish (Argentina)\0" "espa\xc3\xb1ol (Argentina)\0" "ESS\0" "AR\0" "ar-LB\0" "Arabic (Lebanon)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd9\x84\xd8\xa8\xd9\x86\xd8\xa7\xd9\x86)\0" "ARB\0" "LB\0" "en-ZW\0" "English (Zimbabwe)\0" "ENW\0" "ZW\0" "es-EC\0" "Spanish (Ecuador)\0" "espa\xc3\xb1ol (Ecuador)\0" "ESF\0" "EC\0" "ar-KW\0" "Arabic (Kuwait)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd9\x83\xd9\x88\xd9\x8a\xd8\xaa)\0" "ARK\0" "KW\0" "en-PH\0" "English (Philippines)\0" "ENP\0" "PH\0" "es-CL\0" "Spanish (Chile)\0" "espa\xc3\xb1ol (Chile)\0" "ESL\0" "CL\0" "ar-AE\0" "Arabic (United Arab Emirates)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd8\xa7\xd9\x85\xd8\xa7\xd8\xb1\xd8\xa7\xd8\xaa \xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 \xd8\xa7\xd9\x84\xd9\x85\xd8\xaa\xd8\xad\xd8\xaf\xd8\xa9)\0" "ARU\0" "AE\0" "es-UY\0" "Spanish (Uruguay)\0" "espa\xc3\xb1ol (Uruguay)\0" "ESY\0" "UY\0" "ar-BH\0" "Arabic (Bahrain)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd8\xa8\xd8\xad\xd8\xb1\xd9\x8a\xd9\x86)\0" "ARH\0" "BH\0" "es-PY\0" "Spanish (Paraguay)\0" "espa\xc3\xb1ol (Paraguay)\0" "ESZ\0" "PY\0" "ar-QA\0" "Arabic (Qatar)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd9\x82\xd8\xb7\xd8\xb1)\0" "ARQ\0" "QA\0" "es-BO\0" "Spanish (Bolivia)\0" "espa\xc3\xb1ol (Bolivia)\0" "ESB\0" "BO\0" "es-SV\0" "Spanish (El Salvador)\0" "espa\xc3\xb1ol (El Salvador)\0" "ESE\0" "SV\0" "es-HN\0" "Spanish (Honduras)\0" "espa\xc3\xb1ol (Honduras)\0" "ESH\0" "HN\0" "es-NI\0" "Spanish (Nicaragua)\0" "espa\xc3\xb1ol (Nicaragua)\0" "ESI\0" "NI\0" "es-PR\0" "Spanish (Puerto Rico)\0" "espa\xc3\xb1ol (Puerto Rico)\0" "ESU\0" "PR\0" "zh-CHT\0" "af-za\0" "ar-ae\0" "ar-bh\0" "ar-dz\0" "ar-eg\0" "ar-iq\0" "ar-jo\0" "ar-kw\0" "ar-lb\0" "ar-ly\0" "ar-ma\0" "ar-om\0" "ar-qa\0" "ar-sa\0" "ar-sy\0" "ar-tn\0" "ar-ye\0" "be-by\0" "bg-bg\0" "ca-es\0" "cs-cz\0" "da-dk\0" "de-at\0" "de-ch\0" "de-de\0" "de-lu\0" "el-gr\0" "en-au\0" "en-ca\0" "en-gb\0" "en-ie\0" "en-nz\0" "en-ph\0" "en-tt\0" "en-us\0" "en-za\0" "en-zw\0" "es-ar\0" "es-bo\0" "es-cl\0" "es-co\0" "es-cr\0" "es-do\0" "es-ec\0" "es-es\0" "es-gt\0" "es-hn\0" "es-mx\0" "es-ni\0" "es-pa\0" "es-pe\0" "es-pr\0" "es-py\0" "es-sv\0" "es-uy\0" "es-ve\0" "et-ee\0" "eu-es\0" "fa-ir\0" "fi-fi\0" "fo-fo\0" "fr-be\0" "fr-ca\0" "fr-ch\0" "fr-fr\0" "fr-lu\0" "gl-es\0" "gu-in\0" "he-il\0" "hi-in\0" "hr-hr\0" "hu-hu\0" "hy-am\0" "id-id\0" "is-is\0" "it-ch\0" "it-it\0" "ja-jp\0" "ka-ge\0" "kn-in\0" "ko-kr\0" "kok-in\0" "lt-lt\0" "lv-lv\0" "mk-mk\0" "mr-in\0" "nb-no\0" "nl-be\0" "nl-nl\0" "nn-no\0" "pl-pl\0" "pt-br\0" "pt-pt\0" "ro-ro\0" "ru-ru\0" "sk-sk\0" "sl-si\0" "sq-al\0" "sv-fi\0" "sv-se\0" "sw-ke\0" "ta-in\0" "te-in\0" "th-th\0" "tr-tr\0" "uk-ua\0" "vi-vn\0" "zh-chs\0" "zh-cht\0" "zh-cn\0" "zh-hk\0" "zh-mo\0" "zh-sg\0" "zh-tw\0" "United Arab Emirates\0" "AED\0" "United Arab Emirates Dirham\0" "AF\0" "Afghanistan\0" "AFN\0" "Afghani\0" "AG\0" "Antigua and Barbuda\0" "XCD\0" "East Caribbean Dollar\0" "AI\0" "Anguilla\0" "Albania\0" "ALL\0" "Albanian Lek\0" "Armenia\0" "AMD\0" "Armenian Dram\0" "AN\0" "Netherlands Antilles\0" "ANG\0" "Netherlands Antillan Guilder\0" "AO\0" "Angola\0" "AOA\0" "Angolan Kwanza\0" "Argentina\0" "Argentine Peso\0" "AS\0" "American Samoa\0" "USD\0" "US Dollar\0" "Austria\0" "EUR\0" "Euro\0" "Australia\0" "AUD\0" "Australian Dollar\0" "AW\0" "Aruba\0" "AWG\0" "Aruban Guilder\0" "AZ\0" "Azerbaijan\0" "AZM\0" "Azerbaijanian Manat\0" "BA\0" "Bosnia and Herzegovina\0" "BAM\0" "Bosnia-Herzegovina Convertible Mark\0" "BB\0" "Barbados\0" "BBD\0" "Barbados Dollar\0" "BD\0" "Bangladesh\0" "BDT\0" "Bangladesh Taka\0" "Belgium\0" "BF\0" "Burkina Faso\0" "XOF\0" "CFA Franc BCEAO\0" "Bulgaria\0" "BGN\0" "Bulgarian New Lev\0" "Bahrain\0" "BHD\0" "Bahraini Dinar\0" "BI\0" "Burundi\0" "BIF\0" "Burundi Franc\0" "BJ\0" "Benin\0" "BM\0" "Bermuda\0" "BMD\0" "Bermudan Dollar\0" "BN\0" "Brunei\0" "BND\0" "Brunei Dollar\0" "Bolivia\0" "BOB\0" "Boliviano\0" "Brazil\0" "BRL\0" "Brazilian Real\0" "BS\0" "Bahamas\0" "BSD\0" "Bahamian Dollar\0" "BV\0" "Bouvet Island\0" "NOK\0" "Norwegian Krone\0" "BW\0" "Botswana\0" "BWP\0" "Botswanan Pula\0" "Belarus\0" "BYR\0" "Belarussian Ruble\0" "BZ\0" "Belize\0" "BZD\0" "Belize Dollar\0" "Canada\0" "CAD\0" "Canadian Dollar\0" "CC\0" "Cocos Islands\0" "CD\0" "Democratic Republic of the Congo\0" "CDF\0" "Congolese Franc Congolais\0" "CF\0" "Central African Republic\0" "XAF\0" "CFA Franc BEAC\0" "CG\0" "Congo\0" "Switzerland\0" "CHF\0" "Swiss Franc\0" "CI\0" "C\xc3\xb4te d'Ivoire\0" "CK\0" "Cook Islands\0" "NZD\0" "New Zealand Dollar\0" "Chile\0" "CLP\0" "Chilean Peso\0" "CM\0" "Cameroon\0" "China\0" "CNY\0" "Chinese Yuan Renminbi\0" "Colombia\0" "COP\0" "Colombian Peso\0" "Costa Rica\0" "Costa Rican Colon\0" "CU\0" "Cuba\0" "CUP\0" "Cuban Peso\0" "CV\0" "Cape Verde\0" "CVE\0" "Cape Verde Escudo\0" "CX\0" "Christmas Island\0" "CY\0" "Cyprus\0" "CYP\0" "Cyprus Pound\0" "Czech Republic\0" "CZK\0" "Czech Republic Koruna\0" "Germany\0" "DJ\0" "Djibouti\0" "DJF\0" "Djibouti Franc\0" "Denmark\0" "DKK\0" "Danish Krone\0" "DM\0" "Dominica\0" "Dominican Republic\0" "DOP\0" "Dominican Peso\0" "Algeria\0" "DZD\0" "Algerian Dinar\0" "Ecuador\0" "ECS\0" "Ecuador Sucre\0" "Estonia\0" "EEK\0" "Estonian Kroon\0" "Egypt\0" "EGP\0" "Egyptian Pound\0" "EH\0" "Western Sahara\0" "MAD\0" "Moroccan Dirham\0" "ER\0" "Eritrea\0" "ERN\0" "Eritrean Nakfa\0" "Spain\0" "ET\0" "Ethiopia\0" "ETB\0" "Ethiopian Birr\0" "Finland\0" "FJ\0" "Fiji\0" "FJD\0" "Fiji Dollar\0" "FK\0" "Falkland Islands\0" "FKP\0" "Falkland Islands Pound\0" "FM\0" "Micronesia\0" "Faroe Islands\0" "France\0" "GA\0" "Gabon\0" "United Kingdom\0" "GBP\0" "British Pound Sterling\0" "GD\0" "Grenada\0" "Georgia\0" "GEL\0" "Georgian Lari\0" "GF\0" "French Guiana\0" "GH\0" "Ghana\0" "GHC\0" "Ghana Cedi\0" "GI\0" "Gibraltar\0" "GIP\0" "Gibraltar Pound\0" "GL\0" "Greenland\0" "GM\0" "Gambia\0" "GMD\0" "Gambia Dalasi\0" "GN\0" "Guinea\0" "GNF\0" "Guinea Franc\0" "GP\0" "Guadeloupe\0" "GQ\0" "Equatorial Guinea\0" "Greece\0" "Guatemala\0" "GTQ\0" "Guatemala Quetzal\0" "GU\0" "Guam\0" "GY\0" "Guyana\0" "GYD\0" "Guyana Dollar\0" "Hong Kong S.A.R., China\0" "HKD\0" "Hong Kong Dollar\0" "HM\0" "Heard Island and McDonald Islands\0" "Honduras\0" "HNL\0" "Hoduras Lempira\0" "Croatia\0" "HRK\0" "Croatian Kuna\0" "Hungary\0" "HUF\0" "Hungarian Forint\0" "Indonesia\0" "IDR\0" "Indonesian Rupiah\0" "Ireland\0" "Israel\0" "ILS\0" "Israeli New Sheqel\0" "India\0" "INR\0" "Indian Rupee\0" "IO\0" "British Indian Ocean Territory\0" "Iraq\0" "IQD\0" "Iraqi Dinar\0" "Iran\0" "IRR\0" "Iranian Rial\0" "Iceland\0" "ISK\0" "Icelandic Krona\0" "Italy\0" "JM\0" "Jamaica\0" "JMD\0" "Jamaican Dollar\0" "Jordan\0" "JOD\0" "Jordanian Dinar\0" "Japan\0" "JPY\0" "Japanese Yen\0" "Kenya\0" "KES\0" "Kenyan Shilling\0" "KG\0" "Kyrgyzstan\0" "KGS\0" "Kyrgystan Som\0" "KH\0" "Cambodia\0" "KHR\0" "Cambodian Riel\0" "KI\0" "Kiribati\0" "KM\0" "Comoros\0" "KMF\0" "Comoro Franc\0" "KN\0" "Saint Kitts and Nevis\0" "KP\0" "North Korea\0" "KPW\0" "North Korean Won\0" "South Korea\0" "KRW\0" "South Korean Won\0" "Kuwait\0" "KWD\0" "Kuwaiti Dinar\0" "KY\0" "Cayman Islands\0" "KYD\0" "Cayman Islands Dollar\0" "KZ\0" "Kazakhstan\0" "KZT\0" "Kazakhstan Tenge\0" "LA\0" "Laos\0" "LAK\0" "Laotian Kip\0" "Lebanon\0" "LBP\0" "Lebanese Pound\0" "LC\0" "Saint Lucia\0" "LI\0" "Liechtenstein\0" "LK\0" "Sri Lanka\0" "LKR\0" "Sri Lanka Rupee\0" "LR\0" "Liberia\0" "LRD\0" "Liberian Dollar\0" "Lithuania\0" "LTL\0" "Lithuanian Lita\0" "Luxembourg\0" "Latvia\0" "LVL\0" "Latvian Lats\0" "Libya\0" "LYD\0" "Libyan Dinar\0" "Morocco\0" "MC\0" "Monaco\0" "Moldova\0" "MDL\0" "Moldovan Leu\0" "MG\0" "Madagascar\0" "MGF\0" "Madagascar Franc\0" "MH\0" "Marshall Islands\0" "Macedonia\0" "MKD\0" "Macedonian Denar\0" "ML\0" "Mali\0" "MM\0" "Myanmar\0" "MMK\0" "Myanmar Kyat\0" "MN\0" "Mongolia\0" "MNT\0" "Mongolian Tugrik\0" "Macao S.A.R. China\0" "MOP\0" "Macao Pataca\0" "MP\0" "Northern Mariana Islands\0" "MQ\0" "Martinique\0" "MR\0" "Mauritania\0" "MRO\0" "Mauritania Ouguiya\0" "MS\0" "Montserrat\0" "MT\0" "Malta\0" "MTL\0" "Maltese Lira\0" "MU\0" "Mauritius\0" "MUR\0" "Mauritius Rupee\0" "MV\0" "Maldives\0" "MVR\0" "Maldive Islands Rufiyaa\0" "MW\0" "Malawi\0" "MWK\0" "Malawi Kwacha\0" "Mexico\0" "MXN\0" "Mexican Peso\0" "MY\0" "Malaysia\0" "MYR\0" "Malaysian Ringgit\0" "MZ\0" "Mozambique\0" "MZM\0" "Mozambique Metical\0" "NC\0" "New Caledonia\0" "XPF\0" "CFP Franc\0" "NE\0" "Niger\0" "NF\0" "Norfolk Island\0" "NG\0" "Nigeria\0" "NGN\0" "Nigerian Naira\0" "Nicaragua\0" "NIO\0" "Nicaraguan Cordoba Oro\0" "Netherlands\0" "Norway\0" "NP\0" "Nepal\0" "NPR\0" "Nepalese Rupee\0" "NR\0" "Nauru\0" "NU\0" "Niue\0" "New Zealand\0" "Oman\0" "OMR\0" "Oman Rial\0" "Panama\0" "PAB\0" "Panamanian Balboa\0" "Peru\0" "PEN\0" "Peruvian Sol Nuevo\0" "PF\0" "French Polynesia\0" "PG\0" "Papua New Guinea\0" "PGK\0" "Papua New Guinea Kina\0" "Philippines\0" "Philippine Peso\0" "PK\0" "Pakistan\0" "PKR\0" "Pakistan Rupee\0" "Poland\0" "PLN\0" "Polish Zloty\0" "Saint Pierre and Miquelon\0" "PN\0" "Pitcairn\0" "Puerto Rico\0" "Portugal\0" "PW\0" "Palau\0" "Paraguay\0" "PYG\0" "Paraguay Guarani\0" "Qatar\0" "QAR\0" "Qatari Rial\0" "RE\0" "R\xc3\xa9union\0" "Romania\0" "ROL\0" "Romanian Leu\0" "Russia\0" "RUR\0" "Russian Ruble (1991-1998)\0" "RW\0" "Rwanda\0" "RWF\0" "Rwandan Franc\0" "Saudi Arabia\0" "SAR\0" "Saudi Riyal\0" "SB\0" "Solomon Islands\0" "SBD\0" "Solomon Islands Dollar\0" "SC\0" "Seychelles\0" "SCR\0" "Seychelles Rupee\0" "SD\0" "Sudan\0" "SDD\0" "Sudanese Dinar\0" "Sweden\0" "SEK\0" "Swedish Krona\0" "Singapore\0" "SGD\0" "Singapore Dollar\0" "SH\0" "Saint Helena\0" "SHP\0" "Saint Helena Pound\0" "Slovenia\0" "Slovenia Tolar\0" "SJ\0" "Svalbard and Jan Mayen\0" "Slovakia\0" "SKK\0" "Slovak Koruna\0" "SL\0" "Sierra Leone\0" "SLL\0" "Sierra Leone Leone\0" "SM\0" "San Marino\0" "SN\0" "Senegal\0" "SO\0" "Somalia\0" "SOS\0" "Somali Shilling\0" "SR\0" "Suriname\0" "SRG\0" "Suriname Guilder\0" "ST\0" "Sao Tome and Principe\0" "STD\0" "Sao Tome and Principe Dobra\0" "El Salvador\0" "El Salvador Colon\0" "Syria\0" "SYP\0" "Syrian Pound\0" "SZ\0" "Swaziland\0" "SZL\0" "Swaziland Lilangeni\0" "TC\0" "Turks and Caicos Islands\0" "TD\0" "Chad\0" "TF\0" "French Southern Territories\0" "TG\0" "Togo\0" "Thailand\0" "THB\0" "Thai Baht\0" "TJ\0" "Tajikistan\0" "TJS\0" "Tajikistan Somoni\0" "TK\0" "Tokelau\0" "Timor-Leste\0" "TM\0" "Turkmenistan\0" "TMM\0" "Turkmenistan Manat\0" "Tunisia\0" "TND\0" "Tunisian Dinar\0" "TO\0" "Tonga\0" "TOP\0" "Tonga Pa\xc2\xb4\x61nga\0" "Turkey\0" "TRL\0" "Turkish Lira\0" "Trinidad and Tobago\0" "TTD\0" "Trinidad and Tobago Dollar\0" "TV\0" "Tuvalu\0" "Taiwan\0" "TWD\0" "Taiwan New Dollar\0" "TZ\0" "Tanzania\0" "TZS\0" "Tanzanian Shilling\0" "Ukraine\0" "UAH\0" "Ukrainian Hryvnia\0" "UG\0" "Uganda\0" "UGX\0" "Ugandan Shilling\0" "UM\0" "United States Minor Outlying Islands\0" "United States\0" "Uruguay\0" "UYU\0" "Uruguay Peso Uruguayo\0" "UZ\0" "Uzbekistan\0" "UZS\0" "Uzbekistan Sum\0" "VA\0" "Vatican\0" "VC\0" "Saint Vincent and the Grenadines\0" "Venezuela\0" "VEB\0" "Venezuelan Bolivar\0" "VG\0" "British Virgin Islands\0" "U.S. Virgin Islands\0" "Vietnam\0" "VND\0" "Vietnamese Dong\0" "VU\0" "Vanuatu\0" "VUV\0" "Vanuatu Vatu\0" "WF\0" "Wallis and Futuna\0" "WS\0" "Samoa\0" "WST\0" "Western Samoa Tala\0" "Yemen\0" "YER\0" "Yemeni Rial\0" "YT\0" "Mayotte\0" "YU\0" "Yugoslavia\0" "YUM\0" "Yugoslavian Noviy Dinar\0" "South Africa\0" "ZAR\0" "South African Rand\0" "ZM\0" "Zambia\0" "ZMK\0" "Zambian Kwacha\0" "Zimbabwe\0" "ZWD\0" "Zimbabwe Dollar\0" }; #else static const DateTimeFormatEntry datetime_format_entries[] = { { 1, 0, 0, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 9, 18, 25, 45, 65, 89, 113, 120, 131, 142, 151, 169, 0 }, { 9, 18, 25, 45, 65, 89, 113, 120, 131, 142, 151, 169, 0 }, { 9, 18, 25, 45, 65, 89, 113, 120, 131, 142, 151, 169, 0 }, { 9, 18, 25, 45, 65, 89, 113, 120, 131, 142, 151, 169, 0 }, 0, 6, 185, 187, { 189, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 209, 222, 0, 0, 0, 0, 0, 0, 0, 0 }, { 242, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 257, 269, 0, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 296, 307, { 318, 331, 352, 367, 378, 397, 408 }, { 421, 426, 431, 436, 441, 446, 451 }, { 456, 459, 462, 465, 468, 459, 465 }, { 471, 484, 501, 510, 521, 528, 535, 542, 555, 574, 591, 606, 0 }, { 471, 484, 501, 510, 521, 528, 535, 542, 555, 574, 591, 606, 0 }, { 623, 629, 501, 639, 521, 528, 535, 647, 655, 665, 673, 683, 0 }, { 623, 629, 501, 639, 521, 528, 535, 647, 655, 665, 673, 683, 0 }, 2, 1, 691, 187, { 693, 708, 724, 740, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 757, 776, 794, 819, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 856, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 872, 878, { 884, 893, 901, 909, 918, 925, 935 }, { 944, 948, 952, 956, 960, 964, 968 }, { 972, 975, 978, 981, 984, 987, 990 }, { 993, 999, 1006, 1012, 1018, 1023, 1028, 1035, 1041, 1050, 1058, 1067, 0 }, { 993, 999, 1006, 1012, 1018, 1023, 1028, 1035, 1041, 1050, 1058, 1067, 0 }, { 1076, 1081, 1006, 1086, 1018, 1023, 1091, 1096, 1100, 1105, 1110, 1115, 0 }, { 1076, 1081, 1006, 1086, 1018, 1023, 1091, 1096, 1100, 1105, 1110, 1115, 0 }, 2, 1, 185, 187, { 1120, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1140, 1163, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 1180, 0, 0, 0, 0, 0, 0, 0 } }, { 1195, 1204, 1211, { 1218, 1228, 1238, 1248, 1258, 1268, 1278 }, { 1288, 1295, 1302, 1309, 1316, 1323, 1330 }, { 1337, 1341, 1345, 1349, 1353, 1357, 1361 }, { 1365, 1372, 1379, 1386, 1393, 1400, 1407, 1414, 1421, 1428, 1435, 1445, 0 }, { 1365, 1372, 1379, 1386, 1393, 1400, 1407, 1414, 1421, 1428, 1435, 1445, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, 0, 0, 185, 187, { 1518, 1527, 1536, 1545, 1556, 1567, 1578, 1585, 1592, 1599, 0, 0, 0, 0 }, { 1608, 1630, 1658, 1686, 1701, 0, 0, 0, 0, 0 }, { 843, 251, 1722, 1730, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 1739, 1750, 0, 0, 0, 0, 0 }, { 1762, 1778, 1791, 1805, 0, 0, 0, 0 } }, { 1195, 1204, 1211, { 1218, 1228, 1238, 1248, 1258, 1268, 1278 }, { 1288, 1295, 1302, 1309, 1316, 1323, 1330 }, { 1337, 1341, 1345, 1349, 1353, 1357, 1361 }, { 1365, 1372, 1379, 1386, 1393, 1400, 1407, 1414, 1421, 1428, 1435, 1445, 0 }, { 1365, 1372, 1379, 1386, 1393, 1400, 1407, 1414, 1421, 1428, 1435, 1445, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, 0, 0, 185, 187, { 1518, 1527, 1536, 1545, 1556, 1567, 1578, 1585, 1592, 1599, 0, 0, 0, 0 }, { 1608, 1630, 1658, 1686, 1701, 0, 0, 0, 0, 0 }, { 843, 251, 1722, 1730, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 1739, 1750, 0, 0, 0, 0, 0 }, { 1762, 1778, 1791, 1805, 0, 0, 0, 0 } }, { 1812, 1820, 1823, { 1826, 1834, 1844, 1852, 1860, 1869, 1876 }, { 1883, 1886, 1889, 1893, 1896, 1900, 1904 }, { 1907, 1909, 1911, 1914, 1916, 1909, 1914 }, { 1919, 1925, 1931, 1939, 1945, 1953, 1961, 1971, 1977, 1985, 1993, 2002, 0 }, { 2011, 2017, 2024, 2032, 2038, 2046, 2054, 2064, 1977, 2070, 2078, 2088, 0 }, { 2097, 2101, 2106, 2111, 2115, 2120, 2125, 2130, 2134, 2140, 2146, 2150, 0 }, { 2097, 2101, 2106, 2111, 2115, 2120, 2125, 2130, 2134, 2140, 2146, 2150, 0 }, 2, 1, 691, 187, { 2154, 2165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2176, 2194, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 1820, 1823, { 2217, 2225, 2232, 2240, 2247, 2255, 2262 }, { 2270, 2275, 2279, 2283, 2287, 2291, 2295 }, { 1914, 2300, 2302, 2304, 2302, 2306, 2308 }, { 2310, 2317, 2325, 2331, 2337, 2341, 2346, 2351, 2358, 2368, 2376, 2385, 0 }, { 2310, 2317, 2325, 2331, 2337, 2341, 2346, 2351, 2358, 2368, 2376, 2385, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 2418, 2422, 2426, 2430, 2434, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 2418, 2422, 2426, 2430, 2434, 0 }, 2, 1, 2438, 187, { 2440, 2451, 1556, 2460, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2194, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 2471, 2477, { 2484, 2492, 2499, 2508, 2517, 2528, 2536 }, { 2544, 2547, 2550, 2553, 2556, 2559, 2562 }, { 1914, 2300, 2565, 2300, 2565, 2306, 1914 }, { 2567, 2574, 2582, 2588, 2594, 2598, 2603, 2608, 2615, 2625, 2633, 2642, 0 }, { 2567, 2574, 2582, 2588, 2594, 2598, 2603, 2608, 2615, 2625, 2633, 2642, 0 }, { 2651, 2655, 2659, 2664, 2594, 2668, 2672, 2676, 2680, 2684, 2688, 2692, 0 }, { 2651, 2655, 2659, 2664, 2594, 2668, 2672, 2676, 2680, 2684, 2688, 2692, 0 }, 2, 1, 691, 187, { 2154, 2696, 1556, 2705, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2719, 2194, 2738, 0, 0, 0, 0, 0, 0, 0 }, { 251, 2751, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 2763, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 2778, 2785, { 2792, 2807, 2822, 2833, 2848, 2861, 2880 }, { 2895, 2902, 2909, 2916, 2923, 2930, 2937 }, { 2944, 2947, 2950, 2950, 2953, 2953, 2956 }, { 2959, 2980, 3003, 3018, 3035, 3046, 3061, 3076, 3095, 3118, 3137, 3156, 0 }, { 3177, 3198, 3221, 3236, 3253, 3264, 3279, 3294, 3313, 3336, 3355, 3374, 0 }, { 3395, 3402, 3409, 3416, 3423, 3430, 3439, 3448, 3455, 3462, 3469, 3476, 0 }, { 3395, 3402, 3409, 3416, 3423, 3430, 3439, 3448, 3455, 3462, 3469, 3476, 0 }, 2, 1, 185, 187, { 1120, 198, 3483, 189, 3490, 1556, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 242, 843, 251, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 257, 848, 269, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 1820, 1823, { 3558, 3565, 3572, 3580, 3590, 3599, 3606 }, { 3615, 3619, 3623, 3627, 3631, 3635, 3639 }, { 1914, 2300, 2302, 3643, 2302, 2306, 1914 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, 0, 0, 185, 187, { 3711, 3720, 3727, 3736, 1599, 1556, 3747, 0, 0, 0, 0, 0, 0, 0 }, { 3757, 3776, 3789, 3808, 0, 0, 0, 0, 0, 0 }, { 3532, 242, 843, 251, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 257, 848, 269, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3821, 872, 878, { 3833, 3841, 3847, 3854, 3865, 3872, 3880 }, { 3888, 3893, 3898, 3903, 3909, 3914, 3919 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 3929, 3935, 3943, 3949, 3955, 3960, 3966, 3972, 3979, 3990, 3998, 4008, 0 }, { 4018, 4024, 4032, 1012, 4038, 4043, 4049, 4055, 4062, 1050, 4073, 4083, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, 0, 1, 185, 187, { 198, 189, 4149, 3483, 4157, 2451, 2696, 1556, 0, 0, 0, 0, 0, 0 }, { 4164, 4192, 4219, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 4241, 4246, 4252, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 4260, 4268, 4277, 0, 0, 0, 0 }, { 4288, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 4303, 4307, { 4311, 4323, 4335, 4345, 4359, 4369, 4381 }, { 4392, 4395, 4398, 4401, 4404, 4407, 4410 }, { 1914, 2300, 2302, 4413, 2302, 1909, 2308 }, { 4415, 4424, 4433, 4443, 4452, 4461, 4470, 4480, 4487, 4495, 4503, 4513, 0 }, { 4522, 4533, 4544, 4556, 4567, 4578, 4589, 4601, 4610, 4620, 4630, 4642, 0 }, { 4653, 4659, 4665, 4672, 4678, 4684, 4690, 4697, 4701, 4706, 4711, 4718, 0 }, { 4653, 4659, 4665, 4672, 4678, 4684, 4690, 4697, 4701, 4706, 4711, 4718, 0 }, 2, 1, 691, 691, { 4724, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2176, 2194, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4260, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 4733, 4742, 4748, 4754, 4763, 4769, 4778 }, { 4785, 4790, 4795, 4800, 4805, 4810, 4815 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 4820, 4828, 4837, 4842, 4848, 4852, 4857, 4865, 4871, 4881, 1058, 4889, 0 }, { 4820, 4828, 4837, 4842, 4848, 4852, 4857, 4865, 4871, 4881, 1058, 4889, 0 }, { 4899, 4905, 4837, 4912, 4848, 4852, 4917, 4865, 4923, 1105, 1110, 4929, 0 }, { 4899, 4905, 4837, 4912, 4848, 4852, 4917, 4865, 4923, 1105, 1110, 4929, 0 }, 0, 1, 185, 187, { 198, 189, 2696, 2451, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4935, 3520, 4952, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 4246, 4961, 4971, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 4979, 4992, { 5003, 5021, 5035, 5053, 5071, 5089, 5105 }, { 5119, 5131, 5143, 5155, 5167, 5179, 5191 }, { 5198, 5203, 5208, 5213, 5218, 5223, 5228 }, { 5233, 5244, 5257, 5264, 5275, 5282, 5291, 5300, 5313, 5326, 5341, 5354, 0 }, { 5233, 5244, 5257, 5264, 5275, 5282, 5291, 5300, 5313, 5326, 5341, 5354, 0 }, { 5365, 5374, 5257, 5383, 5275, 5392, 5401, 5410, 5419, 5428, 5437, 5446, 0 }, { 5365, 5374, 5257, 5383, 5275, 5392, 5401, 5410, 5419, 5428, 5437, 5446, 0 }, 0, 0, 185, 187, { 198, 5455, 189, 209, 2451, 2440, 5468, 1556, 5481, 5498, 0, 0, 0, 0 }, { 5508, 5455, 5526, 5548, 5481, 0, 0, 0, 0, 0 }, { 251, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 257, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 5569, 5577, 5581, { 5585, 5595, 5603, 5608, 5615, 5628, 5636 }, { 3927, 5644, 4413, 5646, 5650, 1909, 5653 }, { 3927, 5644, 4413, 5657, 5650, 1909, 5657 }, { 5660, 5668, 5677, 5686, 5695, 5702, 5710, 5718, 5728, 5739, 2376, 2385, 0 }, { 5660, 5668, 5677, 5686, 5695, 5702, 5710, 5718, 5728, 5739, 2376, 2385, 0 }, { 5748, 5753, 5759, 5766, 5772, 5778, 5784, 5790, 5795, 5802, 1110, 5807, 0 }, { 5748, 5753, 5759, 5766, 5772, 5778, 5784, 5790, 5795, 5802, 1110, 5807, 0 }, 2, 1, 5812, 187, { 5815, 5829, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5842, 5862, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5876, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 5887, 5892, { 5897, 5908, 5919, 5933, 5947, 5959, 5971 }, { 5983, 5988, 5994, 6000, 6006, 6011, 6017 }, { 1914, 2300, 6022, 2300, 2306, 2306, 2308 }, { 6025, 6033, 4837, 6042, 6049, 6054, 6061, 6068, 2358, 5739, 6076, 6086, 0 }, { 6025, 6033, 4837, 6042, 6049, 6054, 6061, 6068, 2358, 5739, 6076, 6086, 0 }, { 5748, 1081, 4795, 6095, 6049, 5778, 5784, 6100, 6107, 5802, 6112, 1115, 0 }, { 5748, 1081, 4795, 6095, 6049, 5778, 5784, 6100, 6107, 5802, 6112, 1115, 0 }, 2, 1, 691, 187, { 4724, 6118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2719, 2194, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 6130, 6139, 6147, 6156, 6167, 6176, 6185 }, { 6192, 6196, 2402, 6200, 6204, 6208, 6212 }, { 2565, 2308, 2300, 2300, 6216, 3927, 1914 }, { 6218, 6226, 3943, 6235, 6242, 6249, 6256, 3972, 6263, 6273, 6281, 6290, 0 }, { 6299, 6307, 4032, 6316, 6323, 6330, 6337, 4055, 6344, 6354, 1058, 6362, 0 }, { 6371, 2398, 2402, 2406, 6375, 6379, 6383, 6387, 6391, 6395, 2430, 6399, 0 }, { 6371, 2398, 2402, 2406, 6375, 6379, 6383, 6387, 6391, 6395, 2430, 6399, 0 }, 2, 1, 185, 187, { 198, 3490, 189, 6403, 3483, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4935, 6411, 3520, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1195, 6420, 6427, { 6434, 6444, 6454, 6464, 6474, 6484, 6494 }, { 1337, 6504, 6508, 6512, 6516, 6520, 6524 }, { 1337, 6504, 6508, 6512, 6516, 6520, 6524 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, 0, 0, 185, 187, { 1545, 1599, 1578, 1518, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1608, 6555, 6579, 6606, 6635, 6659, 6688, 6708, 0, 0 }, { 843, 251, 1722, 1730, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 1739, 1750, 0, 0, 0, 0, 0 }, { 1762, 6733, 1791, 0, 0, 0, 0, 0 } }, { 6751, 6761, 6768, { 6775, 6785, 6795, 6805, 6815, 6825, 6835 }, { 6845, 6849, 6853, 6857, 6861, 6865, 6869 }, { 6845, 6849, 6853, 6857, 6861, 6865, 6869 }, { 6873, 6878, 6883, 6888, 6893, 6898, 6903, 6908, 6913, 6918, 6924, 6930, 0 }, { 6873, 6878, 6883, 6888, 6893, 6898, 6903, 6908, 6913, 6918, 6924, 6930, 0 }, { 6873, 6878, 6883, 6888, 6893, 6898, 6903, 6908, 6913, 6918, 6924, 6930, 0 }, { 6873, 6878, 6883, 6888, 6893, 6898, 6903, 6908, 6913, 6918, 6924, 6930, 0 }, 0, 0, 2438, 187, { 1556, 6936, 1585, 1527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 6945, 6974, 6998, 7025, 7047, 7078, 7104, 7135, 7161, 7188 }, { 1722, 1730, 843, 251, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1739, 1750, 848, 269, 0, 0, 0, 0, 0 }, { 7210, 7227, 7246, 0, 0, 0, 0, 0 } }, { 289, 7261, 7266, { 7271, 7278, 7286, 7294, 7303, 7313, 7321 }, { 7330, 4395, 7333, 7336, 7339, 7342, 7345 }, { 7348, 2300, 2565, 3643, 2565, 3927, 7348 }, { 7350, 7358, 7367, 2331, 7373, 2341, 2346, 7377, 2358, 2368, 2376, 2385, 0 }, { 7350, 7358, 7367, 2331, 7373, 2341, 2346, 7377, 2358, 2368, 2376, 2385, 0 }, { 2394, 2398, 7386, 2406, 7373, 2410, 2414, 2418, 2422, 2426, 2430, 2434, 0 }, { 2394, 2398, 7386, 2406, 7373, 2410, 2414, 2418, 2422, 2426, 2430, 2434, 0 }, 2, 1, 2438, 187, { 7390, 4157, 2451, 189, 2696, 7399, 1556, 0, 0, 0, 0, 0, 0, 0 }, { 4935, 6411, 3520, 4952, 0, 0, 0, 0, 0, 0 }, { 251, 843, 4241, 7411, 7423, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 7435, 7450, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 7465, 7261, 7266, { 2217, 2225, 2232, 2240, 2247, 2255, 2262 }, { 7473, 7478, 7482, 7486, 7490, 7494, 7498 }, { 1914, 2300, 2302, 2304, 2302, 2306, 2308 }, { 2310, 2317, 4837, 2331, 4848, 2341, 2346, 2351, 2358, 2368, 2376, 6086, 0 }, { 2310, 2317, 4837, 2331, 4848, 2341, 2346, 2351, 2358, 2368, 2376, 6086, 0 }, { 2394, 2398, 2402, 2406, 4848, 2410, 2414, 2418, 2422, 2426, 2430, 7503, 0 }, { 2394, 2398, 2402, 2406, 4848, 2410, 2414, 2418, 2422, 2426, 2430, 7503, 0 }, 0, 0, 691, 691, { 2154, 6118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2176, 2194, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4246, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4268, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 7507, 7517, 7531, 7538, 7545, 7554, 1876 }, { 7562, 7569, 7574, 7578, 7583, 7588, 7592 }, { 1907, 1909, 3643, 7597, 7600, 1909, 1914 }, { 7602, 7611, 7616, 7623, 2337, 7633, 7642, 7649, 7659, 7669, 1993, 7682, 0 }, { 7692, 7701, 7708, 7714, 7723, 7728, 7736, 7742, 7751, 7761, 7775, 7785, 0 }, { 7793, 7797, 2402, 7801, 2337, 7805, 7809, 7813, 7817, 7821, 2146, 7826, 0 }, { 7793, 7797, 2402, 7801, 2337, 7805, 7809, 7813, 7817, 7821, 2146, 7826, 0 }, 2, 1, 691, 187, { 2154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3821, 1820, 1823, { 3833, 7830, 7844, 7857, 7870, 7883, 3880 }, { 6192, 7895, 7899, 7903, 7907, 7911, 7915 }, { 2565, 1914, 2302, 7920, 7920, 1914, 1914 }, { 7922, 7930, 7940, 1012, 7947, 7952, 7958, 4055, 7964, 7973, 7981, 7990, 0 }, { 7922, 7930, 7940, 1012, 7947, 7952, 7958, 4055, 7964, 7973, 7981, 7990, 0 }, { 2394, 7999, 2402, 8003, 4848, 2410, 2414, 6387, 6391, 8007, 2430, 8011, 0 }, { 2394, 7999, 2402, 8003, 4848, 2410, 2414, 6387, 6391, 8007, 2430, 8011, 0 }, 0, 0, 185, 187, { 198, 189, 1120, 3483, 2451, 2440, 4157, 7390, 2696, 2154, 7399, 8015, 4724, 1556 }, { 4164, 4219, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4288, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 8022, 8025, { 8028, 8037, 4748, 8047, 8055, 8063, 8072 }, { 8078, 8081, 4395, 8085, 8088, 8092, 1904 }, { 2565, 6216, 2300, 2300, 6216, 3927, 1914 }, { 8095, 8103, 4837, 8110, 8117, 8122, 8132, 8140, 8146, 8156, 2376, 2385, 0 }, { 8095, 8103, 4837, 8110, 8117, 8122, 8132, 8140, 8146, 8156, 2376, 2385, 0 }, { 8164, 8171, 4837, 4912, 8117, 8177, 8184, 8140, 8189, 1105, 1110, 5807, 0 }, { 8164, 8171, 4837, 4912, 8117, 8177, 8184, 8140, 8189, 1105, 1110, 5807, 0 }, 2, 1, 2438, 187, { 2440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 8195, 8224, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 7261, 7266, { 8241, 8251, 8256, 8263, 8272, 8276, 8283 }, { 8294, 8298, 3699, 8302, 8306, 8310, 8314 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 8319, 8328, 8338, 8345, 4848, 8353, 8359, 2351, 8365, 8376, 8386, 8396, 0 }, { 8319, 8328, 8338, 8345, 4848, 8353, 8359, 2351, 8365, 8376, 8386, 8396, 0 }, { 8406, 1081, 4795, 6095, 4848, 8411, 8416, 5790, 4923, 1105, 1110, 5807, 0 }, { 8406, 1081, 4795, 6095, 4848, 8411, 8416, 5790, 4923, 1105, 1110, 5807, 0 }, 0, 1, 691, 187, { 2154, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 8421, 8441, { 8467, 8490, 352, 8513, 8524, 8539, 8554 }, { 8569, 8574, 8579, 8584, 8589, 8594, 8599 }, { 8604, 8607, 8604, 8610, 8613, 8607, 8610 }, { 8616, 8629, 8644, 8653, 8666, 8673, 8682, 8691, 8704, 8721, 8736, 8749, 0 }, { 8764, 8777, 8792, 8803, 8816, 8823, 8832, 8841, 8856, 8873, 8888, 8901, 0 }, { 8916, 8924, 8644, 8934, 8666, 8673, 8682, 8942, 8950, 8960, 8968, 8978, 0 }, { 8916, 8924, 8644, 8934, 8666, 8673, 8682, 8942, 8950, 8960, 8968, 8978, 0 }, 0, 1, 691, 187, { 2154, 2696, 8015, 2440, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 776, 757, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 1820, 1823, { 8986, 8995, 9007, 9014, 9022, 9032, 9038 }, { 9045, 9049, 9053, 9057, 9061, 9066, 9070 }, { 9074, 9076, 9078, 9080, 9082, 9076, 9080 }, { 9085, 9095, 9104, 9112, 9120, 9128, 9135, 9142, 9150, 1993, 9156, 9164, 0 }, { 9173, 9183, 9192, 9200, 9208, 9216, 9223, 9230, 9239, 7775, 9245, 9255, 0 }, { 9264, 9268, 9273, 9278, 9282, 7809, 2130, 9286, 9290, 2146, 9294, 2150, 0 }, { 9264, 9268, 9273, 9278, 9282, 7809, 2130, 9286, 9290, 2146, 9294, 2150, 0 }, 0, 1, 691, 187, { 9298, 9308, 9316, 9328, 9340, 9350, 9360, 1556, 0, 0, 0, 0, 0, 0 }, { 9372, 9386, 9401, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 1820, 1823, { 9421, 9429, 9438, 9445, 9452, 9461, 1876 }, { 1883, 1886, 9468, 1893, 9471, 9475, 1904 }, { 1907, 1909, 9478, 1914, 9480, 1909, 1914 }, { 5660, 5668, 9483, 6042, 9489, 9494, 9499, 2351, 2358, 5739, 2376, 2385, 0 }, { 9504, 9513, 7708, 9523, 9531, 9537, 9543, 9549, 9557, 9567, 9576, 9585, 0 }, { 2394, 2398, 2402, 2406, 9489, 9494, 9499, 2418, 2422, 2426, 2430, 2434, 0 }, { 2394, 2398, 2402, 2406, 9489, 9494, 9499, 2418, 2422, 2426, 2430, 2434, 0 }, 2, 1, 691, 187, { 2154, 2165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2719, 2194, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 9594, 9603, { 9611, 9618, 9627, 9636, 9648, 9656, 9665 }, { 9675, 9679, 3699, 9684, 9689, 9693, 9697 }, { 2565, 5644, 2300, 2300, 9701, 1909, 1914 }, { 9703, 9709, 4837, 9716, 2337, 9722, 9730, 9737, 9743, 9751, 9757, 9765, 0 }, { 9703, 9709, 4837, 9716, 2337, 9722, 9730, 9737, 9743, 9751, 9757, 9765, 0 }, { 2651, 9773, 3699, 9777, 9781, 9785, 9789, 9793, 9697, 9797, 9801, 9806, 0 }, { 2651, 9773, 3699, 9777, 9781, 9785, 9789, 9793, 9697, 9797, 9801, 9806, 0 }, 0, 1, 691, 187, { 4724, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 9810, 9823, 9826, { 9829, 9837, 9845, 2240, 2247, 2255, 9852 }, { 9860, 9865, 9870, 2283, 2287, 2291, 9874 }, { 1914, 2300, 2302, 2304, 2302, 2306, 2308 }, { 7350, 7358, 4837, 2331, 2337, 2341, 2346, 9879, 2358, 2368, 2376, 2385, 0 }, { 7350, 7358, 4837, 2331, 2337, 2341, 2346, 9879, 2358, 2368, 2376, 2385, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 2418, 2422, 2426, 2430, 2434, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 2418, 2422, 2426, 2430, 2434, 0 }, 2, 1, 2438, 187, { 1556, 6936, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 9887, 9905, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 9928, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 9938, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 0, 0, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, 0, 0, 185, 187, { 1120, 3483, 189, 198, 1129, 9951, 1556, 0, 0, 0, 0, 0, 0, 0 }, { 3520, 9963, 9979, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 3532, 242, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 3540, 257, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 10021, 10026, { 10030, 10036, 10046, 10052, 10063, 10073, 10078 }, { 10088, 10092, 10096, 10100, 10105, 10109, 10113 }, { 1909, 1909, 1914, 10117, 1909, 7600, 7600 }, { 10120, 10125, 10132, 10137, 10143, 10150, 10158, 10165, 10174, 10181, 10186, 10193, 0 }, { 10120, 10125, 10132, 10137, 10143, 10150, 10158, 10165, 10174, 10181, 10186, 10193, 0 }, { 10201, 10205, 3699, 10210, 3668, 10214, 10218, 10222, 10227, 10231, 10235, 10239, 0 }, { 10201, 10205, 3699, 10210, 3668, 10214, 10218, 10222, 10227, 10231, 10235, 10239, 0 }, 0, 1, 691, 187, { 10243, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10253, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 10270, 10288, { 10306, 10317, 10330, 10339, 10346, 10359, 10368 }, { 10306, 10317, 10330, 10339, 10346, 10359, 10368 }, { 1914, 2300, 2302, 3643, 2302, 2306, 1914 }, { 10377, 10388, 10399, 10408, 10419, 10426, 10433, 10446, 10455, 10466, 10479, 10490, 0 }, { 10377, 10388, 10399, 10408, 10419, 10426, 10433, 10446, 10455, 10466, 10479, 10490, 0 }, { 10377, 10388, 10399, 10408, 10419, 10426, 10433, 10446, 10455, 10466, 10479, 10490, 0 }, { 10377, 10388, 10399, 10408, 10419, 10426, 10433, 10446, 10455, 10466, 10479, 10490, 0 }, 0, 0, 185, 187, { 198, 189, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10501, 222, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 242, 843, 251, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 257, 848, 269, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 10515, 10522, 10528, 10535, 10540, 10546, 10552 }, { 10558, 10562, 10566, 10570, 10574, 10578, 10582 }, { 2300, 1914, 1914, 10586, 4413, 3925, 1914 }, { 10588, 10596, 10605, 2588, 10611, 2598, 2603, 10615, 2615, 2625, 2633, 10623, 0 }, { 10588, 10596, 10605, 2588, 10611, 2598, 2603, 10615, 2615, 2625, 2633, 10623, 0 }, { 2651, 2655, 3699, 2664, 10611, 2668, 2672, 10632, 2680, 2684, 2688, 10636, 0 }, { 2651, 2655, 3699, 2664, 10611, 2668, 2672, 10632, 2680, 2684, 2688, 10636, 0 }, 0, 0, 185, 691, { 198, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10640, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4246, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4268, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 10659, 10664, { 10669, 10682, 10701, 10718, 10731, 10744, 10761 }, { 10774, 8574, 8579, 8584, 8589, 8594, 8599 }, { 10779, 8607, 8604, 8610, 8613, 8607, 8610 }, { 10782, 10795, 10806, 10823, 10838, 10853, 10868, 10881, 10896, 10913, 10928, 10945, 0 }, { 10960, 10971, 10984, 10999, 11012, 11025, 11038, 11049, 11062, 11077, 11090, 11109, 0 }, { 11122, 11129, 11136, 11143, 11150, 11157, 11164, 11171, 11178, 11185, 11192, 11199, 0 }, { 11122, 11129, 11136, 11143, 11150, 11157, 11164, 11171, 11178, 11185, 11192, 11199, 0 }, 0, 1, 691, 187, { 2154, 2696, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 11206, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 11224, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 11240, 11253, { 11266, 11281, 11302, 11317, 11330, 11343, 10761 }, { 421, 426, 11358, 436, 11363, 446, 451 }, { 456, 459, 11368, 465, 468, 459, 465 }, { 11371, 11388, 11397, 11412, 521, 11429, 11444, 11457, 11472, 11489, 11510, 11527, 0 }, { 11542, 11559, 11572, 11589, 8816, 11608, 11623, 11636, 11649, 11664, 11687, 11706, 0 }, { 11719, 11726, 11733, 11740, 521, 11747, 11754, 11761, 11768, 11775, 11782, 11789, 0 }, { 11719, 11726, 11733, 11740, 521, 11747, 11754, 11761, 11768, 11775, 11782, 11789, 0 }, 0, 0, 691, 187, { 2696, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3520, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 0, 0, 0, 0, 0, 0, 0 }, { 11796, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 11810, 11815, { 11820, 11828, 11839, 11845, 11851, 11860, 1876 }, { 9045, 9049, 2287, 11866, 9061, 9066, 11870 }, { 9074, 9076, 11874, 9080, 9082, 9076, 9080 }, { 2310, 2317, 9483, 2331, 2337, 11876, 11882, 11888, 2358, 2368, 2376, 2385, 0 }, { 2310, 2317, 9483, 2331, 2337, 11876, 11882, 11888, 2358, 2368, 2376, 2385, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 11895, 2422, 2426, 2430, 2434, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 11895, 2422, 2426, 2430, 2434, 0 }, 0, 1, 5812, 187, { 11899, 6118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 11911, 11931, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 11945, 11950, { 11955, 11966, 11977, 11988, 11999, 12010, 12016 }, { 1909, 9701, 2302, 4413, 1907, 10586, 2308 }, { 1909, 9701, 2302, 4413, 1907, 10586, 2308 }, { 12025, 12033, 12042, 12049, 4848, 12056, 12062, 2351, 2358, 12068, 2376, 12077, 0 }, { 12025, 12033, 12042, 12049, 4848, 12056, 12062, 2351, 2358, 12068, 2376, 12077, 0 }, { 12087, 12092, 12042, 2406, 4848, 12056, 12062, 2418, 12098, 2426, 2430, 12103, 0 }, { 12087, 12092, 12042, 2406, 4848, 12056, 12062, 2418, 12098, 2426, 2430, 12103, 0 }, 2, 1, 691, 187, { 2154, 6118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2719, 2194, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12108, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 12116, 12133, { 12147, 12158, 12168, 12177, 12188, 12200, 12211 }, { 12221, 12224, 12227, 12230, 12233, 12236, 12239 }, { 1914, 1909, 2304, 2302, 7600, 1909, 1914 }, { 12242, 12252, 12263, 12269, 12278, 12284, 12292, 12300, 12308, 12319, 12328, 12338, 0 }, { 12348, 12358, 2325, 12369, 12378, 12384, 12392, 12400, 12408, 12419, 12428, 12438, 0 }, { 12448, 12454, 12263, 12460, 12278, 12465, 12471, 12477, 4128, 12482, 4139, 12487, 0 }, { 12448, 12454, 12263, 12460, 12278, 12465, 12471, 12477, 4128, 12482, 4139, 12487, 0 }, 0, 1, 691, 187, { 2154, 12492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12512, 12539, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12560, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 12576, 11815, { 12582, 12594, 12606, 12618, 12632, 12647, 12660 }, { 12674, 12677, 12680, 12683, 12686, 12689, 9471 }, { 1914, 1909, 12692, 2302, 4413, 1909, 9480 }, { 12694, 12701, 12709, 12715, 12724, 12733, 12743, 12749, 12760, 12770, 12777, 12787, 0 }, { 12694, 12701, 12709, 12715, 12724, 12733, 12743, 12749, 12760, 12770, 12777, 12787, 0 }, { 12795, 12801, 12806, 12811, 12816, 12821, 12828, 12834, 12840, 12846, 12852, 12859, 0 }, { 12795, 12801, 12806, 12811, 12816, 12821, 12828, 12834, 12840, 12846, 12852, 12859, 0 }, 2, 1, 2438, 187, { 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12866, 12894, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 12926, 12938, { 12950, 12965, 12980, 12995, 13012, 13031, 13042 }, { 13053, 13060, 13067, 13074, 13081, 13088, 13095 }, { 0, 0, 0, 0, 0, 0, 0 }, { 13102, 13113, 8644, 13126, 8666, 13137, 13144, 8691, 13151, 13166, 13179, 13190, 0 }, { 13102, 13113, 8644, 13126, 8666, 13137, 13144, 8691, 13151, 13166, 13179, 13190, 0 }, { 13203, 13210, 13217, 13224, 8666, 13137, 13144, 13231, 13238, 13245, 13252, 13259, 0 }, { 13203, 13210, 13217, 13224, 8666, 13137, 13144, 13231, 13238, 13245, 13252, 13259, 0 }, 0, 0, 691, 187, { 2154, 2696, 8015, 2440, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 13266, 13284, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 13303, 13323, { 13340, 13353, 13366, 13382, 13399, 13414, 13423 }, { 13340, 13353, 13366, 13382, 13399, 13414, 13423 }, { 13432, 13435, 13438, 13441, 13444, 13447, 13450 }, { 13453, 13466, 13477, 13486, 13497, 13502, 13511, 13522, 13529, 13544, 13555, 13568, 0 }, { 13581, 13596, 13477, 13486, 13609, 13502, 13616, 13522, 13529, 13544, 13555, 13568, 0 }, { 13453, 13466, 13477, 13486, 13497, 13502, 13511, 13522, 13529, 13544, 13555, 13568, 0 }, { 13453, 13466, 13477, 13486, 13497, 13502, 13511, 13522, 13529, 13544, 13555, 13568, 0 }, 0, 6, 185, 187, { 198, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 242, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 257, 269, 0, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 13629, 13632, { 13635, 13648, 13658, 13667, 13677, 13688, 13699 }, { 13711, 13714, 13719, 13724, 13729, 13734, 13739 }, { 13711, 13744, 13747, 13750, 13753, 13756, 13759 }, { 13762, 13771, 13780, 13789, 13798, 13807, 13816, 13825, 13834, 13843, 13853, 13863, 0 }, { 13873, 13882, 13891, 13900, 13909, 13918, 13927, 13936, 13945, 13954, 13964, 13974, 0 }, { 13984, 13990, 13996, 14002, 14008, 14014, 14020, 14026, 14032, 14038, 14045, 14052, 0 }, { 13984, 13990, 13996, 14002, 14008, 14014, 14020, 14026, 14032, 14038, 14045, 14052, 0 }, 0, 1, 185, 187, { 198, 189, 2451, 2440, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 242, 843, 251, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 257, 848, 269, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 14059, 14083, { 14107, 14120, 14141, 14160, 14181, 14200, 14213 }, { 14224, 14231, 14238, 14245, 14252, 14259, 14266 }, { 14273, 14276, 14276, 14279, 14282, 14285, 14290 }, { 14293, 14308, 14323, 14332, 14343, 14354, 14367, 14380, 14395, 14414, 14433, 14450, 0 }, { 14469, 14486, 14503, 14514, 14527, 14540, 14555, 14570, 14587, 14608, 14629, 14648, 0 }, { 14669, 14676, 14683, 14690, 14697, 14704, 14711, 14718, 14725, 14732, 14739, 14746, 0 }, { 14669, 14676, 14683, 14690, 14697, 14704, 14711, 14718, 14725, 14732, 14739, 14746, 0 }, 0, 1, 691, 187, { 2154, 2696, 14753, 198, 14763, 3490, 1556, 0, 0, 0, 0, 0, 0, 0 }, { 3808, 3502, 10640, 5455, 14774, 14785, 14797, 14814, 0, 0 }, { 251, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 0, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 14832, 14838, 14852, 14875, 14889, 14905, 14912 }, { 14921, 14924, 14929, 14935, 14939, 7600, 14944 }, { 6540, 6528, 6530, 6532, 6534, 6536, 6538 }, { 14948, 14955, 10132, 14962, 3668, 14968, 14974, 14980, 14987, 14996, 15004, 15011, 0 }, { 15018, 15025, 15032, 15037, 15043, 15047, 15052, 15057, 15064, 15073, 15081, 15088, 0 }, { 15095, 7999, 2402, 2406, 15043, 15099, 15103, 15107, 15111, 2426, 15115, 15119, 0 }, { 15095, 7999, 2402, 2406, 15043, 15099, 15103, 15107, 15111, 2426, 15115, 15119, 0 }, 0, 0, 691, 187, { 2154, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 15123, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 1820, 1823, { 15141, 15149, 15160, 15170, 15181, 15190, 15199 }, { 15209, 15213, 15217, 15221, 15225, 15229, 15233 }, { 15237, 12692, 12692, 12692, 2304, 2304, 2308 }, { 15239, 15249, 15257, 15265, 15273, 15281, 15288, 15296, 15304, 15311, 15317, 15324, 0 }, { 15332, 15343, 15352, 15361, 15370, 15379, 15387, 15396, 15405, 15413, 15420, 15428, 0 }, { 15437, 15442, 4795, 15447, 15452, 15457, 15462, 15467, 15472, 15477, 15482, 15487, 0 }, { 15437, 15442, 4795, 15447, 15452, 15457, 15462, 15467, 15472, 15477, 15482, 15487, 0 }, 2, 1, 185, 187, { 1545, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 15503, 15530, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 15551, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 15570, 15591, { 15608, 331, 352, 8513, 15621, 15638, 15649 }, { 15662, 15670, 15678, 15684, 15692, 15700, 15708 }, { 456, 459, 462, 465, 468, 459, 465 }, { 15716, 484, 501, 510, 15731, 15738, 15747, 542, 555, 574, 591, 606, 0 }, { 15716, 484, 501, 510, 15731, 15738, 15747, 542, 555, 574, 591, 606, 0 }, { 15756, 15764, 15772, 639, 15731, 15780, 15788, 647, 655, 665, 673, 683, 0 }, { 15756, 15764, 15772, 639, 15731, 15780, 15788, 647, 655, 665, 673, 683, 0 }, 0, 1, 691, 187, { 15796, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10640, 5455, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 15806, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 0, 0, { 15822, 15829, 15840, 15849, 15858, 15865, 15876 }, { 15886, 15890, 15894, 15898, 15902, 15905, 15909 }, { 0, 0, 0, 0, 0, 0, 0 }, { 15913, 15923, 15932, 15940, 15949, 15962, 15974, 15981, 15988, 15995, 16005, 16017, 0 }, { 15913, 15923, 15932, 15940, 15949, 15962, 15974, 15981, 15988, 15995, 16005, 16017, 0 }, { 16030, 16034, 16038, 16042, 16046, 16050, 16054, 16058, 16062, 16066, 16070, 16074, 0 }, { 16030, 16034, 16038, 16042, 16046, 16050, 16054, 16058, 16062, 16066, 16070, 16074, 0 }, 0, 0, 2438, 187, { 1556, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 16078, 16096, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 0, 0, { 16108, 16113, 16119, 16129, 16141, 16149, 16160 }, { 16169, 16173, 16177, 16181, 16185, 16189, 16193 }, { 0, 0, 0, 0, 0, 0, 0 }, { 16197, 16207, 16217, 16224, 16231, 2598, 16236, 16243, 16250, 16259, 16267, 16275, 0 }, { 16197, 16207, 16217, 16224, 16231, 2598, 16236, 16243, 16250, 16259, 16267, 16275, 0 }, { 2651, 2655, 15909, 16283, 16287, 2668, 2672, 16291, 2680, 2684, 2688, 16295, 0 }, { 2651, 2655, 15909, 16283, 16287, 2668, 2672, 16291, 2680, 2684, 2688, 16295, 0 }, 0, 0, 2438, 187, { 1556, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 16078, 16096, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 1820, 1823, { 16299, 16305, 16316, 16129, 16141, 16149, 16160 }, { 16326, 16330, 16334, 16181, 16185, 16189, 16193 }, { 1914, 2300, 16338, 2302, 1914, 5644, 2300 }, { 16340, 16350, 16361, 16368, 16377, 16383, 16389, 16397, 16405, 16416, 16426, 16435, 0 }, { 16444, 16207, 16453, 16459, 16231, 2598, 16236, 16243, 16466, 16259, 16267, 16275, 0 }, { 2651, 2655, 16476, 2664, 16287, 2668, 2672, 16291, 2680, 2684, 2688, 16295, 0 }, { 2651, 2655, 16476, 2664, 16287, 2668, 2672, 16291, 2680, 2684, 2688, 16295, 0 }, 0, 0, 185, 187, { 3711, 16480, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3757, 3776, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 16492, 16496, { 16500, 16507, 16515, 16523, 16532, 16542, 16549 }, { 2544, 16558, 2550, 16561, 2556, 16564, 2562 }, { 1914, 2300, 2565, 3643, 2565, 3927, 1914 }, { 16567, 16576, 16586, 2588, 10611, 16592, 16598, 16604, 2615, 2625, 2633, 10623, 0 }, { 16567, 16576, 16586, 2588, 10611, 16592, 16598, 16604, 2615, 2625, 2633, 10623, 0 }, { 2651, 2655, 3699, 2664, 10611, 2668, 2672, 2676, 2680, 2684, 2688, 10636, 0 }, { 2651, 2655, 3699, 2664, 10611, 2668, 2672, 2676, 2680, 2684, 2688, 10636, 0 }, 0, 0, 2438, 187, { 1556, 9951, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10640, 5455, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 16613, 16629, 16654, 16682, 16710, 16738, 16766 }, { 16785, 16795, 16805, 16815, 16825, 16835, 16845 }, { 16855, 16859, 16863, 16859, 16867, 16871, 16875 }, { 16879, 16901, 16929, 16945, 16964, 16980, 16999, 17018, 17040, 17071, 17099, 17124, 0 }, { 16879, 16901, 16929, 16945, 16964, 16980, 16999, 17018, 17040, 17071, 17099, 17124, 0 }, { 17152, 17162, 17172, 17182, 17192, 17202, 17212, 17222, 17232, 17242, 17252, 17262, 0 }, { 17152, 17162, 17172, 17182, 17192, 17202, 17212, 17222, 17232, 17242, 17252, 17262, 0 }, 0, 1, 691, 187, { 2154, 17272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 222, 3808, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 17284, 17289, { 5897, 17294, 17305, 17315, 17325, 17335, 17349 }, { 17361, 17365, 17370, 17375, 17379, 17384, 17389 }, { 1914, 2300, 2302, 2300, 5644, 2306, 2308 }, { 2310, 2317, 4837, 6042, 4848, 2341, 2346, 2351, 2358, 2368, 2376, 6086, 0 }, { 2310, 2317, 4837, 6042, 4848, 2341, 2346, 2351, 2358, 2368, 2376, 6086, 0 }, { 2394, 2398, 2402, 2406, 4848, 2410, 2414, 2418, 2422, 2426, 2430, 7503, 0 }, { 2394, 2398, 2402, 2406, 4848, 2410, 2414, 2418, 2422, 2426, 2430, 7503, 0 }, 2, 1, 2438, 187, { 2440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5508, 6118, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 17393, 17409, { 17419, 17438, 17457, 17479, 17498, 17520, 17545 }, { 17564, 17574, 17584, 17597, 17607, 17620, 17636 }, { 17646, 17650, 17657, 17664, 17671, 17678, 17685 }, { 17689, 17705, 17724, 17740, 17759, 17766, 17776, 17792, 17808, 17827, 17849, 17865, 0 }, { 17689, 17705, 17724, 17740, 17759, 17766, 17776, 17792, 17808, 17827, 17849, 17865, 0 }, { 17884, 17891, 17724, 17901, 17759, 17766, 17917, 17930, 17937, 17950, 17966, 17976, 0 }, { 17884, 17891, 17724, 17901, 17759, 17766, 17917, 17930, 17937, 17950, 17966, 17976, 0 }, 0, 0, 2438, 187, { 2440, 2451, 4157, 8015, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 1730, 1722, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 1750, 1739, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 17989, 18004, 18007, { 18010, 18019, 18028, 18038, 18048, 18058, 18070 }, { 18078, 18083, 18087, 18091, 18095, 18100, 18105 }, { 18109, 2302, 2302, 9701, 18109, 18112, 1914 }, { 18115, 18122, 18127, 2588, 18133, 18139, 18146, 18152, 18160, 18170, 18178, 18187, 0 }, { 18115, 18122, 18127, 2588, 18133, 18139, 18146, 18152, 18160, 18170, 18178, 18187, 0 }, { 2651, 18197, 3699, 2664, 18201, 18205, 18210, 18214, 18218, 18222, 2688, 18226, 0 }, { 2651, 18197, 3699, 2664, 18201, 18205, 18210, 18214, 18218, 18222, 2688, 18226, 0 }, 0, 0, 185, 187, { 198, 9951, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 18231, 18257, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 18277, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 18295, 18300, { 18305, 18317, 18328, 18342, 18354, 18364, 18374 }, { 18385, 18390, 18395, 18400, 18405, 18410, 18415 }, { 1914, 3927, 2300, 6216, 2565, 16338, 2308 }, { 18420, 18437, 18450, 18464, 18477, 18490, 18503, 18517, 18529, 18543, 18557, 18571, 0 }, { 18420, 18437, 18450, 18464, 18477, 18490, 18503, 18517, 18529, 18543, 18557, 18571, 0 }, { 18584, 18591, 18596, 18601, 18605, 18610, 18615, 18620, 18625, 18632, 18637, 18643, 0 }, { 18584, 18591, 18596, 18601, 18605, 18610, 18615, 18620, 18625, 18632, 18637, 18643, 0 }, 2, 1, 2438, 187, { 1556, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 16078, 16096, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 7261, 7266, { 18648, 18662, 18672, 18683, 18697, 18708, 18719 }, { 18732, 18737, 18742, 18749, 18755, 18761, 18767 }, { 2565, 2308, 2300, 7600, 2565, 12692, 1914 }, { 18772, 18780, 18788, 18795, 18804, 18814, 18824, 18830, 18838, 18853, 18871, 18879, 0 }, { 18772, 18780, 18788, 18795, 18804, 18814, 18824, 18830, 18838, 18853, 18871, 18879, 0 }, { 18887, 18891, 18788, 18897, 18901, 18906, 18824, 18912, 18917, 18924, 18931, 18936, 0 }, { 18887, 18891, 18788, 18897, 18901, 18906, 18824, 18912, 18917, 18924, 18931, 18936, 0 }, 2, 0, 185, 187, { 198, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4935, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 18941, 18944, { 18948, 18953, 10528, 10535, 18959, 18966, 10552 }, { 18973, 18977, 10566, 10570, 18981, 10578, 10582 }, { 12692, 15237, 1914, 10586, 4413, 3925, 1914 }, { 10588, 10596, 18985, 2588, 10611, 2668, 18989, 18995, 2615, 2625, 2633, 19000, 0 }, { 10588, 10596, 18985, 2588, 10611, 2668, 18989, 18995, 2615, 2625, 2633, 19000, 0 }, { 2651, 2655, 18985, 2664, 10611, 2668, 2672, 19009, 2680, 2684, 2688, 16295, 0 }, { 2651, 2655, 18985, 2664, 10611, 2668, 2672, 19009, 2680, 2684, 2688, 16295, 0 }, 0, 0, 185, 187, { 14753, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 19013, 19035, { 19059, 19074, 19091, 19108, 19125, 19142, 19151 }, { 19162, 19168, 19174, 19180, 19186, 19192, 19198 }, { 19204, 19207, 8610, 8610, 19210, 19204, 8610 }, { 19213, 19226, 19237, 19250, 19261, 19272, 19285, 19296, 19307, 19324, 19335, 19348, 0 }, { 19213, 19226, 19237, 19250, 19261, 19272, 19285, 19296, 19307, 19324, 19335, 19348, 0 }, { 19367, 19375, 19383, 19391, 19399, 19407, 19415, 19423, 19431, 19439, 19447, 19455, 0 }, { 19367, 19375, 19383, 19391, 19399, 19407, 19415, 19423, 19431, 19439, 19447, 19455, 0 }, 0, 0, 185, 187, { 198, 19465, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 19478, 19485, 19511, { 19539, 19546, 19553, 19560, 19567, 19574, 19581 }, { 19539, 19546, 19553, 19560, 19567, 19574, 19581 }, { 19204, 19207, 19588, 19588, 19210, 19204, 19591 }, { 19594, 19607, 501, 19622, 521, 19635, 19644, 542, 19653, 19670, 19685, 19698, 0 }, { 19594, 19607, 501, 19622, 521, 19635, 19644, 542, 19653, 19670, 19685, 19698, 0 }, { 19713, 15764, 15772, 639, 521, 19721, 19729, 647, 19737, 665, 19745, 683, 0 }, { 19713, 15764, 15772, 639, 521, 19721, 19729, 647, 19737, 665, 19745, 683, 0 }, 0, 0, 2438, 187, { 19753, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 19762, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 0, 0, 0, 0, 0, 0, 0 }, { 19781, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 19797, 19806, 19815, 19823, 19832, 19841, 19848 }, { 19857, 19860, 19863, 19866, 19869, 19873, 19876 }, { 6530, 6532, 6534, 6536, 12692, 15237, 6528 }, { 10588, 10596, 19879, 19885, 10611, 2598, 18989, 19892, 16250, 19899, 16267, 19906, 0 }, { 10588, 10596, 19879, 19885, 10611, 2598, 18989, 19892, 16250, 19899, 16267, 19906, 0 }, { 2651, 2655, 18985, 2664, 10611, 2668, 2672, 19914, 2680, 2684, 2688, 10636, 0 }, { 2651, 2655, 18985, 2664, 10611, 2668, 2672, 19914, 2680, 2684, 2688, 10636, 0 }, 0, 0, 185, 187, { 198, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 1820, 1823, { 19918, 19928, 19937, 19946, 19957, 19967, 19972 }, { 19979, 19985, 19990, 19995, 20000, 10578, 20004 }, { 20009, 2565, 1914, 7600, 1909, 3925, 1914 }, { 14948, 14955, 10132, 14962, 3668, 20011, 20016, 20021, 14987, 14996, 15004, 15011, 0 }, { 14948, 14955, 10132, 14962, 3668, 20011, 20016, 20021, 14987, 14996, 15004, 15011, 0 }, { 20028, 20033, 3699, 2664, 3668, 20011, 20016, 20037, 10562, 2684, 20041, 20046, 0 }, { 20028, 20033, 3699, 2664, 3668, 20011, 20016, 20037, 10562, 2684, 20041, 20046, 0 }, 0, 0, 185, 187, { 1545, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 20050, 16096, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 20069, 20097, { 20119, 20138, 20157, 20182, 20201, 20235, 20260 }, { 20279, 20289, 20299, 20315, 20325, 20350, 20366 }, { 20376, 20380, 20387, 20391, 20398, 20405, 20412 }, { 20416, 20444, 20478, 20494, 20513, 20520, 20530, 20546, 20562, 20593, 20615, 20637, 0 }, { 20416, 20444, 20478, 20494, 20513, 20520, 20530, 20546, 20562, 20593, 20615, 20637, 0 }, { 20416, 20444, 20478, 20494, 20513, 20520, 20530, 20546, 20562, 20593, 20615, 20637, 0 }, { 20416, 20444, 20478, 20494, 20513, 20520, 20530, 20546, 20562, 20593, 20615, 20637, 0 }, 0, 1, 2438, 691, { 2451, 4157, 2440, 2451, 2440, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4246, 4241, 20662, 20671, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4268, 4260, 20679, 20691, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 1820, 1823, { 20702, 20718, 20737, 20759, 20778, 20797, 20825 }, { 20847, 20855, 20866, 20880, 20891, 20902, 20922 }, { 20936, 20940, 20947, 20954, 20964, 20971, 20984 }, { 20991, 21007, 21026, 21039, 21058, 21065, 21075, 21091, 21104, 21120, 21139, 21155, 0 }, { 20991, 21007, 21026, 21039, 21058, 21065, 21075, 21091, 21104, 21120, 21139, 21155, 0 }, { 20991, 21007, 21026, 21039, 21058, 21065, 21075, 21091, 21104, 21120, 21139, 21155, 0 }, { 20991, 21007, 21026, 21039, 21058, 21065, 21075, 21091, 21104, 21120, 21139, 21155, 0 }, 0, 0, 2438, 187, { 2451, 4157, 8015, 2440, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 21171, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1730, 1722, 843, 251, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1750, 1739, 848, 269, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 1820, 1823, { 21189, 21208, 21227, 21249, 21268, 21290, 21315 }, { 21334, 21344, 21354, 21367, 21377, 21390, 21406 }, { 21416, 21420, 21427, 21434, 21441, 21448, 21455 }, { 21459, 21487, 21515, 21531, 21550, 21557, 21567, 21583, 21599, 21627, 21649, 21671, 0 }, { 21459, 21487, 21515, 21531, 21550, 21557, 21567, 21583, 21599, 21627, 21649, 21671, 0 }, { 21696, 21715, 21515, 21531, 21550, 21557, 21567, 21734, 21741, 21757, 21773, 21783, 0 }, { 21696, 21715, 21515, 21531, 21550, 21557, 21567, 21734, 21741, 21757, 21773, 21783, 0 }, 0, 0, 2438, 187, { 2451, 4157, 8015, 2440, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 1730, 1722, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 1750, 1739, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 8022, 21796, { 21799, 21818, 21837, 21862, 21881, 21903, 21928 }, { 21947, 21957, 21967, 21983, 21993, 22006, 22022 }, { 22032, 22036, 22043, 22047, 22054, 22061, 22068 }, { 22072, 22094, 22125, 22147, 22166, 22173, 22183, 22199, 22215, 22246, 22268, 22290, 0 }, { 22072, 22094, 22125, 22147, 22166, 22173, 22183, 22199, 22215, 22246, 22268, 22290, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, 0, 0, 2438, 187, { 2451, 4157, 8015, 2440, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 1730, 1722, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 1750, 1739, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 22315, 22340, { 22365, 22384, 22406, 22431, 22447, 22469, 22488 }, { 22498, 22505, 22512, 22519, 22526, 22533, 22540 }, { 22498, 22505, 22512, 22519, 22526, 22533, 22540 }, { 22544, 22560, 22585, 22604, 22623, 22630, 22643, 22656, 22675, 22706, 22731, 22753, 0 }, { 22544, 22560, 22585, 22604, 22623, 22630, 22643, 22778, 22675, 22706, 22731, 22753, 0 }, { 22797, 22805, 22819, 22833, 22623, 22630, 22643, 22844, 22852, 22866, 22877, 22885, 0 }, { 22797, 22805, 22819, 22833, 22623, 22630, 22643, 22844, 22852, 22866, 22877, 22885, 0 }, 0, 0, 2438, 187, { 2440, 2451, 4157, 8015, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 1730, 1722, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 1750, 1739, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 1820, 1823, { 22896, 22918, 22940, 22965, 22987, 23012, 23040 }, { 23062, 23072, 23082, 23095, 23105, 23118, 23134 }, { 23144, 23148, 23155, 23159, 23166, 23173, 23180 }, { 23184, 23200, 23225, 23244, 23266, 23273, 23286, 23299, 23318, 23349, 23374, 23393, 0 }, { 23184, 23200, 23225, 23244, 23266, 23273, 23418, 23299, 23318, 23349, 23374, 23393, 0 }, { 23431, 23438, 23225, 23454, 23266, 23273, 23418, 23299, 23470, 23492, 23508, 23518, 0 }, { 23431, 23438, 23225, 23454, 23266, 23273, 23418, 23299, 23470, 23492, 23508, 23518, 0 }, 0, 0, 2438, 187, { 2451, 4157, 8015, 2440, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 1730, 1722, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 1750, 1739, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 1820, 1823, { 23534, 23553, 23572, 23594, 23613, 23635, 23660 }, { 23679, 23689, 23699, 23712, 23722, 23735, 23751 }, { 23761, 23765, 23772, 23779, 23786, 23793, 23800 }, { 23804, 23820, 23845, 23864, 23886, 23893, 23906, 23919, 23938, 23966, 23991, 24013, 0 }, { 23804, 23820, 23845, 23864, 23886, 23893, 23906, 23919, 23938, 23966, 23991, 24013, 0 }, { 24038, 24046, 24066, 24073, 23886, 24090, 24097, 24105, 24113, 24136, 24153, 24167, 0 }, { 24038, 24046, 24066, 24073, 23886, 24090, 24097, 24105, 24113, 24136, 24153, 24167, 0 }, 0, 0, 2438, 187, { 2451, 4157, 8015, 2440, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 1730, 1722, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 1750, 1739, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 24184, 1820, 1823, { 24192, 24220, 24254, 24282, 24310, 24341, 24378 }, { 24406, 24419, 24438, 24454, 24467, 24486, 24505 }, { 24515, 24522, 24529, 24536, 24543, 24556, 24563 }, { 24567, 24586, 24614, 24636, 24655, 24668, 24678, 24691, 24716, 24747, 24772, 24788, 0 }, { 24567, 24586, 24614, 24636, 24655, 24668, 24678, 24691, 24716, 24747, 24772, 24788, 0 }, { 24807, 24817, 24836, 24846, 24655, 24668, 24678, 24862, 24869, 24894, 24910, 24920, 0 }, { 24807, 24817, 24836, 24846, 24655, 24668, 24678, 24862, 24869, 24894, 24910, 24920, 0 }, 0, 0, 2438, 691, { 2451, 4157, 2696, 8015, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4246, 4241, 20662, 20671, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4268, 4260, 20679, 20691, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 24933, 24961, { 24983, 25002, 25021, 25046, 25065, 25099, 25124 }, { 25143, 20289, 20299, 20315, 25153, 25178, 20366 }, { 0, 0, 0, 0, 0, 0, 0 }, { 25194, 25219, 25250, 25266, 20513, 20520, 20530, 25285, 25301, 25332, 25354, 25376, 0 }, { 25194, 25219, 25250, 25266, 20513, 20520, 20530, 25285, 25301, 25332, 25354, 25376, 0 }, { 25401, 25414, 25250, 25266, 20513, 20520, 20530, 25433, 25440, 25456, 25472, 25482, 0 }, { 25401, 25414, 25250, 25266, 20513, 20520, 20530, 25433, 25440, 25456, 25472, 25482, 0 }, 0, 0, 2438, 187, { 2440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 25495, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1722, 1730, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1739, 1750, 848, 0, 0, 0, 0, 0, 0 }, { 25514, 25522, 0, 0, 0, 0, 0, 0 } }, { 1, 1820, 1823, { 17419, 17438, 25532, 17479, 17498, 17520, 17545 }, { 17564, 17574, 25554, 17597, 17607, 17620, 17636 }, { 17646, 17650, 17657, 17664, 17671, 17678, 17685 }, { 25567, 25592, 17724, 25623, 25642, 17766, 25649, 25662, 25678, 25703, 25725, 25753, 0 }, { 25567, 25592, 17724, 25623, 25642, 17766, 25649, 25662, 25678, 25703, 25725, 25753, 0 }, { 25775, 25788, 17724, 25807, 25642, 17766, 25649, 25823, 25830, 25849, 25865, 25887, 0 }, { 25775, 25788, 17724, 25807, 25642, 17766, 25649, 25823, 25830, 25849, 25865, 25887, 0 }, 0, 0, 2438, 187, { 2440, 2451, 4157, 8015, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 1730, 1722, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 1750, 1739, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 25903, 25908, { 25913, 25920, 25931, 25944, 25957, 25968, 25981 }, { 25992, 25997, 26002, 26007, 26012, 26017, 26022 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540 }, { 26027, 26053, 26081, 26111, 26141, 26167, 26197, 26223, 26251, 26275, 26303, 26340, 0 }, { 26027, 26053, 26081, 26111, 26141, 26167, 26197, 26223, 26251, 26275, 26303, 26340, 0 }, { 26379, 26391, 26403, 26415, 26427, 26439, 26451, 26463, 26475, 26487, 26500, 26513, 0 }, { 26379, 26391, 26403, 26415, 26427, 26439, 26451, 26463, 26475, 26487, 26500, 26513, 0 }, 0, 0, 2438, 187, { 1556, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 26526, 26564, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 26596, 26620, 26642, { 26667, 26695, 26723, 26760, 26791, 26825, 26850 }, { 26884, 26900, 26916, 26941, 26960, 26982, 26995 }, { 27017, 27024, 27031, 27038, 27045, 27052, 27056 }, { 27066, 27100, 27137, 27171, 27205, 27236, 27273, 27310, 27350, 27384, 27418, 27467, 0 }, { 27066, 27100, 27137, 27171, 27205, 27236, 27273, 27310, 27350, 27384, 27418, 27467, 0 }, { 27516, 27529, 27542, 27555, 27568, 27581, 27594, 27607, 27620, 27633, 27649, 27665, 0 }, { 27516, 27529, 27542, 27555, 27568, 27581, 27594, 27607, 27620, 27633, 27649, 27665, 0 }, 0, 0, 185, 187, { 1518, 1527, 1536, 1567, 1556, 1545, 1585, 1578, 1592, 0, 0, 0, 0, 0 }, { 27681, 27724, 27772, 27804, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 27841, 1805, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 27874, 27883, 27893, 27905, 27918, 27927, 27939 }, { 27951, 27955, 27960, 27964, 27968, 27972, 27976 }, { 1914, 27980, 2300, 2300, 15237, 6216, 1914 }, { 27983, 27990, 27999, 28006, 2594, 28013, 28021, 28032, 28037, 28042, 28049, 28058, 0 }, { 27983, 27990, 27999, 28006, 2594, 28013, 28021, 28032, 28037, 28042, 28049, 28058, 0 }, { 28066, 28070, 27960, 28074, 2594, 28078, 28082, 28032, 28037, 28086, 28090, 28095, 0 }, { 28066, 28070, 27960, 28074, 2594, 28078, 28082, 28032, 28037, 28086, 28090, 28095, 0 }, 2, 1, 185, 187, { 198, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 28100, 28116, { 28132, 28154, 28167, 28186, 28196, 28227, 28243 }, { 28132, 28154, 28167, 28186, 28196, 28227, 28243 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540 }, { 28256, 28269, 28288, 28301, 28314, 28327, 28346, 28365, 28378, 28394, 28407, 28432, 0 }, { 28256, 28269, 28288, 28301, 28314, 28327, 28346, 28365, 28378, 28394, 28407, 28432, 0 }, { 28256, 28269, 28288, 28301, 28314, 28327, 28346, 28365, 28378, 28394, 28407, 28432, 0 }, { 28256, 28269, 28288, 28301, 28314, 28327, 28346, 28365, 28378, 28394, 28407, 28432, 0 }, 0, 0, 185, 187, { 189, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3520, 9963, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 28445, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 28480, 28505, { 28530, 28555, 28574, 28602, 28621, 28646, 28665 }, { 28530, 28555, 28574, 28602, 28621, 28646, 28665 }, { 28687, 28691, 28695, 28699, 28709, 28713, 28723 }, { 28727, 28746, 28762, 28775, 28788, 28810, 28829, 28851, 28867, 28883, 28896, 28912, 0 }, { 28727, 28746, 28762, 28775, 28788, 28810, 28829, 28851, 28867, 28883, 28896, 28912, 0 }, { 28928, 28937, 28946, 28955, 28964, 28973, 28985, 28994, 29003, 29012, 29021, 29030, 0 }, { 28928, 28937, 28946, 28955, 28964, 28973, 28985, 28994, 29003, 29012, 29021, 29030, 0 }, 0, 0, 185, 187, { 1120, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 29039, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 7261, 7266, { 3833, 29066, 3847, 29071, 29081, 29087, 3880 }, { 29094, 8298, 3699, 29098, 29103, 29107, 29111 }, { 2565, 2308, 2300, 2300, 29116, 3927, 1914 }, { 29118, 29126, 3943, 3949, 29135, 29140, 29146, 3972, 29152, 29161, 29169, 29178, 0 }, { 29187, 29195, 4032, 1012, 7947, 29204, 29210, 4055, 7964, 7973, 7981, 29216, 0 }, { 29225, 2655, 3699, 29229, 2594, 29233, 29238, 19914, 18218, 29242, 2688, 3707, 0 }, { 29225, 2655, 3699, 29229, 2594, 29233, 29238, 19914, 18218, 29242, 2688, 3707, 0 }, 2, 1, 185, 187, { 198, 17272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5508, 5455, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 29246, 29258, { 29270, 17438, 29298, 17479, 17498, 17520, 17545 }, { 17564, 17574, 25554, 17597, 17607, 17620, 17636 }, { 0, 0, 0, 0, 0, 0, 0 }, { 25567, 25592, 17724, 25623, 25642, 17766, 25649, 29317, 29333, 29361, 25725, 25753, 0 }, { 25567, 25592, 17724, 25623, 25642, 17766, 25649, 29317, 29333, 29361, 25725, 25753, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, 0, 0, 2438, 187, { 2440, 2451, 4157, 8015, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 1730, 1722, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 1750, 1739, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 29383, 29395, { 29404, 29420, 29436, 29464, 29480, 29523, 29548 }, { 29404, 29420, 29576, 29464, 29586, 29608, 29621 }, { 29631, 29635, 29639, 29643, 29647, 29660, 29667 }, { 29674, 29693, 29718, 29737, 29762, 29775, 29788, 29801, 29823, 29857, 29882, 29910, 0 }, { 29674, 29693, 29718, 29737, 29762, 29775, 29788, 29801, 29823, 29857, 29882, 29910, 0 }, { 29938, 29945, 29955, 29737, 29762, 29775, 29788, 29968, 29978, 29991, 30001, 30014, 0 }, { 29938, 29945, 29955, 29737, 29762, 29775, 29788, 29968, 29978, 29991, 30001, 30014, 0 }, 0, 1, 2438, 691, { 1556, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 16078, 16096, 0, 0, 0, 0, 0, 0, 0, 0 }, { 20671, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 20691, 269, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 30027, 30037, { 30050, 30060, 30067, 30080, 30090, 30100, 30110 }, { 30050, 30060, 30120, 30080, 30090, 30100, 30110 }, { 30130, 30134, 30138, 30142, 30146, 30150, 30154 }, { 30158, 30174, 30190, 30200, 30213, 30220, 30227, 30237, 30250, 30269, 30285, 30301, 0 }, { 30158, 30174, 30190, 30200, 30213, 30220, 30227, 30237, 30250, 30317, 30285, 30301, 0 }, { 30336, 30346, 30190, 30356, 30213, 30220, 30227, 30366, 30376, 30386, 30396, 30406, 0 }, { 30336, 30346, 30190, 30356, 30213, 30220, 30227, 30366, 30376, 30386, 30396, 30406, 0 }, 0, 0, 185, 187, { 198, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 30416, 30426, { 30439, 30446, 30452, 30459, 30465, 30471, 30479 }, { 30489, 30493, 30497, 30501, 30505, 30509, 30513 }, { 12692, 12692, 12692, 12692, 12692, 12692, 12692 }, { 30519, 30528, 30537, 30542, 30548, 30554, 30560, 30567, 30573, 30582, 30591, 30599, 0 }, { 30519, 30528, 30537, 30542, 30548, 30554, 30560, 30567, 30573, 30582, 30591, 30599, 0 }, { 30608, 30612, 3699, 30616, 3668, 30620, 30624, 30628, 30633, 30637, 30643, 30647, 0 }, { 30608, 30612, 3699, 30616, 3668, 30620, 30624, 30628, 30633, 30637, 30643, 30647, 0 }, 0, 0, 2438, 187, { 2440, 2451, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10501, 222, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 30651, 30692, { 30733, 30752, 30771, 30796, 30815, 30837, 30862 }, { 30881, 17574, 30891, 17597, 30907, 17620, 17636 }, { 30920, 17650, 30924, 17664, 30928, 17678, 17685 }, { 17689, 30935, 17724, 30963, 25642, 30982, 17776, 30992, 31008, 31039, 31061, 31086, 0 }, { 17689, 30935, 17724, 30963, 25642, 30982, 17776, 30992, 31008, 31039, 31061, 31086, 0 }, { 17689, 30935, 17724, 30963, 25642, 30982, 17776, 30992, 31008, 31039, 31061, 31086, 0 }, { 17689, 30935, 17724, 30963, 25642, 30982, 17776, 30992, 31008, 31039, 31061, 31086, 0 }, 0, 0, 185, 187, { 3711, 3720, 3727, 3736, 1599, 1556, 3747, 0, 0, 0, 0, 0, 0, 0 }, { 31111, 31131, 222, 10501, 0, 0, 0, 0, 0, 0 }, { 3532, 242, 843, 251, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 257, 848, 269, 0, 0, 0, 0, 0 }, { 25522, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 0, 0, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 31145, 31152, 31161, 31176, 31187, 31196, 31203, 31210, 31217, 31228, 31241, 31254, 0 }, { 31145, 31152, 31161, 31176, 31187, 31196, 31203, 31210, 31217, 31228, 31241, 31254, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, 0, 6, 185, 187, { 1518, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3520, 4935, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 1820, 1823, { 31259, 31266, 31272, 31279, 31290, 31298, 31307 }, { 31314, 8298, 3699, 31318, 31322, 31326, 10582 }, { 2308, 2308, 2300, 2300, 5644, 16338, 1914 }, { 3929, 31330, 31338, 3949, 3955, 31344, 31350, 3972, 31356, 31366, 31374, 31384, 0 }, { 3929, 31330, 31338, 3949, 3955, 31344, 31350, 3972, 31356, 31366, 31374, 31384, 0 }, { 31394, 31398, 3699, 29229, 3668, 31402, 31406, 19914, 18218, 2684, 31410, 16295, 0 }, { 31394, 31398, 3699, 29229, 3668, 31402, 31406, 19914, 18218, 2684, 31410, 16295, 0 }, 0, 0, 185, 187, { 3711, 16480, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3757, 3776, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 0, 0, { 31414, 31421, 31429, 31436, 31443, 31451, 31459 }, { 31466, 31469, 31472, 31475, 31478, 31481, 31484 }, { 2308, 2308, 2302, 2308, 12692, 3925, 12692 }, { 31487, 31495, 31505, 31511, 31519, 31524, 31529, 31534, 31541, 19899, 31549, 31557, 0 }, { 31487, 31495, 31505, 31511, 31519, 31524, 31529, 31534, 31541, 19899, 31549, 31557, 0 }, { 2651, 31565, 3699, 31569, 3668, 30620, 30624, 31573, 3639, 2684, 31577, 16295, 0 }, { 2651, 31565, 3699, 31569, 3668, 30620, 30624, 31573, 3639, 2684, 31577, 16295, 0 }, 0, 0, 185, 187, { 1120, 17272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3789, 3808, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 31581, 31592, { 31602, 31620, 31635, 31657, 31670, 31684, 31701 }, { 31725, 31733, 31738, 31657, 31670, 31750, 31757 }, { 0, 0, 0, 0, 0, 0, 0 }, { 31771, 31793, 31809, 31829, 31843, 31860, 31875, 31892, 31906, 31919, 31938, 31952, 0 }, { 31771, 31793, 31809, 31829, 31843, 31860, 31875, 31892, 31906, 31919, 31938, 31952, 0 }, { 31971, 31986, 31995, 32008, 32015, 32025, 32033, 32043, 32050, 32056, 32068, 32075, 0 }, { 31971, 31986, 31995, 32008, 32015, 32025, 32033, 32043, 32050, 32056, 32068, 32075, 0 }, 0, 0, 185, 187, { 198, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 0, 0, { 32087, 32095, 15840, 15849, 15858, 32106, 32116 }, { 16326, 15890, 15894, 15898, 15902, 16189, 32125 }, { 0, 0, 0, 0, 0, 0, 0 }, { 32129, 32138, 32148, 32156, 10611, 3672, 32164, 32170, 32179, 32188, 32197, 32206, 0 }, { 32129, 32138, 32148, 32156, 10611, 3672, 32164, 32170, 32179, 32188, 32197, 32206, 0 }, { 2651, 2655, 15909, 32215, 10611, 2668, 2672, 19914, 18218, 2684, 32219, 16295, 0 }, { 2651, 2655, 15909, 32215, 10611, 2668, 2672, 19914, 18218, 2684, 32219, 16295, 0 }, 0, 0, 2438, 187, { 1556, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 16078, 16096, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 32223, 32236, 32241, { 32246, 32253, 32268, 32282, 32298, 32313, 32329 }, { 6212, 32344, 2402, 32348, 32352, 32356, 32360 }, { 1914, 12692, 2300, 1909, 1914, 2302, 12692 }, { 7350, 7358, 32364, 32371, 32378, 2341, 2346, 32383, 32393, 32404, 32413, 32423, 0 }, { 7350, 7358, 32364, 32371, 32378, 2341, 2346, 32383, 32393, 32404, 32413, 32423, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 2418, 2422, 2426, 2430, 2434, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 2418, 2422, 2426, 2430, 2434, 0 }, 0, 0, 2438, 187, { 2440, 2451, 1556, 2460, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 32433, 2194, 11931, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 32452, 32457, { 32462, 32478, 32486, 32494, 32503, 32515, 32525 }, { 32535, 32541, 32547, 32551, 32555, 32563, 3639 }, { 0, 0, 0, 0, 0, 0, 0 }, { 32570, 32583, 32597, 32606, 32612, 32616, 32621, 32629, 16250, 32642, 16267, 16275, 0 }, { 32570, 32583, 32597, 32606, 32612, 32616, 32621, 32629, 16250, 32642, 16267, 16275, 0 }, { 32651, 2655, 32655, 16283, 32612, 32659, 2672, 32663, 2680, 32671, 2688, 16295, 0 }, { 32651, 2655, 32655, 16283, 32612, 32659, 2672, 32663, 2680, 32671, 2688, 16295, 0 }, 0, 0, 185, 187, { 198, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 32677, 32700, 32707, { 32714, 32724, 32734, 32744, 32754, 32764, 32774 }, { 32784, 32791, 32798, 32805, 32812, 32819, 32826 }, { 32833, 32837, 32841, 32845, 32849, 32853, 32857 }, { 32861, 32868, 32875, 32882, 32889, 32896, 32903, 32910, 32917, 32924, 32931, 32941, 0 }, { 32861, 32868, 32875, 32882, 32889, 32896, 32903, 32910, 32917, 32924, 32931, 32941, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, 0, 0, 185, 187, { 1518, 1527, 1536, 1567, 1556, 1545, 0, 0, 0, 0, 0, 0, 0, 0 }, { 32951, 32975, 33005, 33035, 33052, 0, 0, 0, 0, 0 }, { 1722, 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1739, 848, 269, 0, 0, 0, 0, 0, 0 }, { 33075, 1805, 0, 0, 0, 0, 0, 0 } }, { 289, 0, 0, { 27951, 8298, 33092, 33099, 33109, 33114, 33121 }, { 33128, 6196, 33132, 4800, 33137, 33142, 33147 }, { 4392, 33152, 33155, 33158, 33161, 33164, 33167 }, { 33170, 33177, 33092, 33188, 33194, 33198, 33207, 33214, 33219, 33228, 33233, 33236, 0 }, { 33170, 33177, 33092, 33188, 33194, 33198, 33207, 33214, 33219, 33228, 33233, 33236, 0 }, { 33242, 33246, 33253, 28074, 33194, 33258, 33263, 33214, 33268, 33228, 33233, 33273, 0 }, { 33242, 33246, 33253, 28074, 33194, 33258, 33263, 33214, 33268, 33228, 33233, 33273, 0 }, 2, 1, 2438, 187, { 1556, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 16078, 16096, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 33277, 33282, { 33287, 33295, 33305, 33315, 33324, 33334, 33342 }, { 33352, 33356, 33361, 33365, 33369, 33373, 33377 }, { 1914, 2300, 2565, 2300, 2565, 2306, 1914 }, { 2567, 2574, 2582, 2588, 2594, 2598, 2603, 33381, 33390, 33401, 33410, 33420, 0 }, { 2567, 2574, 2582, 2588, 2594, 2598, 2603, 33381, 33390, 33401, 33410, 33420, 0 }, { 2651, 2655, 2659, 2664, 2594, 2668, 2672, 2676, 2680, 2684, 2688, 2692, 0 }, { 2651, 2655, 2659, 2664, 2594, 2668, 2672, 2676, 2680, 2684, 2688, 2692, 0 }, 0, 0, 185, 187, { 198, 189, 2696, 2451, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4935, 4952, 3520, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 4246, 4961, 4971, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 33430, 33446, 33451, { 33456, 33481, 33510, 33535, 33548, 33563, 33580 }, { 33595, 33600, 33605, 33610, 33615, 33620, 8599 }, { 19210, 19210, 33625, 8610, 8613, 19210, 8610 }, { 33628, 33647, 33662, 33684, 33704, 33720, 33736, 33750, 33776, 33800, 33817, 33834, 0 }, { 33628, 33647, 33662, 33684, 33704, 33720, 33736, 33750, 33776, 33800, 33817, 33834, 0 }, { 33851, 33860, 33869, 33883, 33897, 33909, 33921, 33931, 33947, 33961, 33968, 33975, 0 }, { 33851, 33860, 33869, 33883, 33897, 33909, 33921, 33931, 33947, 33961, 33968, 33975, 0 }, 0, 1, 691, 187, { 2154, 4724, 1556, 33982, 33992, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 34005, 34040, 34069, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 34104, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 0, 0, { 34120, 34132, 34143, 34155, 34167, 34177, 34189 }, { 34204, 34209, 34214, 34219, 34224, 34229, 34234 }, { 0, 0, 0, 0, 0, 0, 0 }, { 34239, 34248, 34260, 34268, 34273, 34283, 34290, 34299, 34306, 34312, 34321, 34332, 0 }, { 34239, 34248, 34260, 34268, 34273, 34283, 34290, 34299, 34306, 34312, 34321, 34332, 0 }, { 34340, 34345, 34350, 34355, 34360, 34365, 34370, 34224, 34375, 34380, 34385, 34390, 0 }, { 34340, 34345, 34350, 34355, 34360, 34365, 34370, 34224, 34375, 34380, 34385, 34390, 0 }, 0, 0, 185, 187, { 1545, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 20050, 16096, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 34395, 34406, 34408, { 34410, 34423, 34431, 34440, 34450, 34460, 34469 }, { 34481, 34485, 34489, 34493, 34497, 34501, 34505 }, { 2565, 2308, 2300, 7600, 12692, 5644, 1914 }, { 34509, 34523, 34534, 34543, 34554, 34566, 34580, 34592, 34605, 34618, 34630, 34643, 0 }, { 34509, 34523, 34534, 34543, 34554, 34566, 34580, 34592, 34605, 34618, 34630, 34643, 0 }, { 34657, 34662, 34668, 34674, 34679, 34685, 34691, 34696, 34702, 34707, 18931, 34713, 0 }, { 34657, 34662, 34668, 34674, 34679, 34685, 34691, 34696, 34702, 34707, 18931, 34713, 0 }, 2, 1, 185, 187, { 198, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 34719, 34741, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 0, 0, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 9, 18, 25, 45, 65, 89, 113, 120, 131, 142, 151, 169, 0 }, { 9, 18, 25, 45, 65, 89, 113, 120, 131, 142, 151, 169, 0 }, { 9, 18, 25, 45, 65, 89, 113, 120, 131, 142, 151, 169, 0 }, { 9, 18, 25, 45, 65, 89, 113, 120, 131, 142, 151, 169, 0 }, 0, 0, 185, 187, { 189, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 209, 222, 0, 0, 0, 0, 0, 0, 0, 0 }, { 242, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 257, 269, 0, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 296, 307, { 318, 331, 352, 367, 378, 397, 408 }, { 421, 426, 431, 436, 441, 446, 451 }, { 456, 459, 462, 465, 468, 459, 465 }, { 471, 484, 501, 510, 521, 528, 535, 542, 555, 574, 591, 606, 0 }, { 471, 484, 501, 510, 521, 528, 535, 542, 555, 574, 591, 606, 0 }, { 623, 629, 501, 639, 521, 528, 535, 647, 655, 665, 673, 683, 0 }, { 623, 629, 501, 639, 521, 528, 535, 647, 655, 665, 673, 683, 0 }, 2, 1, 691, 187, { 693, 708, 724, 740, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 757, 776, 794, 819, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 856, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 872, 878, { 884, 893, 901, 909, 918, 925, 935 }, { 944, 948, 952, 956, 960, 964, 968 }, { 972, 975, 978, 981, 984, 987, 990 }, { 993, 999, 1006, 1012, 1018, 1023, 1028, 1035, 1041, 1050, 1058, 1067, 0 }, { 993, 999, 1006, 1012, 1018, 1023, 1028, 1035, 1041, 1050, 1058, 1067, 0 }, { 1076, 1081, 1006, 1086, 1018, 1023, 1091, 1096, 1100, 1105, 1110, 1115, 0 }, { 1076, 1081, 1006, 1086, 1018, 1023, 1091, 1096, 1100, 1105, 1110, 1115, 0 }, 2, 1, 185, 187, { 1120, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1140, 1163, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 1180, 0, 0, 0, 0, 0, 0, 0 } }, { 1195, 1204, 1211, { 1218, 1228, 1238, 1248, 1258, 1268, 1278 }, { 34757, 34764, 34771, 34778, 34785, 34792, 34799 }, { 1337, 1341, 1345, 1349, 1353, 1357, 1361 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, 0, 0, 185, 187, { 1518, 1545, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1608, 6555, 1686, 34806, 0, 0, 0, 0, 0, 0 }, { 1730, 1722, 251, 843, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1750, 1739, 269, 848, 0, 0, 0, 0, 0 }, { 1762, 1778, 1791, 0, 0, 0, 0, 0 } }, { 1812, 1820, 1823, { 1826, 1834, 1844, 1852, 1860, 1869, 1876 }, { 1883, 1886, 1889, 1893, 1896, 1900, 1904 }, { 1907, 1909, 1911, 1914, 1916, 1909, 1914 }, { 1919, 1925, 1931, 1939, 1945, 1953, 1961, 1971, 1977, 1985, 1993, 2002, 0 }, { 2011, 2017, 2024, 2032, 2038, 2046, 2054, 2064, 1977, 2070, 2078, 2088, 0 }, { 2097, 2101, 2106, 2111, 2115, 2120, 2125, 2130, 2134, 2140, 2146, 2150, 0 }, { 2097, 2101, 2106, 2111, 2115, 2120, 2125, 2130, 2134, 2140, 2146, 2150, 0 }, 2, 1, 691, 187, { 2154, 2165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2176, 2194, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 1820, 1823, { 2217, 2225, 2232, 2240, 2247, 2255, 2262 }, { 2270, 2275, 2279, 2283, 2287, 2291, 2295 }, { 1914, 2300, 2302, 2304, 2302, 2306, 2308 }, { 2310, 2317, 2325, 2331, 2337, 2341, 2346, 2351, 2358, 2368, 2376, 2385, 0 }, { 2310, 2317, 2325, 2331, 2337, 2341, 2346, 2351, 2358, 2368, 2376, 2385, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 2418, 2422, 2426, 2430, 2434, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 2418, 2422, 2426, 2430, 2434, 0 }, 2, 1, 2438, 187, { 2440, 2451, 1556, 2460, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2194, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 2471, 2477, { 2484, 2492, 2499, 2508, 2517, 2528, 2536 }, { 2544, 2547, 2550, 2553, 2556, 2559, 2562 }, { 1914, 2300, 2565, 2300, 2565, 2306, 1914 }, { 2567, 2574, 2582, 2588, 2594, 2598, 2603, 2608, 2615, 2625, 2633, 2642, 0 }, { 2567, 2574, 2582, 2588, 2594, 2598, 2603, 2608, 2615, 2625, 2633, 2642, 0 }, { 2651, 2655, 2659, 2664, 2594, 2668, 2672, 2676, 2680, 2684, 2688, 2692, 0 }, { 2651, 2655, 2659, 2664, 2594, 2668, 2672, 2676, 2680, 2684, 2688, 2692, 0 }, 2, 1, 691, 187, { 2154, 2696, 1556, 2705, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2719, 2194, 2738, 0, 0, 0, 0, 0, 0, 0 }, { 251, 2751, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 2763, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 2778, 2785, { 2792, 2807, 2822, 2833, 2848, 2861, 2880 }, { 2895, 2902, 2909, 2916, 2923, 2930, 2937 }, { 2944, 2947, 2950, 2950, 2953, 2953, 2956 }, { 2959, 2980, 3003, 3018, 3035, 3046, 3061, 3076, 3095, 3118, 3137, 3156, 0 }, { 3177, 3198, 3221, 3236, 3253, 3264, 3279, 3294, 3313, 3336, 3355, 3374, 0 }, { 3395, 3402, 3409, 3416, 3423, 3430, 3439, 3448, 3455, 3462, 3469, 3476, 0 }, { 3395, 3402, 3409, 3416, 3423, 3430, 3439, 3448, 3455, 3462, 3469, 3476, 0 }, 2, 1, 185, 187, { 1120, 198, 3483, 189, 3490, 1556, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 242, 843, 251, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 257, 848, 269, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 1820, 1823, { 3558, 3565, 3572, 3580, 3590, 3599, 3606 }, { 3615, 3619, 3623, 3627, 3631, 3635, 3639 }, { 1914, 2300, 2302, 3643, 2302, 2306, 1914 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, 0, 0, 185, 187, { 3711, 3720, 3727, 3736, 1599, 1556, 3747, 0, 0, 0, 0, 0, 0, 0 }, { 3757, 3776, 3789, 3808, 0, 0, 0, 0, 0, 0 }, { 3532, 242, 843, 251, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 257, 848, 269, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 4303, 4307, { 4311, 4323, 4335, 4345, 4359, 4369, 4381 }, { 4392, 4395, 4398, 4401, 4404, 4407, 4410 }, { 1914, 2300, 2302, 4413, 2302, 1909, 2308 }, { 4415, 4424, 4433, 4443, 4452, 4461, 4470, 4480, 4487, 4495, 4503, 4513, 0 }, { 4522, 4533, 4544, 4556, 4567, 4578, 4589, 4601, 4610, 4620, 4630, 4642, 0 }, { 4653, 4659, 4665, 4672, 4678, 4684, 4690, 4697, 4701, 4706, 4711, 4718, 0 }, { 4653, 4659, 4665, 4672, 4678, 4684, 4690, 4697, 4701, 4706, 4711, 4718, 0 }, 2, 1, 691, 691, { 4724, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2176, 2194, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4260, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 4733, 4742, 4748, 4754, 4763, 4769, 4778 }, { 4785, 4790, 4795, 4800, 4805, 4810, 4815 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 4820, 4828, 4837, 4842, 4848, 4852, 4857, 4865, 4871, 4881, 1058, 4889, 0 }, { 4820, 4828, 4837, 4842, 4848, 4852, 4857, 4865, 4871, 4881, 1058, 4889, 0 }, { 4899, 4905, 4837, 4912, 4848, 4852, 4917, 4865, 4923, 1105, 1110, 4929, 0 }, { 4899, 4905, 4837, 4912, 4848, 4852, 4917, 4865, 4923, 1105, 1110, 4929, 0 }, 2, 1, 185, 187, { 198, 189, 2696, 2451, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4935, 3520, 4952, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 4246, 4961, 4971, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 4979, 4992, { 5003, 5021, 5035, 5053, 5071, 5089, 5105 }, { 5119, 5131, 5143, 5155, 5167, 5179, 5191 }, { 5198, 5203, 5208, 5213, 5218, 5223, 5228 }, { 5233, 5244, 5257, 5264, 5275, 5282, 5291, 5300, 5313, 5326, 5341, 5354, 0 }, { 5233, 5244, 5257, 5264, 5275, 5282, 5291, 5300, 5313, 5326, 5341, 5354, 0 }, { 5365, 5374, 5257, 5383, 5275, 5392, 5401, 5410, 5419, 5428, 5437, 5446, 0 }, { 5365, 5374, 5257, 5383, 5275, 5392, 5401, 5410, 5419, 5428, 5437, 5446, 0 }, 0, 0, 185, 187, { 198, 5455, 189, 209, 2451, 2440, 5468, 1556, 5481, 5498, 0, 0, 0, 0 }, { 5508, 5455, 5526, 5548, 5481, 0, 0, 0, 0, 0 }, { 251, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 257, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 5569, 5577, 5581, { 5585, 5595, 5603, 5608, 5615, 5628, 5636 }, { 3927, 5644, 4413, 5646, 5650, 1909, 5653 }, { 3927, 5644, 4413, 5657, 5650, 1909, 5657 }, { 5660, 5668, 5677, 5686, 5695, 5702, 5710, 5718, 5728, 5739, 2376, 2385, 0 }, { 5660, 5668, 5677, 5686, 5695, 5702, 5710, 5718, 5728, 5739, 2376, 2385, 0 }, { 5748, 5753, 5759, 5766, 5772, 5778, 5784, 5790, 5795, 5802, 1110, 5807, 0 }, { 5748, 5753, 5759, 5766, 5772, 5778, 5784, 5790, 5795, 5802, 1110, 5807, 0 }, 2, 1, 5812, 187, { 5815, 5829, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5842, 5862, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5876, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 5887, 5892, { 5897, 5908, 5919, 5933, 5947, 5959, 5971 }, { 5983, 5988, 5994, 6000, 6006, 6011, 6017 }, { 1914, 2300, 6022, 2300, 2306, 2306, 2308 }, { 6025, 6033, 4837, 6042, 6049, 6054, 6061, 6068, 2358, 5739, 6076, 6086, 0 }, { 6025, 6033, 4837, 6042, 6049, 6054, 6061, 6068, 2358, 5739, 6076, 6086, 0 }, { 5748, 1081, 4795, 6095, 6049, 5778, 5784, 6100, 6107, 5802, 6112, 1115, 0 }, { 5748, 1081, 4795, 6095, 6049, 5778, 5784, 6100, 6107, 5802, 6112, 1115, 0 }, 2, 1, 691, 187, { 4724, 6118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2719, 2194, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 6130, 6139, 6147, 6156, 6167, 6176, 6185 }, { 6192, 6196, 2402, 6200, 6204, 6208, 6212 }, { 2565, 2308, 2300, 2300, 6216, 3927, 1914 }, { 6218, 6226, 3943, 6235, 6242, 6249, 6256, 3972, 6263, 6273, 6281, 6290, 0 }, { 6299, 6307, 4032, 6316, 6323, 6330, 6337, 4055, 6344, 6354, 1058, 6362, 0 }, { 6371, 2398, 2402, 2406, 6375, 6379, 6383, 6387, 6391, 6395, 2430, 6399, 0 }, { 6371, 2398, 2402, 2406, 6375, 6379, 6383, 6387, 6391, 6395, 2430, 6399, 0 }, 2, 1, 185, 187, { 198, 3490, 189, 6403, 3483, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4935, 6411, 3520, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1195, 6420, 6427, { 6434, 6444, 6454, 6464, 6474, 6484, 6494 }, { 1337, 6504, 6508, 6512, 6516, 6520, 6524 }, { 1337, 6504, 6508, 6512, 6516, 6520, 6524 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, 0, 0, 185, 187, { 1545, 1599, 1578, 1518, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1608, 6555, 6579, 6606, 6635, 6659, 6688, 6708, 0, 0 }, { 843, 251, 1722, 1730, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 1739, 1750, 0, 0, 0, 0, 0 }, { 1762, 6733, 1791, 0, 0, 0, 0, 0 } }, { 6751, 6761, 6768, { 6775, 6785, 6795, 6805, 6815, 6825, 6835 }, { 6845, 6849, 6853, 6857, 6861, 6865, 6869 }, { 6845, 6849, 6853, 6857, 6861, 6865, 6869 }, { 6873, 6878, 6883, 6888, 6893, 6898, 6903, 6908, 6913, 6918, 6924, 6930, 0 }, { 6873, 6878, 6883, 6888, 6893, 6898, 6903, 6908, 6913, 6918, 6924, 6930, 0 }, { 6873, 6878, 6883, 6888, 6893, 6898, 6903, 6908, 6913, 6918, 6924, 6930, 0 }, { 6873, 6878, 6883, 6888, 6893, 6898, 6903, 6908, 6913, 6918, 6924, 6930, 0 }, 0, 0, 2438, 187, { 1556, 6936, 1585, 1527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 6945, 6974, 6998, 7025, 7047, 7078, 7104, 7135, 7161, 7188 }, { 1722, 1730, 843, 251, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1739, 1750, 848, 269, 0, 0, 0, 0, 0 }, { 7210, 7227, 7246, 0, 0, 0, 0, 0 } }, { 289, 7261, 7266, { 7271, 7278, 7286, 7294, 7303, 7313, 7321 }, { 7330, 4395, 7333, 7336, 7339, 7342, 7345 }, { 7348, 2300, 2565, 3643, 2565, 3927, 7348 }, { 7350, 7358, 7367, 2331, 7373, 2341, 2346, 7377, 2358, 2368, 2376, 2385, 0 }, { 7350, 7358, 7367, 2331, 7373, 2341, 2346, 7377, 2358, 2368, 2376, 2385, 0 }, { 2394, 2398, 7386, 2406, 7373, 2410, 2414, 2418, 2422, 2426, 2430, 2434, 0 }, { 2394, 2398, 7386, 2406, 7373, 2410, 2414, 2418, 2422, 2426, 2430, 2434, 0 }, 2, 1, 2438, 187, { 7390, 4157, 2451, 189, 2696, 7399, 1556, 0, 0, 0, 0, 0, 0, 0 }, { 4935, 6411, 3520, 4952, 0, 0, 0, 0, 0, 0 }, { 251, 843, 4241, 7411, 7423, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 7435, 7450, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 7465, 7261, 7266, { 2217, 2225, 2232, 2240, 2247, 2255, 2262 }, { 7473, 7478, 7482, 7486, 7490, 7494, 7498 }, { 1914, 2300, 2302, 2304, 2302, 2306, 2308 }, { 2310, 2317, 4837, 2331, 4848, 2341, 2346, 2351, 2358, 2368, 2376, 6086, 0 }, { 2310, 2317, 4837, 2331, 4848, 2341, 2346, 2351, 2358, 2368, 2376, 6086, 0 }, { 2394, 2398, 2402, 2406, 4848, 2410, 2414, 2418, 2422, 2426, 2430, 7503, 0 }, { 2394, 2398, 2402, 2406, 4848, 2410, 2414, 2418, 2422, 2426, 2430, 7503, 0 }, 2, 1, 691, 691, { 2154, 6118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2176, 2194, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4246, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4268, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 7507, 7517, 7531, 7538, 7545, 7554, 1876 }, { 7562, 7569, 7574, 7578, 7583, 7588, 7592 }, { 1907, 1909, 3643, 7597, 7600, 1909, 1914 }, { 7602, 7611, 7616, 7623, 2337, 7633, 7642, 7649, 7659, 7669, 1993, 7682, 0 }, { 7692, 7701, 7708, 7714, 7723, 7728, 7736, 7742, 7751, 7761, 7775, 7785, 0 }, { 7793, 7797, 2402, 7801, 2337, 7805, 7809, 7813, 7817, 7821, 2146, 7826, 0 }, { 7793, 7797, 2402, 7801, 2337, 7805, 7809, 7813, 7817, 7821, 2146, 7826, 0 }, 2, 1, 691, 187, { 2154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3821, 1820, 1823, { 3833, 7830, 7844, 7857, 7870, 7883, 3880 }, { 6192, 7895, 7899, 7903, 7907, 7911, 7915 }, { 2565, 1914, 2302, 7920, 7920, 1914, 1914 }, { 7922, 7930, 7940, 1012, 7947, 7952, 7958, 4055, 7964, 7973, 7981, 7990, 0 }, { 7922, 7930, 7940, 1012, 7947, 7952, 7958, 4055, 7964, 7973, 7981, 7990, 0 }, { 2394, 7999, 2402, 8003, 4848, 2410, 2414, 6387, 6391, 8007, 2430, 8011, 0 }, { 2394, 7999, 2402, 8003, 4848, 2410, 2414, 6387, 6391, 8007, 2430, 8011, 0 }, 0, 0, 185, 187, { 198, 189, 1120, 3483, 2451, 2440, 4157, 7390, 2696, 2154, 7399, 8015, 4724, 1556 }, { 4164, 4219, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4288, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 8022, 8025, { 8028, 8037, 4748, 8047, 8055, 8063, 8072 }, { 8078, 8081, 4395, 8085, 8088, 8092, 1904 }, { 2565, 6216, 2300, 2300, 6216, 3927, 1914 }, { 8095, 8103, 4837, 8110, 8117, 8122, 8132, 8140, 8146, 8156, 2376, 2385, 0 }, { 8095, 8103, 4837, 8110, 8117, 8122, 8132, 8140, 8146, 8156, 2376, 2385, 0 }, { 8164, 8171, 4837, 4912, 8117, 8177, 8184, 8140, 8189, 1105, 1110, 5807, 0 }, { 8164, 8171, 4837, 4912, 8117, 8177, 8184, 8140, 8189, 1105, 1110, 5807, 0 }, 2, 1, 2438, 187, { 2440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 8195, 8224, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 7261, 7266, { 8241, 8251, 8256, 8263, 8272, 8276, 8283 }, { 8294, 8298, 3699, 8302, 8306, 8310, 8314 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 8319, 8328, 8338, 8345, 4848, 8353, 8359, 2351, 8365, 8376, 8386, 8396, 0 }, { 8319, 8328, 8338, 8345, 4848, 8353, 8359, 2351, 8365, 8376, 8386, 8396, 0 }, { 8406, 1081, 4795, 6095, 4848, 8411, 8416, 5790, 4923, 1105, 1110, 5807, 0 }, { 8406, 1081, 4795, 6095, 4848, 8411, 8416, 5790, 4923, 1105, 1110, 5807, 0 }, 0, 1, 691, 187, { 2154, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 8421, 8441, { 8467, 8490, 352, 8513, 8524, 8539, 8554 }, { 8569, 8574, 8579, 8584, 8589, 8594, 8599 }, { 8604, 8607, 8604, 8610, 8613, 8607, 8610 }, { 8616, 8629, 8644, 8653, 8666, 8673, 8682, 8691, 8704, 8721, 8736, 8749, 0 }, { 8764, 8777, 8792, 8803, 8816, 8823, 8832, 8841, 8856, 8873, 8888, 8901, 0 }, { 8916, 8924, 8644, 8934, 8666, 8673, 8682, 8942, 8950, 8960, 8968, 8978, 0 }, { 8916, 8924, 8644, 8934, 8666, 8673, 8682, 8942, 8950, 8960, 8968, 8978, 0 }, 0, 1, 691, 187, { 2154, 2696, 8015, 2440, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 776, 757, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 1820, 1823, { 8986, 8995, 9007, 9014, 9022, 9032, 9038 }, { 9045, 9049, 9053, 9057, 9061, 9066, 9070 }, { 9074, 9076, 9078, 9080, 9082, 9076, 9080 }, { 9085, 9095, 9104, 9112, 9120, 9128, 9135, 9142, 9150, 1993, 9156, 9164, 0 }, { 9173, 9183, 9192, 9200, 9208, 9216, 9223, 9230, 9239, 7775, 9245, 9255, 0 }, { 9264, 9268, 9273, 9278, 9282, 7809, 2130, 9286, 9290, 2146, 9294, 2150, 0 }, { 9264, 9268, 9273, 9278, 9282, 7809, 2130, 9286, 9290, 2146, 9294, 2150, 0 }, 0, 1, 691, 187, { 9298, 9308, 9316, 9328, 9340, 9350, 9360, 1556, 0, 0, 0, 0, 0, 0 }, { 9372, 9386, 9401, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 1820, 1823, { 9421, 9429, 9438, 9445, 9452, 9461, 1876 }, { 1883, 1886, 9468, 1893, 9471, 9475, 1904 }, { 1907, 1909, 9478, 1914, 9480, 1909, 1914 }, { 5660, 5668, 9483, 6042, 9489, 9494, 9499, 2351, 2358, 5739, 2376, 2385, 0 }, { 9504, 9513, 7708, 9523, 9531, 9537, 9543, 9549, 9557, 9567, 9576, 9585, 0 }, { 2394, 2398, 2402, 2406, 9489, 9494, 9499, 2418, 2422, 2426, 2430, 2434, 0 }, { 2394, 2398, 2402, 2406, 9489, 9494, 9499, 2418, 2422, 2426, 2430, 2434, 0 }, 2, 1, 691, 187, { 2154, 2165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2719, 2194, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 9594, 9603, { 9611, 9618, 9627, 9636, 9648, 9656, 9665 }, { 9675, 9679, 3699, 9684, 9689, 9693, 9697 }, { 2565, 5644, 2300, 2300, 9701, 1909, 1914 }, { 9703, 9709, 4837, 9716, 2337, 9722, 9730, 9737, 9743, 9751, 9757, 9765, 0 }, { 9703, 9709, 4837, 9716, 2337, 9722, 9730, 9737, 9743, 9751, 9757, 9765, 0 }, { 2651, 9773, 3699, 9777, 9781, 9785, 9789, 9793, 9697, 9797, 9801, 9806, 0 }, { 2651, 9773, 3699, 9777, 9781, 9785, 9789, 9793, 9697, 9797, 9801, 9806, 0 }, 0, 1, 691, 187, { 4724, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 9810, 9823, 9826, { 9829, 9837, 9845, 2240, 2247, 2255, 9852 }, { 9860, 9865, 9870, 2283, 2287, 2291, 9874 }, { 1914, 2300, 2302, 2304, 2302, 2306, 2308 }, { 7350, 7358, 4837, 2331, 2337, 2341, 2346, 9879, 2358, 2368, 2376, 2385, 0 }, { 7350, 7358, 4837, 2331, 2337, 2341, 2346, 9879, 2358, 2368, 2376, 2385, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 2418, 2422, 2426, 2430, 2434, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 2418, 2422, 2426, 2430, 2434, 0 }, 2, 1, 2438, 187, { 1556, 6936, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 9887, 9905, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 9928, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 9938, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 0, 0, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, 0, 0, 185, 187, { 1120, 3483, 189, 198, 1129, 9951, 1556, 0, 0, 0, 0, 0, 0, 0 }, { 3520, 9963, 9979, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 3532, 242, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 3540, 257, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 10021, 10026, { 10030, 10036, 10046, 10052, 10063, 10073, 10078 }, { 10088, 10092, 10096, 10100, 10105, 10109, 10113 }, { 1909, 1909, 1914, 10117, 1909, 7600, 7600 }, { 10120, 10125, 10132, 10137, 10143, 10150, 10158, 10165, 10174, 10181, 10186, 10193, 0 }, { 10120, 10125, 10132, 10137, 10143, 10150, 10158, 10165, 10174, 10181, 10186, 10193, 0 }, { 10201, 10205, 3699, 10210, 3668, 10214, 10218, 10222, 10227, 10231, 10235, 10239, 0 }, { 10201, 10205, 3699, 10210, 3668, 10214, 10218, 10222, 10227, 10231, 10235, 10239, 0 }, 0, 1, 691, 187, { 10243, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10253, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 10270, 10288, { 10306, 10317, 10330, 10339, 10346, 10359, 10368 }, { 10306, 10317, 10330, 10339, 10346, 10359, 10368 }, { 1914, 2300, 2302, 3643, 2302, 2306, 1914 }, { 10377, 10388, 10399, 10408, 10419, 10426, 10433, 10446, 10455, 10466, 10479, 10490, 0 }, { 10377, 10388, 10399, 10408, 10419, 10426, 10433, 10446, 10455, 10466, 10479, 10490, 0 }, { 10377, 10388, 10399, 10408, 10419, 10426, 10433, 10446, 10455, 10466, 10479, 10490, 0 }, { 10377, 10388, 10399, 10408, 10419, 10426, 10433, 10446, 10455, 10466, 10479, 10490, 0 }, 0, 0, 185, 187, { 198, 189, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10501, 222, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 242, 843, 251, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 257, 848, 269, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 10515, 10522, 10528, 10535, 10540, 10546, 10552 }, { 10558, 10562, 10566, 10570, 10574, 10578, 10582 }, { 2300, 1914, 1914, 10586, 4413, 3925, 1914 }, { 10588, 10596, 10605, 2588, 10611, 2598, 2603, 10615, 2615, 2625, 2633, 10623, 0 }, { 10588, 10596, 10605, 2588, 10611, 2598, 2603, 10615, 2615, 2625, 2633, 10623, 0 }, { 2651, 2655, 3699, 2664, 10611, 2668, 2672, 10632, 2680, 2684, 2688, 10636, 0 }, { 2651, 2655, 3699, 2664, 10611, 2668, 2672, 10632, 2680, 2684, 2688, 10636, 0 }, 0, 0, 185, 691, { 198, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10640, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4246, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4268, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 10659, 10664, { 10669, 10682, 10701, 10718, 10731, 10744, 10761 }, { 10774, 8574, 8579, 8584, 8589, 8594, 8599 }, { 10779, 8607, 8604, 8610, 8613, 8607, 8610 }, { 10782, 10795, 10806, 10823, 10838, 10853, 10868, 10881, 10896, 10913, 10928, 10945, 0 }, { 10960, 10971, 10984, 10999, 11012, 11025, 11038, 11049, 11062, 11077, 11090, 11109, 0 }, { 11122, 11129, 11136, 11143, 11150, 11157, 11164, 11171, 11178, 11185, 11192, 11199, 0 }, { 11122, 11129, 11136, 11143, 11150, 11157, 11164, 11171, 11178, 11185, 11192, 11199, 0 }, 0, 1, 691, 187, { 2154, 2696, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 11206, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 11224, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 11240, 11253, { 11266, 11281, 11302, 11317, 11330, 11343, 10761 }, { 421, 426, 11358, 436, 11363, 446, 451 }, { 456, 459, 11368, 465, 468, 459, 465 }, { 11371, 11388, 11397, 11412, 521, 11429, 11444, 11457, 11472, 11489, 11510, 11527, 0 }, { 11542, 11559, 11572, 11589, 8816, 11608, 11623, 11636, 11649, 11664, 11687, 11706, 0 }, { 11719, 11726, 11733, 11740, 521, 11747, 11754, 11761, 11768, 11775, 11782, 11789, 0 }, { 11719, 11726, 11733, 11740, 521, 11747, 11754, 11761, 11768, 11775, 11782, 11789, 0 }, 0, 0, 691, 187, { 2696, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3520, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 0, 0, 0, 0, 0, 0, 0 }, { 11796, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 11810, 11815, { 11820, 11828, 11839, 11845, 11851, 11860, 1876 }, { 9045, 9049, 2287, 11866, 9061, 9066, 11870 }, { 9074, 9076, 11874, 9080, 9082, 9076, 9080 }, { 2310, 2317, 9483, 2331, 2337, 11876, 11882, 11888, 2358, 2368, 2376, 2385, 0 }, { 2310, 2317, 9483, 2331, 2337, 11876, 11882, 11888, 2358, 2368, 2376, 2385, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 11895, 2422, 2426, 2430, 2434, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 11895, 2422, 2426, 2430, 2434, 0 }, 0, 1, 5812, 187, { 11899, 6118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 11911, 11931, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 11945, 11950, { 11955, 11966, 11977, 11988, 11999, 12010, 12016 }, { 1909, 9701, 2302, 4413, 1907, 10586, 2308 }, { 1909, 9701, 2302, 4413, 1907, 10586, 2308 }, { 12025, 12033, 12042, 12049, 4848, 12056, 12062, 2351, 2358, 12068, 2376, 12077, 0 }, { 12025, 12033, 12042, 12049, 4848, 12056, 12062, 2351, 2358, 12068, 2376, 12077, 0 }, { 12087, 12092, 12042, 2406, 4848, 12056, 12062, 2418, 12098, 2426, 2430, 12103, 0 }, { 12087, 12092, 12042, 2406, 4848, 12056, 12062, 2418, 12098, 2426, 2430, 12103, 0 }, 2, 1, 691, 187, { 2154, 6118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2719, 2194, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12108, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 12116, 12133, { 12147, 12158, 12168, 12177, 12188, 12200, 12211 }, { 12221, 12224, 12227, 12230, 12233, 12236, 12239 }, { 1914, 1909, 2304, 2302, 7600, 1909, 1914 }, { 12242, 12252, 12263, 12269, 12278, 12284, 12292, 12300, 12308, 12319, 12328, 12338, 0 }, { 12348, 12358, 2325, 12369, 12378, 12384, 12392, 12400, 12408, 12419, 12428, 12438, 0 }, { 12448, 12454, 12263, 12460, 12278, 12465, 12471, 12477, 4128, 12482, 4139, 12487, 0 }, { 12448, 12454, 12263, 12460, 12278, 12465, 12471, 12477, 4128, 12482, 4139, 12487, 0 }, 0, 1, 691, 187, { 2154, 12492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12512, 12539, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12560, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 12576, 11815, { 12582, 12594, 12606, 12618, 12632, 12647, 12660 }, { 12674, 12677, 12680, 12683, 12686, 12689, 9471 }, { 1914, 1909, 12692, 2302, 4413, 1909, 9480 }, { 12694, 12701, 12709, 12715, 12724, 12733, 12743, 12749, 12760, 12770, 12777, 12787, 0 }, { 12694, 12701, 12709, 12715, 12724, 12733, 12743, 12749, 12760, 12770, 12777, 12787, 0 }, { 12795, 12801, 12806, 12811, 12816, 12821, 12828, 12834, 12840, 12846, 12852, 12859, 0 }, { 12795, 12801, 12806, 12811, 12816, 12821, 12828, 12834, 12840, 12846, 12852, 12859, 0 }, 2, 1, 2438, 187, { 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12866, 12894, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 12926, 12938, { 12950, 12965, 12980, 12995, 13012, 13031, 13042 }, { 13053, 13060, 13067, 13074, 13081, 13088, 13095 }, { 0, 0, 0, 0, 0, 0, 0 }, { 13102, 13113, 8644, 13126, 8666, 13137, 13144, 8691, 13151, 13166, 13179, 13190, 0 }, { 13102, 13113, 8644, 13126, 8666, 13137, 13144, 8691, 13151, 13166, 13179, 13190, 0 }, { 13203, 13210, 13217, 13224, 8666, 13137, 13144, 13231, 13238, 13245, 13252, 13259, 0 }, { 13203, 13210, 13217, 13224, 8666, 13137, 13144, 13231, 13238, 13245, 13252, 13259, 0 }, 0, 1, 691, 187, { 2154, 2696, 8015, 2440, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 13266, 13284, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 13303, 13323, { 13340, 13353, 13366, 13382, 13399, 13414, 13423 }, { 13340, 13353, 13366, 13382, 13399, 13414, 13423 }, { 13432, 13435, 13438, 13441, 13444, 13447, 13450 }, { 13453, 13466, 13477, 13486, 13497, 13502, 13511, 13522, 13529, 13544, 13555, 13568, 0 }, { 13581, 13596, 13477, 13486, 13609, 13502, 13616, 13522, 13529, 13544, 13555, 13568, 0 }, { 13453, 13466, 13477, 13486, 13497, 13502, 13511, 13522, 13529, 13544, 13555, 13568, 0 }, { 13453, 13466, 13477, 13486, 13497, 13502, 13511, 13522, 13529, 13544, 13555, 13568, 0 }, 0, 6, 185, 187, { 198, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 242, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 257, 269, 0, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 13629, 13632, { 13635, 13648, 13658, 13667, 13677, 13688, 13699 }, { 13711, 13714, 13719, 13724, 13729, 13734, 13739 }, { 13711, 13744, 13747, 13750, 13753, 13756, 13759 }, { 13762, 13771, 13780, 13789, 13798, 13807, 13816, 13825, 13834, 13843, 13853, 13863, 0 }, { 13873, 13882, 13891, 13900, 13909, 13918, 13927, 13936, 13945, 13954, 13964, 13974, 0 }, { 13984, 13990, 13996, 14002, 14008, 14014, 14020, 14026, 14032, 14038, 14045, 14052, 0 }, { 13984, 13990, 13996, 14002, 14008, 14014, 14020, 14026, 14032, 14038, 14045, 14052, 0 }, 0, 1, 185, 187, { 198, 189, 2451, 2440, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 242, 843, 251, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 257, 848, 269, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 14059, 14083, { 14107, 14120, 14141, 14160, 14181, 14200, 14213 }, { 14224, 14231, 14238, 14245, 14252, 14259, 14266 }, { 14273, 14276, 14276, 14279, 14282, 14285, 14290 }, { 14293, 14308, 14323, 14332, 14343, 14354, 14367, 14380, 14395, 14414, 14433, 14450, 0 }, { 14469, 14486, 14503, 14514, 14527, 14540, 14555, 14570, 14587, 14608, 14629, 14648, 0 }, { 14669, 14676, 14683, 14690, 14697, 14704, 14711, 14718, 14725, 14732, 14739, 14746, 0 }, { 14669, 14676, 14683, 14690, 14697, 14704, 14711, 14718, 14725, 14732, 14739, 14746, 0 }, 0, 1, 691, 187, { 2154, 2696, 14753, 198, 14763, 3490, 1556, 0, 0, 0, 0, 0, 0, 0 }, { 3808, 3502, 10640, 5455, 14774, 14785, 14797, 14814, 0, 0 }, { 251, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 0, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 14832, 14838, 14852, 14875, 14889, 14905, 14912 }, { 14921, 14924, 14929, 14935, 14939, 7600, 14944 }, { 6540, 6528, 6530, 6532, 6534, 6536, 6538 }, { 14948, 14955, 10132, 14962, 3668, 14968, 14974, 14980, 14987, 14996, 15004, 15011, 0 }, { 15018, 15025, 15032, 15037, 15043, 15047, 15052, 15057, 15064, 15073, 15081, 15088, 0 }, { 15095, 7999, 2402, 2406, 15043, 15099, 15103, 15107, 15111, 2426, 15115, 15119, 0 }, { 15095, 7999, 2402, 2406, 15043, 15099, 15103, 15107, 15111, 2426, 15115, 15119, 0 }, 0, 1, 691, 187, { 2154, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 15123, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 1820, 1823, { 15141, 15149, 15160, 15170, 15181, 15190, 15199 }, { 15209, 15213, 15217, 15221, 15225, 15229, 15233 }, { 15237, 12692, 12692, 12692, 2304, 2304, 2308 }, { 15239, 15249, 15257, 15265, 15273, 15281, 15288, 15296, 15304, 15311, 15317, 15324, 0 }, { 15332, 15343, 15352, 15361, 15370, 15379, 15387, 15396, 15405, 15413, 15420, 15428, 0 }, { 15437, 15442, 4795, 15447, 15452, 15457, 15462, 15467, 15472, 15477, 15482, 15487, 0 }, { 15437, 15442, 4795, 15447, 15452, 15457, 15462, 15467, 15472, 15477, 15482, 15487, 0 }, 2, 1, 185, 187, { 1545, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 15503, 15530, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 15551, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 15570, 15591, { 15608, 331, 352, 8513, 15621, 15638, 15649 }, { 15662, 15670, 15678, 15684, 15692, 15700, 15708 }, { 456, 459, 462, 465, 468, 459, 465 }, { 15716, 484, 501, 510, 15731, 15738, 15747, 542, 555, 574, 591, 606, 0 }, { 15716, 484, 501, 510, 15731, 15738, 15747, 542, 555, 574, 591, 606, 0 }, { 15756, 15764, 15772, 639, 15731, 15780, 15788, 647, 655, 665, 673, 683, 0 }, { 15756, 15764, 15772, 639, 15731, 15780, 15788, 647, 655, 665, 673, 683, 0 }, 0, 1, 691, 187, { 15796, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10640, 5455, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 15806, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 0, 0, { 15822, 15829, 15840, 15849, 15858, 15865, 15876 }, { 15886, 15890, 15894, 15898, 15902, 15905, 15909 }, { 0, 0, 0, 0, 0, 0, 0 }, { 15913, 15923, 15932, 15940, 15949, 15962, 15974, 15981, 15988, 15995, 16005, 16017, 0 }, { 15913, 15923, 15932, 15940, 15949, 15962, 15974, 15981, 15988, 15995, 16005, 16017, 0 }, { 16030, 16034, 16038, 16042, 16046, 16050, 16054, 16058, 16062, 16066, 16070, 16074, 0 }, { 16030, 16034, 16038, 16042, 16046, 16050, 16054, 16058, 16062, 16066, 16070, 16074, 0 }, 0, 0, 2438, 187, { 1556, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 16078, 16096, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 0, 0, { 16108, 16113, 16119, 16129, 16141, 16149, 16160 }, { 16169, 16173, 16177, 16181, 16185, 16189, 16193 }, { 0, 0, 0, 0, 0, 0, 0 }, { 16197, 16207, 16217, 16224, 16231, 2598, 16236, 16243, 16250, 16259, 16267, 16275, 0 }, { 16197, 16207, 16217, 16224, 16231, 2598, 16236, 16243, 16250, 16259, 16267, 16275, 0 }, { 2651, 2655, 15909, 16283, 16287, 2668, 2672, 16291, 2680, 2684, 2688, 16295, 0 }, { 2651, 2655, 15909, 16283, 16287, 2668, 2672, 16291, 2680, 2684, 2688, 16295, 0 }, 0, 0, 2438, 187, { 1556, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 16078, 16096, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 1820, 1823, { 16299, 16305, 16316, 16129, 16141, 16149, 16160 }, { 16326, 16330, 16334, 16181, 16185, 16189, 16193 }, { 1914, 2300, 16338, 2302, 1914, 5644, 2300 }, { 16340, 16350, 16361, 16368, 16377, 16383, 16389, 16397, 16405, 16416, 16426, 16435, 0 }, { 16444, 16207, 16453, 16459, 16231, 2598, 16236, 16243, 16466, 16259, 16267, 16275, 0 }, { 2651, 2655, 16476, 2664, 16287, 2668, 2672, 16291, 2680, 2684, 2688, 16295, 0 }, { 2651, 2655, 16476, 2664, 16287, 2668, 2672, 16291, 2680, 2684, 2688, 16295, 0 }, 0, 0, 185, 187, { 3711, 16480, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3757, 3776, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 16492, 16496, { 16500, 16507, 16515, 16523, 16532, 16542, 16549 }, { 2544, 16558, 2550, 16561, 2556, 16564, 2562 }, { 1914, 2300, 2565, 3643, 2565, 3927, 1914 }, { 16567, 16576, 16586, 2588, 10611, 16592, 16598, 16604, 2615, 2625, 2633, 10623, 0 }, { 16567, 16576, 16586, 2588, 10611, 16592, 16598, 16604, 2615, 2625, 2633, 10623, 0 }, { 2651, 2655, 3699, 2664, 10611, 2668, 2672, 2676, 2680, 2684, 2688, 10636, 0 }, { 2651, 2655, 3699, 2664, 10611, 2668, 2672, 2676, 2680, 2684, 2688, 10636, 0 }, 0, 0, 2438, 187, { 1556, 9951, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10640, 5455, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 16613, 16629, 16654, 16682, 16710, 16738, 16766 }, { 16785, 16795, 16805, 16815, 16825, 16835, 16845 }, { 16855, 16859, 16863, 16859, 16867, 16871, 16875 }, { 16879, 16901, 16929, 16945, 16964, 16980, 16999, 17018, 17040, 17071, 17099, 17124, 0 }, { 16879, 16901, 16929, 16945, 16964, 16980, 16999, 17018, 17040, 17071, 17099, 17124, 0 }, { 17152, 17162, 17172, 17182, 17192, 17202, 17212, 17222, 17232, 17242, 17252, 17262, 0 }, { 17152, 17162, 17172, 17182, 17192, 17202, 17212, 17222, 17232, 17242, 17252, 17262, 0 }, 0, 1, 691, 187, { 2154, 17272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 222, 3808, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 17284, 17289, { 5897, 17294, 17305, 17315, 17325, 17335, 17349 }, { 17361, 17365, 17370, 17375, 17379, 17384, 17389 }, { 1914, 2300, 2302, 2300, 5644, 2306, 2308 }, { 2310, 2317, 4837, 6042, 4848, 2341, 2346, 2351, 2358, 2368, 2376, 6086, 0 }, { 2310, 2317, 4837, 6042, 4848, 2341, 2346, 2351, 2358, 2368, 2376, 6086, 0 }, { 2394, 2398, 2402, 2406, 4848, 2410, 2414, 2418, 2422, 2426, 2430, 7503, 0 }, { 2394, 2398, 2402, 2406, 4848, 2410, 2414, 2418, 2422, 2426, 2430, 7503, 0 }, 2, 1, 2438, 187, { 2440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5508, 6118, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 17393, 17409, { 17419, 17438, 17457, 17479, 17498, 17520, 17545 }, { 17564, 17574, 17584, 17597, 17607, 17620, 17636 }, { 17646, 17650, 17657, 17664, 17671, 17678, 17685 }, { 17689, 17705, 17724, 17740, 17759, 17766, 17776, 17792, 17808, 17827, 17849, 17865, 0 }, { 17689, 17705, 17724, 17740, 17759, 17766, 17776, 17792, 17808, 17827, 17849, 17865, 0 }, { 17884, 17891, 17724, 17901, 17759, 17766, 17917, 17930, 17937, 17950, 17966, 17976, 0 }, { 17884, 17891, 17724, 17901, 17759, 17766, 17917, 17930, 17937, 17950, 17966, 17976, 0 }, 0, 0, 2438, 187, { 2440, 2451, 4157, 8015, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 1730, 1722, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 1750, 1739, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 17989, 18004, 18007, { 18010, 18019, 18028, 18038, 18048, 18058, 18070 }, { 18078, 18083, 18087, 18091, 18095, 18100, 18105 }, { 18109, 2302, 2302, 9701, 18109, 18112, 1914 }, { 18115, 18122, 18127, 2588, 18133, 18139, 18146, 18152, 18160, 18170, 18178, 18187, 0 }, { 18115, 18122, 18127, 2588, 18133, 18139, 18146, 18152, 18160, 18170, 18178, 18187, 0 }, { 2651, 18197, 3699, 2664, 18201, 18205, 18210, 18214, 18218, 18222, 2688, 18226, 0 }, { 2651, 18197, 3699, 2664, 18201, 18205, 18210, 18214, 18218, 18222, 2688, 18226, 0 }, 0, 0, 185, 187, { 198, 9951, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 18231, 18257, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 18277, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 18295, 18300, { 18305, 18317, 18328, 18342, 18354, 18364, 18374 }, { 18385, 18390, 18395, 18400, 18405, 18410, 18415 }, { 1914, 3927, 2300, 6216, 2565, 16338, 2308 }, { 18420, 18437, 18450, 18464, 18477, 18490, 18503, 18517, 18529, 18543, 18557, 18571, 0 }, { 18420, 18437, 18450, 18464, 18477, 18490, 18503, 18517, 18529, 18543, 18557, 18571, 0 }, { 18584, 18591, 18596, 18601, 18605, 18610, 18615, 18620, 18625, 18632, 18637, 18643, 0 }, { 18584, 18591, 18596, 18601, 18605, 18610, 18615, 18620, 18625, 18632, 18637, 18643, 0 }, 2, 1, 2438, 187, { 1556, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 16078, 16096, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 19797, 19806, 19815, 19823, 19832, 19841, 19848 }, { 19857, 19860, 19863, 19866, 19869, 19873, 19876 }, { 6530, 6532, 6534, 6536, 12692, 15237, 6528 }, { 10588, 10596, 19879, 19885, 10611, 2598, 18989, 19892, 16250, 19899, 16267, 19906, 0 }, { 10588, 10596, 19879, 19885, 10611, 2598, 18989, 19892, 16250, 19899, 16267, 19906, 0 }, { 2651, 2655, 18985, 2664, 10611, 2668, 2672, 19914, 2680, 2684, 2688, 10636, 0 }, { 2651, 2655, 18985, 2664, 10611, 2668, 2672, 19914, 2680, 2684, 2688, 10636, 0 }, 0, 0, 185, 187, { 198, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 1820, 1823, { 19918, 19928, 19937, 19946, 19957, 19967, 19972 }, { 19979, 19985, 19990, 19995, 20000, 10578, 20004 }, { 20009, 2565, 1914, 7600, 1909, 3925, 1914 }, { 14948, 14955, 10132, 14962, 3668, 20011, 20016, 20021, 14987, 14996, 15004, 15011, 0 }, { 14948, 14955, 10132, 14962, 3668, 20011, 20016, 20021, 14987, 14996, 15004, 15011, 0 }, { 20028, 20033, 3699, 2664, 3668, 20011, 20016, 20037, 10562, 2684, 20041, 20046, 0 }, { 20028, 20033, 3699, 2664, 3668, 20011, 20016, 20037, 10562, 2684, 20041, 20046, 0 }, 0, 1, 185, 187, { 1545, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 20050, 16096, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 20069, 20097, { 20119, 20138, 20157, 20182, 20201, 20235, 20260 }, { 20279, 20289, 20299, 20315, 20325, 20350, 20366 }, { 20376, 20380, 20387, 20391, 20398, 20405, 20412 }, { 20416, 20444, 20478, 20494, 20513, 20520, 20530, 20546, 20562, 20593, 20615, 20637, 0 }, { 20416, 20444, 20478, 20494, 20513, 20520, 20530, 20546, 20562, 20593, 20615, 20637, 0 }, { 20416, 20444, 20478, 20494, 20513, 20520, 20530, 20546, 20562, 20593, 20615, 20637, 0 }, { 20416, 20444, 20478, 20494, 20513, 20520, 20530, 20546, 20562, 20593, 20615, 20637, 0 }, 0, 0, 2438, 691, { 2451, 4157, 2440, 2451, 2440, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4246, 4241, 20662, 20671, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4268, 4260, 20679, 20691, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 1820, 1823, { 21189, 21208, 21227, 21249, 21268, 21290, 21315 }, { 21334, 21344, 21354, 21367, 21377, 21390, 21406 }, { 21416, 21420, 21427, 21434, 21441, 21448, 21455 }, { 21459, 21487, 21515, 21531, 21550, 21557, 21567, 21583, 21599, 21627, 21649, 21671, 0 }, { 21459, 21487, 21515, 21531, 21550, 21557, 21567, 21583, 21599, 21627, 21649, 21671, 0 }, { 21696, 21715, 21515, 21531, 21550, 21557, 21567, 21734, 21741, 21757, 21773, 21783, 0 }, { 21696, 21715, 21515, 21531, 21550, 21557, 21567, 21734, 21741, 21757, 21773, 21783, 0 }, 0, 0, 2438, 187, { 2451, 4157, 8015, 2440, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 1730, 1722, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 1750, 1739, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 8022, 21796, { 21799, 21818, 21837, 21862, 21881, 21903, 21928 }, { 21947, 21957, 21967, 21983, 21993, 22006, 22022 }, { 22032, 22036, 22043, 22047, 22054, 22061, 22068 }, { 22072, 22094, 22125, 22147, 22166, 22173, 22183, 22199, 22215, 22246, 22268, 22290, 0 }, { 22072, 22094, 22125, 22147, 22166, 22173, 22183, 22199, 22215, 22246, 22268, 22290, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, 0, 0, 2438, 187, { 2451, 4157, 8015, 2440, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 1730, 1722, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 1750, 1739, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 22315, 22340, { 22365, 22384, 22406, 22431, 22447, 22469, 22488 }, { 22498, 22505, 22512, 22519, 22526, 22533, 22540 }, { 22498, 22505, 22512, 22519, 22526, 22533, 22540 }, { 22544, 22560, 22585, 22604, 22623, 22630, 22643, 22656, 22675, 22706, 22731, 22753, 0 }, { 22544, 22560, 22585, 22604, 22623, 22630, 22643, 22778, 22675, 22706, 22731, 22753, 0 }, { 22797, 22805, 22819, 22833, 22623, 22630, 22643, 22844, 22852, 22866, 22877, 22885, 0 }, { 22797, 22805, 22819, 22833, 22623, 22630, 22643, 22844, 22852, 22866, 22877, 22885, 0 }, 0, 0, 2438, 187, { 2440, 2451, 4157, 8015, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 1730, 1722, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 1750, 1739, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 1820, 1823, { 22896, 22918, 22940, 22965, 22987, 23012, 23040 }, { 23062, 23072, 23082, 23095, 23105, 23118, 23134 }, { 23144, 23148, 23155, 23159, 23166, 23173, 23180 }, { 23184, 23200, 23225, 23244, 23266, 23273, 23286, 23299, 23318, 23349, 23374, 23393, 0 }, { 23184, 23200, 23225, 23244, 23266, 23273, 23418, 23299, 23318, 23349, 23374, 23393, 0 }, { 23431, 23438, 23225, 23454, 23266, 23273, 23418, 23299, 23470, 23492, 23508, 23518, 0 }, { 23431, 23438, 23225, 23454, 23266, 23273, 23418, 23299, 23470, 23492, 23508, 23518, 0 }, 0, 0, 2438, 187, { 2451, 4157, 8015, 2440, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 1730, 1722, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 1750, 1739, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 1820, 1823, { 23534, 23553, 23572, 23594, 23613, 23635, 23660 }, { 23679, 23689, 23699, 23712, 23722, 23735, 23751 }, { 23761, 23765, 23772, 23779, 23786, 23793, 23800 }, { 23804, 23820, 23845, 23864, 23886, 23893, 23906, 23919, 23938, 23966, 23991, 24013, 0 }, { 23804, 23820, 23845, 23864, 23886, 23893, 23906, 23919, 23938, 23966, 23991, 24013, 0 }, { 24038, 24046, 24066, 24073, 23886, 24090, 24097, 24105, 24113, 24136, 24153, 24167, 0 }, { 24038, 24046, 24066, 24073, 23886, 24090, 24097, 24105, 24113, 24136, 24153, 24167, 0 }, 0, 0, 2438, 187, { 2451, 4157, 8015, 2440, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 1730, 1722, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 1750, 1739, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 24184, 1820, 1823, { 24192, 24220, 24254, 24282, 24310, 24341, 24378 }, { 24406, 24419, 24438, 24454, 24467, 24486, 24505 }, { 24515, 24522, 24529, 24536, 24543, 24556, 24563 }, { 24567, 24586, 24614, 24636, 24655, 24668, 24678, 24691, 24716, 24747, 24772, 24788, 0 }, { 24567, 24586, 24614, 24636, 24655, 24668, 24678, 24691, 24716, 24747, 24772, 24788, 0 }, { 24807, 24817, 24836, 24846, 24655, 24668, 24678, 24862, 24869, 24894, 24910, 24920, 0 }, { 24807, 24817, 24836, 24846, 24655, 24668, 24678, 24862, 24869, 24894, 24910, 24920, 0 }, 0, 0, 2438, 691, { 2451, 4157, 2696, 8015, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4246, 4241, 20662, 20671, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4268, 4260, 20679, 20691, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 24933, 24961, { 24983, 25002, 25021, 25046, 25065, 25099, 25124 }, { 25143, 20289, 20299, 20315, 25153, 25178, 20366 }, { 0, 0, 0, 0, 0, 0, 0 }, { 25194, 25219, 25250, 25266, 20513, 20520, 20530, 25285, 25301, 25332, 25354, 25376, 0 }, { 25194, 25219, 25250, 25266, 20513, 20520, 20530, 25285, 25301, 25332, 25354, 25376, 0 }, { 25401, 25414, 25250, 25266, 20513, 20520, 20530, 25433, 25440, 25456, 25472, 25482, 0 }, { 25401, 25414, 25250, 25266, 20513, 20520, 20530, 25433, 25440, 25456, 25472, 25482, 0 }, 0, 0, 2438, 187, { 2440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 25495, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1722, 1730, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1739, 1750, 848, 0, 0, 0, 0, 0, 0 }, { 25514, 25522, 0, 0, 0, 0, 0, 0 } }, { 1, 1820, 1823, { 17419, 17438, 25532, 17479, 17498, 17520, 17545 }, { 17564, 17574, 25554, 17597, 17607, 17620, 17636 }, { 17646, 17650, 17657, 17664, 17671, 17678, 17685 }, { 25567, 25592, 17724, 25623, 25642, 17766, 25649, 25662, 25678, 25703, 25725, 25753, 0 }, { 25567, 25592, 17724, 25623, 25642, 17766, 25649, 25662, 25678, 25703, 25725, 25753, 0 }, { 25775, 25788, 17724, 25807, 25642, 17766, 25649, 25823, 25830, 25849, 25865, 25887, 0 }, { 25775, 25788, 17724, 25807, 25642, 17766, 25649, 25823, 25830, 25849, 25865, 25887, 0 }, 0, 0, 2438, 187, { 2440, 2451, 4157, 8015, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 1730, 1722, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 1750, 1739, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 26596, 26620, 26642, { 26667, 26695, 26723, 26760, 26791, 26825, 26850 }, { 26884, 26900, 26916, 26941, 26960, 26982, 26995 }, { 27017, 27024, 27031, 27038, 27045, 27052, 27056 }, { 27066, 27100, 27137, 27171, 27205, 27236, 27273, 27310, 27350, 27384, 27418, 27467, 0 }, { 27066, 27100, 27137, 27171, 27205, 27236, 27273, 27310, 27350, 27384, 27418, 27467, 0 }, { 27516, 27529, 27542, 27555, 27568, 27581, 27594, 27607, 27620, 27633, 27649, 27665, 0 }, { 27516, 27529, 27542, 27555, 27568, 27581, 27594, 27607, 27620, 27633, 27649, 27665, 0 }, 0, 0, 185, 187, { 1518, 1527, 1536, 1567, 1556, 1545, 1585, 1578, 1592, 0, 0, 0, 0, 0 }, { 27681, 27724, 27772, 27804, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 27841, 1805, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 27874, 27883, 27893, 27905, 27918, 27927, 27939 }, { 27951, 27955, 27960, 27964, 27968, 27972, 27976 }, { 1914, 27980, 2300, 2300, 15237, 6216, 1914 }, { 27983, 27990, 27999, 28006, 2594, 28013, 28021, 28032, 28037, 28042, 28049, 28058, 0 }, { 27983, 27990, 27999, 28006, 2594, 28013, 28021, 28032, 28037, 28042, 28049, 28058, 0 }, { 28066, 28070, 27960, 28074, 2594, 28078, 28082, 28032, 28037, 28086, 28090, 28095, 0 }, { 28066, 28070, 27960, 28074, 2594, 28078, 28082, 28032, 28037, 28086, 28090, 28095, 0 }, 2, 1, 185, 187, { 198, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 28100, 28116, { 28132, 28154, 28167, 28186, 28196, 28227, 28243 }, { 28132, 28154, 28167, 28186, 28196, 28227, 28243 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540 }, { 28256, 28269, 28288, 28301, 28314, 28327, 28346, 28365, 28378, 28394, 28407, 28432, 0 }, { 28256, 28269, 28288, 28301, 28314, 28327, 28346, 28365, 28378, 28394, 28407, 28432, 0 }, { 28256, 28269, 28288, 28301, 28314, 28327, 28346, 28365, 28378, 28394, 28407, 28432, 0 }, { 28256, 28269, 28288, 28301, 28314, 28327, 28346, 28365, 28378, 28394, 28407, 28432, 0 }, 0, 0, 185, 187, { 189, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3520, 9963, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 28445, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 28480, 28505, { 28530, 28555, 28574, 28602, 28621, 28646, 28665 }, { 28530, 28555, 28574, 28602, 28621, 28646, 28665 }, { 28687, 28691, 28695, 28699, 28709, 28713, 28723 }, { 28727, 28746, 28762, 28775, 28788, 28810, 28829, 28851, 28867, 28883, 28896, 28912, 0 }, { 28727, 28746, 28762, 28775, 28788, 28810, 28829, 28851, 28867, 28883, 28896, 28912, 0 }, { 28928, 28937, 28946, 28955, 28964, 28973, 28985, 28994, 29003, 29012, 29021, 29030, 0 }, { 28928, 28937, 28946, 28955, 28964, 28973, 28985, 28994, 29003, 29012, 29021, 29030, 0 }, 0, 0, 185, 187, { 1120, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 29039, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 7261, 7266, { 3833, 29066, 3847, 29071, 29081, 29087, 3880 }, { 29094, 8298, 3699, 29098, 29103, 29107, 29111 }, { 2565, 2308, 2300, 2300, 29116, 3927, 1914 }, { 29118, 29126, 3943, 3949, 29135, 29140, 29146, 3972, 29152, 29161, 29169, 29178, 0 }, { 29187, 29195, 4032, 1012, 7947, 29204, 29210, 4055, 7964, 7973, 7981, 29216, 0 }, { 29225, 2655, 3699, 29229, 2594, 29233, 29238, 19914, 18218, 29242, 2688, 3707, 0 }, { 29225, 2655, 3699, 29229, 2594, 29233, 29238, 19914, 18218, 29242, 2688, 3707, 0 }, 2, 1, 185, 187, { 198, 17272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5508, 5455, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 29246, 29258, { 29270, 17438, 29298, 17479, 17498, 17520, 17545 }, { 17564, 17574, 25554, 17597, 17607, 17620, 17636 }, { 0, 0, 0, 0, 0, 0, 0 }, { 25567, 25592, 17724, 25623, 25642, 17766, 25649, 29317, 29333, 29361, 25725, 25753, 0 }, { 25567, 25592, 17724, 25623, 25642, 17766, 25649, 29317, 29333, 29361, 25725, 25753, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, 0, 0, 2438, 187, { 2440, 2451, 4157, 8015, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 1730, 1722, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 1750, 1739, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 29383, 29395, { 29404, 29420, 29436, 29464, 29480, 29523, 29548 }, { 29404, 29420, 29576, 29464, 29586, 29608, 29621 }, { 29631, 29635, 29639, 29643, 29647, 29660, 29667 }, { 29674, 29693, 29718, 29737, 29762, 29775, 29788, 29801, 29823, 29857, 29882, 29910, 0 }, { 29674, 29693, 29718, 29737, 29762, 29775, 29788, 29801, 29823, 29857, 29882, 29910, 0 }, { 29938, 29945, 29955, 29737, 29762, 29775, 29788, 29968, 29978, 29991, 30001, 30014, 0 }, { 29938, 29945, 29955, 29737, 29762, 29775, 29788, 29968, 29978, 29991, 30001, 30014, 0 }, 0, 1, 2438, 691, { 1556, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 16078, 16096, 0, 0, 0, 0, 0, 0, 0, 0 }, { 20671, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 20691, 269, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 30027, 30037, { 30050, 30060, 30067, 30080, 30090, 30100, 30110 }, { 30050, 30060, 30120, 30080, 30090, 30100, 30110 }, { 30130, 30134, 30138, 30142, 30146, 30150, 30154 }, { 30158, 30174, 30190, 30200, 30213, 30220, 30227, 30237, 30250, 30269, 30285, 30301, 0 }, { 30158, 30174, 30190, 30200, 30213, 30220, 30227, 30237, 30250, 30317, 30285, 30301, 0 }, { 30336, 30346, 30190, 30356, 30213, 30220, 30227, 30366, 30376, 30386, 30396, 30406, 0 }, { 30336, 30346, 30190, 30356, 30213, 30220, 30227, 30366, 30376, 30386, 30396, 30406, 0 }, 0, 0, 185, 187, { 198, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 30651, 30692, { 30733, 30752, 30771, 30796, 30815, 30837, 30862 }, { 30881, 17574, 30891, 17597, 30907, 17620, 17636 }, { 30920, 17650, 30924, 17664, 30928, 17678, 17685 }, { 17689, 30935, 17724, 30963, 25642, 30982, 17776, 30992, 31008, 31039, 31061, 31086, 0 }, { 17689, 30935, 17724, 30963, 25642, 30982, 17776, 30992, 31008, 31039, 31061, 31086, 0 }, { 17689, 30935, 17724, 30963, 25642, 30982, 17776, 30992, 31008, 31039, 31061, 31086, 0 }, { 17689, 30935, 17724, 30963, 25642, 30982, 17776, 30992, 31008, 31039, 31061, 31086, 0 }, 0, 0, 185, 187, { 3711, 3720, 3727, 3736, 1599, 1556, 3747, 0, 0, 0, 0, 0, 0, 0 }, { 31111, 31131, 222, 10501, 0, 0, 0, 0, 0, 0 }, { 3532, 242, 843, 251, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 257, 848, 269, 0, 0, 0, 0, 0 }, { 25522, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 0, 0, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, { 31145, 31152, 31161, 31176, 31187, 31196, 31203, 31210, 31217, 31228, 31241, 31254, 0 }, { 31145, 31152, 31161, 31176, 31187, 31196, 31203, 31210, 31217, 31228, 31241, 31254, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, 0, 6, 185, 187, { 1518, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3520, 4935, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 1820, 1823, { 31259, 31266, 31272, 31279, 31290, 31298, 31307 }, { 31314, 8298, 3699, 31318, 31322, 31326, 10582 }, { 2308, 2308, 2300, 2300, 5644, 16338, 1914 }, { 3929, 31330, 31338, 3949, 3955, 31344, 31350, 3972, 31356, 31366, 31374, 31384, 0 }, { 3929, 31330, 31338, 3949, 3955, 31344, 31350, 3972, 31356, 31366, 31374, 31384, 0 }, { 31394, 31398, 3699, 29229, 3668, 31402, 31406, 19914, 18218, 2684, 31410, 16295, 0 }, { 31394, 31398, 3699, 29229, 3668, 31402, 31406, 19914, 18218, 2684, 31410, 16295, 0 }, 0, 0, 185, 187, { 3711, 16480, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3757, 3776, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 0, 0, { 31414, 31421, 31429, 31436, 31443, 31451, 31459 }, { 31466, 31469, 31472, 31475, 31478, 31481, 31484 }, { 2308, 2308, 2302, 2308, 12692, 3925, 12692 }, { 31487, 31495, 31505, 31511, 31519, 31524, 31529, 31534, 31541, 19899, 31549, 31557, 0 }, { 31487, 31495, 31505, 31511, 31519, 31524, 31529, 31534, 31541, 19899, 31549, 31557, 0 }, { 2651, 31565, 3699, 31569, 3668, 30620, 30624, 31573, 3639, 2684, 31577, 16295, 0 }, { 2651, 31565, 3699, 31569, 3668, 30620, 30624, 31573, 3639, 2684, 31577, 16295, 0 }, 0, 0, 185, 187, { 1120, 17272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3789, 3808, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 31581, 31592, { 31602, 31620, 31635, 31657, 31670, 31684, 31701 }, { 31725, 31733, 31738, 31657, 31670, 31750, 31757 }, { 0, 0, 0, 0, 0, 0, 0 }, { 31771, 31793, 31809, 31829, 31843, 31860, 31875, 31892, 31906, 31919, 31938, 31952, 0 }, { 31771, 31793, 31809, 31829, 31843, 31860, 31875, 31892, 31906, 31919, 31938, 31952, 0 }, { 31971, 31986, 31995, 32008, 32015, 32025, 32033, 32043, 32050, 32056, 32068, 32075, 0 }, { 31971, 31986, 31995, 32008, 32015, 32025, 32033, 32043, 32050, 32056, 32068, 32075, 0 }, 0, 0, 185, 187, { 198, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 0, 0, { 32087, 32095, 15840, 15849, 15858, 32106, 32116 }, { 16326, 15890, 15894, 15898, 15902, 16189, 32125 }, { 0, 0, 0, 0, 0, 0, 0 }, { 32129, 32138, 32148, 32156, 10611, 3672, 32164, 32170, 32179, 32188, 32197, 32206, 0 }, { 32129, 32138, 32148, 32156, 10611, 3672, 32164, 32170, 32179, 32188, 32197, 32206, 0 }, { 2651, 2655, 15909, 32215, 10611, 2668, 2672, 19914, 18218, 2684, 32219, 16295, 0 }, { 2651, 2655, 15909, 32215, 10611, 2668, 2672, 19914, 18218, 2684, 32219, 16295, 0 }, 0, 0, 2438, 187, { 1556, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 16078, 16096, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 32223, 32236, 32241, { 32246, 32253, 32268, 32282, 32298, 32313, 32329 }, { 6212, 32344, 2402, 32348, 32352, 32356, 32360 }, { 1914, 12692, 2300, 1909, 1914, 2302, 12692 }, { 7350, 7358, 32364, 32371, 32378, 2341, 2346, 32383, 32393, 32404, 32413, 32423, 0 }, { 7350, 7358, 32364, 32371, 32378, 2341, 2346, 32383, 32393, 32404, 32413, 32423, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 2418, 2422, 2426, 2430, 2434, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 2418, 2422, 2426, 2430, 2434, 0 }, 0, 0, 2438, 187, { 2440, 2451, 1556, 2460, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 32433, 2194, 11931, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 32452, 32457, { 32462, 32478, 32486, 32494, 32503, 32515, 32525 }, { 32535, 32541, 32547, 32551, 32555, 32563, 3639 }, { 0, 0, 0, 0, 0, 0, 0 }, { 32570, 32583, 32597, 32606, 32612, 32616, 32621, 32629, 16250, 32642, 16267, 16275, 0 }, { 32570, 32583, 32597, 32606, 32612, 32616, 32621, 32629, 16250, 32642, 16267, 16275, 0 }, { 32651, 2655, 32655, 16283, 32612, 32659, 2672, 32663, 2680, 32671, 2688, 16295, 0 }, { 32651, 2655, 32655, 16283, 32612, 32659, 2672, 32663, 2680, 32671, 2688, 16295, 0 }, 0, 0, 185, 187, { 198, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 32677, 32700, 32707, { 32714, 32724, 32734, 32744, 32754, 32764, 32774 }, { 32784, 32791, 32798, 32805, 32812, 32819, 32826 }, { 32833, 32837, 32841, 32845, 32849, 32853, 32857 }, { 32861, 32868, 32875, 32882, 32889, 32896, 32903, 32910, 32917, 32924, 32931, 32941, 0 }, { 32861, 32868, 32875, 32882, 32889, 32896, 32903, 32910, 32917, 32924, 32931, 32941, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540, 6542, 6544, 6546, 6549, 6552, 0 }, 0, 0, 185, 187, { 1518, 1527, 1536, 1567, 1556, 1545, 0, 0, 0, 0, 0, 0, 0, 0 }, { 32951, 32975, 33005, 33035, 33052, 0, 0, 0, 0, 0 }, { 1722, 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1739, 848, 269, 0, 0, 0, 0, 0, 0 }, { 33075, 1805, 0, 0, 0, 0, 0, 0 } }, { 289, 0, 0, { 27951, 8298, 33092, 33099, 33109, 33114, 33121 }, { 33128, 6196, 33132, 4800, 33137, 33142, 33147 }, { 4392, 33152, 33155, 33158, 33161, 33164, 33167 }, { 33170, 33177, 33092, 33188, 33194, 33198, 33207, 33214, 33219, 33228, 33233, 33236, 0 }, { 33170, 33177, 33092, 33188, 33194, 33198, 33207, 33214, 33219, 33228, 33233, 33236, 0 }, { 33242, 33246, 33253, 28074, 33194, 33258, 33263, 33214, 33268, 33228, 33233, 33273, 0 }, { 33242, 33246, 33253, 28074, 33194, 33258, 33263, 33214, 33268, 33228, 33233, 33273, 0 }, 2, 1, 2438, 187, { 1556, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 16078, 16096, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 33430, 33446, 33451, { 33456, 33481, 33510, 33535, 33548, 33563, 33580 }, { 33595, 33600, 33605, 33610, 33615, 33620, 8599 }, { 19210, 19210, 33625, 8610, 8613, 19210, 8610 }, { 33628, 33647, 33662, 33684, 33704, 33720, 33736, 33750, 33776, 33800, 33817, 33834, 0 }, { 33628, 33647, 33662, 33684, 33704, 33720, 33736, 33750, 33776, 33800, 33817, 33834, 0 }, { 33851, 33860, 33869, 33883, 33897, 33909, 33921, 33931, 33947, 33961, 33968, 33975, 0 }, { 33851, 33860, 33869, 33883, 33897, 33909, 33921, 33931, 33947, 33961, 33968, 33975, 0 }, 0, 1, 691, 187, { 2154, 4724, 1556, 33982, 33992, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 34005, 34040, 34069, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 34104, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 0, 0, { 34120, 34132, 34143, 34155, 34167, 34177, 34189 }, { 34204, 34209, 34214, 34219, 34224, 34229, 34234 }, { 0, 0, 0, 0, 0, 0, 0 }, { 34239, 34248, 34260, 34268, 34273, 34283, 34290, 34299, 34306, 34312, 34321, 34332, 0 }, { 34239, 34248, 34260, 34268, 34273, 34283, 34290, 34299, 34306, 34312, 34321, 34332, 0 }, { 34340, 34345, 34350, 34355, 34360, 34365, 34370, 34224, 34375, 34380, 34385, 34390, 0 }, { 34340, 34345, 34350, 34355, 34360, 34365, 34370, 34224, 34375, 34380, 34385, 34390, 0 }, 0, 0, 185, 187, { 1545, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 20050, 16096, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 34395, 34406, 34408, { 34410, 34423, 34431, 34440, 34450, 34460, 34469 }, { 34481, 34485, 34489, 34493, 34497, 34501, 34505 }, { 2565, 2308, 2300, 7600, 12692, 5644, 1914 }, { 34509, 34523, 34534, 34543, 34554, 34566, 34580, 34592, 34605, 34618, 34630, 34643, 0 }, { 34509, 34523, 34534, 34543, 34554, 34566, 34580, 34592, 34605, 34618, 34630, 34643, 0 }, { 34657, 34662, 34668, 34674, 34679, 34685, 34691, 34696, 34702, 34707, 18931, 34713, 0 }, { 34657, 34662, 34668, 34674, 34679, 34685, 34691, 34696, 34702, 34707, 18931, 34713, 0 }, 2, 1, 185, 187, { 198, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 34719, 34741, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 34826, 34829, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34929, 34932, 34935, 34938, 34941, 13447, 13438 }, { 34944, 34968, 34977, 34986, 34997, 35006, 35019, 35028, 35033, 35044, 35066, 35090, 0 }, { 34944, 34968, 34977, 34986, 34997, 35006, 35019, 35028, 35033, 35044, 35066, 35090, 0 }, { 34944, 34968, 34977, 34986, 34997, 35006, 35019, 35028, 35033, 35044, 35066, 35090, 0 }, { 34944, 34968, 34977, 34986, 34997, 35006, 35019, 35028, 35033, 35044, 35066, 35090, 0 }, 0, 6, 185, 187, { 198, 189, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10501, 222, 0, 0, 0, 0, 0, 0, 0, 0 }, { 242, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 257, 269, 0, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 1195, 1204, 1211, { 1218, 1228, 1238, 1248, 1258, 1268, 1278 }, { 1288, 1295, 1302, 1309, 1316, 1323, 1330 }, { 1337, 1341, 1345, 1349, 1353, 1357, 1361 }, { 1365, 1372, 1379, 1386, 1393, 1400, 1407, 1414, 1421, 1428, 1435, 1445, 0 }, { 1365, 1372, 1379, 1386, 1393, 1400, 1407, 1414, 1421, 1428, 1435, 1445, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, 0, 0, 185, 187, { 1518, 1527, 1536, 1545, 1556, 1567, 1578, 1585, 1592, 1599, 0, 0, 0, 0 }, { 1608, 1630, 1658, 1686, 1701, 0, 0, 0, 0, 0 }, { 843, 251, 1722, 1730, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 1739, 1750, 0, 0, 0, 0, 0 }, { 1762, 1778, 1791, 1805, 0, 0, 0, 0 } }, { 35112, 2471, 2477, { 2484, 2492, 2499, 2508, 2517, 2528, 2536 }, { 2544, 2547, 2550, 2553, 2556, 2559, 2562 }, { 1914, 2300, 2565, 2300, 2565, 2306, 1914 }, { 2567, 2574, 2582, 2588, 2594, 2598, 2603, 2608, 2615, 2625, 2633, 2642, 0 }, { 2567, 2574, 2582, 2588, 2594, 2598, 2603, 2608, 2615, 2625, 2633, 2642, 0 }, { 2651, 2655, 2659, 2664, 2594, 2668, 2672, 2676, 2680, 2684, 2688, 2692, 0 }, { 2651, 2655, 2659, 2664, 2594, 2668, 2672, 2676, 2680, 2684, 2688, 2692, 0 }, 2, 1, 691, 187, { 2154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2719, 2194, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 8022, 21796, { 3558, 3565, 3572, 3580, 3590, 3599, 3606 }, { 3615, 3619, 3623, 3627, 3631, 3635, 3639 }, { 1914, 2300, 2302, 3643, 2302, 2306, 1914 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, 2, 1, 185, 187, { 198, 189, 3483, 8015, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 3502, 10640, 0, 0, 0, 0, 0, 0 }, { 251, 843, 242, 3532, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 257, 3540, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3821, 7261, 7266, { 3833, 3841, 3847, 3854, 3865, 3872, 3880 }, { 35121, 6196, 4795, 35126, 35132, 35137, 35141 }, { 2565, 2308, 2300, 29116, 3925, 3927, 1914 }, { 4018, 4024, 4032, 1012, 4038, 4043, 4049, 4055, 4062, 1050, 4073, 4083, 0 }, { 4018, 4024, 4032, 1012, 4038, 4043, 4049, 4055, 4062, 1050, 4073, 4083, 0 }, { 35147, 5753, 35151, 1086, 35156, 2410, 2414, 1096, 1100, 1105, 1110, 35160, 0 }, { 35147, 5753, 35151, 1086, 35156, 2410, 2414, 1096, 1100, 1105, 1110, 35160, 0 }, 0, 0, 185, 187, { 198, 3490, 189, 4149, 3483, 2451, 1556, 0, 0, 0, 0, 0, 0, 0 }, { 4164, 4219, 0, 0, 0, 0, 0, 0, 0, 0 }, { 242, 3532, 843, 251, 0, 0, 0, 0, 0, 0, 0, 0 }, { 257, 3540, 848, 269, 0, 0, 0, 0, 0 }, { 4288, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 4733, 4742, 4748, 4754, 4763, 4769, 4778 }, { 4785, 4790, 4795, 4800, 4805, 4810, 4815 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 4820, 4828, 4837, 4842, 4848, 4852, 4857, 4865, 4871, 4881, 1058, 4889, 0 }, { 4820, 4828, 4837, 4842, 4848, 4852, 4857, 4865, 4871, 4881, 1058, 4889, 0 }, { 4899, 4905, 4837, 4912, 4848, 4852, 4917, 4865, 4923, 1105, 1110, 4929, 0 }, { 4899, 4905, 4837, 4912, 4848, 4852, 4917, 4865, 4923, 1105, 1110, 4929, 0 }, 2, 1, 2438, 187, { 2451, 198, 189, 2440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4935, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 4246, 4961, 4971, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 35165, 1820, 1823, { 6130, 6139, 6147, 6156, 6167, 6176, 6185 }, { 6192, 6196, 2402, 6200, 6204, 6208, 6212 }, { 2565, 2308, 2300, 2300, 6216, 3927, 1914 }, { 6218, 6226, 3943, 6235, 6242, 6249, 6256, 3972, 6263, 6273, 6281, 6290, 0 }, { 6299, 6307, 4032, 6316, 6323, 6330, 6337, 4055, 6344, 6354, 1058, 6362, 0 }, { 6371, 2398, 2402, 2406, 6375, 6379, 6383, 6387, 6391, 6395, 2430, 6399, 0 }, { 6371, 2398, 2402, 2406, 6375, 6379, 6383, 6387, 6391, 6395, 2430, 6399, 0 }, 2, 1, 691, 187, { 2154, 14774, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 35173, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 7261, 7266, { 7271, 7278, 7286, 7294, 7303, 7313, 7321 }, { 7330, 4395, 7333, 7336, 7339, 7342, 7345 }, { 7348, 2300, 2565, 3643, 2565, 3927, 7348 }, { 7350, 7358, 7367, 2331, 7373, 2341, 2346, 7377, 2358, 2368, 2376, 2385, 0 }, { 7350, 7358, 7367, 2331, 7373, 2341, 2346, 7377, 2358, 2368, 2376, 2385, 0 }, { 2394, 2398, 7386, 2406, 7373, 2410, 2414, 2418, 2422, 2426, 2430, 2434, 0 }, { 2394, 2398, 7386, 2406, 7373, 2410, 2414, 2418, 2422, 2426, 2430, 2434, 0 }, 2, 1, 185, 187, { 14753, 4149, 2451, 2696, 7399, 1556, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4935, 3747, 3520, 5498, 0, 0, 0, 0, 0, 0 }, { 843, 251, 35183, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 35193, 35198, { 2217, 9837, 35203, 2240, 2247, 2255, 35210 }, { 2270, 9865, 35218, 2283, 2287, 2291, 35222 }, { 1914, 2300, 2302, 2304, 2302, 2306, 2308 }, { 2310, 2317, 4837, 2331, 4848, 2341, 2346, 2351, 2358, 2368, 2376, 6086, 0 }, { 2310, 2317, 4837, 2331, 4848, 2341, 2346, 2351, 2358, 2368, 2376, 6086, 0 }, { 2394, 2398, 2402, 2406, 4848, 2410, 2414, 2418, 2422, 2426, 2430, 7503, 0 }, { 2394, 2398, 2402, 2406, 4848, 2410, 2414, 2418, 2422, 2426, 2430, 7503, 0 }, 2, 1, 691, 187, { 2154, 6118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2176, 2194, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3821, 7261, 7266, { 3833, 7830, 7844, 7857, 7870, 7883, 3880 }, { 6192, 7895, 7899, 7903, 7907, 7911, 7915 }, { 2565, 1914, 2302, 7920, 7920, 1914, 1914 }, { 35226, 35234, 35244, 3949, 29135, 35251, 35257, 3972, 29152, 29161, 29169, 35263, 0 }, { 35226, 35234, 35244, 3949, 29135, 35251, 35257, 3972, 29152, 29161, 29169, 35263, 0 }, { 2651, 20033, 3699, 29229, 2594, 2668, 2672, 19914, 18218, 29242, 2688, 2692, 0 }, { 2651, 20033, 3699, 29229, 2594, 2668, 2672, 19914, 18218, 29242, 2688, 2692, 0 }, 2, 1, 185, 187, { 198, 2154, 2440, 189, 2696, 2451, 1545, 1567, 1556, 1599, 35272, 6936, 0, 0 }, { 4219, 4164, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4288, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 9823, 9826, { 9829, 9837, 9845, 2240, 2247, 2255, 9852 }, { 9860, 9865, 9870, 2283, 2287, 2291, 9874 }, { 1914, 2300, 2302, 2304, 2302, 2306, 2308 }, { 7350, 7358, 4837, 2331, 2337, 2341, 2346, 9879, 2358, 2368, 2376, 2385, 0 }, { 7350, 7358, 4837, 2331, 2337, 2341, 2346, 9879, 2358, 2368, 2376, 2385, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 2418, 2422, 2426, 2430, 2434, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 2418, 2422, 2426, 2430, 2434, 0 }, 2, 1, 2438, 187, { 2440, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4935, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 35281, 35292, 35316, 35346, 35363, 35385, 35394 }, { 14921, 14924, 14929, 14935, 14939, 7600, 14944 }, { 6540, 6528, 6530, 6532, 6534, 6536, 6538 }, { 35405, 35418, 501, 35431, 521, 35442, 35451, 542, 35460, 35477, 35492, 35505, 0 }, { 35405, 35418, 501, 35431, 521, 35442, 35451, 542, 35460, 35477, 35492, 35505, 0 }, { 15095, 7999, 2402, 2406, 15043, 15099, 15103, 15107, 15111, 2426, 15115, 15119, 0 }, { 15095, 7999, 2402, 2406, 15043, 15099, 15103, 15107, 15111, 2426, 15115, 15119, 0 }, 0, 1, 691, 187, { 2154, 2696, 8015, 189, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3520, 5455, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 7261, 7266, { 18648, 18662, 18672, 18683, 18697, 18708, 18719 }, { 18732, 18737, 18742, 18749, 18755, 18761, 18767 }, { 2565, 2308, 2300, 7600, 2565, 12692, 1914 }, { 18772, 18780, 18788, 18795, 18804, 18814, 18824, 18830, 18838, 18853, 18871, 18879, 0 }, { 18772, 18780, 18788, 18795, 18804, 18814, 18824, 18830, 18838, 18853, 18871, 18879, 0 }, { 18887, 18891, 18788, 18897, 18901, 18906, 18824, 18912, 18917, 18924, 18931, 18936, 0 }, { 18887, 18891, 18788, 18897, 18901, 18906, 18824, 18912, 18917, 18924, 18931, 18936, 0 }, 2, 0, 185, 187, { 198, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4935, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 1820, 1823, { 35518, 35533, 35548, 35563, 35580, 35597, 35606 }, { 35617, 35624, 35631, 35638, 35645, 19574, 35652 }, { 35659, 19207, 8610, 8613, 8607, 19204, 19588 }, { 13102, 13113, 8644, 13126, 8666, 13137, 13144, 8691, 13151, 13166, 13179, 13190, 0 }, { 13102, 13113, 8644, 13126, 8666, 13137, 13144, 8691, 13151, 13166, 13179, 13190, 0 }, { 13203, 13210, 13217, 13224, 8666, 13137, 13144, 13231, 13238, 13245, 13252, 13259, 0 }, { 13203, 13210, 13217, 13224, 8666, 13137, 13144, 13231, 13238, 13245, 13252, 13259, 0 }, 0, 1, 185, 187, { 1545, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 20050, 16096, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 20069, 20097, { 20119, 20138, 20157, 20182, 20201, 20235, 20260 }, { 20279, 20289, 20299, 20315, 20325, 20350, 20366 }, { 20376, 20380, 20387, 20391, 20398, 20405, 20412 }, { 20416, 20444, 20478, 20494, 20513, 20520, 20530, 20546, 20562, 20593, 20615, 20637, 0 }, { 20416, 20444, 20478, 20494, 20513, 20520, 20530, 20546, 20562, 20593, 20615, 20637, 0 }, { 20416, 20444, 20478, 20494, 20513, 20520, 20530, 20546, 20562, 20593, 20615, 20637, 0 }, { 20416, 20444, 20478, 20494, 20513, 20520, 20530, 20546, 20562, 20593, 20615, 20637, 0 }, 0, 5, 2438, 691, { 2451, 4157, 8015, 2440, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4246, 4241, 20662, 20671, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4268, 4260, 20679, 20691, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 34826, 34829, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34929, 34932, 34935, 34938, 34941, 13447, 13438 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, 0, 6, 185, 187, { 198, 189, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10501, 222, 0, 0, 0, 0, 0, 0, 0, 0 }, { 242, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 257, 269, 0, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 1195, 1204, 1211, { 1218, 1228, 1238, 1248, 1258, 1268, 1278 }, { 34757, 34764, 34771, 34778, 34785, 34792, 34799 }, { 1337, 1341, 1345, 1349, 1353, 1357, 1361 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, 0, 0, 185, 187, { 1120, 3483, 189, 1578, 1599, 1518, 1545, 1556, 0, 0, 0, 0, 0, 0 }, { 1608, 6555, 1686, 1701, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 1762, 1778, 1791, 1805, 0, 0, 0, 0 } }, { 35112, 2471, 2477, { 2484, 2492, 2499, 2508, 2517, 2528, 2536 }, { 2544, 2547, 2550, 2553, 2556, 2559, 2562 }, { 1914, 2300, 2565, 2300, 2565, 2306, 1914 }, { 35791, 2574, 2582, 2588, 2594, 2598, 2603, 2608, 2615, 2625, 2633, 2642, 0 }, { 35791, 2574, 2582, 2588, 2594, 2598, 2603, 2608, 2615, 2625, 2633, 2642, 0 }, { 35799, 2655, 2659, 2664, 2594, 2668, 2672, 2676, 2680, 2684, 2688, 2692, 0 }, { 35799, 2655, 2659, 2664, 2594, 2668, 2672, 2676, 2680, 2684, 2688, 2692, 0 }, 2, 1, 691, 187, { 2154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2719, 2194, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 3558, 3565, 3572, 3580, 3590, 3599, 3606 }, { 3615, 3619, 3623, 3627, 3631, 3635, 3639 }, { 1914, 2300, 2302, 3643, 2302, 2306, 1914 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, 0, 0, 185, 187, { 14753, 4149, 3483, 1120, 189, 198, 3747, 5468, 1556, 1599, 1545, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 848, 269, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3821, 872, 878, { 3833, 3841, 3847, 3854, 3865, 3872, 3880 }, { 3888, 3893, 3898, 3903, 3909, 3914, 3919 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 3929, 3935, 3943, 3949, 3955, 3960, 3966, 3972, 3979, 3990, 3998, 4008, 0 }, { 4018, 4024, 4032, 1012, 4038, 4043, 4049, 4055, 4062, 1050, 4073, 4083, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, 2, 1, 185, 187, { 198, 189, 4149, 3483, 4157, 2451, 2696, 1556, 0, 0, 0, 0, 0, 0 }, { 4164, 4192, 4219, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 4241, 4246, 4252, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 4260, 4268, 4277, 0, 0, 0, 0 }, { 4288, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 4733, 4742, 4748, 4754, 4763, 4769, 4778 }, { 4785, 4790, 4795, 4800, 4805, 4810, 4815 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 4820, 4828, 4837, 4842, 4848, 4852, 4857, 4865, 4871, 4881, 1058, 4889, 0 }, { 4820, 4828, 4837, 4842, 4848, 4852, 4857, 4865, 4871, 4881, 1058, 4889, 0 }, { 4899, 4905, 4837, 4912, 4848, 4852, 4917, 4865, 4923, 1105, 1110, 4929, 0 }, { 4899, 4905, 4837, 4912, 4848, 4852, 4917, 4865, 4923, 1105, 1110, 4929, 0 }, 0, 0, 2438, 187, { 1556, 6936, 2451, 35804, 189, 3490, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3520, 1129, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 4246, 4961, 4971, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 0, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 35813, 18295, 18300, { 35826, 35834, 35842, 35850, 35862, 35871, 35883 }, { 18385, 18390, 18395, 18400, 18405, 18410, 18415 }, { 1914, 2300, 2565, 6216, 2565, 16338, 2308 }, { 18420, 18437, 18450, 18464, 18477, 18490, 18503, 18517, 18529, 18543, 18557, 18571, 0 }, { 18420, 18437, 18450, 18464, 18477, 18490, 18503, 18517, 18529, 18543, 18557, 18571, 0 }, { 35894, 35905, 35912, 35920, 35927, 35934, 35941, 35949, 35955, 35963, 35971, 35979, 0 }, { 35894, 35905, 35912, 35920, 35927, 35934, 35941, 35949, 35955, 35963, 35971, 35979, 0 }, 2, 1, 691, 187, { 4724, 2154, 8015, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 35986, 36012, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 34826, 34829, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34929, 34932, 34935, 34938, 34941, 13447, 13438 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, 0, 6, 185, 187, { 198, 189, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10501, 222, 0, 0, 0, 0, 0, 0, 0, 0 }, { 242, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 257, 269, 0, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 1195, 1204, 1211, { 1218, 1228, 1238, 1248, 1258, 1268, 1278 }, { 1288, 1295, 1302, 1309, 1316, 1323, 1330 }, { 1337, 1341, 1345, 1349, 1353, 1357, 1361 }, { 1365, 1372, 1379, 1386, 1393, 1400, 1407, 1414, 1421, 1428, 1435, 1445, 0 }, { 1365, 1372, 1379, 1386, 1393, 1400, 1407, 1414, 1421, 1428, 1435, 1445, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, 0, 0, 185, 187, { 1120, 3483, 189, 1578, 1599, 1518, 1545, 1556, 0, 0, 0, 0, 0, 0 }, { 1608, 6555, 1686, 34806, 0, 0, 0, 0, 0, 0 }, { 1722, 1730, 843, 251, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1739, 1750, 848, 269, 0, 0, 0, 0, 0 }, { 1762, 1778, 1791, 0, 0, 0, 0, 0 } }, { 35112, 2471, 2477, { 2484, 2492, 2499, 2508, 2517, 2528, 2536 }, { 2544, 2547, 2550, 2553, 2556, 2559, 2562 }, { 1914, 2300, 2565, 2300, 2565, 2306, 1914 }, { 2567, 2574, 2582, 2588, 2594, 2598, 2603, 2608, 2615, 2625, 2633, 2642, 0 }, { 2567, 2574, 2582, 2588, 2594, 2598, 2603, 2608, 2615, 2625, 2633, 2642, 0 }, { 2651, 2655, 2659, 2664, 2594, 2668, 2672, 2676, 2680, 2684, 2688, 2692, 0 }, { 2651, 2655, 2659, 2664, 2594, 2668, 2672, 2676, 2680, 2684, 2688, 2692, 0 }, 2, 1, 691, 187, { 2154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2719, 2194, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 3558, 3565, 3572, 3580, 3590, 3599, 3606 }, { 3615, 3619, 3623, 3627, 3631, 3635, 3639 }, { 1914, 2300, 2302, 3643, 2302, 2306, 1914 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, 0, 0, 2438, 187, { 1556, 198, 189, 3483, 6936, 36030, 3747, 14785, 1556, 0, 0, 0, 0, 0 }, { 3776, 31111, 36038, 6411, 0, 0, 0, 0, 0, 0 }, { 3532, 242, 251, 843, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 257, 269, 848, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 36049, 872, 878, { 3833, 3841, 3847, 3854, 3865, 3872, 3880 }, { 3888, 3893, 3898, 3903, 3909, 3914, 3919 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 3929, 3935, 3943, 3949, 3955, 3960, 3966, 3972, 3979, 3990, 3998, 4008, 0 }, { 4018, 4024, 4032, 1012, 4038, 4043, 4049, 4055, 4062, 1050, 4073, 4083, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, 0, 0, 185, 187, { 14753, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36057, 36085, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 1180, 0, 0, 0, 0, 0, 0, 0 } }, { 35165, 1820, 1823, { 4733, 4742, 4748, 4754, 4763, 4769, 4778 }, { 4785, 4790, 4795, 4800, 4805, 4810, 4815 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 4820, 4828, 4837, 4842, 4848, 4852, 4857, 4865, 4871, 4881, 1058, 4889, 0 }, { 4820, 4828, 4837, 4842, 4848, 4852, 4857, 4865, 4871, 4881, 1058, 4889, 0 }, { 4899, 4905, 4837, 4912, 4848, 4852, 4917, 4865, 4923, 1105, 1110, 4929, 0 }, { 4899, 4905, 4837, 4912, 4848, 4852, 4917, 4865, 4923, 1105, 1110, 4929, 0 }, 2, 1, 691, 187, { 2154, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 35173, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 1820, 1823, { 8986, 8995, 9007, 9014, 9022, 9032, 9038 }, { 9045, 9049, 9053, 9057, 9061, 9066, 9070 }, { 9074, 9076, 9078, 9080, 9082, 9076, 9080 }, { 9085, 9095, 9104, 9112, 9120, 9128, 9135, 9142, 9150, 1993, 9156, 9164, 0 }, { 9173, 9183, 9192, 9200, 9208, 9216, 9223, 9230, 9239, 7775, 9245, 9255, 0 }, { 9264, 9268, 9273, 9278, 9282, 7809, 2130, 9286, 9290, 2146, 9294, 2150, 0 }, { 9264, 9268, 9273, 9278, 9282, 7809, 2130, 9286, 9290, 2146, 9294, 2150, 0 }, 0, 1, 691, 187, { 9328, 36107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 9401, 9372, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36120, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 34826, 34829, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34929, 34932, 34935, 34938, 34941, 13447, 13438 }, { 36131, 36142, 13477, 36153, 36164, 36171, 36180, 36193, 35739, 35752, 35765, 35778, 0 }, { 36131, 36142, 13477, 36153, 36164, 36171, 36180, 36193, 35739, 35752, 35765, 35778, 0 }, { 36131, 36142, 13477, 36153, 36164, 36171, 36180, 36193, 35739, 35752, 35765, 35778, 0 }, { 36131, 36142, 13477, 36153, 36164, 36171, 36180, 36193, 35739, 35752, 35765, 35778, 0 }, 0, 6, 2438, 187, { 2440, 2451, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10501, 222, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 257, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 1195, 1204, 1211, { 1218, 1228, 1238, 1248, 1258, 1268, 1278 }, { 34757, 34764, 34771, 34778, 34785, 34792, 34799 }, { 1337, 1341, 1345, 1349, 1353, 1357, 1361 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, 0, 0, 185, 187, { 1120, 3483, 189, 1578, 1599, 1518, 1545, 1556, 0, 0, 0, 0, 0, 0 }, { 1608, 36200, 36227, 2460, 1686, 34806, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 1762, 1778, 1791, 1805, 0, 0, 0, 0 } }, { 35112, 2471, 2477, { 2484, 2492, 2499, 2508, 2517, 2528, 2536 }, { 2544, 2547, 2550, 2553, 2556, 2559, 2562 }, { 1914, 2300, 2565, 2300, 2565, 2306, 1914 }, { 2567, 2574, 2582, 2588, 2594, 2598, 2603, 2608, 2615, 2625, 2633, 2642, 0 }, { 2567, 2574, 2582, 2588, 2594, 2598, 2603, 2608, 2615, 2625, 2633, 2642, 0 }, { 2651, 2655, 2659, 2664, 2594, 2668, 2672, 2676, 2680, 2684, 2688, 2692, 0 }, { 2651, 2655, 2659, 2664, 2594, 2668, 2672, 2676, 2680, 2684, 2688, 2692, 0 }, 2, 1, 691, 187, { 2154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2719, 2194, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 36243, 7261, 7266, { 3558, 3565, 3572, 3580, 3590, 3599, 3606 }, { 3615, 3619, 3623, 3627, 3631, 3635, 3639 }, { 1914, 2300, 2302, 3643, 2302, 2306, 1914 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, 0, 0, 185, 187, { 14753, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 36250, 0, 0, 0, 0, 0, 0, 0 } }, { 36049, 872, 878, { 3833, 3841, 3847, 3854, 3865, 3872, 3880 }, { 3888, 3893, 3898, 3903, 3909, 3914, 3919 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 3929, 3935, 3943, 3949, 3955, 3960, 3966, 3972, 3979, 3990, 3998, 4008, 0 }, { 4018, 4024, 4032, 1012, 4038, 4043, 4049, 4055, 4062, 1050, 4073, 4083, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, 0, 1, 185, 187, { 1120, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36057, 36085, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 1180, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 4733, 4742, 4748, 4754, 4763, 4769, 4778 }, { 4785, 4790, 4795, 4800, 4805, 4810, 4815 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 4820, 4828, 4837, 4842, 4848, 4852, 4857, 4865, 4871, 4881, 1058, 4889, 0 }, { 4820, 4828, 4837, 4842, 4848, 4852, 4857, 4865, 4871, 4881, 1058, 4889, 0 }, { 4899, 4905, 4837, 4912, 4848, 4852, 4917, 4865, 4923, 1105, 1110, 4929, 0 }, { 4899, 4905, 4837, 4912, 4848, 4852, 4917, 4865, 4923, 1105, 1110, 4929, 0 }, 2, 1, 185, 187, { 198, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4935, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 36260, 36270, { 8986, 8995, 9007, 9014, 9022, 9032, 9038 }, { 9045, 9049, 9053, 9057, 9061, 9066, 9070 }, { 0, 0, 0, 0, 0, 0, 0 }, { 2310, 2317, 15032, 2331, 2337, 2341, 2346, 11888, 36278, 36288, 36296, 36305, 0 }, { 2310, 2317, 15032, 2331, 2337, 2341, 2346, 11888, 36278, 36288, 36296, 36305, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 11895, 2422, 2426, 2430, 2434, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 11895, 2422, 2426, 2430, 2434, 0 }, 0, 1, 691, 187, { 9328, 36314, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36329, 9386, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36120, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 34826, 34829, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34929, 34932, 34935, 34938, 34941, 13447, 13438 }, { 35662, 35673, 13477, 35686, 36164, 35706, 36350, 36363, 36370, 35752, 36381, 36392, 0 }, { 35662, 35673, 13477, 35686, 36164, 35706, 36350, 36363, 36370, 35752, 36381, 36392, 0 }, { 35662, 35673, 13477, 35686, 36164, 35706, 36350, 36363, 36370, 35752, 36381, 36392, 0 }, { 35662, 35673, 13477, 35686, 36164, 35706, 36350, 36363, 36370, 35752, 36381, 36392, 0 }, 0, 6, 2438, 187, { 2440, 2451, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10501, 222, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 257, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 36243, 7261, 7266, { 3558, 3565, 3572, 3580, 3590, 3599, 3606 }, { 3615, 3619, 3623, 3627, 3631, 3635, 3639 }, { 1914, 2300, 2302, 3643, 2302, 2306, 1914 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, 2, 0, 185, 187, { 198, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4935, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 3532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 3540, 0, 0, 0, 0, 0, 0, 0 }, { 36250, 0, 0, 0, 0, 0, 0, 0 } }, { 36403, 872, 878, { 3833, 3841, 3847, 3854, 3865, 3872, 3880 }, { 3888, 3893, 3898, 3903, 3909, 3914, 3919 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 3929, 3935, 3943, 3949, 3955, 3960, 3966, 3972, 3979, 3990, 3998, 4008, 0 }, { 4018, 4024, 4032, 1012, 4038, 4043, 4049, 4055, 4062, 1050, 4073, 4083, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, 0, 0, 185, 187, { 3736, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36057, 36085, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 36250, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 4733, 4742, 4748, 4754, 4763, 4769, 4778 }, { 4785, 4790, 4795, 4800, 4805, 4810, 4815 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 4820, 4828, 4837, 4842, 4848, 4852, 4857, 4865, 4871, 4881, 1058, 4889, 0 }, { 4820, 4828, 4837, 4842, 4848, 4852, 4857, 4865, 4871, 4881, 1058, 4889, 0 }, { 4899, 4905, 4837, 4912, 4848, 4852, 4917, 4865, 4923, 1105, 1110, 4929, 0 }, { 4899, 4905, 4837, 4912, 4848, 4852, 4917, 4865, 4923, 1105, 1110, 4929, 0 }, 2, 1, 185, 187, { 198, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4935, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 36260, 36270, { 11820, 36411, 9007, 11845, 9022, 9032, 9038 }, { 9045, 9049, 9053, 11866, 9061, 9066, 9070 }, { 9074, 9076, 9078, 9080, 9082, 9076, 9080 }, { 2310, 2317, 15032, 2331, 2337, 2410, 2414, 11888, 36278, 36288, 36296, 36305, 0 }, { 2310, 2317, 15032, 2331, 2337, 2410, 2414, 11888, 36278, 36288, 36296, 36305, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 11895, 2422, 2426, 2430, 2434, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 11895, 2422, 2426, 2430, 2434, 0 }, 0, 1, 691, 187, { 9298, 9328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36329, 9386, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 4246, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 4268, 0, 0, 0, 0, 0, 0, 0 }, { 36120, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 34826, 34829, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34929, 34932, 34935, 34938, 34941, 13447, 13438 }, { 36131, 36142, 13477, 36153, 36164, 36171, 36180, 36193, 35739, 35752, 35765, 35778, 0 }, { 36131, 36142, 13477, 36153, 36164, 36171, 36180, 36193, 35739, 35752, 35765, 35778, 0 }, { 36131, 36142, 13477, 36153, 36164, 36171, 36180, 36193, 35739, 35752, 35765, 35778, 0 }, { 36131, 36142, 13477, 36153, 36164, 36171, 36180, 36193, 35739, 35752, 35765, 35778, 0 }, 0, 0, 2438, 187, { 2440, 2451, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10501, 222, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 257, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 1820, 1823, { 3558, 3565, 3572, 3580, 3590, 3599, 3606 }, { 3615, 3619, 3623, 3627, 3631, 3635, 3639 }, { 1914, 2300, 2302, 3643, 2302, 2306, 1914 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, 0, 0, 185, 187, { 1545, 9951, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10640, 5455, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 36250, 0, 0, 0, 0, 0, 0, 0 } }, { 36049, 872, 878, { 3833, 3841, 3847, 3854, 3865, 3872, 3880 }, { 3888, 3893, 3898, 3903, 3909, 3914, 3919 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 3929, 3935, 3943, 3949, 3955, 3960, 3966, 3972, 3979, 3990, 3998, 4008, 0 }, { 4018, 4024, 4032, 1012, 4038, 4043, 4049, 4055, 4062, 1050, 4073, 4083, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, 0, 0, 185, 187, { 1120, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36057, 36085, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 1180, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 36422, 36440, { 36455, 36468, 36487, 36500, 36515, 36532, 10761 }, { 36543, 36550, 36557, 36564, 36571, 36578, 36585 }, { 456, 459, 36592, 465, 468, 459, 465 }, { 36595, 36608, 501, 510, 15731, 15738, 15747, 542, 36623, 36642, 36657, 36674, 0 }, { 36595, 36608, 501, 510, 15731, 15738, 15747, 542, 36623, 36642, 36657, 36674, 0 }, { 36691, 36698, 36705, 36712, 15731, 36719, 36726, 36733, 36740, 36747, 36754, 36761, 0 }, { 36691, 36698, 36705, 36712, 15731, 36719, 36726, 36733, 36740, 36747, 36754, 36761, 0 }, 0, 1, 691, 187, { 9298, 9328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2194, 11931, 2719, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 34826, 34829, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34929, 34932, 34935, 34938, 34941, 13447, 13438 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, 0, 6, 185, 187, { 198, 189, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10501, 222, 0, 0, 0, 0, 0, 0, 0, 0 }, { 242, 251, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 257, 269, 848, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 36243, 1820, 1823, { 3558, 3565, 3572, 3580, 3590, 3599, 3606 }, { 3615, 3619, 3623, 3627, 3631, 3635, 3639 }, { 1914, 2300, 2302, 3643, 2302, 2306, 1914 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, 0, 0, 185, 187, { 1120, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 36250, 0, 0, 0, 0, 0, 0, 0 } }, { 36049, 872, 878, { 3833, 3841, 3847, 3854, 3865, 3872, 3880 }, { 3888, 3893, 3898, 3903, 3909, 3914, 3919 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 3929, 3935, 3943, 3949, 3955, 3960, 3966, 3972, 3979, 3990, 3998, 4008, 0 }, { 4018, 4024, 4032, 1012, 4038, 4043, 4049, 4055, 4062, 1050, 4073, 4083, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, 0, 0, 185, 187, { 1120, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36057, 36085, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 1180, 0, 0, 0, 0, 0, 0, 0 } }, { 24184, 36422, 36440, { 36455, 36468, 36487, 36500, 36515, 36532, 10761 }, { 36543, 36550, 36557, 36564, 36571, 36578, 36585 }, { 456, 459, 36592, 465, 468, 459, 465 }, { 36595, 36608, 501, 510, 15731, 15738, 15747, 542, 36623, 36642, 36657, 36674, 0 }, { 36595, 36608, 501, 510, 15731, 15738, 15747, 542, 36623, 36642, 36657, 36674, 0 }, { 36691, 36698, 36705, 36712, 15731, 36719, 36726, 36733, 36740, 36747, 36754, 36761, 0 }, { 36691, 36698, 36705, 36712, 15731, 36719, 36726, 36733, 36740, 36747, 36754, 36761, 0 }, 0, 1, 691, 187, { 4724, 8015, 2165, 2154, 36768, 2696, 36777, 1556, 0, 0, 0, 0, 0, 0 }, { 2194, 11931, 2719, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 34826, 34829, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34929, 34932, 34935, 34938, 34941, 13447, 13438 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, 0, 0, 185, 187, { 198, 189, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10501, 222, 0, 0, 0, 0, 0, 0, 0, 0 }, { 242, 251, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 257, 269, 848, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 36049, 872, 878, { 3833, 3841, 3847, 3854, 3865, 3872, 3880 }, { 3888, 3893, 3898, 3903, 3909, 3914, 3919 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 3929, 3935, 3943, 3949, 3955, 3960, 3966, 3972, 3979, 3990, 3998, 4008, 0 }, { 4018, 4024, 4032, 1012, 4038, 4043, 4049, 4055, 4062, 1050, 4073, 4083, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, 0, 0, 185, 187, { 14753, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36057, 36085, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 1180, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 36260, 36270, { 11820, 36411, 9007, 11845, 9022, 9032, 9038 }, { 9045, 9049, 9053, 11866, 9061, 9066, 9070 }, { 9074, 9076, 9078, 9080, 9082, 9076, 9080 }, { 2310, 2317, 15032, 2331, 2337, 2410, 2414, 11888, 36278, 36288, 36296, 36305, 0 }, { 2310, 2317, 15032, 2331, 2337, 2410, 2414, 11888, 36278, 36288, 36296, 36305, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 11895, 2422, 2426, 2430, 2434, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 11895, 2422, 2426, 2430, 2434, 0 }, 0, 1, 691, 691, { 9298, 9328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36329, 9386, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4246, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4268, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36120, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 34826, 34829, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34929, 34932, 34935, 34938, 34941, 13447, 13438 }, { 34944, 34968, 34977, 34986, 34997, 35006, 35019, 35028, 35033, 35044, 35066, 35090, 0 }, { 34944, 34968, 34977, 34986, 34997, 35006, 35019, 35028, 35033, 35044, 35066, 35090, 0 }, { 34944, 34968, 34977, 34986, 34997, 35006, 35019, 35028, 35033, 35044, 35066, 35090, 0 }, { 34944, 34968, 34977, 34986, 34997, 35006, 35019, 35028, 35033, 35044, 35066, 35090, 0 }, 0, 6, 185, 187, { 198, 189, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10501, 222, 0, 0, 0, 0, 0, 0, 0, 0 }, { 242, 251, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 257, 269, 848, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 1820, 1823, { 3558, 3565, 3572, 3580, 3590, 3599, 3606 }, { 3615, 3619, 3623, 3627, 3631, 3635, 3639 }, { 1914, 2300, 2302, 3643, 2302, 2306, 1914 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, 0, 0, 185, 187, { 198, 14785, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10640, 5455, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36250, 0, 0, 0, 0, 0, 0, 0 } }, { 36049, 872, 878, { 3833, 3841, 3847, 3854, 3865, 3872, 3880 }, { 3888, 3893, 3898, 3903, 3909, 3914, 3919 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 3929, 3935, 3943, 3949, 3955, 3960, 3966, 3972, 3979, 3990, 3998, 4008, 0 }, { 4018, 4024, 4032, 1012, 4038, 4043, 4049, 4055, 4062, 1050, 4073, 4083, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, 0, 0, 185, 187, { 14753, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36057, 36085, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 1180, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 36422, 36440, { 36455, 36468, 36487, 8513, 36515, 36532, 10761 }, { 36543, 36550, 36557, 36788, 36571, 36578, 36585 }, { 456, 459, 36592, 465, 468, 459, 465 }, { 36595, 36608, 501, 510, 15731, 36719, 36726, 542, 36623, 36642, 36657, 36674, 0 }, { 36595, 36608, 501, 510, 15731, 36719, 36726, 542, 36623, 36642, 36657, 36674, 0 }, { 36691, 36698, 36705, 36712, 15731, 36719, 36726, 36733, 36740, 36747, 36754, 36761, 0 }, { 36691, 36698, 36705, 36712, 15731, 36719, 36726, 36733, 36740, 36747, 36754, 36761, 0 }, 0, 1, 691, 187, { 9328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 9372, 9386, 9401, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 36120, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 34826, 34829, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34929, 34932, 34935, 34938, 34941, 13447, 13438 }, { 34944, 34968, 34977, 34986, 34997, 35006, 35019, 35028, 35033, 35044, 35066, 35090, 0 }, { 34944, 34968, 34977, 34986, 34997, 35006, 35019, 35028, 35033, 35044, 35066, 35090, 0 }, { 34944, 34968, 34977, 34986, 34997, 35006, 35019, 35028, 35033, 35044, 35066, 35090, 0 }, { 34944, 34968, 34977, 34986, 34997, 35006, 35019, 35028, 35033, 35044, 35066, 35090, 0 }, 0, 6, 185, 187, { 198, 189, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10501, 222, 0, 0, 0, 0, 0, 0, 0, 0 }, { 242, 251, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 257, 269, 848, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 3558, 3565, 3572, 3580, 3590, 3599, 3606 }, { 3615, 3619, 3623, 3627, 3631, 3635, 3639 }, { 1914, 2300, 2302, 3643, 2302, 2306, 1914 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, 0, 0, 185, 187, { 198, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 36250, 0, 0, 0, 0, 0, 0, 0 } }, { 36049, 872, 878, { 3833, 3841, 3847, 3854, 3865, 3872, 3880 }, { 3888, 3893, 3898, 3903, 3909, 3914, 3919 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 3929, 3935, 3943, 3949, 3955, 3960, 3966, 3972, 3979, 3990, 3998, 4008, 0 }, { 4018, 4024, 4032, 1012, 4038, 4043, 4049, 4055, 4062, 1050, 4073, 4083, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, 0, 0, 185, 187, { 1120, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36057, 36085, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 36795, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 36260, 36270, { 11820, 36411, 9007, 11845, 9022, 9032, 9038 }, { 9045, 9049, 9053, 11866, 9061, 9066, 9070 }, { 9074, 9076, 9078, 9080, 9082, 9076, 9080 }, { 2310, 2317, 15032, 2331, 2337, 2410, 2414, 11888, 36278, 36288, 36296, 36305, 0 }, { 2310, 2317, 15032, 2331, 2337, 2410, 2414, 11888, 36278, 36288, 36296, 36305, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 11895, 2422, 2426, 2430, 2434, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 11895, 2422, 2426, 2430, 2434, 0 }, 0, 1, 691, 691, { 9298, 9328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36329, 9386, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4246, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4268, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36120, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 34826, 34829, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34929, 34932, 34935, 34938, 34941, 13447, 13438 }, { 34944, 34968, 34977, 34986, 34997, 35006, 35019, 35028, 35033, 35044, 35066, 35090, 0 }, { 34944, 34968, 34977, 34986, 34997, 35006, 35019, 35028, 35033, 35044, 35066, 35090, 0 }, { 34944, 34968, 34977, 34986, 34997, 35006, 35019, 35028, 35033, 35044, 35066, 35090, 0 }, { 34944, 34968, 34977, 34986, 34997, 35006, 35019, 35028, 35033, 35044, 35066, 35090, 0 }, 0, 1, 185, 187, { 198, 189, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10501, 222, 0, 0, 0, 0, 0, 0, 0, 0 }, { 242, 251, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 257, 269, 848, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 1820, 1823, { 3558, 3565, 3572, 3580, 3590, 3599, 3606 }, { 3615, 3619, 3623, 3627, 3631, 3635, 3639 }, { 1914, 2300, 2302, 3643, 2302, 2306, 1914 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, 0, 0, 185, 187, { 1120, 36805, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10640, 5455, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 36250, 0, 0, 0, 0, 0, 0, 0 } }, { 36049, 872, 878, { 3833, 3841, 3847, 3854, 3865, 3872, 3880 }, { 3888, 3893, 3898, 3903, 3909, 3914, 3919 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 3929, 3935, 3943, 3949, 3955, 3960, 3966, 3972, 3979, 3990, 3998, 4008, 0 }, { 4018, 4024, 4032, 1012, 4038, 4043, 4049, 4055, 4062, 1050, 4073, 4083, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, 0, 1, 185, 187, { 1120, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36057, 36085, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 1180, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 36422, 36440, { 36455, 36468, 36487, 8513, 36515, 36532, 10761 }, { 36543, 36550, 36557, 36788, 36571, 36578, 36585 }, { 456, 459, 36592, 465, 468, 459, 465 }, { 36595, 36608, 501, 510, 15731, 36719, 36726, 542, 36623, 36642, 36657, 36674, 0 }, { 36595, 36608, 501, 510, 15731, 36719, 36726, 542, 36623, 36642, 36657, 36674, 0 }, { 36691, 36698, 36705, 36712, 15731, 36719, 36726, 36733, 36740, 36747, 36754, 36761, 0 }, { 36691, 36698, 36705, 36712, 15731, 36719, 36726, 36733, 36740, 36747, 36754, 36761, 0 }, 0, 1, 691, 187, { 9298, 9308, 9316, 9328, 9340, 9350, 9360, 36817, 0, 0, 0, 0, 0, 0 }, { 9372, 9386, 9401, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 36120, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 34826, 34829, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34929, 34932, 34935, 34938, 34941, 13447, 13438 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, 0, 6, 185, 187, { 198, 189, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10501, 222, 0, 0, 0, 0, 0, 0, 0, 0 }, { 242, 251, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 257, 269, 848, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 3558, 3565, 3572, 3580, 3590, 3599, 3606 }, { 3615, 3619, 3623, 3627, 3631, 3635, 3639 }, { 1914, 2300, 2302, 3643, 2302, 2306, 1914 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, 0, 0, 185, 187, { 198, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 36250, 0, 0, 0, 0, 0, 0, 0 } }, { 36049, 872, 878, { 3833, 3841, 3847, 3854, 3865, 3872, 3880 }, { 3888, 3893, 3898, 3903, 3909, 3914, 3919 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 3929, 3935, 3943, 3949, 3955, 3960, 3966, 3972, 3979, 3990, 3998, 4008, 0 }, { 4018, 4024, 4032, 1012, 4038, 4043, 4049, 4055, 4062, 1050, 4073, 4083, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, 0, 1, 2438, 187, { 2440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36057, 36085, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 36795, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 34826, 34829, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34929, 34932, 34935, 34938, 34941, 13447, 13438 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, 0, 6, 185, 187, { 198, 189, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10501, 222, 0, 0, 0, 0, 0, 0, 0, 0 }, { 242, 251, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 257, 269, 848, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 36049, 872, 878, { 3833, 3841, 3847, 3854, 3865, 3872, 3880 }, { 3888, 3893, 3898, 3903, 3909, 3914, 3919 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 3929, 3935, 3943, 3949, 3955, 3960, 3966, 3972, 3979, 3990, 3998, 4008, 0 }, { 4018, 4024, 4032, 1012, 4038, 4043, 4049, 4055, 4062, 1050, 4073, 4083, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, 0, 1, 185, 187, { 1120, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36057, 36085, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 242, 3532, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 257, 3540, 0, 0, 0, 0, 0 }, { 1180, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 34826, 34829, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34929, 34932, 34935, 34938, 34941, 13447, 13438 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, 0, 6, 185, 187, { 198, 189, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10501, 222, 0, 0, 0, 0, 0, 0, 0, 0 }, { 242, 251, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 257, 269, 848, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 36049, 872, 878, { 3833, 3841, 3847, 3854, 3865, 3872, 3880 }, { 3888, 3893, 3898, 3903, 3909, 3914, 3919 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 3929, 3935, 3943, 3949, 3955, 3960, 3966, 3972, 3979, 3990, 3998, 4008, 0 }, { 4018, 4024, 4032, 1012, 4038, 4043, 4049, 4055, 4062, 1050, 4073, 4083, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, 0, 0, 185, 187, { 1120, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36057, 36085, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 1180, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 34826, 34829, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34832, 34843, 34858, 34875, 34892, 34905, 34918 }, { 34929, 34932, 34935, 34938, 34941, 13447, 13438 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, { 35662, 35673, 13477, 35686, 35697, 35706, 35717, 35728, 35739, 35752, 35765, 35778, 0 }, 0, 6, 185, 187, { 198, 189, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10501, 222, 0, 0, 0, 0, 0, 0, 0, 0 }, { 242, 251, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 257, 269, 848, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 8022, 21796, { 3558, 3565, 3572, 3580, 3590, 3599, 3606 }, { 3615, 3619, 3623, 3627, 3631, 3635, 3639 }, { 1914, 2300, 2302, 3643, 2302, 2306, 1914 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, 0, 0, 2438, 187, { 2440, 2451, 4157, 8015, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 5455, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 36829, 257, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 36049, 872, 878, { 3833, 3841, 3847, 3854, 3865, 3872, 3880 }, { 3888, 3893, 3898, 3903, 3909, 3914, 3919 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 3929, 3935, 3943, 3949, 3955, 3960, 3966, 3972, 3979, 3990, 3998, 4008, 0 }, { 4018, 4024, 4032, 1012, 4038, 4043, 4049, 4055, 4062, 1050, 4073, 4083, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, 0, 0, 185, 187, { 1120, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36057, 36085, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 1180, 0, 0, 0, 0, 0, 0, 0 } }, { 36049, 872, 878, { 3833, 3841, 3847, 3854, 3865, 3872, 3880 }, { 3888, 3893, 3898, 3903, 3909, 3914, 3919 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 3929, 3935, 3943, 3949, 3955, 3960, 3966, 3972, 3979, 3990, 3998, 4008, 0 }, { 4018, 4024, 4032, 1012, 4038, 4043, 4049, 4055, 4062, 1050, 4073, 4083, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, 0, 0, 185, 187, { 1120, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36057, 36085, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 1180, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 8022, 21796, { 3558, 3565, 3572, 3580, 3590, 3599, 3606 }, { 3615, 3619, 3623, 3627, 3631, 3635, 3639 }, { 1914, 2300, 2302, 3643, 2302, 2306, 1914 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 3645, 3653, 3662, 2588, 3668, 3672, 3677, 2608, 2615, 3682, 2633, 3690, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, { 2651, 2655, 3699, 2664, 3668, 2668, 2672, 2676, 2680, 3703, 2688, 3707, 0 }, 0, 0, 185, 187, { 1120, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3502, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 36250, 0, 0, 0, 0, 0, 0, 0 } }, { 36049, 872, 878, { 3833, 3841, 3847, 3854, 3865, 3872, 3880 }, { 3888, 3893, 3898, 3903, 3909, 3914, 3919 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 3929, 3935, 3943, 3949, 3955, 3960, 3966, 3972, 3979, 3990, 3998, 4008, 0 }, { 4018, 4024, 4032, 1012, 4038, 4043, 4049, 4055, 4062, 1050, 4073, 4083, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, 0, 0, 185, 187, { 1120, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36840, 36868, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 1180, 0, 0, 0, 0, 0, 0, 0 } }, { 36049, 872, 878, { 3833, 3841, 3847, 3854, 3865, 3872, 3880 }, { 3888, 3893, 3898, 3903, 3909, 3914, 3919 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 3929, 3935, 3943, 3949, 3955, 3960, 3966, 3972, 3979, 3990, 3998, 4008, 0 }, { 4018, 4024, 4032, 1012, 4038, 4043, 4049, 4055, 4062, 1050, 4073, 4083, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, 0, 0, 185, 187, { 1120, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36057, 36085, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 1180, 0, 0, 0, 0, 0, 0, 0 } }, { 36403, 872, 878, { 3833, 3841, 3847, 3854, 3865, 3872, 3880 }, { 3888, 3893, 3898, 3903, 3909, 3914, 3919 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 3929, 3935, 3943, 3949, 3955, 3960, 3966, 3972, 3979, 3990, 3998, 4008, 0 }, { 4018, 4024, 4032, 1012, 4038, 4043, 4049, 4055, 4062, 1050, 4073, 4083, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, 0, 0, 185, 187, { 3736, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36057, 36085, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3532, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 269, 0, 0, 0, 0, 0, 0, 0 }, { 36250, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 1820, 1823, { 3833, 3841, 3847, 3854, 3865, 3872, 3880 }, { 3888, 3893, 3898, 3903, 3909, 3914, 3919 }, { 2565, 2308, 2300, 2300, 3925, 3927, 1914 }, { 3929, 3935, 3943, 3949, 3955, 3960, 3966, 3972, 3979, 3990, 3998, 4008, 0 }, { 4018, 4024, 4032, 1012, 4038, 4043, 4049, 4055, 4062, 1050, 4073, 4083, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, { 4093, 4098, 3898, 4103, 4108, 4113, 4118, 4123, 4128, 4134, 4139, 4144, 0 }, 0, 0, 185, 187, { 3711, 3720, 3727, 3736, 1599, 1556, 3747, 0, 0, 0, 0, 0, 0, 0 }, { 31111, 31131, 222, 10501, 0, 0, 0, 0, 0, 0 }, { 3532, 242, 843, 251, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3540, 257, 848, 269, 0, 0, 0, 0, 0 }, { 4288, 0, 0, 0, 0, 0, 0, 0 } }, { 24184, 36422, 36440, { 36455, 36468, 36487, 36500, 36515, 36532, 10761 }, { 36543, 36550, 36557, 36564, 36571, 36578, 36585 }, { 456, 459, 36592, 465, 468, 459, 465 }, { 36595, 36608, 501, 510, 15731, 15738, 15747, 542, 36623, 36642, 36657, 36674, 0 }, { 36595, 36608, 501, 510, 15731, 15738, 15747, 542, 36623, 36642, 36657, 36674, 0 }, { 36691, 36698, 36705, 36712, 15731, 36719, 36726, 36733, 36740, 36747, 36754, 36761, 0 }, { 36691, 36698, 36705, 36712, 15731, 36719, 36726, 36733, 36740, 36747, 36754, 36761, 0 }, 0, 1, 691, 187, { 4724, 8015, 2165, 2154, 36768, 2696, 36777, 1556, 0, 0, 0, 0, 0, 0 }, { 2194, 11931, 2719, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 36260, 36270, { 8986, 8995, 9007, 9014, 9022, 9032, 9038 }, { 9045, 9049, 9053, 9057, 9061, 9066, 9070 }, { 0, 0, 0, 0, 0, 0, 0 }, { 2310, 2317, 15032, 2331, 2337, 2341, 2346, 11888, 36278, 36288, 36296, 36305, 0 }, { 2310, 2317, 15032, 2331, 2337, 2341, 2346, 11888, 36278, 36288, 36296, 36305, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 11895, 2422, 2426, 2430, 2434, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 11895, 2422, 2426, 2430, 2434, 0 }, 0, 1, 691, 187, { 9328, 36314, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36329, 9386, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36120, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 36422, 36440, { 36455, 36468, 36487, 8513, 36515, 36532, 10761 }, { 36543, 36550, 36557, 36788, 36571, 36578, 36585 }, { 456, 459, 36592, 465, 468, 459, 465 }, { 36595, 36608, 501, 510, 15731, 36719, 36726, 542, 36623, 36642, 36657, 36674, 0 }, { 36595, 36608, 501, 510, 15731, 36719, 36726, 542, 36623, 36642, 36657, 36674, 0 }, { 36691, 36698, 36705, 36712, 15731, 36719, 36726, 36733, 36740, 36747, 36754, 36761, 0 }, { 36691, 36698, 36705, 36712, 15731, 36719, 36726, 36733, 36740, 36747, 36754, 36761, 0 }, 0, 1, 691, 187, { 9328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 9372, 9386, 9401, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 36120, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 36260, 36270, { 11820, 36411, 9007, 11845, 9022, 9032, 9038 }, { 9045, 9049, 9053, 11866, 9061, 9066, 9070 }, { 9074, 9076, 9078, 9080, 9082, 9076, 9080 }, { 2310, 2317, 15032, 2331, 2337, 2410, 2414, 11888, 36278, 36288, 36296, 36305, 0 }, { 2310, 2317, 15032, 2331, 2337, 2410, 2414, 11888, 36278, 36288, 36296, 36305, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 11895, 2422, 2426, 2430, 2434, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 11895, 2422, 2426, 2430, 2434, 0 }, 0, 1, 691, 691, { 9298, 9328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36329, 9386, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4246, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4268, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36120, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 35281, 35292, 35316, 35346, 35363, 35385, 35394 }, { 14921, 14924, 14929, 14935, 14939, 7600, 14944 }, { 6540, 6528, 6530, 6532, 6534, 6536, 6538 }, { 35405, 35418, 501, 35431, 521, 35442, 35451, 542, 35460, 35477, 35492, 35505, 0 }, { 35405, 35418, 501, 35431, 521, 35442, 35451, 542, 35460, 35477, 35492, 35505, 0 }, { 15095, 7999, 2402, 2406, 15043, 15099, 15103, 15107, 15111, 2426, 15115, 15119, 0 }, { 15095, 7999, 2402, 2406, 15043, 15099, 15103, 15107, 15111, 2426, 15115, 15119, 0 }, 0, 1, 691, 187, { 2154, 2696, 8015, 189, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3520, 5455, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1195, 1204, 1211, { 1218, 1228, 1238, 1248, 1258, 1268, 1278 }, { 1288, 1295, 1302, 1309, 1316, 1323, 1330 }, { 1337, 1341, 1345, 1349, 1353, 1357, 1361 }, { 1365, 1372, 1379, 1386, 1393, 1400, 1407, 1414, 1421, 1428, 1435, 1445, 0 }, { 1365, 1372, 1379, 1386, 1393, 1400, 1407, 1414, 1421, 1428, 1435, 1445, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, 0, 0, 185, 187, { 1518, 1527, 1536, 1545, 1556, 1567, 1578, 1585, 1592, 1599, 0, 0, 0, 0 }, { 1608, 1630, 1658, 1686, 1701, 0, 0, 0, 0, 0 }, { 843, 251, 1722, 1730, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 1739, 1750, 0, 0, 0, 0, 0 }, { 1762, 1778, 1791, 1805, 0, 0, 0, 0 } }, { 1812, 35193, 35198, { 2217, 9837, 35203, 2240, 2247, 2255, 35210 }, { 2270, 9865, 35218, 2283, 2287, 2291, 35222 }, { 1914, 2300, 2302, 2304, 2302, 2306, 2308 }, { 2310, 2317, 4837, 2331, 4848, 2341, 2346, 2351, 2358, 2368, 2376, 6086, 0 }, { 2310, 2317, 4837, 2331, 4848, 2341, 2346, 2351, 2358, 2368, 2376, 6086, 0 }, { 2394, 2398, 2402, 2406, 4848, 2410, 2414, 2418, 2422, 2426, 2430, 7503, 0 }, { 2394, 2398, 2402, 2406, 4848, 2410, 2414, 2418, 2422, 2426, 2430, 7503, 0 }, 2, 1, 691, 187, { 2154, 6118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2176, 2194, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 36260, 36270, { 8986, 8995, 9007, 9014, 9022, 9032, 9038 }, { 9045, 9049, 9053, 9057, 9061, 9066, 9070 }, { 0, 0, 0, 0, 0, 0, 0 }, { 2310, 2317, 15032, 2331, 2337, 2341, 2346, 11888, 36278, 36288, 36296, 36305, 0 }, { 2310, 2317, 15032, 2331, 2337, 2341, 2346, 11888, 36278, 36288, 36296, 36305, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 11895, 2422, 2426, 2430, 2434, 0 }, { 2394, 2398, 2402, 2406, 2337, 2410, 2414, 11895, 2422, 2426, 2430, 2434, 0 }, 0, 1, 691, 187, { 9328, 36314, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36329, 9386, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36120, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 1820, 1823, { 14832, 14838, 14852, 14875, 14889, 14905, 14912 }, { 14921, 14924, 14929, 14935, 14939, 7600, 14944 }, { 6540, 6528, 6530, 6532, 6534, 6536, 6538 }, { 14948, 14955, 10132, 14962, 3668, 14968, 14974, 14980, 14987, 14996, 15004, 15011, 0 }, { 15018, 15025, 15032, 15037, 15043, 15047, 15052, 15057, 15064, 15073, 15081, 15088, 0 }, { 15095, 7999, 2402, 2406, 15043, 15099, 15103, 15107, 15111, 2426, 15115, 15119, 0 }, { 15095, 7999, 2402, 2406, 15043, 15099, 15103, 15107, 15111, 2426, 15115, 15119, 0 }, 0, 1, 691, 187, { 2154, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 15123, 3520, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 1820, 1823, { 35518, 35533, 35548, 35563, 35580, 35597, 35606 }, { 35617, 35624, 35631, 35638, 35645, 19574, 35652 }, { 35659, 19207, 8610, 8613, 8607, 19204, 19588 }, { 13102, 13113, 8644, 13126, 8666, 13137, 13144, 8691, 13151, 13166, 13179, 13190, 0 }, { 13102, 13113, 8644, 13126, 8666, 13137, 13144, 8691, 13151, 13166, 13179, 13190, 0 }, { 13203, 13210, 13217, 13224, 8666, 13137, 13144, 13231, 13238, 13245, 13252, 13259, 0 }, { 13203, 13210, 13217, 13224, 8666, 13137, 13144, 13231, 13238, 13245, 13252, 13259, 0 }, 0, 1, 185, 187, { 1545, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 20050, 16096, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 25903, 25908, { 25913, 25920, 25931, 25944, 25957, 25968, 25981 }, { 25992, 25997, 26002, 26007, 26012, 26017, 26022 }, { 6528, 6530, 6532, 6534, 6536, 6538, 6540 }, { 26027, 26053, 26081, 26111, 26141, 26167, 26197, 26223, 26251, 26275, 26303, 26340, 0 }, { 26027, 26053, 26081, 26111, 26141, 26167, 26197, 26223, 26251, 26275, 26303, 26340, 0 }, { 26379, 26391, 26403, 26415, 26427, 26439, 26451, 26463, 26475, 26487, 26500, 26513, 0 }, { 26379, 26391, 26403, 26415, 26427, 26439, 26451, 26463, 26475, 26487, 26500, 26513, 0 }, 0, 0, 2438, 187, { 1556, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 26526, 26564, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 1195, 1204, 1211, { 1218, 1228, 1238, 1248, 1258, 1268, 1278 }, { 34757, 34764, 34771, 34778, 34785, 34792, 34799 }, { 1337, 1341, 1345, 1349, 1353, 1357, 1361 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, 0, 0, 185, 187, { 1120, 3483, 189, 1578, 1599, 1518, 1545, 1556, 0, 0, 0, 0, 0, 0 }, { 1608, 6555, 1686, 1701, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 1762, 1778, 1791, 1805, 0, 0, 0, 0 } }, { 1195, 1204, 1211, { 1218, 1228, 1238, 1248, 1258, 1268, 1278 }, { 34757, 34764, 34771, 34778, 34785, 34792, 34799 }, { 1337, 1341, 1345, 1349, 1353, 1357, 1361 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, { 1455, 1460, 1465, 1470, 1475, 1480, 1485, 1490, 1495, 1500, 1506, 1512, 0 }, 0, 0, 185, 187, { 1120, 3483, 189, 1578, 1599, 1518, 1545, 1556, 0, 0, 0, 0, 0, 0 }, { 1608, 6555, 1686, 1701, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 1762, 1778, 1791, 1805, 0, 0, 0, 0 } }, { 7465, 7261, 7266, { 2217, 2225, 2232, 2240, 2247, 2255, 2262 }, { 7473, 7478, 7482, 7486, 7490, 7494, 7498 }, { 1914, 2300, 2302, 2304, 2302, 2306, 2308 }, { 2310, 2317, 4837, 2331, 4848, 2341, 2346, 2351, 2358, 2368, 2376, 6086, 0 }, { 2310, 2317, 4837, 2331, 4848, 2341, 2346, 2351, 2358, 2368, 2376, 6086, 0 }, { 2394, 2398, 2402, 2406, 4848, 2410, 2414, 2418, 2422, 2426, 2430, 7503, 0 }, { 2394, 2398, 2402, 2406, 4848, 2410, 2414, 2418, 2422, 2426, 2430, 7503, 0 }, 2, 1, 691, 691, { 2154, 6118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2176, 2194, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4246, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4268, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 1812, 36422, 36440, { 36455, 36468, 36487, 8513, 36515, 36532, 10761 }, { 36543, 36550, 36557, 36788, 36571, 36578, 36585 }, { 456, 459, 36592, 465, 468, 459, 465 }, { 36595, 36608, 501, 510, 15731, 36719, 36726, 542, 36623, 36642, 36657, 36674, 0 }, { 36595, 36608, 501, 510, 15731, 36719, 36726, 542, 36623, 36642, 36657, 36674, 0 }, { 36691, 36698, 36705, 36712, 15731, 36719, 36726, 36733, 36740, 36747, 36754, 36761, 0 }, { 36691, 36698, 36705, 36712, 15731, 36719, 36726, 36733, 36740, 36747, 36754, 36761, 0 }, 0, 1, 691, 691, { 9298, 9328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36329, 9386, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4246, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 4268, 0, 0, 0, 0, 0, 0, 0, 0 }, { 36120, 0, 0, 0, 0, 0, 0, 0 } }, { 1, 12926, 12938, { 12950, 12965, 12980, 12995, 13012, 13031, 13042 }, { 13053, 13060, 13067, 13074, 13081, 13088, 13095 }, { 0, 0, 0, 0, 0, 0, 0 }, { 13102, 13113, 8644, 13126, 8666, 13137, 13144, 8691, 13151, 13166, 13179, 13190, 0 }, { 13102, 13113, 8644, 13126, 8666, 13137, 13144, 8691, 13151, 13166, 13179, 13190, 0 }, { 13203, 13210, 13217, 13224, 8666, 13137, 13144, 13231, 13238, 13245, 13252, 13259, 0 }, { 13203, 13210, 13217, 13224, 8666, 13137, 13144, 13231, 13238, 13245, 13252, 13259, 0 }, 0, 1, 691, 187, { 2154, 2696, 8015, 2440, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 13266, 13284, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 848, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 1820, 1823, { 19918, 19928, 19937, 19946, 19957, 19967, 19972 }, { 19979, 19985, 19990, 19995, 20000, 10578, 20004 }, { 20009, 2565, 1914, 7600, 1909, 3925, 1914 }, { 14948, 14955, 10132, 14962, 3668, 20011, 20016, 20021, 14987, 14996, 15004, 15011, 0 }, { 14948, 14955, 10132, 14962, 3668, 20011, 20016, 20021, 14987, 14996, 15004, 15011, 0 }, { 20028, 20033, 3699, 2664, 3668, 20011, 20016, 20037, 10562, 2684, 20041, 20046, 0 }, { 20028, 20033, 3699, 2664, 3668, 20011, 20016, 20037, 10562, 2684, 20041, 20046, 0 }, 0, 1, 185, 187, { 1545, 15492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 20050, 16096, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12916, 0, 0, 0, 0, 0, 0, 0 } }, { 289, 30416, 30426, { 30439, 30446, 30452, 30459, 30465, 30471, 30479 }, { 30489, 30493, 30497, 30501, 30505, 30509, 30513 }, { 12692, 12692, 12692, 12692, 12692, 12692, 12692 }, { 30519, 30528, 30537, 30542, 30548, 30554, 30560, 30567, 30573, 30582, 30591, 30599, 0 }, { 30519, 30528, 30537, 30542, 30548, 30554, 30560, 30567, 30573, 30582, 30591, 30599, 0 }, { 30608, 30612, 3699, 30616, 3668, 30620, 30624, 30628, 30633, 30637, 30643, 30647, 0 }, { 30608, 30612, 3699, 30616, 3668, 30620, 30624, 30628, 30633, 30637, 30643, 30647, 0 }, 0, 0, 2438, 187, { 2440, 2451, 1556, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10501, 222, 0, 0, 0, 0, 0, 0, 0, 0 }, { 843, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 848, 269, 0, 0, 0, 0, 0, 0, 0 }, { 278, 0, 0, 0, 0, 0, 0, 0 } }, { 3551, 0, 0, { 31414, 31421, 31429, 31436, 31443, 31451, 31459 }, { 31466, 31469, 31472, 31475, 31478, 31481, 31484 }, { 2308, 2308, 2302, 2308, 12692, 3925, 12692 }, { 31487, 31495, 31505, 31511, 31519, 31524, 31529, 31534, 31541, 19899, 31549, 31557, 0 }, { 31487, 31495, 31505, 31511, 31519, 31524, 31529, 31534, 31541, 19899, 31549, 31557, 0 }, { 2651, 31565, 3699, 31569, 3668, 30620, 30624, 31573, 3639, 2684, 31577, 16295, 0 }, { 2651, 31565, 3699, 31569, 3668, 30620, 30624, 31573, 3639, 2684, 31577, 16295, 0 }, 0, 0, 185, 187, { 1120, 17272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 3789, 3808, 0, 0, 0, 0, 0, 0, 0, 0 }, { 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 269, 0, 0, 0, 0, 0, 0, 0, 0 }, { 2207, 0, 0, 0, 0, 0, 0, 0 } } }; static const NumberFormatEntry number_format_entries[] = { { 691, 36891, 691, 36891, 36893, 36903, 36906, 36921, 36924, 36934, 2438, 36943, 3, 2, 0, 0, 3, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 36951, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 36973, 36982, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 36990, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 2, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 36990, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 2, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 36993, 36957, 36959, 36963, 36997, 37009, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37021, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 37024, 37035, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 37046, 37060, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37073, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 0, 0, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 36969, 36957, 37094, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 36969, 36957, 36959, 36963, 37103, 37111, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37119, 36957, 36959, 36963, 36924, 36934, 2438, 37123, 2, 2, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37128, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37021, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 37075, 37131, 2438, 36967, 9, 2, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37141, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37145, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 0, 0, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 37149, 37159, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 0, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 9, 2, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37168, 36957, 36959, 36963, 37172, 37191, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37210, 36957, 36959, 36963, 37075, 37131, 2438, 36967, 9, 2, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 37213, 691, 37213, 37217, 36957, 36959, 36963, 37221, 37230, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 0, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37239, 36957, 37247, 36963, 37264, 37292, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37319, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 2, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 36969, 36957, 36959, 36963, 36997, 37009, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37322, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 36948, 37021, 36957, 37328, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37335, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37339, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 2, 2, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37343, 36957, 37346, 36963, 37369, 36934, 37385, 37393, 3, 0, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37401, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37404, 36957, 37408, 36963, 36924, 36934, 2438, 36967, 5, 1, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37425, 36957, 0, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 37429, 37443, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 36969, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 36969, 36957, 37456, 36963, 37470, 37482, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37493, 36957, 36959, 36963, 37496, 37507, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 0, 36957, 0, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, 0 }, { 3, 0 } }, { 185, 36891, 185, 36891, 37517, 36903, 37526, 36921, 37537, 36934, 37552, 37393, 3, 0, 0, 0, 3, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37559, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37563, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 0, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 9, 2, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 37569, 37579, 2438, 36967, 8, 3, 7, 3, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37588, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 9, 2, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36948, 691, 36948, 10586, 36957, 0, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 10586, 36957, 0, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 10586, 36957, 37595, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 10586, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 0, 36957, 37601, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37021, 36957, 37328, 36963, 36924, 36934, 2438, 36967, 2, 0, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37642, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 691, 36891, 691, 36891, 36969, 36957, 0, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 36969, 36957, 37328, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 36969, 36957, 0, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37646, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 0, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 0, 36957, 37649, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37666, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 0, 36903, 36959, 36921, 36924, 36934, 2438, 36967, 9, 2, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37670, 36957, 37677, 36963, 36924, 36934, 2438, 36967, 12, 2, 1, 0, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 691, 36891, 691, 36891, 0, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 691, 36891, 691, 36891, 37642, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 691, 36891, 691, 36891, 37642, 36957, 0, 36963, 36924, 36934, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 691, 36891, 691, 36891, 37642, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 691, 36891, 691, 36891, 37642, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 691, 36891, 691, 36891, 37642, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 691, 36891, 691, 36891, 37642, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 12, 2, 2, 2, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 691, 36891, 691, 36891, 37642, 36957, 0, 36963, 36924, 36934, 2438, 36967, 12, 2, 1, 1, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 37704, 36891, 691, 36891, 37642, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 691, 36891, 691, 36891, 0, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 9, 2, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 36990, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 2, 0, 1, 1, 1, 2, 2, { 3, 0 }, { 3, 0 } }, { 691, 36891, 691, 36891, 37706, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37709, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 5, 1, 1, 1, 2, 2, 2, { 3, -1 }, { 3, 0 } }, { 36891, 691, 36891, 691, 37713, 36957, 37717, 36963, 36924, 36934, 2438, 36967, 2, 0, 1, 1, 1, 0, 2, { 3, 0 }, { 3, 0 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37642, 36957, 0, 36963, 36924, 36934, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 691, 36891, 691, 36891, 37754, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, 2 } }, { 691, 36891, 691, 36891, 37762, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 1, { 3, 0 }, { 3, 0 } }, { 36891, 36948, 36891, 36948, 0, 36957, 0, 36963, 37103, 37111, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37769, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, 2 } }, { 36891, 691, 36891, 691, 37782, 36903, 0, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37785, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 0, 36957, 0, 36963, 36924, 36934, 2438, 36967, 9, 2, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37789, 36957, 0, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36948, 691, 36948, 10586, 36957, 0, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37021, 36957, 37328, 36963, 36924, 36934, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, 0 }, { 3, 0 } }, { 691, 36891, 691, 36891, 37789, 36957, 0, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 36990, 36957, 0, 36963, 36924, 36934, 2438, 36967, 2, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, 0 } }, { 36891, 36948, 36891, 36948, 36969, 36957, 0, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 0, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37239, 36957, 0, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37793, 36957, 0, 36963, 36924, 36934, 2438, 36967, 9, 2, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37706, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 36893, 36903, 36906, 36921, 36924, 36934, 2438, 36943, 3, 2, 0, 0, 3, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 36951, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 36973, 36982, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37796, 36957, 37800, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 36993, 36957, 36959, 36963, 36997, 37009, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37021, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 37024, 37035, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 37046, 37060, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37073, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 0, 0, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 36969, 36957, 37094, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 36969, 36957, 36959, 36963, 37103, 37111, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37119, 36957, 36959, 36963, 36924, 36934, 2438, 37123, 2, 2, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37128, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37021, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 37075, 37131, 2438, 36967, 9, 2, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37141, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37145, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 0, 0, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 37149, 37159, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37021, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 9, 2, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37168, 36957, 36959, 36963, 37172, 37191, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37210, 36957, 36959, 36963, 37075, 37131, 2438, 36967, 9, 2, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 37213, 691, 37213, 37217, 36957, 36959, 36963, 37221, 37230, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 0, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37239, 36957, 37247, 36963, 37264, 37292, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37319, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 2, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 36969, 36957, 36959, 36963, 36997, 37009, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37322, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 36948, 37021, 36957, 37328, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37335, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37339, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 2, 2, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37343, 36957, 37346, 36963, 37369, 36934, 37385, 37393, 3, 0, 0, 0, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37401, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37404, 36957, 37408, 36963, 36924, 36934, 2438, 36967, 5, 1, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37425, 36957, 0, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 37429, 37443, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 36969, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 36969, 36957, 37456, 36963, 37470, 37482, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37493, 36957, 36959, 36963, 37496, 37507, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37810, 36957, 0, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, 0 }, { 3, 0 } }, { 185, 36891, 185, 36891, 37517, 36903, 37526, 36921, 37537, 36934, 37552, 37393, 3, 0, 0, 0, 3, 0, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37559, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37563, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37817, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 9, 2, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 37569, 37579, 2438, 36967, 8, 3, 7, 3, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37588, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 9, 2, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36948, 691, 36948, 10586, 36957, 0, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 10586, 36957, 0, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 10586, 36957, 37595, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 10586, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 0, 36957, 37601, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37021, 36957, 37328, 36963, 36924, 36934, 2438, 36967, 2, 0, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37642, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 691, 36891, 691, 36891, 36969, 36957, 0, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37021, 36957, 37328, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37666, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37822, 36903, 36959, 36921, 36924, 36934, 2438, 36967, 9, 2, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37642, 36957, 37677, 36963, 36924, 36934, 2438, 36967, 12, 2, 1, 0, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 691, 36891, 691, 36891, 37642, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 691, 36891, 691, 36891, 37642, 36957, 0, 36963, 36924, 36934, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 691, 36891, 691, 36891, 37642, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 691, 36891, 691, 36891, 37642, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 691, 36891, 691, 36891, 37642, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 691, 36891, 691, 36891, 37642, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 12, 2, 2, 2, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 691, 36891, 691, 36891, 37642, 36957, 0, 36963, 36924, 36934, 2438, 36967, 12, 2, 1, 1, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 37704, 36891, 691, 36891, 37642, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 691, 36891, 691, 36891, 36990, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 2, 0, 1, 1, 1, 2, 2, { 3, 0 }, { 3, 0 } }, { 691, 36891, 691, 36891, 37706, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37709, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 5, 1, 1, 1, 2, 2, 2, { 3, -1 }, { 3, 0 } }, { 36891, 691, 36891, 691, 37713, 36957, 37717, 36963, 36924, 36934, 2438, 36967, 2, 0, 1, 1, 1, 0, 2, { 3, 0 }, { 3, 0 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37642, 36957, 0, 36963, 36924, 36934, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 691, 36891, 691, 36891, 37754, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, 2 } }, { 691, 36891, 691, 36891, 37762, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 1, { 3, 0 }, { 3, 0 } }, { 691, 36891, 691, 36891, 37769, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, 2 } }, { 36891, 691, 36891, 691, 37782, 36903, 0, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37785, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37789, 36957, 0, 36963, 36924, 36934, 2438, 36967, 9, 2, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37789, 36957, 0, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36948, 691, 36948, 10586, 36957, 0, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37021, 36957, 37328, 36963, 36924, 36934, 2438, 36967, 12, 2, 0, 0, 1, 2, 2, { 3, 0 }, { 3, 0 } }, { 691, 36891, 691, 36891, 37789, 36957, 0, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 36990, 36957, 0, 36963, 36924, 36934, 2438, 36967, 2, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, 0 } }, { 36891, 36948, 36891, 36948, 36969, 36957, 0, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37239, 36957, 0, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37793, 36957, 0, 36963, 36924, 36934, 2438, 36967, 9, 2, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37706, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37828, 36903, 36906, 36921, 36924, 36934, 2438, 36943, 3, 2, 0, 0, 3, 0, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37141, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 2, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 37838, 691, 37838, 37217, 36957, 36959, 36963, 37024, 37035, 2438, 36967, 2, 2, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37706, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37073, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 1, 0, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 37103, 37111, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 37838, 691, 37838, 37217, 36957, 36959, 36963, 37075, 37131, 2438, 36967, 2, 2, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 36948, 36969, 36957, 36959, 36963, 37149, 37159, 2438, 36967, 12, 2, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37021, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 36969, 36957, 36959, 36963, 37075, 37131, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 36969, 36957, 37328, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37840, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 36969, 36957, 0, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37848, 36903, 36959, 36921, 36924, 36934, 2438, 36967, 9, 2, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37855, 36957, 37677, 36963, 36924, 36934, 2438, 36967, 12, 2, 1, 0, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 691, 36891, 691, 36891, 37859, 36903, 36959, 36921, 36924, 36934, 2438, 36943, 3, 2, 0, 0, 3, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37073, 36957, 37800, 36963, 36924, 36934, 2438, 36967, 0, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 37024, 37035, 2438, 36967, 9, 2, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37073, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37073, 36957, 36959, 36963, 37103, 37111, 2438, 36967, 15, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 36969, 36957, 37328, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37869, 36903, 36906, 36921, 36924, 36934, 2438, 36943, 3, 0, 0, 0, 3, 3, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37073, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 0, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 37024, 37035, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37073, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 7920, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 1, 0, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36948, 691, 36948, 37217, 36957, 36959, 36963, 37103, 37111, 2438, 36967, 2, 2, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37879, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37882, 36903, 36906, 36921, 36924, 36934, 2438, 36943, 3, 2, 0, 0, 3, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37892, 36957, 37800, 36963, 36924, 36934, 2438, 36967, 0, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 37838, 691, 37838, 0, 36957, 36959, 36963, 37024, 37035, 2438, 36967, 9, 2, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37073, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37897, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 1, 0, 0, 0, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 37103, 37111, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37879, 36957, 0, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37901, 36903, 36906, 36921, 36924, 36934, 2438, 36943, 3, 2, 0, 0, 3, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 36969, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37911, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 1, 0, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 36969, 36957, 36959, 36963, 37103, 37111, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37879, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37915, 36903, 36906, 36921, 36924, 36934, 2438, 36943, 3, 2, 0, 0, 3, 3, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 10586, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37073, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 1, 0, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37925, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37930, 36903, 36906, 36921, 36924, 36934, 2438, 36943, 3, 2, 0, 0, 3, 3, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37073, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37940, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 2, 0, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37925, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37944, 36903, 36906, 36921, 36924, 36934, 2438, 36943, 3, 2, 0, 0, 3, 0, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37073, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 1, 0, 0, 0, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37954, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37959, 36903, 36906, 36921, 36924, 36934, 2438, 36943, 3, 2, 0, 0, 3, 0, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37073, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37969, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 1, 0, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37973, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37981, 36903, 36906, 36921, 36924, 36934, 2438, 36943, 3, 2, 0, 0, 3, 3, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37073, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37073, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 1, 0, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37991, 36903, 36906, 36921, 36924, 36934, 2438, 36943, 3, 2, 0, 0, 3, 0, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37073, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37073, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 2, 0, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 36969, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 38001, 36903, 36906, 36921, 36924, 36934, 2438, 36943, 3, 2, 0, 0, 3, 3, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37785, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37073, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 2, 0, 0, 0, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 38011, 36903, 36906, 36921, 36924, 36934, 2438, 36943, 3, 2, 0, 0, 3, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37073, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 9, 2, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 38021, 36903, 36906, 36921, 36924, 36934, 2438, 36943, 3, 2, 0, 0, 3, 3, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 38031, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 12, 2, 0, 0, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 38035, 36903, 36906, 36921, 36924, 36934, 2438, 36943, 3, 2, 0, 0, 3, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37642, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 12, 2, 1, 1, 1, 2, 2, { 3, 2 }, { 3, 2 } }, { 36891, 691, 36891, 691, 38045, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 1, 0, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37073, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 1, 0, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37073, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 1, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 2308, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 1, 0, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 38048, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 1, 0, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37073, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 1, 0, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37073, 36957, 36959, 36963, 37075, 37085, 2438, 36967, 0, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, 0 } }, { 36891, 691, 36891, 691, 37925, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37879, 36957, 0, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 38051, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 38059, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37840, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 36990, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 2, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37021, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37879, 36957, 0, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 37817, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 9, 2, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37848, 36903, 36959, 36921, 36924, 36934, 2438, 36967, 9, 2, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 0, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 9, 2, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 38064, 36957, 37800, 36963, 36924, 36934, 2438, 36967, 0, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 38064, 36957, 37800, 36963, 36924, 36934, 2438, 36967, 0, 0, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37021, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 9, 2, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 36891, 691, 36891, 691, 38059, 36957, 36959, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 37810, 36957, 0, 36963, 36924, 36934, 2438, 36967, 8, 3, 1, 1, 1, 2, 2, { 3, 0 }, { 3, 0 } }, { 36891, 36948, 36891, 36948, 37822, 36903, 36959, 36921, 36924, 36934, 2438, 36967, 9, 2, 1, 1, 1, 0, 2, { 3, -1 }, { 3, -1 } }, { 36891, 36948, 36891, 36948, 0, 36957, 0, 36963, 37103, 37111, 2438, 36967, 8, 3, 0, 0, 1, 2, 2, { 3, -1 }, { 3, -1 } }, { 691, 36891, 691, 36891, 37789, 36957, 0, 36963, 36924, 36934, 2438, 36967, 9, 2, 1, 1, 1, 2, 2, { 3, -1 }, { 3, -1 } } }; static const CultureInfoEntry culture_entries[] = { { 0x0001, 0x007F, 768, -1, 38068, 38071, 38078, 38093, 38097, 38068, 0, { 0, 0, 38101, 0 }, 0, 0, { 1256, 20420, 10004, 720, 1, ';' } }, { 0x0002, 0x007F, 257, -1, 38129, 38132, 38142, 38161, 38165, 38129, 0, { 38169, 0, 0, 0 }, 1, 1, { 1251, 21025, 10007, 866, 0, ';' } }, { 0x0003, 0x007F, 257, -1, 38211, 38214, 38222, 38230, 38234, 38211, 0, { 38238, 0, 0, 0 }, 2, 2, { 1252, 500, 10000, 850, 0, ';' } }, { 0x0004, 0x0004, 257, -1, 38258, 38265, 38293, 38300, 38304, 38308, 0, { 38311, 0, 0, 0 }, 3, 3, { 936, 500, 10008, 936, 0, ',' } }, { 0x0004, 0x7804, 257, -1, 38318, 38326, 38293, 38300, 38304, 38308, 0, { 38311, 0, 0, 0 }, 4, 4, { 936, 500, 10008, 936, 0, ',' } }, { 0x0005, 0x007F, 257, -1, 38347, 38350, 38356, 38366, 38370, 38347, 0, { 38374, 0, 0, 0 }, 5, 5, { 1250, 500, 10029, 852, 0, ';' } }, { 0x0006, 0x007F, 257, -1, 38400, 38403, 38410, 38416, 38420, 38400, 0, { 38424, 0, 0, 0 }, 6, 6, { 1252, 20277, 10000, 850, 0, ';' } }, { 0x0007, 0x007F, 257, -1, 38445, 38448, 38455, 38463, 38467, 38445, 0, { 38471, 0, 0, 0 }, 7, 7, { 1252, 20273, 10000, 850, 0, ';' } }, { 0x0008, 0x007F, 257, -1, 38496, 38499, 38505, 38522, 38526, 38496, 0, { 38530, 0, 0, 0 }, 8, 8, { 1253, 20273, 10006, 737, 0, ';' } }, { 0x0009, 0x007F, 257, -1, 38572, 38575, 38575, 38583, 38587, 38572, 0, { 38591, 0, 0, 0 }, 9, 9, { 1252, 37, 10000, 437, 0, ',' } }, { 0x000A, 0x007F, 257, -1, 38610, 38613, 38621, 38630, 38634, 38610, 0, { 38638, 0, 0, 0 }, 10, 10, { 1252, 20284, 10000, 850, 0, ';' } }, { 0x000B, 0x007F, 257, -1, 38660, 38663, 38671, 38677, 38681, 38660, 0, { 38685, 0, 0, 0 }, 11, 11, { 1252, 20278, 10000, 850, 0, ';' } }, { 0x000C, 0x007F, 257, -1, 38710, 38713, 38720, 38730, 38734, 38710, 0, { 38738, 0, 0, 0 }, 12, 12, { 1252, 20297, 10000, 850, 0, ';' } }, { 0x000D, 0x007F, 257, -1, 38760, 38763, 38770, 38781, 38785, 38760, 0, { 38789, 0, 0, 0 }, 13, 13, { 1255, 500, 10005, 862, 1, ',' } }, { 0x000E, 0x007F, 257, -1, 38822, 38825, 38835, 38842, 38846, 38822, 0, { 38850, 0, 0, 0 }, 14, 14, { 1250, 500, 10029, 852, 0, ';' } }, { 0x000F, 0x007F, 257, -1, 38866, 38869, 38879, 38889, 38893, 38866, 0, { 38897, 0, 0, 0 }, 15, 15, { 1252, 20871, 10079, 850, 0, ';' } }, { 0x0010, 0x007F, 257, -1, 38917, 38920, 38928, 38937, 38941, 38917, 0, { 38945, 0, 0, 0 }, 16, 16, { 1252, 20280, 10000, 850, 0, ';' } }, { 0x0011, 0x007F, 257, -1, 38967, 38970, 38979, 38989, 38993, 38967, 0, { 38997, 0, 0, 0 }, 17, 17, { 932, 20290, 10001, 932, 0, ',' } }, { 0x0012, 0x007F, 257, -1, 39024, 39027, 39034, 39044, 39048, 39024, 0, { 39052, 0, 0, 0 }, 18, 18, { 949, 20833, 10003, 949, 0, ',' } }, { 0x0013, 0x007F, 257, -1, 39062, 39065, 39071, 39082, 39086, 39062, 0, { 39090, 0, 0, 0 }, 19, 19, { 1252, 500, 10000, 850, 0, ';' } }, { 0x0014, 0x007F, 257, -1, 39112, 39115, 39125, 39131, 39135, 39139, 0, { 38424, 0, 0, 0 }, 20, 20, { 1252, 20277, 10000, 850, 0, ';' } }, { 0x0015, 0x007F, 257, -1, 39142, 39145, 39152, 39159, 39163, 39142, 0, { 39167, 0, 0, 0 }, 21, 21, { 1250, 20880, 10029, 852, 0, ';' } }, { 0x0016, 0x007F, 257, -1, 39191, 39194, 39205, 39216, 39220, 39191, 0, { 39224, 0, 0, 0 }, 22, 22, { 1252, 500, 10000, 850, 0, ';' } }, { 0x0017, 0x007F, 257, -1, 39247, 39250, 39258, 39268, 39272, 39247, 0, { 39276, 0, 0, 0 }, 23, 23, { 1252, 20273, 10000, 850, 0, ';' } }, { 0x0018, 0x007F, 257, -1, 39296, 39299, 39308, 39317, 39321, 39296, 0, { 39325, 0, 0, 0 }, 24, 24, { 1250, 20880, 10029, 852, 0, ';' } }, { 0x0019, 0x007F, 257, -1, 39344, 39347, 39355, 39370, 39374, 39344, 0, { 39378, 0, 0, 0 }, 25, 25, { 1251, 20880, 10007, 866, 0, ';' } }, { 0x001A, 0x007F, 257, -1, 39424, 39427, 39436, 39445, 39449, 39424, 0, { 39453, 0, 0, 0 }, 26, 26, { 1250, 500, 10082, 852, 0, ';' } }, { 0x001B, 0x007F, 257, -1, 12674, 39476, 39483, 39495, 39499, 12674, 0, { 39503, 0, 0, 0 }, 27, 27, { 1250, 20880, 10029, 852, 0, ';' } }, { 0x001C, 0x007F, 257, -1, 39527, 39530, 39539, 39545, 39549, 39527, 0, { 39553, 0, 0, 0 }, 28, 28, { 1250, 20880, 10029, 852, 0, ';' } }, { 0x001D, 0x007F, 257, -1, 39573, 39576, 39584, 39592, 39596, 39573, 0, { 38424, 0, 0, 0 }, 29, 29, { 1252, 20278, 10000, 850, 0, ';' } }, { 0x001E, 0x007F, 512, -1, 39600, 39603, 39608, 39618, 39622, 39600, 0, { 0, 39626, 0, 0 }, 30, 30, { 874, 20838, 10021, 874, 0, ',' } }, { 0x001F, 0x007F, 257, -1, 12683, 39657, 39665, 39674, 39678, 12683, 0, { 39682, 0, 0, 0 }, 31, 31, { 1254, 20905, 10081, 857, 0, ';' } }, { 0x0020, 0x007F, 257, -1, 39696, 39699, 39704, 39713, 39717, 39696, 0, { 39721, 0, 0, 0 }, 32, 32, { 1256, 20420, 10004, 720, 1, ';' } }, { 0x0021, 0x007F, 257, -1, 39751, 39754, 39765, 39782, 39786, 39751, 0, { 39790, 0, 0, 0 }, 33, 33, { 1252, 500, 10000, 850, 0, ';' } }, { 0x0022, 0x007F, 257, -1, 39809, 39812, 39822, 39843, 39847, 39809, 0, { 39851, 0, 0, 0 }, 34, 34, { 1251, 500, 10017, 866, 0, ';' } }, { 0x0023, 0x007F, 257, -1, 39897, 39900, 39911, 39932, 39936, 39897, 0, { 39940, 0, 0, 0 }, 35, 35, { 1251, 500, 10007, 866, 0, ';' } }, { 0x0024, 0x007F, 257, -1, 39982, 39985, 39995, 40009, 40013, 39982, 0, { 40017, 0, 0, 0 }, 36, 36, { 1250, 20880, 10029, 852, 0, ';' } }, { 0x0025, 0x007F, 257, -1, 40039, 40042, 40051, 40057, 40061, 40039, 0, { 40065, 0, 0, 0 }, 37, 37, { 1257, 500, 10029, 775, 0, ';' } }, { 0x0026, 0x007F, 257, -1, 40085, 40088, 40096, 40106, 40110, 40085, 0, { 40114, 0, 0, 0 }, 38, 38, { 1257, 500, 10029, 775, 0, ';' } }, { 0x0027, 0x007F, 257, -1, 40133, 40136, 40147, 40157, 40161, 40133, 0, { 40165, 0, 0, 0 }, 39, 39, { 1257, 500, 10029, 775, 0, ';' } }, { 0x0028, 0x007F, 257, -1, 40188, 40191, 40197, 40210, 40214, 40188, 0, { 0, 0, 0, 0 }, 40, 40, { 1251, 20880, 10007, 866, 0, ';' } }, { 0x0029, 0x007F, 257, -1, 40218, 40221, 40229, 40240, 40244, 40218, 0, { 40248, 0, 0, 0 }, 41, 41, { 1256, 20420, 10004, 720, 1, ';' } }, { 0x002A, 0x007F, 257, -1, 40272, 40275, 40286, 40301, 35137, 40272, 0, { 40305, 0, 0, 0 }, 42, 42, { 1258, 500, 10000, 1258, 0, ',' } }, { 0x002B, 0x007F, 257, -1, 40320, 40323, 40332, 40347, 40351, 40320, 0, { 40355, 0, 0, 0 }, 43, 43, { 0, 500, 2, 1, 0, ',' } }, { 0x002C, 0x007F, 257, -1, 40385, 40388, 40400, 40412, 40416, 40385, 0, { 40420, 0, 0, 0 }, 44, 44, { 1254, 20905, 10081, 857, 0, ';' } }, { 0x002D, 0x007F, 257, -1, 40439, 40442, 40449, 40457, 40461, 40439, 0, { 40465, 0, 0, 0 }, 45, 45, { 1252, 500, 10000, 850, 0, ';' } }, { 0x002F, 0x007F, 257, -1, 40485, 40488, 40499, 40520, 40524, 40485, 0, { 40528, 0, 0, 0 }, 46, 46, { 1251, 500, 10007, 866, 0, ';' } }, { 0x0032, 0x007F, 257, -1, 40572, 40575, 40582, 40591, 40595, 40572, 0, { 0, 0, 0, 0 }, 47, 47, { 1252, 500, 10000, 850, 0, ',' } }, { 0x0034, 0x007F, 257, -1, 40599, 40602, 40608, 40617, 40621, 40599, 0, { 0, 0, 0, 0 }, 48, 48, { 1252, 500, 10000, 850, 0, ',' } }, { 0x0035, 0x007F, 257, -1, 40625, 40628, 40633, 40641, 40645, 40625, 0, { 40649, 0, 0, 0 }, 49, 49, { 1252, 500, 10000, 850, 0, ',' } }, { 0x0036, 0x007F, 257, -1, 40670, 40673, 40673, 40683, 40687, 40670, 0, { 40691, 0, 0, 0 }, 50, 50, { 1252, 500, 10000, 850, 0, ',' } }, { 0x0037, 0x007F, 257, -1, 40711, 40714, 40723, 40745, 40749, 40711, 0, { 40753, 0, 0, 0 }, 51, 51, { 0, 500, 2, 1, 0, ';' } }, { 0x0038, 0x007F, 257, -1, 40818, 40821, 40829, 40839, 40843, 40818, 0, { 0, 0, 0, 0 }, 52, 52, { 1252, 20277, 10079, 850, 0, ';' } }, { 0x0039, 0x007F, 257, -1, 40847, 40850, 40856, 40872, 40876, 40847, 0, { 40880, 0, 0, 0 }, 53, 53, { 0, 500, 2, 1, 0, ',' } }, { 0x003A, 0x007F, 257, -1, 40933, 40936, 40944, 40950, 40954, 40933, 0, { 40958, 0, 0, 0 }, 54, 54, { 0, 500, 2, 1, 0, ',' } }, { 0x003B, 0x007F, 257, -1, 40979, 40982, 40996, 41013, 41017, 40979, 0, { 41021, 0, 0, 0 }, 55, 55, { 1252, 20277, 10000, 850, 0, ';' } }, { 0x003C, 0x007F, 257, -1, 41040, 41043, 41049, 41057, 41061, 41040, 0, { 41065, 0, 0, 0 }, 56, 56, { 1252, 500, 10000, 850, 0, ',' } }, { 0x003E, 0x007F, 257, -1, 41086, 41089, 41095, 41109, 41113, 41086, 0, { 41117, 0, 0, 0 }, 57, 57, { 1252, 500, 10000, 850, 0, ';' } }, { 0x003F, 0x007F, 257, -1, 41134, 41137, 41144, 41164, 41168, 41134, 0, { 41172, 0, 0, 0 }, 58, 58, { 0, 500, 2, 1, 0, ';' } }, { 0x0040, 0x007F, 257, -1, 41214, 41217, 41224, 41241, 41245, 41214, 0, { 41249, 0, 0, 0 }, 59, 59, { 1251, 20880, 10007, 866, 0, ';' } }, { 0x0041, 0x007F, 257, -1, 41287, 41290, 41298, 41308, 41312, 41287, 0, { 41316, 0, 0, 0 }, 60, 60, { 1252, 500, 10000, 437, 0, ',' } }, { 0x0043, 0x007F, 257, -1, 41337, 41340, 41346, 41357, 41361, 41337, 0, { 41365, 0, 0, 0 }, 61, 61, { 1254, 500, 10029, 857, 0, ';' } }, { 0x0045, 0x007F, 257, -1, 41385, 41388, 41396, 41412, 41416, 41385, 0, { 41420, 0, 0, 0 }, 62, 62, { 0, 500, 2, 1, 0, ',' } }, { 0x0046, 0x007F, 257, -1, 41485, 41488, 41496, 41515, 41519, 41485, 0, { 41523, 0, 0, 0 }, 63, 63, { 0, 500, 2, 1, 0, ',' } }, { 0x0047, 0x007F, 257, -1, 41570, 41573, 41582, 41604, 41608, 41570, 0, { 41612, 0, 0, 0 }, 64, 64, { 0, 500, 2, 1, 0, ',' } }, { 0x0048, 0x007F, 257, -1, 41668, 41671, 41677, 41693, 41697, 41668, 0, { 0, 0, 0, 0 }, 65, 65, { 0, 500, 2, 1, 0, ',' } }, { 0x0049, 0x007F, 257, -1, 41701, 41704, 41710, 41726, 41730, 41701, 0, { 41734, 0, 0, 0 }, 66, 66, { 0, 500, 2, 1, 0, ',' } }, { 0x004A, 0x007F, 257, -1, 41799, 41802, 41809, 41828, 41832, 41799, 0, { 41836, 0, 0, 0 }, 67, 67, { 0, 500, 2, 1, 0, ',' } }, { 0x004B, 0x007F, 257, -1, 37319, 41901, 41909, 41925, 41929, 37319, 0, { 41933, 0, 0, 0 }, 68, 68, { 0, 500, 2, 1, 0, ',' } }, { 0x004C, 0x007F, 257, -1, 41998, 42001, 42011, 42030, 42034, 41998, 0, { 42038, 0, 0, 0 }, 69, 69, { 0, 500, 2, 1, 0, ',' } }, { 0x004D, 0x007F, 257, -1, 42082, 42085, 42094, 42116, 42120, 42082, 0, { 42124, 0, 0, 0 }, 70, 70, { 0, 500, 2, 1, 0, ',' } }, { 0x004E, 0x007F, 257, -1, 42177, 42180, 42188, 42204, 2402, 42177, 0, { 42208, 0, 0, 0 }, 71, 71, { 0, 500, 2, 1, 0, ',' } }, { 0x0050, 0x007F, 257, -1, 42270, 42273, 42283, 42296, 42300, 42270, 0, { 42304, 0, 0, 0 }, 72, 72, { 1251, 20880, 10007, 866, 0, ';' } }, { 0x0051, 0x007F, 257, -1, 42336, 42339, 42347, 42372, 42376, 42336, 0, { 0, 0, 0, 0 }, 73, 73, { 0, 500, 2, 1, 0, ',' } }, { 0x0052, 0x007F, 257, -1, 42380, 42383, 42389, 42397, 42401, 42380, 0, { 42405, 0, 0, 0 }, 74, 74, { 1252, 20285, 10000, 850, 0, ',' } }, { 0x0053, 0x007F, 257, -1, 42421, 42424, 42430, 42446, 42450, 42421, 0, { 42454, 0, 0, 0 }, 75, 75, { 0, 500, 2, 1, 0, ',' } }, { 0x0054, 0x007F, 257, -1, 42509, 42512, 42516, 42526, 42530, 42509, 0, { 42534, 0, 0, 0 }, 76, 76, { 0, 500, 2, 1, 0, ',' } }, { 0x0056, 0x007F, 257, -1, 42580, 42583, 42592, 42599, 42603, 42580, 0, { 38945, 0, 0, 0 }, 77, 77, { 1252, 500, 10000, 850, 0, ';' } }, { 0x0057, 0x007F, 257, -1, 42607, 42611, 42619, 42638, 42607, 42607, 0, { 0, 0, 0, 0 }, 78, 78, { 0, 500, 2, 1, 0, ',' } }, { 0x005B, 0x007F, 257, -1, 42642, 42645, 42653, 42669, 42673, 42642, 0, { 42677, 0, 0, 0 }, 79, 79, { 0, 500, 2, 1, 0, ',' } }, { 0x005E, 0x007F, 257, -1, 8022, 42736, 42744, 42757, 42761, 8022, 0, { 42765, 0, 0, 0 }, 80, 80, { 0, 500, 2, 1, 0, ';' } }, { 0x005F, 0x007F, 257, -1, 42810, 42814, 42838, 42848, 42810, 42810, 0, { 0, 0, 0, 0 }, 81, 81, { 1252, 20297, 10000, 850, 0, ';' } }, { 0x0061, 0x007F, 257, -1, 1883, 42852, 42859, 42878, 42882, 1883, 0, { 42886, 0, 0, 0 }, 82, 82, { 0, 500, 2, 1, 0, ',' } }, { 0x0063, 0x007F, 1024, -1, 42936, 42939, 42946, 42955, 42959, 42936, 0, { 0, 0, 0, 0 }, 83, 83, { 0, 500, 2, 1, 1, ';' } }, { 0x0064, 0x007F, 257, -1, 42963, 42967, 42967, 42976, 42963, 42963, 0, { 42980, 0, 0, 0 }, 84, 84, { 1252, 500, 10000, 437, 0, ',' } }, { 0x0068, 0x007F, 257, -1, 43003, 43006, 43006, 43012, 43016, 43003, 0, { 0, 0, 0, 0 }, 85, 85, { 1252, 37, 10000, 437, 0, ',' } }, { 0x006A, 0x007F, 257, -1, 43020, 43023, 43030, 43045, 43049, 43020, 0, { 0, 0, 0, 0 }, 86, 86, { 1252, 37, 10000, 437, 0, ',' } }, { 0x006C, 0x007F, 257, -1, 43053, 43057, 43072, 43089, 43053, 43053, 0, { 0, 0, 0, 0 }, 87, 87, { 1252, 500, 10000, 850, 0, ',' } }, { 0x006F, 0x007F, 257, -1, 43093, 43096, 43108, 43120, 43124, 43093, 0, { 43128, 0, 0, 0 }, 88, 88, { 1252, 20277, 10000, 850, 0, ';' } }, { 0x0070, 0x007F, 257, -1, 43155, 43158, 43158, 43163, 43167, 43155, 0, { 0, 0, 0, 0 }, 89, 89, { 1252, 37, 10000, 437, 0, ',' } }, { 0x0078, 0x007F, 257, -1, 43171, 43174, 43185, 43195, 43199, 43171, 0, { 43203, 0, 0, 0 }, 90, 90, { 0, 500, 2, 1, 0, ',' } }, { 0x007E, 0x007F, 257, -1, 43216, 43219, 43226, 43236, 43240, 43216, 0, { 43244, 0, 0, 0 }, 91, 91, { 1252, 20297, 10000, 850, 0, ';' } }, { 0x0084, 0x007F, 257, -1, 43264, 43268, 43281, 43300, 43264, 43264, 0, { 43304, 0, 0, 0 }, 92, 92, { 1252, 20297, 10000, 850, 0, ';' } }, { 0x0085, 0x007F, 257, -1, 43329, 43333, 43339, 43357, 43329, 43329, 0, { 0, 0, 0, 0 }, 93, 93, { 1251, 20880, 10007, 866, 0, ';' } }, { 0x0087, 0x007F, 257, -1, 43361, 43364, 43364, 43376, 43380, 43361, 0, { 0, 0, 0, 0 }, 94, 94, { 1252, 37, 10000, 437, 0, ';' } }, { 0x0091, 0x007F, 257, -1, 43384, 43387, 43403, 43413, 43417, 43384, 0, { 43421, 0, 0, 0 }, 95, 95, { 1252, 20285, 10000, 850, 0, ',' } }, { 0x0401, 0x0001, 768, 95, 43446, 43452, 43474, 38093, 38097, 38068, 13629, { 0, 0, 38101, 0 }, 96, 96, { 1256, 20420, 10004, 720, 1, ';' } }, { 0x0402, 0x0002, 257, 11, 43538, 43544, 43565, 38161, 38165, 38129, 43603, { 38169, 0, 0, 0 }, 97, 97, { 1251, 21025, 10007, 866, 0, ';' } }, { 0x0403, 0x0003, 257, 31, 43606, 43612, 43628, 38230, 38234, 38211, 43646, { 38238, 0, 0, 0 }, 98, 98, { 1252, 500, 10000, 850, 0, ';' } }, { 0x0404, 0x7C04, 257, 107, 43649, 43655, 43677, 43693, 38304, 38308, 43697, { 43700, 0, 0, 0 }, 99, 99, { 950, 500, 10002, 950, 0, ',' } }, { 0x0405, 0x0005, 257, 23, 43707, 43713, 43736, 38366, 38370, 38347, 43766, { 38374, 0, 0, 0 }, 100, 100, { 1250, 500, 10029, 852, 0, ';' } }, { 0x0406, 0x0006, 257, 25, 43769, 43775, 43792, 38416, 38420, 38400, 43808, { 38424, 0, 0, 0 }, 101, 101, { 1252, 20277, 10000, 850, 0, ';' } }, { 0x0407, 0x0007, 257, 24, 43811, 43817, 43834, 38463, 38467, 38445, 43856, { 38471, 0, 0, 0 }, 102, 102, { 1252, 20273, 10000, 850, 0, ';' } }, { 0x0408, 0x0008, 257, 39, 43859, 43865, 43880, 38522, 38526, 38496, 43912, { 38530, 0, 0, 0 }, 103, 103, { 1253, 20273, 10006, 737, 0, ';' } }, { 0x0409, 0x0009, 257, 109, 43915, 43921, 43921, 38583, 38587, 38572, 43945, { 38591, 0, 0, 0 }, 104, 104, { 1252, 37, 10000, 437, 0, ',' } }, { 0x040B, 0x000B, 257, 33, 43948, 43954, 43972, 38677, 38681, 38660, 43986, { 38685, 0, 0, 0 }, 105, 105, { 1252, 20278, 10000, 850, 0, ';' } }, { 0x040C, 0x000C, 257, 35, 43989, 43995, 44011, 38730, 38734, 38710, 44030, { 38738, 0, 0, 0 }, 106, 106, { 1252, 20297, 10000, 850, 0, ';' } }, { 0x040D, 0x000D, 257, 47, 44033, 44039, 44055, 38781, 38785, 38760, 44079, { 38789, 0, 0, 0 }, 107, 107, { 1255, 500, 10005, 862, 1, ',' } }, { 0x040E, 0x000E, 257, 44, 44082, 44088, 44108, 38842, 38846, 38822, 44131, { 38850, 0, 0, 0 }, 108, 108, { 1250, 500, 10029, 852, 0, ';' } }, { 0x040F, 0x000F, 257, 51, 44134, 44140, 44160, 38889, 38893, 38866, 44180, { 38897, 0, 0, 0 }, 109, 109, { 1252, 20871, 10079, 850, 0, ';' } }, { 0x0410, 0x0010, 257, 52, 44183, 44189, 44205, 38937, 38941, 38917, 44223, { 38945, 0, 0, 0 }, 110, 110, { 1252, 20280, 10000, 850, 0, ';' } }, { 0x0411, 0x0011, 257, 55, 44226, 44232, 44249, 38989, 38993, 38967, 44268, { 38997, 0, 0, 0 }, 111, 111, { 932, 20290, 10001, 932, 0, ',' } }, { 0x0412, 0x0012, 257, 58, 44271, 44277, 44298, 39044, 39048, 39024, 44323, { 39052, 0, 0, 0 }, 112, 112, { 949, 20833, 10003, 949, 0, ',' } }, { 0x0413, 0x0013, 257, 77, 44326, 44332, 44352, 39082, 39086, 39062, 44375, { 39090, 0, 0, 0 }, 113, 113, { 1252, 500, 10000, 850, 0, ';' } }, { 0x0414, 0x7C14, 257, 78, 44378, 44384, 44411, 39131, 39135, 39139, 44433, { 38424, 0, 0, 0 }, 114, 114, { 1252, 20277, 10000, 850, 0, ';' } }, { 0x0415, 0x0015, 257, 86, 44436, 44442, 44458, 39159, 39163, 39142, 44474, { 39167, 0, 0, 0 }, 115, 115, { 1250, 20880, 10029, 852, 0, ';' } }, { 0x0416, 0x0016, 257, 14, 44477, 44483, 44503, 39216, 39220, 39191, 44523, { 39224, 0, 0, 0 }, 116, 116, { 1252, 500, 10000, 850, 0, ';' } }, { 0x0417, 0x0017, 257, 18, 44526, 44532, 44554, 39268, 39272, 39247, 13632, { 39276, 0, 0, 0 }, 117, 117, { 1252, 20273, 10000, 850, 0, ';' } }, { 0x0418, 0x0018, 257, 91, 44573, 44579, 44598, 39317, 39321, 39296, 44618, { 39325, 0, 0, 0 }, 118, 118, { 1250, 20880, 10029, 852, 0, ';' } }, { 0x0419, 0x0019, 257, 93, 44621, 44627, 44644, 39370, 39374, 39344, 44674, { 39378, 0, 0, 0 }, 119, 119, { 1251, 20880, 10007, 866, 0, ';' } }, { 0x041A, 0x001A, 257, 43, 44677, 44683, 44702, 39445, 39449, 39424, 44722, { 39453, 0, 0, 0 }, 120, 120, { 1250, 500, 10082, 852, 0, ';' } }, { 0x041B, 0x001B, 257, 99, 44725, 44731, 44749, 39495, 39499, 12674, 44773, { 39503, 0, 0, 0 }, 121, 121, { 1250, 20880, 10029, 852, 0, ';' } }, { 0x041C, 0x001C, 257, 2, 44776, 44782, 44801, 39545, 39549, 39527, 44819, { 39553, 0, 0, 0 }, 122, 122, { 1250, 20880, 10029, 852, 0, ';' } }, { 0x041D, 0x001D, 257, 96, 44822, 44828, 44845, 39592, 39596, 39573, 44863, { 38424, 0, 0, 0 }, 123, 123, { 1252, 20278, 10000, 850, 0, ';' } }, { 0x041E, 0x001E, 512, 102, 44866, 44872, 44888, 39618, 39622, 39600, 44910, { 0, 39626, 0, 0 }, 124, 124, { 874, 20838, 10021, 874, 0, ',' } }, { 0x041F, 0x001F, 257, 105, 44913, 44919, 44936, 39674, 39678, 12683, 44956, { 39682, 0, 0, 0 }, 125, 125, { 1254, 20905, 10081, 857, 0, ';' } }, { 0x0420, 0x0020, 257, 85, 44959, 44965, 44981, 39713, 39717, 39696, 45007, { 39721, 0, 0, 0 }, 126, 126, { 1256, 20420, 10004, 720, 1, ';' } }, { 0x0421, 0x0021, 257, 45, 45010, 45016, 45039, 39782, 39786, 39751, 45068, { 39790, 0, 0, 0 }, 127, 127, { 1252, 500, 10000, 850, 0, ';' } }, { 0x0422, 0x0022, 257, 108, 45071, 45077, 45097, 39843, 39847, 39809, 45135, { 39851, 0, 0, 0 }, 128, 128, { 1251, 500, 10017, 866, 0, ';' } }, { 0x0423, 0x0023, 257, 15, 45138, 45144, 45165, 39932, 39936, 39897, 45205, { 39940, 0, 0, 0 }, 129, 129, { 1251, 500, 10007, 866, 0, ';' } }, { 0x0424, 0x0024, 257, 98, 45208, 45214, 45235, 40009, 40013, 39982, 45261, { 40017, 0, 0, 0 }, 130, 130, { 1250, 20880, 10029, 852, 0, ';' } }, { 0x0425, 0x0025, 257, 29, 45264, 45270, 45289, 40057, 40061, 40039, 45303, { 40065, 0, 0, 0 }, 131, 131, { 1257, 500, 10029, 775, 0, ';' } }, { 0x0426, 0x0026, 257, 66, 45306, 45312, 45329, 40106, 40110, 40085, 45349, { 40114, 0, 0, 0 }, 132, 132, { 1257, 500, 10029, 775, 0, ';' } }, { 0x0427, 0x0027, 257, 64, 45352, 45358, 45381, 40157, 40161, 40133, 45401, { 40165, 0, 0, 0 }, 133, 133, { 1257, 500, 10029, 775, 0, ';' } }, { 0x0428, 0x7C28, 257, 103, 45404, 45415, 45444, 40210, 40214, 40188, 45480, { 0, 0, 0, 0 }, 134, 134, { 1251, 20880, 10007, 866, 0, ';' } }, { 0x0429, 0x0029, 257, 50, 45483, 45489, 45504, 40240, 40244, 40218, 45528, { 40248, 0, 0, 0 }, 135, 135, { 1256, 20420, 10004, 720, 1, ';' } }, { 0x042A, 0x002A, 257, 113, 45531, 45537, 45558, 40301, 35137, 40272, 45586, { 40305, 0, 0, 0 }, 136, 136, { 1258, 500, 10000, 1258, 0, ',' } }, { 0x042B, 0x002B, 257, 3, 45589, 45595, 45614, 40347, 40351, 40320, 1820, { 40355, 0, 0, 0 }, 137, 137, { 0, 500, 2, 1, 0, ',' } }, { 0x042C, 0x782C, 257, 7, 45648, 45659, 45691, 40412, 40416, 40385, 45717, { 40420, 0, 0, 0 }, 138, 138, { 1254, 20905, 10081, 857, 0, ';' } }, { 0x042D, 0x002D, 257, 31, 45720, 45726, 45741, 40457, 40461, 40439, 43646, { 40465, 0, 0, 0 }, 139, 139, { 1252, 500, 10000, 850, 0, ';' } }, { 0x042F, 0x002F, 257, 71, 45760, 45766, 45789, 40520, 40524, 40485, 45833, { 40528, 0, 0, 0 }, 140, 140, { 1251, 500, 10007, 866, 0, ';' } }, { 0x0432, 0x0032, 257, 115, 45836, 45842, 40582, 40591, 40595, 40572, 45864, { 0, 0, 0, 0 }, 141, 141, { 1252, 500, 10000, 850, 0, ',' } }, { 0x0434, 0x0034, 257, 115, 45867, 45873, 40608, 40617, 40621, 40599, 45864, { 0, 0, 0, 0 }, 142, 142, { 1252, 500, 10000, 850, 0, ',' } }, { 0x0435, 0x0035, 257, 115, 45894, 45900, 45920, 40641, 40645, 40625, 45864, { 40649, 0, 0, 0 }, 143, 143, { 1252, 500, 10000, 850, 0, ',' } }, { 0x0436, 0x0036, 257, 115, 45945, 45951, 45976, 40683, 40687, 40670, 45864, { 40691, 0, 0, 0 }, 144, 144, { 1252, 500, 10000, 850, 0, ',' } }, { 0x0437, 0x0037, 257, 37, 46000, 46006, 46025, 40745, 40749, 40711, 46080, { 40753, 0, 0, 0 }, 145, 145, { 0, 500, 2, 1, 0, ';' } }, { 0x0438, 0x0038, 257, 34, 46083, 46089, 46113, 40839, 40843, 40818, 46134, { 0, 0, 0, 0 }, 146, 146, { 1252, 20277, 10079, 850, 0, ';' } }, { 0x0439, 0x0039, 257, 48, 46137, 46143, 46157, 40872, 40876, 40847, 46188, { 40880, 0, 0, 0 }, 147, 147, { 0, 500, 2, 1, 0, ',' } }, { 0x043A, 0x003A, 257, 73, 46191, 46197, 46213, 40950, 40954, 40933, 46227, { 40958, 0, 0, 0 }, 148, 148, { 0, 500, 2, 1, 0, ',' } }, { 0x043B, 0x003B, 257, 78, 46230, 46236, 46259, 41013, 41017, 40979, 44433, { 41021, 0, 0, 0 }, 149, 149, { 1252, 20277, 10000, 850, 0, ';' } }, { 0x0441, 0x0041, 257, 56, 46284, 46290, 46306, 41308, 41312, 41287, 46324, { 41316, 0, 0, 0 }, 150, 150, { 1252, 500, 10000, 437, 0, ',' } }, { 0x0443, 0x7C43, 257, 111, 46327, 46338, 46364, 41357, 41361, 41337, 46390, { 41365, 0, 0, 0 }, 151, 151, { 1254, 500, 10029, 857, 0, ';' } }, { 0x0445, 0x0045, 257, 48, 46393, 46399, 46415, 41412, 41416, 41385, 46188, { 41420, 0, 0, 0 }, 152, 152, { 0, 500, 2, 1, 0, ',' } }, { 0x0447, 0x0047, 257, 48, 46446, 46452, 46469, 41604, 41608, 41570, 46188, { 41612, 0, 0, 0 }, 153, 153, { 0, 500, 2, 1, 0, ',' } }, { 0x0448, 0x0048, 257, 48, 46506, 46512, 46526, 41693, 41697, 41668, 46188, { 0, 0, 0, 0 }, 154, 154, { 0, 500, 2, 1, 0, ',' } }, { 0x0449, 0x0049, 257, 48, 46557, 46563, 46577, 41726, 41730, 41701, 46188, { 41734, 0, 0, 0 }, 155, 155, { 0, 500, 2, 1, 0, ',' } }, { 0x044A, 0x004A, 257, 48, 46617, 46623, 46638, 41828, 41832, 41799, 46188, { 41836, 0, 0, 0 }, 156, 156, { 0, 500, 2, 1, 0, ',' } }, { 0x044B, 0x004B, 257, 48, 46685, 46691, 46707, 41925, 41929, 37319, 46188, { 41933, 0, 0, 0 }, 157, 157, { 0, 500, 2, 1, 0, ',' } }, { 0x044C, 0x004C, 257, 48, 46738, 46744, 46762, 42030, 42034, 41998, 46188, { 42038, 0, 0, 0 }, 158, 158, { 0, 500, 2, 1, 0, ',' } }, { 0x044D, 0x004D, 257, 48, 46802, 46808, 46825, 42116, 42120, 42082, 46188, { 42124, 0, 0, 0 }, 159, 159, { 0, 500, 2, 1, 0, ',' } }, { 0x044E, 0x004E, 257, 48, 46862, 46868, 46884, 42204, 2402, 42177, 46188, { 42208, 0, 0, 0 }, 160, 160, { 0, 500, 2, 1, 0, ',' } }, { 0x0451, 0x0051, 257, 20, 46915, 46921, 46937, 42372, 42376, 42336, 13711, { 0, 0, 0, 0 }, 161, 161, { 0, 500, 2, 1, 0, ',' } }, { 0x0452, 0x0052, 257, 36, 46983, 46989, 47012, 42397, 42401, 42380, 47039, { 42405, 0, 0, 0 }, 162, 162, { 1252, 20285, 10000, 850, 0, ',' } }, { 0x0453, 0x0053, 257, 57, 47042, 47048, 47065, 42446, 42450, 42421, 47105, { 42454, 0, 0, 0 }, 163, 163, { 0, 500, 2, 1, 0, ',' } }, { 0x0454, 0x0054, 257, 60, 47108, 47114, 47125, 42526, 42530, 42509, 47147, { 42534, 0, 0, 0 }, 164, 164, { 0, 500, 2, 1, 0, ',' } }, { 0x0456, 0x0056, 257, 31, 47150, 47156, 47173, 42599, 42603, 42580, 43646, { 38945, 0, 0, 0 }, 165, 165, { 1252, 500, 10000, 850, 0, ';' } }, { 0x0457, 0x0057, 257, 48, 47190, 47197, 47213, 42638, 42607, 42607, 46188, { 0, 0, 0, 0 }, 166, 166, { 0, 500, 2, 1, 0, ',' } }, { 0x045B, 0x005B, 257, 63, 47247, 47253, 47273, 42669, 42673, 42642, 47323, { 42677, 0, 0, 0 }, 167, 167, { 0, 500, 2, 1, 0, ',' } }, { 0x045E, 0x005E, 257, 32, 47326, 47332, 47351, 42757, 42761, 8022, 47382, { 42765, 0, 0, 0 }, 168, 168, { 0, 500, 2, 1, 0, ';' } }, { 0x0461, 0x0061, 257, 79, 47385, 47391, 47406, 42878, 42882, 1883, 47443, { 42886, 0, 0, 0 }, 169, 169, { 0, 500, 2, 1, 0, ',' } }, { 0x0463, 0x0063, 1024, 1, 47446, 47452, 47473, 42955, 42959, 42936, 47503, { 0, 0, 0, 0 }, 170, 170, { 0, 500, 2, 1, 1, ';' } }, { 0x0464, 0x0064, 257, 84, 47506, 47513, 47536, 42976, 42963, 42963, 47557, { 42980, 0, 0, 0 }, 171, 171, { 1252, 500, 10000, 437, 0, ',' } }, { 0x0468, 0x7C68, 257, 75, 47560, 47571, 47594, 43012, 43016, 43003, 47611, { 0, 0, 0, 0 }, 172, 172, { 1252, 37, 10000, 437, 0, ',' } }, { 0x046A, 0x006A, 257, 75, 47614, 47620, 47637, 43045, 43049, 43020, 47611, { 0, 0, 0, 0 }, 173, 173, { 1252, 37, 10000, 437, 0, ',' } }, { 0x046C, 0x006C, 257, 115, 47683, 47690, 43072, 43089, 43053, 43053, 45864, { 0, 0, 0, 0 }, 174, 174, { 1252, 500, 10000, 850, 0, ',' } }, { 0x046F, 0x006F, 257, 38, 47720, 47726, 47750, 43120, 43124, 43093, 47781, { 43128, 0, 0, 0 }, 175, 175, { 1252, 20277, 10000, 850, 0, ';' } }, { 0x0470, 0x0070, 257, 75, 47784, 47790, 47790, 43163, 43167, 43155, 47611, { 0, 0, 0, 0 }, 176, 176, { 1252, 37, 10000, 437, 0, ',' } }, { 0x0478, 0x0078, 257, 20, 47805, 47811, 47830, 43195, 43199, 43171, 13711, { 43203, 0, 0, 0 }, 177, 177, { 0, 500, 2, 1, 0, ',' } }, { 0x047E, 0x007E, 257, 35, 47849, 47855, 47871, 43236, 43240, 43216, 44030, { 43244, 0, 0, 0 }, 178, 178, { 1252, 20297, 10000, 850, 0, ';' } }, { 0x0485, 0x0085, 257, 93, 47890, 47897, 43339, 43357, 43329, 43329, 44674, { 0, 0, 0, 0 }, 179, 179, { 1251, 20880, 10007, 866, 0, ';' } }, { 0x0487, 0x0087, 257, 94, 47912, 47918, 47918, 43376, 43380, 43361, 47939, { 0, 0, 0, 0 }, 180, 180, { 1252, 37, 10000, 437, 0, ';' } }, { 0x0491, 0x0091, 257, 36, 47942, 47948, 47981, 43413, 43417, 43384, 47039, { 43421, 0, 0, 0 }, 181, 181, { 1252, 20285, 10000, 850, 0, ',' } }, { 0x0801, 0x0001, 257, 49, 48017, 48023, 48037, 48067, 38097, 38068, 48071, { 48074, 0, 0, 0 }, 182, 182, { 1256, 20420, 10004, 720, 1, ';' } }, { 0x0804, 0x0004, 257, 20, 48106, 38326, 48112, 38300, 38304, 38308, 13711, { 38311, 0, 0, 0 }, 183, 183, { 936, 500, 10008, 936, 0, ',' } }, { 0x0807, 0x0007, 257, 18, 48128, 48134, 48155, 48173, 38467, 38445, 13632, { 38471, 0, 0, 0 }, 184, 184, { 1252, 20273, 10000, 850, 0, ';' } }, { 0x0809, 0x0009, 257, 36, 48177, 48183, 48183, 48208, 38587, 38572, 47039, { 38591, 0, 0, 0 }, 185, 185, { 1252, 20285, 10000, 850, 0, ',' } }, { 0x080A, 0x000A, 257, 74, 48212, 48218, 48235, 48254, 38634, 38610, 48258, { 38945, 0, 0, 0 }, 186, 186, { 1252, 20284, 10000, 850, 0, ',' } }, { 0x080C, 0x000C, 257, 10, 48261, 48267, 48284, 48305, 38734, 38710, 48309, { 38738, 0, 0, 0 }, 187, 187, { 1252, 20297, 10000, 850, 0, ';' } }, { 0x0810, 0x0010, 257, 18, 48312, 48318, 48340, 48360, 38941, 38917, 13632, { 38945, 0, 0, 0 }, 188, 188, { 1252, 500, 10000, 850, 0, ';' } }, { 0x0813, 0x0013, 257, 10, 48364, 48370, 48386, 48407, 39086, 39062, 48309, { 39090, 0, 0, 0 }, 189, 189, { 1252, 500, 10000, 850, 0, ';' } }, { 0x0814, 0x7814, 257, 78, 48411, 48417, 48444, 48460, 48464, 48468, 44433, { 38424, 0, 0, 0 }, 190, 190, { 1252, 20277, 10000, 850, 0, ';' } }, { 0x0816, 0x0016, 257, 88, 48471, 48477, 48499, 48521, 39220, 39191, 48525, { 39224, 0, 0, 0 }, 191, 191, { 1252, 500, 10000, 850, 0, ';' } }, { 0x081D, 0x001D, 257, 33, 48528, 48534, 48552, 48570, 39596, 39573, 43986, { 38424, 0, 0, 0 }, 192, 192, { 1252, 20278, 10000, 850, 0, ';' } }, { 0x082C, 0x742C, 257, 7, 48574, 48585, 45691, 48620, 40416, 40385, 45717, { 40420, 0, 0, 0 }, 193, 193, { 1251, 20880, 10007, 866, 0, ';' } }, { 0x083C, 0x003C, 257, 46, 48624, 48630, 48646, 41057, 41061, 41040, 48662, { 41065, 0, 0, 0 }, 194, 194, { 1252, 500, 10000, 850, 0, ',' } }, { 0x0843, 0x7843, 257, 111, 48665, 48676, 46364, 41357, 41361, 41337, 46390, { 48705, 0, 0, 0 }, 195, 195, { 1251, 20880, 10007, 866, 0, ';' } }, { 0x0845, 0x0045, 257, 9, 48743, 48749, 48770, 48813, 41416, 41385, 48817, { 41420, 0, 0, 0 }, 196, 196, { 0, 500, 2, 1, 0, ',' } }, { 0x0C01, 0x0001, 257, 30, 48820, 48826, 48841, 48865, 38097, 38068, 48869, { 48074, 0, 0, 0 }, 197, 197, { 1256, 20420, 10004, 720, 1, ';' } }, { 0x0C04, 0x7C04, 257, 41, 48872, 48878, 48921, 48958, 38304, 38308, 48962, { 43700, 0, 0, 0 }, 198, 198, { 950, 500, 10002, 950, 0, ',' } }, { 0x0C07, 0x0007, 257, 5, 48965, 48971, 48988, 49010, 38467, 38445, 49014, { 38471, 0, 0, 0 }, 199, 199, { 1252, 20273, 10000, 850, 0, ';' } }, { 0x0C09, 0x0009, 257, 6, 49017, 49023, 49023, 49043, 38587, 38572, 49047, { 38591, 0, 0, 0 }, 200, 200, { 1252, 500, 10000, 850, 0, ',' } }, { 0x0C0A, 0x000A, 257, 31, 49050, 49056, 49072, 49091, 38634, 38610, 43646, { 38638, 0, 0, 0 }, 201, 201, { 1252, 20284, 10000, 850, 0, ';' } }, { 0x0C0C, 0x000C, 257, 17, 49095, 49101, 49117, 49136, 38734, 38710, 49140, { 49143, 0, 0, 0 }, 202, 202, { 1252, 20297, 10000, 850, 0, ';' } }, { 0x0C3B, 0x003B, 257, 33, 49165, 49171, 49195, 49221, 49225, 40979, 43986, { 41021, 0, 0, 0 }, 203, 203, { 1252, 20278, 10000, 850, 0, ';' } }, { 0x1001, 0x0001, 257, 67, 49229, 49235, 49250, 49278, 38097, 38068, 49282, { 48074, 0, 0, 0 }, 204, 204, { 1256, 20420, 10004, 720, 1, ';' } }, { 0x1004, 0x0004, 257, 97, 49285, 49291, 49323, 49342, 38304, 38308, 49346, { 38311, 0, 0, 0 }, 205, 205, { 936, 500, 10008, 936, 0, ',' } }, { 0x1007, 0x0007, 257, 65, 49349, 49355, 49375, 49395, 38467, 38445, 49399, { 38471, 0, 0, 0 }, 206, 206, { 1252, 20273, 10000, 850, 0, ';' } }, { 0x1009, 0x0009, 257, 17, 49402, 49408, 49408, 49425, 38587, 38572, 49140, { 38591, 0, 0, 0 }, 207, 207, { 1252, 37, 10000, 850, 0, ',' } }, { 0x100A, 0x000A, 257, 40, 49429, 49435, 49455, 49476, 38634, 38610, 49480, { 38638, 0, 0, 0 }, 208, 208, { 1252, 20284, 10000, 850, 0, ',' } }, { 0x100C, 0x000C, 257, 18, 49483, 49489, 49510, 49529, 38734, 38710, 13632, { 38738, 0, 0, 0 }, 209, 209, { 1252, 20297, 10000, 850, 0, ';' } }, { 0x101A, 0x001A, 257, 8, 49533, 49539, 49573, 49604, 49608, 39424, 49612, { 39453, 0, 0, 0 }, 210, 210, { 1250, 870, 10082, 852, 0, ';' } }, { 0x1401, 0x0001, 257, 27, 49615, 49621, 49638, 49670, 38097, 38068, 49674, { 48074, 0, 0, 0 }, 211, 211, { 1256, 20420, 10004, 720, 1, ';' } }, { 0x1404, 0x7C04, 257, 72, 49677, 49683, 49722, 49759, 38304, 38308, 49763, { 43700, 0, 0, 0 }, 212, 212, { 950, 500, 10002, 950, 0, ',' } }, { 0x1407, 0x0007, 257, 62, 49766, 49772, 49795, 49819, 38467, 38445, 49823, { 38471, 0, 0, 0 }, 213, 213, { 1252, 20273, 10000, 850, 0, ';' } }, { 0x1409, 0x0009, 257, 80, 49826, 49832, 49832, 49854, 38587, 38572, 49858, { 38591, 0, 0, 0 }, 214, 214, { 1252, 500, 10000, 850, 0, ',' } }, { 0x140A, 0x000A, 257, 22, 49861, 49867, 49888, 49910, 38634, 38610, 49914, { 38638, 0, 0, 0 }, 215, 215, { 1252, 20284, 10000, 850, 0, ',' } }, { 0x140C, 0x000C, 257, 65, 49917, 49923, 49943, 49966, 38734, 38710, 49399, { 38738, 0, 0, 0 }, 216, 216, { 1252, 20297, 10000, 850, 0, ';' } }, { 0x141A, 0x681A, 257, 8, 49970, 49981, 50021, 50052, 50056, 50060, 49612, { 50063, 0, 0, 0 }, 217, 217, { 1250, 870, 10082, 852, 0, ';' } }, { 0x1801, 0x0001, 257, 68, 50086, 50092, 50109, 50139, 38097, 38068, 50143, { 48074, 0, 0, 0 }, 218, 218, { 1256, 20420, 10004, 720, 1, ';' } }, { 0x1809, 0x0009, 257, 46, 50146, 50152, 50152, 50170, 38587, 38572, 48662, { 38591, 0, 0, 0 }, 219, 219, { 1252, 500, 10000, 850, 0, ',' } }, { 0x180A, 0x000A, 257, 82, 50174, 50180, 50197, 50216, 38634, 38610, 50220, { 38638, 0, 0, 0 }, 220, 220, { 1252, 20284, 10000, 850, 0, ',' } }, { 0x180C, 0x000C, 257, 69, 50223, 50229, 50245, 50264, 38734, 38710, 50268, { 38738, 0, 0, 0 }, 221, 221, { 1252, 20297, 10000, 850, 0, ';' } }, { 0x181A, 0x701A, 257, 8, 50271, 50282, 50322, 50374, 50378, 50382, 49612, { 50063, 0, 0, 0 }, 222, 222, { 1250, 870, 10082, 852, 0, ';' } }, { 0x1C01, 0x0001, 257, 104, 50385, 50391, 50408, 50434, 38097, 38068, 50438, { 48074, 0, 0, 0 }, 223, 223, { 1256, 20420, 10004, 720, 1, ';' } }, { 0x1C09, 0x0009, 257, 115, 50441, 50447, 50447, 50470, 38587, 38572, 45864, { 38591, 0, 0, 0 }, 224, 224, { 1252, 500, 10000, 437, 0, ',' } }, { 0x1C0A, 0x000A, 257, 26, 50474, 50480, 50509, 50542, 38634, 38610, 50546, { 38638, 0, 0, 0 }, 225, 225, { 1252, 20284, 10000, 850, 0, ',' } }, { 0x1C1A, 0x6C1A, 257, 8, 50549, 50560, 50322, 50603, 50607, 50382, 49612, { 40528, 0, 0, 0 }, 226, 226, { 1251, 21025, 10007, 855, 0, ';' } }, { 0x2001, 0x0001, 257, 81, 50611, 50617, 50631, 50659, 38097, 38068, 50663, { 48074, 0, 0, 0 }, 227, 227, { 1256, 20420, 10004, 720, 1, ';' } }, { 0x2009, 0x0009, 257, 53, 50666, 50672, 50672, 50690, 38587, 38572, 50694, { 38591, 0, 0, 0 }, 228, 228, { 1252, 500, 10000, 850, 0, ',' } }, { 0x200A, 0x000A, 257, 112, 50697, 50703, 50723, 50744, 38634, 38610, 50748, { 38638, 0, 0, 0 }, 229, 229, { 1252, 20284, 10000, 850, 0, ',' } }, { 0x201A, 0x641A, 257, 8, 50751, 50762, 50021, 50805, 50809, 50060, 49612, { 40528, 0, 0, 0 }, 230, 230, { 1251, 870, 10082, 855, 0, ';' } }, { 0x2401, 0x0001, 257, 114, 50813, 50819, 50834, 50862, 38097, 38068, 50866, { 48074, 0, 0, 0 }, 231, 231, { 1256, 20420, 10004, 720, 1, ';' } }, { 0x240A, 0x000A, 257, 21, 50869, 50875, 50894, 50914, 38634, 38610, 50918, { 38638, 0, 0, 0 }, 232, 232, { 1252, 20284, 10000, 850, 0, ',' } }, { 0x241A, 0x701A, 257, 92, 50921, 50932, 50956, 50984, 2130, 50382, 50988, { 50063, 0, 0, 0 }, 233, 233, { 1250, 500, 10029, 852, 0, ';' } }, { 0x2801, 0x0001, 257, 101, 50991, 50997, 51012, 51040, 38097, 38068, 51044, { 48074, 0, 0, 0 }, 234, 234, { 1256, 20420, 10004, 720, 1, ';' } }, { 0x2809, 0x0009, 257, 16, 51047, 51053, 51053, 51070, 38587, 38572, 51074, { 38591, 0, 0, 0 }, 235, 235, { 1252, 500, 10000, 850, 0, ';' } }, { 0x280A, 0x000A, 257, 83, 51077, 51083, 51098, 51115, 38634, 38610, 51119, { 38638, 0, 0, 0 }, 236, 236, { 1252, 20284, 10000, 850, 0, ',' } }, { 0x281A, 0x6C1A, 257, 92, 51122, 51133, 50956, 51160, 2130, 50382, 50988, { 40528, 0, 0, 0 }, 237, 237, { 1251, 21025, 10007, 855, 0, ';' } }, { 0x2C01, 0x0001, 257, 54, 51164, 51170, 51186, 51216, 38097, 38068, 51220, { 48074, 0, 0, 0 }, 238, 238, { 1256, 20420, 10004, 720, 1, ';' } }, { 0x2C09, 0x0009, 257, 106, 51223, 51229, 51229, 51259, 38587, 38572, 51263, { 38591, 0, 0, 0 }, 239, 239, { 1252, 500, 10000, 850, 0, ';' } }, { 0x2C0A, 0x000A, 257, 4, 51266, 51272, 51292, 51313, 38634, 38610, 51317, { 38638, 0, 0, 0 }, 240, 240, { 1252, 20284, 10000, 850, 0, ',' } }, { 0x2C1A, 0x701A, 257, 70, 51320, 51331, 51359, 51392, 2130, 50382, 51396, { 50063, 0, 0, 0 }, 241, 241, { 1250, 500, 10029, 852, 0, ';' } }, { 0x3001, 0x0001, 257, 61, 51399, 51405, 51422, 51450, 38097, 38068, 51454, { 48074, 0, 0, 0 }, 242, 242, { 1256, 20420, 10004, 720, 1, ';' } }, { 0x3009, 0x0009, 257, 116, 51457, 51463, 51463, 51482, 38587, 38572, 51486, { 38591, 0, 0, 0 }, 243, 243, { 1252, 500, 10000, 437, 0, ',' } }, { 0x300A, 0x000A, 257, 28, 51489, 51495, 51513, 51532, 38634, 38610, 51536, { 38638, 0, 0, 0 }, 244, 244, { 1252, 20284, 10000, 850, 0, ',' } }, { 0x301A, 0x6C1A, 257, 70, 51539, 51550, 51359, 51581, 2130, 50382, 51396, { 40528, 0, 0, 0 }, 245, 245, { 1251, 21025, 10007, 855, 0, ';' } }, { 0x3401, 0x0001, 257, 59, 51585, 51591, 51607, 51637, 38097, 38068, 51641, { 48074, 0, 0, 0 }, 246, 246, { 1256, 20420, 10004, 720, 1, ';' } }, { 0x3409, 0x0009, 257, 84, 51644, 51650, 51650, 51672, 38587, 38572, 47557, { 38591, 0, 0, 0 }, 247, 247, { 1252, 500, 10000, 437, 0, ',' } }, { 0x340A, 0x000A, 257, 19, 51676, 51682, 51698, 51715, 38634, 38610, 51719, { 38638, 0, 0, 0 }, 248, 248, { 1252, 20284, 10000, 850, 0, ',' } }, { 0x3801, 0x0001, 257, 0, 51722, 51728, 51758, 51822, 38097, 38068, 51826, { 48074, 0, 0, 0 }, 249, 249, { 1256, 20420, 10004, 720, 1, ';' } }, { 0x380A, 0x000A, 257, 110, 51829, 51835, 51853, 51872, 38634, 38610, 51876, { 38638, 0, 0, 0 }, 250, 250, { 1252, 20284, 10000, 850, 0, ',' } }, { 0x3C01, 0x0001, 257, 12, 51879, 51885, 51902, 51934, 38097, 38068, 51938, { 48074, 0, 0, 0 }, 251, 251, { 1256, 20420, 10004, 720, 1, ';' } }, { 0x3C0A, 0x000A, 257, 89, 51941, 51947, 51966, 51986, 38634, 38610, 51990, { 38638, 0, 0, 0 }, 252, 252, { 1252, 20284, 10000, 850, 0, ',' } }, { 0x4001, 0x0001, 257, 90, 51993, 51999, 52014, 52038, 38097, 38068, 52042, { 48074, 0, 0, 0 }, 253, 253, { 1256, 20420, 10004, 720, 1, ';' } }, { 0x4009, 0x0009, 257, 48, 52045, 52051, 52051, 52067, 38587, 38572, 46188, { 38591, 0, 0, 0 }, 254, 254, { 1252, 37, 10000, 437, 0, ',' } }, { 0x400A, 0x000A, 257, 13, 52071, 52077, 52095, 52114, 38634, 38610, 52118, { 38638, 0, 0, 0 }, 255, 255, { 1252, 20284, 10000, 850, 0, ',' } }, { 0x440A, 0x000A, 257, 100, 52121, 52127, 52149, 52172, 38634, 38610, 52176, { 38638, 0, 0, 0 }, 256, 256, { 1252, 20284, 10000, 850, 0, ',' } }, { 0x4809, 0x0009, 257, 97, 52179, 52185, 52185, 52205, 38587, 38572, 49346, { 38591, 0, 0, 0 }, 257, 257, { 1252, 37, 10000, 437, 0, ',' } }, { 0x480A, 0x000A, 257, 42, 52209, 52215, 52234, 52254, 38634, 38610, 52258, { 38638, 0, 0, 0 }, 258, 258, { 1252, 20284, 10000, 850, 0, ',' } }, { 0x4C0A, 0x000A, 257, 76, 52261, 52267, 52287, 52308, 38634, 38610, 52312, { 38638, 0, 0, 0 }, 259, 259, { 1252, 20284, 10000, 850, 0, ',' } }, { 0x500A, 0x000A, 257, 87, 52315, 52321, 52343, 52366, 38634, 38610, 52370, { 38638, 0, 0, 0 }, 260, 260, { 1252, 20284, 10000, 850, 0, ',' } }, { 0x540A, 0x000A, 257, 109, 52373, 52379, 52403, 52429, 38634, 38610, 43945, { 38638, 0, 0, 0 }, 261, 261, { 1252, 20284, 10000, 850, 0, ',' } }, { 0x641A, 0x781A, 257, -1, 52433, 52441, 52460, 50805, 50809, 50060, 0, { 40528, 0, 0, 0 }, 262, 262, { 1251, 870, 10082, 855, 0, ';' } }, { 0x681A, 0x781A, 257, -1, 52469, 52477, 52460, 50052, 50056, 50060, 0, { 50063, 0, 0, 0 }, 263, 263, { 1250, 870, 10082, 852, 0, ';' } }, { 0x6C1A, 0x7C1A, 257, -1, 52493, 52501, 52520, 51160, 2130, 50382, 0, { 40528, 0, 0, 0 }, 264, 264, { 1251, 21025, 10007, 855, 0, ';' } }, { 0x701A, 0x7C1A, 257, -1, 52533, 52541, 52520, 50984, 2130, 50382, 0, { 50063, 0, 0, 0 }, 265, 265, { 1250, 500, 10029, 852, 0, ';' } }, { 0x742C, 0x002C, 257, -1, 52557, 52565, 40400, 48620, 40416, 40385, 0, { 40420, 0, 0, 0 }, 266, 266, { 1251, 20880, 10007, 866, 0, ';' } }, { 0x7804, 0x007F, 257, -1, 38308, 38326, 38293, 38300, 38304, 38308, 0, { 38311, 0, 0, 0 }, 267, 267, { 936, 500, 10008, 936, 0, ',' } }, { 0x7814, 0x0014, 257, -1, 48468, 52588, 52606, 48460, 48464, 48468, 0, { 38424, 0, 0, 0 }, 268, 268, { 1252, 20277, 10000, 850, 0, ';' } }, { 0x781A, 0x007F, 257, -1, 50060, 52614, 52460, 50052, 50056, 50060, 0, { 50063, 0, 0, 0 }, 269, 269, { 1250, 870, 10082, 852, 0, ';' } }, { 0x782C, 0x002C, 257, -1, 52622, 52630, 40400, 40412, 40416, 40385, 0, { 40420, 0, 0, 0 }, 270, 270, { 1254, 20905, 10081, 857, 0, ';' } }, { 0x7843, 0x0043, 257, -1, 52650, 52658, 41346, 41357, 41361, 41337, 0, { 48705, 0, 0, 0 }, 271, 271, { 1251, 20880, 10007, 866, 0, ';' } }, { 0x7850, 0x0050, 257, -1, 52675, 52683, 42283, 52704, 42300, 42270, 0, { 42304, 0, 0, 0 }, 272, 272, { 1251, 20880, 10007, 866, 0, ';' } }, { 0x7C04, 0x7804, 257, -1, 52708, 43655, 38293, 43693, 38304, 38308, 0, { 43700, 0, 0, 0 }, 273, 273, { 950, 500, 10002, 950, 0, ',' } }, { 0x7C04, 0x7C04, 257, -1, 52716, 52723, 38293, 43693, 38304, 38308, 0, { 43700, 0, 0, 0 }, 274, 274, { 950, 500, 10002, 950, 0, ',' } }, { 0x7C14, 0x0014, 257, -1, 39139, 52752, 52770, 39131, 39135, 39139, 0, { 38424, 0, 0, 0 }, 275, 275, { 1252, 20277, 10000, 850, 0, ';' } }, { 0x7C1A, 0x007F, 257, -1, 50382, 52784, 52520, 52792, 2130, 50382, 0, { 40528, 0, 0, 0 }, 276, 276, { 1250, 500, 10029, 852, 0, ';' } }, { 0x7C28, 0x0028, 257, -1, 52796, 52804, 40197, 40210, 40214, 40188, 0, { 0, 0, 0, 0 }, 277, 277, { 1251, 20880, 10007, 866, 0, ';' } }, { 0x7C43, 0x0043, 257, -1, 52821, 52829, 41346, 41357, 41361, 41337, 0, { 41365, 0, 0, 0 }, 278, 278, { 1254, 500, 10029, 857, 0, ';' } }, { 0x7C5F, 0x005F, 257, -1, 52843, 52852, 42838, 42848, 42810, 42810, 0, { 0, 0, 0, 0 }, 279, 279, { 1252, 20297, 10000, 850, 0, ';' } }, { 0x7C68, 0x0068, 257, -1, 52884, 52892, 43006, 43012, 43016, 43003, 0, { 0, 0, 0, 0 }, 280, 280, { 1252, 37, 10000, 437, 0, ',' } } }; static const CultureInfoNameEntry culture_name_entries[] = { { 40670, 50 }, /* af */ { 52906, 144 }, /* af-za */ { 8022, 80 }, /* am */ { 52912, 168 }, /* am-et */ { 38068, 0 }, /* ar */ { 52918, 249 }, /* ar-ae */ { 52924, 251 }, /* ar-bh */ { 52930, 211 }, /* ar-dz */ { 52936, 197 }, /* ar-eg */ { 52942, 182 }, /* ar-iq */ { 52948, 238 }, /* ar-jo */ { 52954, 246 }, /* ar-kw */ { 52960, 242 }, /* ar-lb */ { 52966, 204 }, /* ar-ly */ { 52972, 218 }, /* ar-ma */ { 52978, 227 }, /* ar-om */ { 52984, 253 }, /* ar-qa */ { 52990, 96 }, /* ar-sa */ { 52996, 234 }, /* ar-sy */ { 53002, 223 }, /* ar-tn */ { 53008, 231 }, /* ar-ye */ { 42082, 70 }, /* as */ { 53014, 159 }, /* as-in */ { 40385, 44 }, /* az */ { 53020, 266 }, /* az-cyrl */ { 53028, 193 }, /* az-cyrl-az */ { 53039, 270 }, /* az-latn */ { 53047, 138 }, /* az-latn-az */ { 39897, 35 }, /* be */ { 53058, 129 }, /* be-by */ { 38129, 1 }, /* bg */ { 53064, 97 }, /* bg-bg */ { 41385, 62 }, /* bn */ { 53070, 196 }, /* bn-bd */ { 53076, 152 }, /* bn-in */ { 42336, 73 }, /* bo */ { 53082, 161 }, /* bo-cn */ { 43216, 91 }, /* br */ { 53088, 178 }, /* br-fr */ { 50060, 269 }, /* bs */ { 53094, 262 }, /* bs-cyrl */ { 53102, 230 }, /* bs-cyrl-ba */ { 53113, 263 }, /* bs-latn */ { 53121, 217 }, /* bs-latn-ba */ { 38211, 2 }, /* ca */ { 53132, 98 }, /* ca-es */ { 38347, 5 }, /* cs */ { 53138, 100 }, /* cs-cz */ { 42380, 74 }, /* cy */ { 53144, 162 }, /* cy-gb */ { 38400, 6 }, /* da */ { 53150, 101 }, /* da-dk */ { 38445, 7 }, /* de */ { 53156, 199 }, /* de-at */ { 53162, 184 }, /* de-ch */ { 53168, 102 }, /* de-de */ { 53174, 213 }, /* de-li */ { 53180, 206 }, /* de-lu */ { 38496, 8 }, /* el */ { 53186, 103 }, /* el-gr */ { 38572, 9 }, /* en */ { 53192, 200 }, /* en-au */ { 53198, 235 }, /* en-bz */ { 53204, 207 }, /* en-ca */ { 53210, 185 }, /* en-gb */ { 53216, 219 }, /* en-ie */ { 53222, 254 }, /* en-in */ { 53228, 228 }, /* en-jm */ { 53234, 214 }, /* en-nz */ { 53240, 247 }, /* en-ph */ { 53246, 257 }, /* en-sg */ { 53252, 239 }, /* en-tt */ { 53258, 104 }, /* en-us */ { 53264, 224 }, /* en-za */ { 53270, 243 }, /* en-zw */ { 38610, 10 }, /* es */ { 53276, 240 }, /* es-ar */ { 53282, 255 }, /* es-bo */ { 53288, 248 }, /* es-cl */ { 53294, 232 }, /* es-co */ { 53300, 215 }, /* es-cr */ { 53306, 225 }, /* es-do */ { 53312, 244 }, /* es-ec */ { 53318, 201 }, /* es-es */ { 53324, 208 }, /* es-gt */ { 53330, 258 }, /* es-hn */ { 53336, 186 }, /* es-mx */ { 53342, 259 }, /* es-ni */ { 53348, 220 }, /* es-pa */ { 53354, 236 }, /* es-pe */ { 53360, 260 }, /* es-pr */ { 53366, 252 }, /* es-py */ { 53372, 256 }, /* es-sv */ { 53378, 261 }, /* es-us */ { 53384, 250 }, /* es-uy */ { 53390, 229 }, /* es-ve */ { 40039, 37 }, /* et */ { 53396, 131 }, /* et-ee */ { 40439, 45 }, /* eu */ { 53402, 139 }, /* eu-es */ { 40218, 41 }, /* fa */ { 53408, 135 }, /* fa-ir */ { 38660, 11 }, /* fi */ { 53414, 105 }, /* fi-fi */ { 42963, 84 }, /* fil */ { 53420, 171 }, /* fil-ph */ { 40818, 52 }, /* fo */ { 53427, 146 }, /* fo-fo */ { 38710, 12 }, /* fr */ { 53433, 187 }, /* fr-be */ { 53439, 202 }, /* fr-ca */ { 53445, 209 }, /* fr-ch */ { 53451, 106 }, /* fr-fr */ { 53457, 216 }, /* fr-lu */ { 53463, 221 }, /* fr-mc */ { 41040, 56 }, /* ga */ { 53469, 194 }, /* ga-ie */ { 43384, 95 }, /* gd */ { 53475, 181 }, /* gd-gb */ { 42580, 77 }, /* gl */ { 53481, 165 }, /* gl-es */ { 43264, 92 }, /* gsw */ { 41570, 64 }, /* gu */ { 53487, 153 }, /* gu-in */ { 43003, 85 }, /* ha */ { 53493, 280 }, /* ha-latn */ { 53501, 172 }, /* ha-latn-ng */ { 38760, 13 }, /* he */ { 53512, 107 }, /* he-il */ { 40847, 53 }, /* hi */ { 53518, 147 }, /* hi-in */ { 39424, 26 }, /* hr */ { 53524, 210 }, /* hr-ba */ { 53530, 120 }, /* hr-hr */ { 38822, 14 }, /* hu */ { 53536, 108 }, /* hu-hu */ { 40320, 43 }, /* hy */ { 53542, 137 }, /* hy-am */ { 39751, 33 }, /* id */ { 53548, 127 }, /* id-id */ { 43155, 89 }, /* ig */ { 53554, 176 }, /* ig-ng */ { 43171, 90 }, /* ii */ { 53560, 177 }, /* ii-cn */ { 38866, 15 }, /* is */ { 53566, 109 }, /* is-is */ { 38917, 16 }, /* it */ { 53572, 188 }, /* it-ch */ { 53578, 110 }, /* it-it */ { 38967, 17 }, /* ja */ { 53584, 111 }, /* ja-jp */ { 40711, 51 }, /* ka */ { 53590, 145 }, /* ka-ge */ { 41134, 58 }, /* kk */ { 43093, 88 }, /* kl */ { 53596, 175 }, /* kl-gl */ { 42421, 75 }, /* km */ { 53602, 163 }, /* km-kh */ { 37319, 68 }, /* kn */ { 53608, 157 }, /* kn-in */ { 39024, 18 }, /* ko */ { 53614, 112 }, /* ko-kr */ { 42607, 78 }, /* kok */ { 53620, 166 }, /* kok-in */ { 41214, 59 }, /* ky */ { 42509, 76 }, /* lo */ { 53627, 164 }, /* lo-la */ { 40133, 39 }, /* lt */ { 53633, 133 }, /* lt-lt */ { 40085, 38 }, /* lv */ { 53639, 132 }, /* lv-lv */ { 40485, 46 }, /* mk */ { 53645, 140 }, /* mk-mk */ { 41998, 69 }, /* ml */ { 53651, 158 }, /* ml-in */ { 42270, 72 }, /* mn */ { 53657, 272 }, /* mn-cyrl */ { 42177, 71 }, /* mr */ { 53665, 160 }, /* mr-in */ { 41086, 57 }, /* ms */ { 40933, 54 }, /* mt */ { 53671, 148 }, /* mt-mt */ { 39139, 275 }, /* nb */ { 53677, 114 }, /* nb-no */ { 1883, 82 }, /* ne */ { 53683, 169 }, /* ne-np */ { 39062, 19 }, /* nl */ { 53689, 189 }, /* nl-be */ { 53695, 113 }, /* nl-nl */ { 48468, 268 }, /* nn */ { 53701, 190 }, /* nn-no */ { 39112, 20 }, /* no */ { 43053, 87 }, /* nso */ { 53707, 174 }, /* nso-za */ { 41668, 65 }, /* or */ { 53714, 154 }, /* or-in */ { 41485, 63 }, /* pa */ { 39142, 21 }, /* pl */ { 53720, 115 }, /* pl-pl */ { 42936, 83 }, /* ps */ { 53726, 170 }, /* ps-af */ { 39191, 22 }, /* pt */ { 53732, 116 }, /* pt-br */ { 53738, 191 }, /* pt-pt */ { 39247, 23 }, /* rm */ { 53744, 117 }, /* rm-ch */ { 39296, 24 }, /* ro */ { 53750, 118 }, /* ro-ro */ { 39344, 25 }, /* ru */ { 53756, 119 }, /* ru-ru */ { 43361, 94 }, /* rw */ { 53762, 180 }, /* rw-rw */ { 43329, 93 }, /* sah */ { 53768, 179 }, /* sah-ru */ { 40979, 55 }, /* se */ { 53775, 203 }, /* se-fi */ { 53781, 149 }, /* se-no */ { 42642, 79 }, /* si */ { 53787, 167 }, /* si-lk */ { 12674, 27 }, /* sk */ { 53793, 121 }, /* sk-sk */ { 39982, 36 }, /* sl */ { 53799, 130 }, /* sl-si */ { 39527, 28 }, /* sq */ { 53805, 122 }, /* sq-al */ { 50382, 276 }, /* sr */ { 53811, 264 }, /* sr-cyrl */ { 53819, 226 }, /* sr-cyrl-ba */ { 53830, 245 }, /* sr-cyrl-me */ { 53841, 237 }, /* sr-cyrl-rs */ { 53852, 265 }, /* sr-latn */ { 53860, 222 }, /* sr-latn-ba */ { 53871, 241 }, /* sr-latn-me */ { 53882, 233 }, /* sr-latn-rs */ { 39573, 29 }, /* sv */ { 53893, 192 }, /* sv-fi */ { 53899, 123 }, /* sv-se */ { 41287, 60 }, /* sw */ { 53905, 150 }, /* sw-ke */ { 41701, 66 }, /* ta */ { 53911, 155 }, /* ta-in */ { 41799, 67 }, /* te */ { 53917, 156 }, /* te-in */ { 40188, 40 }, /* tg */ { 53923, 277 }, /* tg-cyrl */ { 53931, 134 }, /* tg-cyrl-tj */ { 39600, 30 }, /* th */ { 53942, 124 }, /* th-th */ { 40572, 47 }, /* tn */ { 53948, 141 }, /* tn-za */ { 12683, 31 }, /* tr */ { 53954, 125 }, /* tr-tr */ { 42810, 81 }, /* tzm */ { 53960, 279 }, /* tzm-latn */ { 39809, 34 }, /* uk */ { 53969, 128 }, /* uk-ua */ { 39696, 32 }, /* ur */ { 53975, 126 }, /* ur-pk */ { 41337, 61 }, /* uz */ { 53981, 271 }, /* uz-cyrl */ { 53989, 195 }, /* uz-cyrl-uz */ { 54000, 278 }, /* uz-latn */ { 54008, 151 }, /* uz-latn-uz */ { 40272, 42 }, /* vi */ { 54019, 136 }, /* vi-vn */ { 40599, 48 }, /* xh */ { 54025, 142 }, /* xh-za */ { 43020, 86 }, /* yo */ { 54031, 173 }, /* yo-ng */ { 38308, 267 }, /* zh */ { 54037, 3 }, /* zh-chs */ { 54044, 274 }, /* zh-cht */ { 54051, 183 }, /* zh-cn */ { 54057, 4 }, /* zh-hans */ { 54065, 273 }, /* zh-hant */ { 54073, 198 }, /* zh-hk */ { 54079, 212 }, /* zh-mo */ { 54085, 205 }, /* zh-sg */ { 54091, 99 }, /* zh-tw */ { 40625, 49 }, /* zu */ { 54097, 143 } /* zu-za */ }; static const RegionInfoEntry region_entries[] = { { 224, 51826, 48865, 48865, 54103, 54124, 38011, 54171, 54175, 54203 }, { 3, 47503, 54227, 54227, 54231, 54243, 37782, 54262, 54266, 54281 }, { 6, 44819, 54294, 54294, 54298, 54306, 37322, 54316, 54320, 54333 }, { 7, 1820, 50139, 50139, 54347, 54355, 37563, 54372, 54376, 54390 }, { 11, 51317, 49670, 49670, 54416, 54416, 37073, 51040, 54426, 54441 }, { 14, 49014, 54456, 54456, 54460, 54468, 36969, 54480, 54484, 54484 }, { 12, 49047, 54489, 54489, 54493, 54493, 37073, 54503, 54507, 54507 }, { 5, 45717, 40412, 40412, 54525, 54536, 37817, 54548, 54552, 54570 }, { 25, 49612, 54590, 54590, 54594, 54617, 37879, 54637, 54641, 54677 }, { 23, 48817, 54697, 54697, 54701, 54712, 37855, 54737, 54741, 54758 }, { 21, 48309, 39932, 39932, 54799, 54807, 36969, 54480, 54484, 54816 }, { 35, 43603, 38161, 38161, 54821, 54830, 36951, 54847, 54851, 54865 }, { 17, 51938, 54891, 54891, 54895, 54903, 38021, 54918, 54922, 54937 }, { 26, 52118, 54961, 54961, 54965, 54965, 38045, 42372, 54973, 54992 }, { 32, 44523, 55002, 55002, 55006, 55013, 37210, 55020, 55024, 55039 }, { 29, 45205, 55055, 55055, 55059, 55067, 37425, 55084, 55088, 55105 }, { 24, 51074, 55137, 55137, 55141, 55141, 37073, 55148, 55152, 55152 }, { 39, 49140, 55166, 55166, 55170, 55170, 37073, 55177, 55181, 55197 }, { 223, 13632, 55213, 55213, 55217, 55229, 37217, 37217, 55236, 55248 }, { 46, 51719, 55262, 55262, 55266, 55266, 37073, 55272, 55276, 55289 }, { 45, 13711, 55302, 55302, 55306, 55312, 36990, 55331, 55335, 55348 }, { 51, 50918, 55367, 55367, 55371, 55371, 37073, 55380, 55384, 55399 }, { 54, 49914, 55415, 55415, 55419, 55419, 37897, 55430, 55434, 55453 }, { 75, 43766, 55474, 55474, 55478, 55493, 36993, 55511, 55515, 55537 }, { 94, 43856, 38463, 38463, 55552, 55560, 36969, 54480, 54484, 54484 }, { 61, 43808, 55572, 55572, 55576, 55584, 37021, 55592, 55596, 55609 }, { 65, 50546, 55621, 55621, 55625, 55644, 37073, 55666, 55670, 55685 }, { 4, 49674, 55701, 55701, 55705, 55713, 37882, 55728, 55732, 55747 }, { 66, 51536, 55771, 55771, 55775, 55775, 37073, 55783, 55787, 55797 }, { 70, 45303, 52429, 52429, 55819, 55827, 36969, 54480, 54484, 54816 }, { 67, 48869, 55833, 55833, 55837, 55843, 37859, 55850, 55854, 55869 }, { 217, 43646, 38630, 38630, 55887, 55893, 36969, 54480, 54484, 54816 }, { 73, 47382, 55901, 55901, 55905, 55914, 37762, 55930, 55934, 55949 }, { 77, 43986, 38677, 38677, 55975, 55983, 36969, 54480, 54484, 54816 }, { 81, 46134, 55989, 55989, 55993, 56007, 37021, 55592, 55596, 56016 }, { 84, 44030, 38730, 38730, 56029, 56029, 36969, 54480, 54484, 54816 }, { 242, 47039, 56036, 56036, 56040, 56055, 37706, 56072, 56076, 56099 }, { 88, 46080, 56121, 56121, 56125, 56133, 0, 56164, 56168, 56182 }, { 93, 47781, 56217, 56217, 56221, 56231, 37021, 55592, 55596, 56248 }, { 98, 43912, 56268, 56268, 56272, 56279, 36969, 54480, 54484, 56292 }, { 99, 49480, 56301, 56301, 56305, 56305, 7920, 56315, 56319, 56338 }, { 104, 48962, 56359, 56359, 56363, 56383, 37073, 56411, 56415, 56432 }, { 106, 52258, 56439, 56439, 56443, 56443, 2308, 56452, 56456, 56473 }, { 108, 44722, 39445, 39445, 56492, 56500, 37319, 56509, 56513, 56527 }, { 109, 44131, 38842, 38842, 56541, 56549, 37128, 56563, 56567, 56584 }, { 111, 45068, 56598, 56598, 56602, 56602, 37401, 56612, 56616, 56634 }, { 68, 48662, 56651, 56651, 56655, 56663, 36969, 54480, 54484, 54484 }, { 117, 44079, 56669, 56669, 56673, 56680, 37119, 56691, 56695, 56714 }, { 113, 46188, 39782, 39782, 56721, 56727, 37642, 56740, 56744, 56757 }, { 121, 48071, 56792, 56792, 56796, 56801, 37828, 56814, 56818, 56830 }, { 116, 45528, 56852, 56852, 56856, 56861, 37517, 56872, 56876, 56889 }, { 110, 44180, 38889, 38889, 56909, 56917, 37021, 56925, 56929, 56946 }, { 118, 44223, 38937, 38937, 56962, 56968, 36969, 54480, 54484, 54484 }, { 124, 50694, 56975, 56975, 56979, 56979, 37073, 56987, 56991, 56991 }, { 126, 51220, 57007, 57007, 57011, 57018, 37981, 57031, 57035, 57051 }, { 122, 44268, 38989, 38989, 57073, 57079, 37141, 57086, 57090, 57103 }, { 129, 46324, 57113, 57113, 57117, 57117, 37666, 57123, 57127, 57143 }, { 40, 47105, 42446, 42446, 57161, 57170, 37709, 57192, 57196, 57211 }, { 134, 44323, 39044, 39044, 57243, 57255, 37145, 57268, 57272, 57289 }, { 136, 51641, 57306, 57306, 57310, 57317, 38001, 57330, 57334, 57348 }, { 138, 47147, 42526, 42526, 57370, 42516, 37713, 57375, 57379, 57391 }, { 139, 51454, 57411, 57411, 57415, 57423, 37991, 57434, 57438, 57453 }, { 145, 49823, 57475, 57475, 57479, 57479, 0, 37217, 55236, 57493 }, { 42, 47323, 57511, 57511, 57515, 57525, 37754, 57557, 57561, 57578 }, { 141, 45401, 57626, 57626, 57630, 57640, 37493, 57648, 57652, 57669 }, { 147, 49399, 57684, 57684, 57688, 57699, 36969, 54480, 54484, 54484 }, { 140, 45349, 57709, 57709, 57713, 57720, 36969, 54480, 54484, 57728 }, { 148, 49282, 57733, 57733, 57737, 57743, 37869, 57754, 57758, 57771 }, { 159, 50143, 42204, 42204, 57791, 57799, 37901, 57812, 57816, 57832 }, { 158, 50268, 57852, 57852, 57856, 57856, 36969, 54480, 54484, 54816 }, { 270, 51396, 57863, 57863, 57867, 57878, 36969, 54480, 54484, 57896 }, { 19618, 45833, 57901, 57901, 57905, 57915, 37588, 57901, 57936, 57953 }, { 151, 49763, 57985, 57985, 57989, 58005, 37892, 58033, 58037, 58053 }, { 163, 46227, 40950, 40950, 58063, 58063, 36969, 54480, 54484, 58069 }, { 166, 48258, 58074, 58074, 58078, 58085, 37073, 58093, 58097, 58110 }, { 175, 47611, 58124, 58124, 58128, 58136, 37789, 58145, 58149, 58164 }, { 182, 52312, 58170, 58170, 58174, 58174, 38048, 58184, 58188, 58208 }, { 176, 44375, 39082, 39082, 58231, 58243, 36969, 54480, 54484, 54484 }, { 177, 44433, 39131, 39131, 58253, 58260, 37021, 58266, 58270, 58286 }, { 178, 47443, 58300, 58300, 58304, 58310, 37769, 58326, 58330, 58345 }, { 183, 49858, 58386, 58386, 58390, 58390, 37073, 58402, 58406, 58406 }, { 164, 50663, 58425, 58425, 58429, 58434, 37930, 58445, 58449, 58460 }, { 192, 50220, 41515, 41515, 58480, 58487, 37911, 58495, 58499, 58517 }, { 187, 51119, 58534, 58534, 58538, 58543, 37969, 58549, 58553, 58572 }, { 201, 47557, 58590, 58590, 58594, 58606, 37785, 58616, 58620, 58620 }, { 190, 45007, 58636, 58636, 58640, 58649, 37343, 58664, 58668, 58684 }, { 191, 44474, 58712, 58712, 58716, 58723, 37168, 58730, 58734, 58747 }, { 202, 52370, 58761, 58761, 58765, 58765, 37073, 55783, 55787, 55797 }, { 193, 48525, 58777, 58777, 58781, 58781, 36969, 54480, 54484, 54484 }, { 185, 51990, 58790, 58790, 58794, 58794, 38031, 58803, 58807, 58826 }, { 197, 52042, 58845, 58845, 58849, 58855, 38035, 58862, 58866, 58878 }, { 200, 44618, 58896, 58896, 58900, 58908, 0, 58917, 58921, 58934 }, { 271, 50988, 52792, 52792, 58948, 58955, 37954, 58968, 58972, 58986 }, { 203, 44674, 39370, 39370, 58999, 59006, 37239, 59019, 59023, 59037 }, { 204, 47939, 59069, 59069, 59073, 59073, 37793, 59080, 59084, 0 }, { 205, 13629, 59098, 59098, 59102, 59115, 36893, 59162, 59166, 59178 }, { 221, 44863, 59198, 59198, 59202, 59209, 37021, 59217, 59221, 59235 }, { 215, 49346, 59248, 59248, 59252, 59262, 37073, 59272, 59276, 59293 }, { 212, 45261, 59306, 59306, 59310, 59319, 36969, 54480, 54484, 59329 }, { 143, 44773, 59334, 59334, 59338, 59347, 36969, 54480, 54484, 54484 }, { 72, 52176, 40009, 40009, 59357, 59357, 37073, 55783, 55787, 55797 }, { 222, 51044, 59369, 59369, 59373, 59379, 37959, 59390, 59394, 59407 }, { 227, 44910, 39618, 39618, 59427, 39608, 37335, 59436, 59440, 59450 }, { 228, 45480, 59469, 59469, 59473, 59484, 37810, 59505, 59509, 59528 }, { 234, 50438, 59541, 59541, 59545, 59553, 37915, 59562, 59566, 59581 }, { 235, 44956, 59602, 59602, 59606, 59613, 37339, 59622, 59626, 59639 }, { 225, 51263, 59653, 59653, 59657, 59657, 37073, 59677, 59681, 59681 }, { 237, 43697, 59708, 59708, 59712, 59719, 37796, 59726, 59730, 59748 }, { 241, 45135, 39843, 39843, 59758, 59766, 37404, 59781, 59785, 59803 }, { 244, 43945, 59837, 59837, 59841, 59841, 37073, 55783, 55787, 55787 }, { 246, 51876, 59855, 59855, 59859, 59859, 37073, 59867, 59871, 59886 }, { 247, 46390, 41357, 41357, 59900, 59911, 37822, 59924, 59928, 59943 }, { 249, 50748, 59962, 59962, 59966, 59966, 37940, 59976, 59980, 60000 }, { 251, 45586, 60020, 60020, 60024, 60032, 37559, 60043, 60047, 60063 }, { 261, 50866, 60082, 60082, 60086, 60092, 37944, 60103, 60107, 60119 }, { 209, 45864, 60137, 60137, 60141, 0, 10586, 60154, 60158, 0 }, { 264, 51486, 60177, 60177, 60181, 60181, 37073, 55783, 55787, 55787 } }; static const RegionInfoNameEntry region_name_entries[] = { { 51826, 0 }, /* AE */ { 47503, 1 }, /* AF */ { 44819, 2 }, /* AL */ { 1820, 3 }, /* AM */ { 51317, 4 }, /* AR */ { 49014, 5 }, /* AT */ { 49047, 6 }, /* AU */ { 45717, 7 }, /* AZ */ { 49612, 8 }, /* BA */ { 48817, 9 }, /* BD */ { 48309, 10 }, /* BE */ { 43603, 11 }, /* BG */ { 51938, 12 }, /* BH */ { 52118, 13 }, /* BO */ { 44523, 14 }, /* BR */ { 45205, 15 }, /* BY */ { 51074, 16 }, /* BZ */ { 49140, 17 }, /* CA */ { 13632, 18 }, /* CH */ { 51719, 19 }, /* CL */ { 13711, 20 }, /* CN */ { 50918, 21 }, /* CO */ { 49914, 22 }, /* CR */ { 43766, 23 }, /* CZ */ { 43856, 24 }, /* DE */ { 43808, 25 }, /* DK */ { 50546, 26 }, /* DO */ { 49674, 27 }, /* DZ */ { 51536, 28 }, /* EC */ { 45303, 29 }, /* EE */ { 48869, 30 }, /* EG */ { 43646, 31 }, /* ES */ { 47382, 32 }, /* ET */ { 43986, 33 }, /* FI */ { 46134, 34 }, /* FO */ { 44030, 35 }, /* FR */ { 47039, 36 }, /* GB */ { 46080, 37 }, /* GE */ { 47781, 38 }, /* GL */ { 43912, 39 }, /* GR */ { 49480, 40 }, /* GT */ { 48962, 41 }, /* HK */ { 52258, 42 }, /* HN */ { 44722, 43 }, /* HR */ { 44131, 44 }, /* HU */ { 45068, 45 }, /* ID */ { 48662, 46 }, /* IE */ { 44079, 47 }, /* IL */ { 46188, 48 }, /* IN */ { 48071, 49 }, /* IQ */ { 45528, 50 }, /* IR */ { 44180, 51 }, /* IS */ { 44223, 52 }, /* IT */ { 50694, 53 }, /* JM */ { 51220, 54 }, /* JO */ { 44268, 55 }, /* JP */ { 46324, 56 }, /* KE */ { 47105, 57 }, /* KH */ { 44323, 58 }, /* KR */ { 51641, 59 }, /* KW */ { 47147, 60 }, /* LA */ { 51454, 61 }, /* LB */ { 49823, 62 }, /* LI */ { 47323, 63 }, /* LK */ { 45401, 64 }, /* LT */ { 49399, 65 }, /* LU */ { 45349, 66 }, /* LV */ { 49282, 67 }, /* LY */ { 50143, 68 }, /* MA */ { 50268, 69 }, /* MC */ { 51396, 70 }, /* ME */ { 45833, 71 }, /* MK */ { 49763, 72 }, /* MO */ { 46227, 73 }, /* MT */ { 48258, 74 }, /* MX */ { 47611, 75 }, /* NG */ { 52312, 76 }, /* NI */ { 44375, 77 }, /* NL */ { 44433, 78 }, /* NO */ { 47443, 79 }, /* NP */ { 49858, 80 }, /* NZ */ { 50663, 81 }, /* OM */ { 50220, 82 }, /* PA */ { 51119, 83 }, /* PE */ { 47557, 84 }, /* PH */ { 45007, 85 }, /* PK */ { 44474, 86 }, /* PL */ { 52370, 87 }, /* PR */ { 48525, 88 }, /* PT */ { 51990, 89 }, /* PY */ { 52042, 90 }, /* QA */ { 44618, 91 }, /* RO */ { 50988, 92 }, /* RS */ { 44674, 93 }, /* RU */ { 47939, 94 }, /* RW */ { 13629, 95 }, /* SA */ { 44863, 96 }, /* SE */ { 49346, 97 }, /* SG */ { 45261, 98 }, /* SI */ { 44773, 99 }, /* SK */ { 52176, 100 }, /* SV */ { 51044, 101 }, /* SY */ { 44910, 102 }, /* TH */ { 45480, 103 }, /* TJ */ { 50438, 104 }, /* TN */ { 44956, 105 }, /* TR */ { 51263, 106 }, /* TT */ { 43697, 107 }, /* TW */ { 45135, 108 }, /* UA */ { 43945, 109 }, /* US */ { 51876, 110 }, /* UY */ { 46390, 111 }, /* UZ */ { 50748, 112 }, /* VE */ { 45586, 113 }, /* VN */ { 50866, 114 }, /* YE */ { 45864, 115 }, /* ZA */ { 51486, 116 } /* ZW */ }; static const char locale_strings[] = { "\0" "dd MMMM\0" "\xd9\x85\xd8\xad\xd8\xb1\xd9\x85\0" "\xd8\xb5\xd9\x81\xd8\xb1\0" "\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xb9 \xd8\xa7\xd9\x84\xd8\xa3\xd9\x88\xd9\x84\0" "\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xb9 \xd8\xa7\xd9\x84\xd8\xa2\xd8\xae\xd8\xb1\0" "\xd8\xac\xd9\x85\xd8\xa7\xd8\xaf\xd9\x89 \xd8\xa7\xd9\x84\xd8\xa3\xd9\x88\xd9\x84\xd9\x89\0" "\xd8\xac\xd9\x85\xd8\xa7\xd8\xaf\xd9\x89 \xd8\xa7\xd9\x84\xd8\xa2\xd8\xae\xd8\xb1\xd8\xa9\0" "\xd8\xb1\xd8\xac\xd8\xa8\0" "\xd8\xb4\xd8\xb9\xd8\xa8\xd8\xa7\xd9\x86\0" "\xd8\xb1\xd9\x85\xd8\xb6\xd8\xa7\xd9\x86\0" "\xd8\xb4\xd9\x88\xd8\xa7\xd9\x84\0" "\xd8\xb0\xd9\x88 \xd8\xa7\xd9\x84\xd9\x82\xd8\xb9\xd8\xaf\xd8\xa9\0" "\xd8\xb0\xd9\x88 \xd8\xa7\xd9\x84\xd8\xad\xd8\xac\xd8\xa9\0" "/\0" ":\0" "dd/MM/yy\0" "dd/MM/yyyy\0" "dd/MMMM/yyyy\0" "dddd, dd MMMM, yyyy\0" "hh:mm tt\0" "HH:mm\0" "hh:mm:ss tt\0" "HH:mm:ss\0" "MMMM, yyyy\0" "d MMMM\0" "\xd0\xbf\xd1\x80.\xd0\xbe\xd0\xb1.\0" "\xd1\x81\xd0\xbb.\xd0\xbe\xd0\xb1.\0" "\xd0\xbd\xd0\xb5\xd0\xb4\xd0\xb5\xd0\xbb\xd1\x8f\0" "\xd0\xbf\xd0\xbe\xd0\xbd\xd0\xb5\xd0\xb4\xd0\xb5\xd0\xbb\xd0\xbd\xd0\xb8\xd0\xba\0" "\xd0\xb2\xd1\x82\xd0\xbe\xd1\x80\xd0\xbd\xd0\xb8\xd0\xba\0" "\xd1\x81\xd1\x80\xd1\x8f\xd0\xb4\xd0\xb0\0" "\xd1\x87\xd0\xb5\xd1\x82\xd0\xb2\xd1\x8a\xd1\x80\xd1\x82\xd1\x8a\xd0\xba\0" "\xd0\xbf\xd0\xb5\xd1\x82\xd1\x8a\xd0\xba\0" "\xd1\x81\xd1\x8a\xd0\xb1\xd0\xbe\xd1\x82\xd0\xb0\0" "\xd0\xbd\xd0\xb4\0" "\xd0\xbf\xd0\xbd\0" "\xd0\xb2\xd1\x82\0" "\xd1\x81\xd1\x80\0" "\xd1\x87\xd1\x82\0" "\xd0\xbf\xd1\x82\0" "\xd1\x81\xd0\xb1\0" "\xd0\xbd\0" "\xd0\xbf\0" "\xd0\xb2\0" "\xd1\x81\0" "\xd1\x87\0" "\xd1\x8f\xd0\xbd\xd1\x83\xd0\xb0\xd1\x80\xd0\xb8\0" "\xd1\x84\xd0\xb5\xd0\xb2\xd1\x80\xd1\x83\xd0\xb0\xd1\x80\xd0\xb8\0" "\xd0\xbc\xd0\xb0\xd1\x80\xd1\x82\0" "\xd0\xb0\xd0\xbf\xd1\x80\xd0\xb8\xd0\xbb\0" "\xd0\xbc\xd0\xb0\xd0\xb9\0" "\xd1\x8e\xd0\xbd\xd0\xb8\0" "\xd1\x8e\xd0\xbb\xd0\xb8\0" "\xd0\xb0\xd0\xb2\xd0\xb3\xd1\x83\xd1\x81\xd1\x82\0" "\xd1\x81\xd0\xb5\xd0\xbf\xd1\x82\xd0\xb5\xd0\xbc\xd0\xb2\xd1\x80\xd0\xb8\0" "\xd0\xbe\xd0\xba\xd1\x82\xd0\xbe\xd0\xbc\xd0\xb2\xd1\x80\xd0\xb8\0" "\xd0\xbd\xd0\xbe\xd0\xb5\xd0\xbc\xd0\xb2\xd1\x80\xd0\xb8\0" "\xd0\xb4\xd0\xb5\xd0\xba\xd0\xb5\xd0\xbc\xd0\xb2\xd1\x80\xd0\xb8\0" "\xd1\x8f\xd0\xbd.\0" "\xd1\x84\xd0\xb5\xd0\xb2\xd1\x80.\0" "\xd0\xb0\xd0\xbf\xd1\x80.\0" "\xd0\xb0\xd0\xb2\xd0\xb3.\0" "\xd1\x81\xd0\xb5\xd0\xbf\xd1\x82.\0" "\xd0\xbe\xd0\xba\xd1\x82.\0" "\xd0\xbd\xd0\xbe\xd0\xb5\xd0\xbc.\0" "\xd0\xb4\xd0\xb5\xd0\xba.\0" ".\0" "d.M.yyyy '\xd0\xb3.'\0" "dd.M.yyyy '\xd0\xb3.'\0" "d.MM.yyyy '\xd0\xb3.'\0" "dd.MM.yyyy '\xd0\xb3.'\0" "dd MMMM yyyy '\xd0\xb3.'\0" "d MMMM yyyy '\xd0\xb3.'\0" "dddd, dd MMMM yyyy '\xd0\xb3.'\0" "dddd, d MMMM yyyy '\xd0\xb3.'\0" "H:mm\0" "H:mm:ss\0" "MMMM yyyy '\xd0\xb3.'\0" "a. m.\0" "p. m.\0" "diumenge\0" "dilluns\0" "dimarts\0" "dimecres\0" "dijous\0" "divendres\0" "dissabte\0" "dg.\0" "dl.\0" "dt.\0" "dc.\0" "dj.\0" "dv.\0" "ds.\0" "dg\0" "dl\0" "dt\0" "dc\0" "dj\0" "dv\0" "ds\0" "gener\0" "febrer\0" "mar\xc3\xa7\0" "abril\0" "maig\0" "juny\0" "juliol\0" "agost\0" "setembre\0" "octubre\0" "novembre\0" "desembre\0" "gen.\0" "feb.\0" "abr.\0" "jul.\0" "ag.\0" "set.\0" "oct.\0" "nov.\0" "des.\0" "d/M/yyyy\0" "d MMM yyyy\0" "dddd, d MMMM 'de' yyyy\0" "d MMMM 'de' yyyy\0" "MMMM 'de' yyyy\0" "M\xe6\x9c\x88\x64\xe6\x97\xa5\0" "\xe4\xb8\x8a\xe5\x8d\x88\0" "\xe4\xb8\x8b\xe5\x8d\x88\0" "\xe6\x98\x9f\xe6\x9c\x9f\xe6\x97\xa5\0" "\xe6\x98\x9f\xe6\x9c\x9f\xe4\xb8\x80\0" "\xe6\x98\x9f\xe6\x9c\x9f\xe4\xba\x8c\0" "\xe6\x98\x9f\xe6\x9c\x9f\xe4\xb8\x89\0" "\xe6\x98\x9f\xe6\x9c\x9f\xe5\x9b\x9b\0" "\xe6\x98\x9f\xe6\x9c\x9f\xe4\xba\x94\0" "\xe6\x98\x9f\xe6\x9c\x9f\xe5\x85\xad\0" "\xe5\x91\xa8\xe6\x97\xa5\0" "\xe5\x91\xa8\xe4\xb8\x80\0" "\xe5\x91\xa8\xe4\xba\x8c\0" "\xe5\x91\xa8\xe4\xb8\x89\0" "\xe5\x91\xa8\xe5\x9b\x9b\0" "\xe5\x91\xa8\xe4\xba\x94\0" "\xe5\x91\xa8\xe5\x85\xad\0" "\xe6\x97\xa5\0" "\xe4\xb8\x80\0" "\xe4\xba\x8c\0" "\xe4\xb8\x89\0" "\xe5\x9b\x9b\0" "\xe4\xba\x94\0" "\xe5\x85\xad\0" "\xe4\xb8\x80\xe6\x9c\x88\0" "\xe4\xba\x8c\xe6\x9c\x88\0" "\xe4\xb8\x89\xe6\x9c\x88\0" "\xe5\x9b\x9b\xe6\x9c\x88\0" "\xe4\xba\x94\xe6\x9c\x88\0" "\xe5\x85\xad\xe6\x9c\x88\0" "\xe4\xb8\x83\xe6\x9c\x88\0" "\xe5\x85\xab\xe6\x9c\x88\0" "\xe4\xb9\x9d\xe6\x9c\x88\0" "\xe5\x8d\x81\xe6\x9c\x88\0" "\xe5\x8d\x81\xe4\xb8\x80\xe6\x9c\x88\0" "\xe5\x8d\x81\xe4\xba\x8c\xe6\x9c\x88\0" "1\xe6\x9c\x88\0" "2\xe6\x9c\x88\0" "3\xe6\x9c\x88\0" "4\xe6\x9c\x88\0" "5\xe6\x9c\x88\0" "6\xe6\x9c\x88\0" "7\xe6\x9c\x88\0" "8\xe6\x9c\x88\0" "9\xe6\x9c\x88\0" "10\xe6\x9c\x88\0" "11\xe6\x9c\x88\0" "12\xe6\x9c\x88\0" "yyyy/M/d\0" "yyyy-M-d\0" "yyyy.M.d\0" "yyyy/MM/dd\0" "yyyy-MM-dd\0" "yyyy.MM.dd\0" "yy/M/d\0" "yy-M-d\0" "yy.M.d\0" "yy/MM/dd\0" "yyyy'\xe5\xb9\xb4'M'\xe6\x9c\x88'd'\xe6\x97\xa5'\0" "yyyy'\xe5\xb9\xb4'M'\xe6\x9c\x88'd'\xe6\x97\xa5', dddd\0" "dddd, yyyy'\xe5\xb9\xb4'M'\xe6\x9c\x88'd'\xe6\x97\xa5'\0" "yyyy\xe5\xb9\xb4MMMd\xe6\x97\xa5\0" "yyyy\xe5\xb9\xb4MMMd\xe6\x97\xa5, dddd\0" "tt h:mm\0" "tt hh:mm\0" "tt h:mm:ss\0" "tt hh:mm:ss\0" "yyyy'\xe5\xb9\xb4'M'\xe6\x9c\x88'\0" "yyyy'\xe5\xb9\xb4'MMM\0" "yyyy'\xe5\xb9\xb4'MMMM\0" "yyyy.M\0" "d. MMMM\0" "AM\0" "PM\0" "ned\xc4\x9ble\0" "pond\xc4\x9bl\xc3\xad\0" "\xc3\xbater\xc3\xbd\0" "st\xc5\x99\x65\x64\x61\0" "\xc4\x8dtvrtek\0" "p\xc3\xa1tek\0" "sobota\0" "ne\0" "po\0" "\xc3\xbat\0" "st\0" "\xc4\x8dt\0" "p\xc3\xa1\0" "so\0" "N\0" "P\0" "\xc3\x9a\0" "S\0" "\xc4\x8c\0" "leden\0" "\xc3\xbanor\0" "b\xc5\x99\x65zen\0" "duben\0" "kv\xc4\x9bten\0" "\xc4\x8d\x65rven\0" "\xc4\x8d\x65rvenec\0" "srpen\0" "z\xc3\xa1\xc5\x99\xc3\xad\0" "\xc5\x99\xc3\xadjen\0" "listopad\0" "prosinec\0" "ledna\0" "\xc3\xbanora\0" "b\xc5\x99\x65zna\0" "dubna\0" "kv\xc4\x9btna\0" "\xc4\x8d\x65rvna\0" "\xc4\x8d\x65rvence\0" "srpna\0" "\xc5\x99\xc3\xadjna\0" "listopadu\0" "prosince\0" "led\0" "\xc3\xbano\0" "b\xc5\x99\x65\0" "dub\0" "kv\xc4\x9b\0" "\xc4\x8dvn\0" "\xc4\x8dvc\0" "srp\0" "z\xc3\xa1\xc5\x99\0" "\xc5\x99\xc3\xadj\0" "lis\0" "pro\0" "dd.MM.yyyy\0" "d. M. yyyy\0" "dddd d. MMMM yyyy\0" "d. MMMM yyyy\0" "MMMM yyyy\0" "s\xc3\xb8ndag\0" "mandag\0" "tirsdag\0" "onsdag\0" "torsdag\0" "fredag\0" "l\xc3\xb8rdag\0" "s\xc3\xb8n\0" "man\0" "tir\0" "ons\0" "tor\0" "fre\0" "l\xc3\xb8r\0" "M\0" "T\0" "O\0" "F\0" "L\0" "januar\0" "februar\0" "marts\0" "april\0" "maj\0" "juni\0" "juli\0" "august\0" "september\0" "oktober\0" "november\0" "december\0" "jan\0" "feb\0" "mar\0" "apr\0" "jun\0" "jul\0" "aug\0" "sep\0" "okt\0" "nov\0" "dec\0" "-\0" "dd-MM-yyyy\0" "dd-MM-yy\0" "yyyy MM dd\0" "vorm.\0" "nachm.\0" "Sonntag\0" "Montag\0" "Dienstag\0" "Mittwoch\0" "Donnerstag\0" "Freitag\0" "Samstag\0" "So\0" "Mo\0" "Di\0" "Mi\0" "Do\0" "Fr\0" "Sa\0" "D\0" "Januar\0" "Februar\0" "M\xc3\xa4rz\0" "April\0" "Mai\0" "Juni\0" "Juli\0" "August\0" "September\0" "Oktober\0" "November\0" "Dezember\0" "Jan\0" "Feb\0" "M\xc3\xa4r\0" "Apr\0" "Jun\0" "Jul\0" "Aug\0" "Sep\0" "Okt\0" "Nov\0" "Dez\0" "dd.MM.yy\0" "dd. MMM. yyyy\0" "dddd, d. MMMM yyyy\0" "d. MMM. yyyy\0" "HH:mm' Uhr'\0" "HH:mm:ss' Uhr'\0" "\xcf\x80.\xce\xbc.\0" "\xce\xbc.\xce\xbc.\0" "\xce\x9a\xcf\x85\xcf\x81\xce\xb9\xce\xb1\xce\xba\xce\xae\0" "\xce\x94\xce\xb5\xcf\x85\xcf\x84\xce\xad\xcf\x81\xce\xb1\0" "\xce\xa4\xcf\x81\xce\xaf\xcf\x84\xce\xb7\0" "\xce\xa4\xce\xb5\xcf\x84\xce\xac\xcf\x81\xcf\x84\xce\xb7\0" "\xce\xa0\xce\xad\xce\xbc\xcf\x80\xcf\x84\xce\xb7\0" "\xce\xa0\xce\xb1\xcf\x81\xce\xb1\xcf\x83\xce\xba\xce\xb5\xcf\x85\xce\xae\0" "\xce\xa3\xce\xac\xce\xb2\xce\xb2\xce\xb1\xcf\x84\xce\xbf\0" "\xce\x9a\xcf\x85\xcf\x81\0" "\xce\x94\xce\xb5\xcf\x85\0" "\xce\xa4\xcf\x81\xce\xaf\0" "\xce\xa4\xce\xb5\xcf\x84\0" "\xce\xa0\xce\xad\xce\xbc\0" "\xce\xa0\xce\xb1\xcf\x81\0" "\xce\xa3\xce\xac\xce\xb2\0" "\xce\x9a\0" "\xce\x94\0" "\xce\xa4\0" "\xce\xa0\0" "\xce\xa3\0" "\xce\x99\xce\xb1\xce\xbd\xce\xbf\xcf\x85\xce\xac\xcf\x81\xce\xb9\xce\xbf\xcf\x82\0" "\xce\xa6\xce\xb5\xce\xb2\xcf\x81\xce\xbf\xcf\x85\xce\xac\xcf\x81\xce\xb9\xce\xbf\xcf\x82\0" "\xce\x9c\xce\xac\xcf\x81\xcf\x84\xce\xb9\xce\xbf\xcf\x82\0" "\xce\x91\xcf\x80\xcf\x81\xce\xaf\xce\xbb\xce\xb9\xce\xbf\xcf\x82\0" "\xce\x9c\xce\xac\xce\xb9\xce\xbf\xcf\x82\0" "\xce\x99\xce\xbf\xcf\x8d\xce\xbd\xce\xb9\xce\xbf\xcf\x82\0" "\xce\x99\xce\xbf\xcf\x8d\xce\xbb\xce\xb9\xce\xbf\xcf\x82\0" "\xce\x91\xcf\x8d\xce\xb3\xce\xbf\xcf\x85\xcf\x83\xcf\x84\xce\xbf\xcf\x82\0" "\xce\xa3\xce\xb5\xcf\x80\xcf\x84\xce\xad\xce\xbc\xce\xb2\xcf\x81\xce\xb9\xce\xbf\xcf\x82\0" "\xce\x9f\xce\xba\xcf\x84\xcf\x8e\xce\xb2\xcf\x81\xce\xb9\xce\xbf\xcf\x82\0" "\xce\x9d\xce\xbf\xce\xad\xce\xbc\xce\xb2\xcf\x81\xce\xb9\xce\xbf\xcf\x82\0" "\xce\x94\xce\xb5\xce\xba\xce\xad\xce\xbc\xce\xb2\xcf\x81\xce\xb9\xce\xbf\xcf\x82\0" "\xce\x99\xce\xb1\xce\xbd\xce\xbf\xcf\x85\xce\xb1\xcf\x81\xce\xaf\xce\xbf\xcf\x85\0" "\xce\xa6\xce\xb5\xce\xb2\xcf\x81\xce\xbf\xcf\x85\xce\xb1\xcf\x81\xce\xaf\xce\xbf\xcf\x85\0" "\xce\x9c\xce\xb1\xcf\x81\xcf\x84\xce\xaf\xce\xbf\xcf\x85\0" "\xce\x91\xcf\x80\xcf\x81\xce\xb9\xce\xbb\xce\xaf\xce\xbf\xcf\x85\0" "\xce\x9c\xce\xb1\xce\x90\xce\xbf\xcf\x85\0" "\xce\x99\xce\xbf\xcf\x85\xce\xbd\xce\xaf\xce\xbf\xcf\x85\0" "\xce\x99\xce\xbf\xcf\x85\xce\xbb\xce\xaf\xce\xbf\xcf\x85\0" "\xce\x91\xcf\x85\xce\xb3\xce\xbf\xcf\x8d\xcf\x83\xcf\x84\xce\xbf\xcf\x85\0" "\xce\xa3\xce\xb5\xcf\x80\xcf\x84\xce\xb5\xce\xbc\xce\xb2\xcf\x81\xce\xaf\xce\xbf\xcf\x85\0" "\xce\x9f\xce\xba\xcf\x84\xcf\x89\xce\xb2\xcf\x81\xce\xaf\xce\xbf\xcf\x85\0" "\xce\x9d\xce\xbf\xce\xb5\xce\xbc\xce\xb2\xcf\x81\xce\xaf\xce\xbf\xcf\x85\0" "\xce\x94\xce\xb5\xce\xba\xce\xb5\xce\xbc\xce\xb2\xcf\x81\xce\xaf\xce\xbf\xcf\x85\0" "\xce\x99\xce\xb1\xce\xbd\0" "\xce\xa6\xce\xb5\xce\xb2\0" "\xce\x9c\xce\xac\xcf\x81\0" "\xce\x91\xcf\x80\xcf\x81\0" "\xce\x9c\xce\xac\xce\xb9\0" "\xce\x99\xce\xbf\xcf\x8d\xce\xbd\0" "\xce\x99\xce\xbf\xcf\x8d\xce\xbb\0" "\xce\x91\xcf\x8d\xce\xb3\0" "\xce\xa3\xce\xb5\xcf\x80\0" "\xce\x9f\xce\xba\xcf\x84\0" "\xce\x9d\xce\xbf\xce\xad\0" "\xce\x94\xce\xb5\xce\xba\0" "d/M/yy\0" "dd/MMM/yyyy\0" "dddd, d MMMM yyyy\0" "d MMMM yyyy\0" "h:mm tt\0" "h:mm:ss tt\0" "MMMM d\0" "Sunday\0" "Monday\0" "Tuesday\0" "Wednesday\0" "Thursday\0" "Friday\0" "Saturday\0" "Sun\0" "Mon\0" "Tue\0" "Wed\0" "Thu\0" "Fri\0" "Sat\0" "W\0" "January\0" "February\0" "March\0" "May\0" "June\0" "July\0" "October\0" "December\0" "Mar\0" "Oct\0" "Dec\0" "M/d/yyyy\0" "M/d/yy\0" "MM/dd/yy\0" "MM/dd/yyyy\0" "dd-MMM-yy\0" "dddd, MMMM d, yyyy\0" "MMMM d, yyyy\0" "dddd, d MMMM, yyyy\0" "d MMMM, yyyy\0" "d 'de' MMMM\0" "domingo\0" "lunes\0" "martes\0" "mi\xc3\xa9rcoles\0" "jueves\0" "viernes\0" "s\xc3\xa1\x62\x61\x64o\0" "Dom.\0" "Lun.\0" "Mar.\0" "Mi\xc3\xa9.\0" "Jue.\0" "Vie.\0" "S\xc3\xa1\x62.\0" "J\0" "V\0" "Enero\0" "Febrero\0" "Marzo\0" "Abril\0" "Mayo\0" "Junio\0" "Julio\0" "Agosto\0" "Septiembre\0" "Octubre\0" "Noviembre\0" "Diciembre\0" "enero\0" "febrero\0" "marzo\0" "mayo\0" "junio\0" "julio\0" "agosto\0" "septiembre\0" "noviembre\0" "diciembre\0" "Ene.\0" "Feb.\0" "Abr.\0" "May.\0" "Jun.\0" "Jul.\0" "Ago.\0" "Sept.\0" "Oct.\0" "Nov.\0" "Dic.\0" "d/MM/yy\0" "d-M-yy\0" "dddd, d' de 'MMMM' de 'yyyy\0" "dddd d' de 'MMMM' de 'yyyy\0" "d' de 'MMMM' de 'yyyy\0" "H.mm\0" "HH.mm\0" "HH'H'mm\0" "H.mm.ss\0" "HH.mm.ss\0" "HH'H'mm.ss\0" "MMMM' de 'yyyy\0" "ap.\0" "ip.\0" "sunnuntaina\0" "maanantaina\0" "tiistaina\0" "keskiviikkona\0" "torstaina\0" "perjantaina\0" "lauantaina\0" "su\0" "ma\0" "ti\0" "ke\0" "to\0" "pe\0" "la\0" "K\0" "tammikuu\0" "helmikuu\0" "maaliskuu\0" "huhtikuu\0" "toukokuu\0" "kes\xc3\xa4kuu\0" "hein\xc3\xa4kuu\0" "elokuu\0" "syyskuu\0" "lokakuu\0" "marraskuu\0" "joulukuu\0" "tammikuuta\0" "helmikuuta\0" "maaliskuuta\0" "huhtikuuta\0" "toukokuuta\0" "kes\xc3\xa4kuuta\0" "hein\xc3\xa4kuuta\0" "elokuuta\0" "syyskuuta\0" "lokakuuta\0" "marraskuuta\0" "joulukuuta\0" "tammi\0" "helmi\0" "maalis\0" "huhti\0" "touko\0" "kes\xc3\xa4\0" "hein\xc3\xa4\0" "elo\0" "syys\0" "loka\0" "marras\0" "joulu\0" "d.M.yyyy\0" "dimanche\0" "lundi\0" "mardi\0" "mercredi\0" "jeudi\0" "vendredi\0" "samedi\0" "dim.\0" "lun.\0" "mar.\0" "mer.\0" "jeu.\0" "ven.\0" "sam.\0" "janvier\0" "f\xc3\xa9vrier\0" "mars\0" "avril\0" "mai\0" "juin\0" "juillet\0" "ao\xc3\xbbt\0" "septembre\0" "octobre\0" "d\xc3\xa9\x63\x65mbre\0" "janv.\0" "f\xc3\xa9vr.\0" "avr.\0" "juil.\0" "sept.\0" "d\xc3\xa9\x63.\0" "dddd d MMMM yyyy\0" "d MMM yy\0" "HH' h 'mm\0" "HH'h'mm\0" "\xd7\x9c\xd7\xa4\xd7\xa0\xd7\x94\xd7\xb4\xd7\xa6\0" "\xd7\x90\xd7\x97\xd7\x94\xd7\xb4\xd7\xa6\0" "\xd7\x99\xd7\x95\xd7\x9d \xd7\xa8\xd7\x90\xd7\xa9\xd7\x95\xd7\x9f\0" "\xd7\x99\xd7\x95\xd7\x9d \xd7\xa9\xd7\xa0\xd7\x99\0" "\xd7\x99\xd7\x95\xd7\x9d \xd7\xa9\xd7\x9c\xd7\x99\xd7\xa9\xd7\x99\0" "\xd7\x99\xd7\x95\xd7\x9d \xd7\xa8\xd7\x91\xd7\x99\xd7\xa2\xd7\x99\0" "\xd7\x99\xd7\x95\xd7\x9d \xd7\x97\xd7\x9e\xd7\x99\xd7\xa9\xd7\x99\0" "\xd7\x99\xd7\x95\xd7\x9d \xd7\xa9\xd7\x99\xd7\xa9\xd7\x99\0" "\xd7\x99\xd7\x95\xd7\x9d \xd7\xa9\xd7\x91\xd7\xaa\0" "\xd7\x99\xd7\x95\xd7\x9d \xd7\x90\xd7\xb3\0" "\xd7\x99\xd7\x95\xd7\x9d \xd7\x91\xd7\xb3\0" "\xd7\x99\xd7\x95\xd7\x9d \xd7\x92\xd7\xb3\0" "\xd7\x99\xd7\x95\xd7\x9d \xd7\x93\xd7\xb3\0" "\xd7\x99\xd7\x95\xd7\x9d \xd7\x94\xd7\xb3\0" "\xd7\x99\xd7\x95\xd7\x9d \xd7\x95\xd7\xb3\0" "\xd7\xa9\xd7\x91\xd7\xaa\0" "\xd7\x90\xd7\xb3\0" "\xd7\x91\xd7\xb3\0" "\xd7\x92\xd7\xb3\0" "\xd7\x93\xd7\xb3\0" "\xd7\x94\xd7\xb3\0" "\xd7\x95\xd7\xb3\0" "\xd7\xa9\xd7\xb3\0" "\xd7\x99\xd7\xa0\xd7\x95\xd7\x90\xd7\xa8\0" "\xd7\xa4\xd7\x91\xd7\xa8\xd7\x95\xd7\x90\xd7\xa8\0" "\xd7\x9e\xd7\xa8\xd7\xa5\0" "\xd7\x90\xd7\xa4\xd7\xa8\xd7\x99\xd7\x9c\0" "\xd7\x9e\xd7\x90\xd7\x99\0" "\xd7\x99\xd7\x95\xd7\xa0\xd7\x99\0" "\xd7\x99\xd7\x95\xd7\x9c\xd7\x99\0" "\xd7\x90\xd7\x95\xd7\x92\xd7\x95\xd7\xa1\xd7\x98\0" "\xd7\xa1\xd7\xa4\xd7\x98\xd7\x9e\xd7\x91\xd7\xa8\0" "\xd7\x90\xd7\x95\xd7\xa7\xd7\x98\xd7\x95\xd7\x91\xd7\xa8\0" "\xd7\xa0\xd7\x95\xd7\x91\xd7\x9e\xd7\x91\xd7\xa8\0" "\xd7\x93\xd7\xa6\xd7\x9e\xd7\x91\xd7\xa8\0" "\xd7\x99\xd7\xa0\xd7\x95\xd7\xb3\0" "\xd7\xa4\xd7\x91\xd7\xa8\xd7\xb3\0" "\xd7\x90\xd7\xa4\xd7\xa8\xd7\xb3\0" "\xd7\x99\xd7\x95\xd7\xa0\xd7\xb3\0" "\xd7\x99\xd7\x95\xd7\x9c\xd7\xb3\0" "\xd7\x90\xd7\x95\xd7\x92\xd7\xb3\0" "\xd7\xa1\xd7\xa4\xd7\x98\xd7\xb3\0" "\xd7\x90\xd7\x95\xd7\xa7\xd7\xb3\0" "\xd7\xa0\xd7\x95\xd7\x91\xd7\xb3\0" "\xd7\x93\xd7\xa6\xd7\x9e\xd7\xb3\0" "dd MMMM yyyy\0" "dd-MMMM-yyyy\0" "dd '\xd7\x91'MMMM yyyy\0" "dd MMM yy\0" "dddd dd MMMM yyyy\0" "dddd dd '\xd7\x91'MMMM yyyy\0" "ddd dd '\xd7\x91'MMMM yyyy\0" "MMMM d.\0" "de.\0" "du.\0" "vas\xc3\xa1rnap\0" "h\xc3\xa9tf\xc5\x91\0" "kedd\0" "szerda\0" "cs\xc3\xbct\xc3\xb6rt\xc3\xb6k\0" "p\xc3\xa9ntek\0" "szombat\0" "H\0" "Sze\0" "Cs\0" "Szo\0" "Sz\0" "janu\xc3\xa1r\0" "febru\xc3\xa1r\0" "m\xc3\xa1rcius\0" "\xc3\xa1prilis\0" "m\xc3\xa1jus\0" "j\xc3\xbanius\0" "j\xc3\xbalius\0" "augusztus\0" "szeptember\0" "okt\xc3\xb3\x62\x65r\0" "jan.\0" "febr.\0" "m\xc3\xa1rc.\0" "\xc3\xa1pr.\0" "m\xc3\xa1j.\0" "j\xc3\xban.\0" "j\xc3\xbal.\0" "aug.\0" "szept.\0" "okt.\0" "dec.\0" ". \0" "yyyy. MM. dd.\0" "yyyy. MMM d.\0" "yyyy. MMMM d., dddd\0" "yyyy. MMMM d.\0" "yyyy. MMMM\0" "f.h.\0" "e.h.\0" "sunnudagur\0" "m\xc3\xa1nudagur\0" "\xc3\xberi\xc3\xb0judagur\0" "mi\xc3\xb0vikudagur\0" "fimmtudagur\0" "f\xc3\xb6studagur\0" "laugardagur\0" "sun.\0" "m\xc3\xa1n.\0" "\xc3\xberi.\0" "mi\xc3\xb0.\0" "fim.\0" "f\xc3\xb6s.\0" "lau.\0" "\xc3\x9e\0" "jan\xc3\xba\x61r\0" "febr\xc3\xba\x61r\0" "apr\xc3\xadl\0" "ma\xc3\xad\0" "j\xc3\xban\xc3\xad\0" "j\xc3\xbal\xc3\xad\0" "\xc3\xa1g\xc3\xbast\0" "n\xc3\xb3vember\0" "desember\0" "apr.\0" "\xc3\xa1g\xc3\xba.\0" "sep.\0" "n\xc3\xb3v.\0" "d. MMM yyyy\0" "domenica\0" "luned\xc3\xac\0" "marted\xc3\xac\0" "mercoled\xc3\xac\0" "gioved\xc3\xac\0" "venerd\xc3\xac\0" "sabato\0" "dom\0" "lun\0" "mer\0" "gio\0" "ven\0" "sab\0" "G\0" "Gennaio\0" "Febbraio\0" "Aprile\0" "Maggio\0" "Giugno\0" "Luglio\0" "Settembre\0" "Ottobre\0" "Novembre\0" "Dicembre\0" "gennaio\0" "febbraio\0" "aprile\0" "maggio\0" "giugno\0" "luglio\0" "settembre\0" "ottobre\0" "dicembre\0" "gen\0" "mag\0" "giu\0" "lug\0" "ago\0" "set\0" "ott\0" "dic\0" "dd.M.yy\0" "d-MMM-yy\0" "\xe5\x8d\x88\xe5\x89\x8d\0" "\xe5\x8d\x88\xe5\xbe\x8c\0" "\xe6\x97\xa5\xe6\x9b\x9c\xe6\x97\xa5\0" "\xe6\x9c\x88\xe6\x9b\x9c\xe6\x97\xa5\0" "\xe7\x81\xab\xe6\x9b\x9c\xe6\x97\xa5\0" "\xe6\xb0\xb4\xe6\x9b\x9c\xe6\x97\xa5\0" "\xe6\x9c\xa8\xe6\x9b\x9c\xe6\x97\xa5\0" "\xe9\x87\x91\xe6\x9b\x9c\xe6\x97\xa5\0" "\xe5\x9c\x9f\xe6\x9b\x9c\xe6\x97\xa5\0" "\xe6\x9c\x88\0" "\xe7\x81\xab\0" "\xe6\xb0\xb4\0" "\xe6\x9c\xa8\0" "\xe9\x87\x91\0" "\xe5\x9c\x9f\0" "1\0" "2\0" "3\0" "4\0" "5\0" "6\0" "7\0" "8\0" "9\0" "10\0" "11\0" "12\0" "yyyy'\xe5\xb9\xb4'MM'\xe6\x9c\x88'dd'\xe6\x97\xa5'\0" "yyyy'\xe5\xb9\xb4'M'\xe6\x9c\x88'd'\xe6\x97\xa5 'dddd\0" "yyyy'\xe5\xb9\xb4'MM'\xe6\x9c\x88'dd'\xe6\x97\xa5 'dddd\0" "yyyy'\xe5\xb9\xb4'MMM'\xe6\x9c\x88'd'\xe6\x97\xa5'\0" "yyyy'\xe5\xb9\xb4'MMM'\xe6\x9c\x88'd'\xe6\x97\xa5 'dddd\0" "yyyy'\xe5\xb9\xb4'MMMMd'\xe6\x97\xa5'\0" "yyyy'\xe5\xb9\xb4'MMMMd'\xe6\x97\xa5 'dddd\0" "yyyy'\xe5\xb9\xb4'MMM'\xe6\x9c\x88'\0" "M\xec\x9b\x94 d\xec\x9d\xbc\0" "\xec\x98\xa4\xec\xa0\x84\0" "\xec\x98\xa4\xed\x9b\x84\0" "\xec\x9d\xbc\xec\x9a\x94\xec\x9d\xbc\0" "\xec\x9b\x94\xec\x9a\x94\xec\x9d\xbc\0" "\xed\x99\x94\xec\x9a\x94\xec\x9d\xbc\0" "\xec\x88\x98\xec\x9a\x94\xec\x9d\xbc\0" "\xeb\xaa\xa9\xec\x9a\x94\xec\x9d\xbc\0" "\xea\xb8\x88\xec\x9a\x94\xec\x9d\xbc\0" "\xed\x86\xa0\xec\x9a\x94\xec\x9d\xbc\0" "\xec\x9d\xbc\0" "\xec\x9b\x94\0" "\xed\x99\x94\0" "\xec\x88\x98\0" "\xeb\xaa\xa9\0" "\xea\xb8\x88\0" "\xed\x86\xa0\0" "1\xec\x9b\x94\0" "2\xec\x9b\x94\0" "3\xec\x9b\x94\0" "4\xec\x9b\x94\0" "5\xec\x9b\x94\0" "6\xec\x9b\x94\0" "7\xec\x9b\x94\0" "8\xec\x9b\x94\0" "9\xec\x9b\x94\0" "10\xec\x9b\x94\0" "11\xec\x9b\x94\0" "12\xec\x9b\x94\0" "yy-MM-dd\0" "yyyy'\xeb\x85\x84' M'\xec\x9b\x94' d'\xec\x9d\xbc' dddd\0" "yyyy'\xeb\x85\x84' M'\xec\x9b\x94' d'\xec\x9d\xbc'\0" "yy'\xeb\x85\x84' M'\xec\x9b\x94' d'\xec\x9d\xbc' dddd\0" "yy'\xeb\x85\x84' M'\xec\x9b\x94' d'\xec\x9d\xbc'\0" "yyyy'\xeb\x85\x84' MM'\xec\x9b\x94' dd'\xec\x9d\xbc' dddd\0" "yyyy'\xeb\x85\x84' MM'\xec\x9b\x94' dd'\xec\x9d\xbc'\0" "yyyy'\xeb\x85\x84 'MMM'\xec\x9b\x94 'd'\xec\x9d\xbc 'dddd\0" "yyyy'\xeb\x85\x84 'MMM'\xec\x9b\x94 'd'\xec\x9d\xbc'\0" "yyyy'\xeb\x85\x84 'MMMM d'\xec\x9d\xbc 'dddd\0" "yyyy'\xeb\x85\x84 'MMMM d'\xec\x9d\xbc'\0" "yyyy'\xeb\x85\x84' M'\xec\x9b\x94'\0" "yyyy'\xeb\x85\x84' MMM'\xec\x9b\x94'\0" "yyyy'\xeb\x85\x84' MMMM\0" "a.m.\0" "p.m.\0" "zondag\0" "maandag\0" "dinsdag\0" "woensdag\0" "donderdag\0" "vrijdag\0" "zaterdag\0" "zo\0" "di\0" "wo\0" "do\0" "vr\0" "za\0" "Z\0" "januari\0" "februari\0" "maart\0" "mei\0" "augustus\0" "mrt\0" "d-M-yyyy\0" "dd.MMM.yyyy\0" "HH.mm' uur'\0" "HH:mm' uur'\0" "HH.mm.ss' uur'\0" "HH:mm:ss' uur'\0" "d.MMMM.\0" "s\xc3\xb8.\0" "ma.\0" "ti.\0" "on.\0" "to.\0" "fr.\0" "l\xc3\xb8.\0" "des\0" "niedziela\0" "poniedzia\xc5\x82\x65k\0" "wtorek\0" "\xc5\x9broda\0" "czwartek\0" "pi\xc4\x85tek\0" "niedz.\0" "pon.\0" "wt.\0" "\xc5\x9br.\0" "czw.\0" "pt.\0" "sob.\0" "\xc5\x9a\0" "C\0" "stycze\xc5\x84\0" "luty\0" "marzec\0" "kwiecie\xc5\x84\0" "czerwiec\0" "lipiec\0" "sierpie\xc5\x84\0" "wrzesie\xc5\x84\0" "pa\xc5\xba\x64ziernik\0" "grudzie\xc5\x84\0" "stycznia\0" "lutego\0" "marca\0" "kwietnia\0" "maja\0" "czerwca\0" "lipca\0" "sierpnia\0" "wrze\xc5\x9bnia\0" "pa\xc5\xba\x64ziernika\0" "listopada\0" "grudnia\0" "sty\0" "lut\0" "kwi\0" "cze\0" "lip\0" "sie\0" "wrz\0" "pa\xc5\xba\0" "gru\0" "segunda-feira\0" "ter\xc3\xa7\x61-feira\0" "quarta-feira\0" "quinta-feira\0" "sexta-feira\0" "seg\0" "ter\0" "qua\0" "qui\0" "sex\0" "s\xc3\xa1\x62\0" "Q\0" "janeiro\0" "fevereiro\0" "mar\xc3\xa7o\0" "maio\0" "junho\0" "julho\0" "setembro\0" "outubro\0" "novembro\0" "dezembro\0" "fev\0" "abr\0" "out\0" "dez\0" "d.M.yy\0" "am\0" "sm\0" "dumengia\0" "glindesdi\0" "mesemna\0" "gievgia\0" "venderdi\0" "sonda\0" "du\0" "gli\0" "me\0" "gie\0" "ve\0" "schaner\0" "favrer\0" "avrigl\0" "matg\0" "zercladur\0" "fanadur\0" "avust\0" "settember\0" "october\0" "schan.\0" "favr.\0" "zercl.\0" "fan.\0" "sett.\0" "dddd, 'ils' d 'da' MMMM yyyy\0" "d 'da' MMMM yyyy\0" "duminic\xc4\x83\0" "luni\0" "mar\xc8\x9bi\0" "miercuri\0" "joi\0" "vineri\0" "s\xc3\xa2mb\xc4\x83t\xc4\x83\0" "Dum\0" "Lun\0" "Mie\0" "Joi\0" "Vin\0" "S\xc3\xa2m\0" "ianuarie\0" "februarie\0" "martie\0" "aprilie\0" "iunie\0" "iulie\0" "septembrie\0" "octombrie\0" "noiembrie\0" "decembrie\0" "ian.\0" "iun.\0" "iul.\0" "\xd0\xb4\xd0\xbe \xd0\xbf\xd0\xbe\xd0\xbb\xd1\x83\xd0\xb4\xd0\xbd\xd1\x8f\0" "\xd0\xbf\xd0\xbe\xd1\x81\xd0\xbb\xd0\xb5 \xd0\xbf\xd0\xbe\xd0\xbb\xd1\x83\xd0\xb4\xd0\xbd\xd1\x8f\0" "\xd0\xb2\xd0\xbe\xd1\x81\xd0\xba\xd1\x80\xd0\xb5\xd1\x81\xd0\xb5\xd0\xbd\xd1\x8c\xd0\xb5\0" "\xd0\xbf\xd0\xbe\xd0\xbd\xd0\xb5\xd0\xb4\xd0\xb5\xd0\xbb\xd1\x8c\xd0\xbd\xd0\xb8\xd0\xba\0" "\xd1\x81\xd1\x80\xd0\xb5\xd0\xb4\xd0\xb0\0" "\xd1\x87\xd0\xb5\xd1\x82\xd0\xb2\xd0\xb5\xd1\x80\xd0\xb3\0" "\xd0\xbf\xd1\x8f\xd1\x82\xd0\xbd\xd0\xb8\xd1\x86\xd0\xb0\0" "\xd1\x81\xd1\x83\xd0\xb1\xd0\xb1\xd0\xbe\xd1\x82\xd0\xb0\0" "\xd0\x92\xd1\x81\0" "\xd0\x9f\xd0\xbd\0" "\xd0\x92\xd1\x82\0" "\xd0\xa1\xd1\x80\0" "\xd0\xa7\xd1\x82\0" "\xd0\x9f\xd1\x82\0" "\xd0\xa1\xd0\xb1\0" "\xd0\x92\0" "\xd0\x9f\0" "\xd0\xa1\0" "\xd0\xa7\0" "\xd0\xaf\xd0\xbd\xd0\xb2\xd0\xb0\xd1\x80\xd1\x8c\0" "\xd0\xa4\xd0\xb5\xd0\xb2\xd1\x80\xd0\xb0\xd0\xbb\xd1\x8c\0" "\xd0\x9c\xd0\xb0\xd1\x80\xd1\x82\0" "\xd0\x90\xd0\xbf\xd1\x80\xd0\xb5\xd0\xbb\xd1\x8c\0" "\xd0\x9c\xd0\xb0\xd0\xb9\0" "\xd0\x98\xd1\x8e\xd0\xbd\xd1\x8c\0" "\xd0\x98\xd1\x8e\xd0\xbb\xd1\x8c\0" "\xd0\x90\xd0\xb2\xd0\xb3\xd1\x83\xd1\x81\xd1\x82\0" "\xd0\xa1\xd0\xb5\xd0\xbd\xd1\x82\xd1\x8f\xd0\xb1\xd1\x80\xd1\x8c\0" "\xd0\x9e\xd0\xba\xd1\x82\xd1\x8f\xd0\xb1\xd1\x80\xd1\x8c\0" "\xd0\x9d\xd0\xbe\xd1\x8f\xd0\xb1\xd1\x80\xd1\x8c\0" "\xd0\x94\xd0\xb5\xd0\xba\xd0\xb0\xd0\xb1\xd1\x80\xd1\x8c\0" "\xd1\x8f\xd0\xbd\xd0\xb2\xd0\xb0\xd1\x80\xd1\x8f\0" "\xd1\x84\xd0\xb5\xd0\xb2\xd1\x80\xd0\xb0\xd0\xbb\xd1\x8f\0" "\xd0\xbc\xd0\xb0\xd1\x80\xd1\x82\xd0\xb0\0" "\xd0\xb0\xd0\xbf\xd1\x80\xd0\xb5\xd0\xbb\xd1\x8f\0" "\xd0\xbc\xd0\xb0\xd1\x8f\0" "\xd0\xb8\xd1\x8e\xd0\xbd\xd1\x8f\0" "\xd0\xb8\xd1\x8e\xd0\xbb\xd1\x8f\0" "\xd0\xb0\xd0\xb2\xd0\xb3\xd1\x83\xd1\x81\xd1\x82\xd0\xb0\0" "\xd1\x81\xd0\xb5\xd0\xbd\xd1\x82\xd1\x8f\xd0\xb1\xd1\x80\xd1\x8f\0" "\xd0\xbe\xd0\xba\xd1\x82\xd1\x8f\xd0\xb1\xd1\x80\xd1\x8f\0" "\xd0\xbd\xd0\xbe\xd1\x8f\xd0\xb1\xd1\x80\xd1\x8f\0" "\xd0\xb4\xd0\xb5\xd0\xba\xd0\xb0\xd0\xb1\xd1\x80\xd1\x8f\0" "\xd0\xaf\xd0\xbd\xd0\xb2.\0" "\xd0\xa4\xd0\xb5\xd0\xb2\xd1\x80.\0" "\xd0\x90\xd0\xbf\xd1\x80.\0" "\xd0\x90\xd0\xb2\xd0\xb3.\0" "\xd0\xa1\xd0\xb5\xd0\xbd\xd1\x82.\0" "\xd0\x9e\xd0\xba\xd1\x82.\0" "\xd0\x9d\xd0\xbe\xd1\x8f\xd0\xb1.\0" "\xd0\x94\xd0\xb5\xd0\xba.\0" "nedjelja\0" "ponedjeljak\0" "utorak\0" "srijeda\0" "\xc4\x8d\x65tvrtak\0" "petak\0" "subota\0" "ned\0" "pon\0" "uto\0" "sri\0" "\xc4\x8d\x65t\0" "pet\0" "sub\0" "n\0" "p\0" "u\0" "s\0" "\xc4\x8d\0" "sije\xc4\x8d\x61nj\0" "velja\xc4\x8d\x61\0" "o\xc5\xbeujak\0" "travanj\0" "svibanj\0" "lipanj\0" "srpanj\0" "kolovoz\0" "rujan\0" "studeni\0" "prosinac\0" "sije\xc4\x8dnja\0" "velja\xc4\x8d\x65\0" "o\xc5\xbeujka\0" "travnja\0" "svibnja\0" "lipnja\0" "srpnja\0" "kolovoza\0" "rujna\0" "studenoga\0" "prosinca\0" "sij\0" "velj\0" "o\xc5\xbeu\0" "tra\0" "svi\0" "kol\0" "ruj\0" "stu\0" "d.M.yyyy.\0" "d.M.yy.\0" "d. M. yyyy.\0" "dd.MM.yyyy.\0" "d. M. yy.\0" "dd.MM.yy.\0" "dd. MM. yy.\0" "d. MMMM yyyy.\0" "dd. MMMM yyyy.\0" "dddd, d. MMMM yyyy.\0" "nede\xc4\xbe\x61\0" "pondelok\0" "utorok\0" "streda\0" "\xc5\xa1tvrtok\0" "piatok\0" "ut\0" "\xc5\xa1t\0" "pi\0" "U\0" "\xc5\xa0\0" "marec\0" "m\xc3\xa1j\0" "j\xc3\xban\0" "j\xc3\xbal\0" "janu\xc3\xa1ra\0" "febru\xc3\xa1ra\0" "apr\xc3\xadla\0" "m\xc3\xa1ja\0" "j\xc3\xbana\0" "j\xc3\xbala\0" "augusta\0" "septembra\0" "okt\xc3\xb3\x62ra\0" "novembra\0" "decembra\0" "paradite\0" "pasdite\0" "e diel\0" "e h\xc3\xabn\xc3\xab\0" "e mart\xc3\xab\0" "e m\xc3\xabrkur\xc3\xab\0" "e enjte\0" "e premte\0" "e shtun\xc3\xab\0" "Die\0" "H\xc3\xabn\0" "M\xc3\xabr\0" "Enj\0" "Pre\0" "Sht\0" "E\0" "janar\0" "shkurt\0" "prill\0" "qershor\0" "korrik\0" "gusht\0" "shtator\0" "tetor\0" "n\xc3\xabntor\0" "dhjetor\0" "Shk\0" "Pri\0" "Maj\0" "Qer\0" "Kor\0" "Gsh\0" "Tet\0" "N\xc3\xabn\0" "Dhj\0" "'den 'd MMMM\0" "FM\0" "EM\0" "s\xc3\xb6ndag\0" "m\xc3\xa5ndag\0" "tisdag\0" "l\xc3\xb6rdag\0" "s\xc3\xb6n\0" "m\xc3\xa5n\0" "tis\0" "l\xc3\xb6r\0" "augusti\0" "'den 'd MMMM yyyy\0" "dddd' den 'd MMMM yyyy\0" "'kl 'H:mm\0" "'kl 'H:mm:ss\0" "dd MMM yyyy\0" "ddd d MMMM yyyy\0" "'\xe0\xb8\xa7\xe0\xb8\xb1\xe0\xb8\x99'dddd'\xe0\xb8\x97\xe0\xb8\xb5\xe0\xb9\x88' d MMMM gg yyyy\0" "\xc3\x96\xc3\x96\0" "\xc3\x96S\0" "Pazar\0" "Pazartesi\0" "Sal\xc4\xb1\0" "\xc3\x87\x61r\xc5\x9f\x61mba\0" "Per\xc5\x9f\x65mbe\0" "Cuma\0" "Cumartesi\0" "Paz\0" "Pzt\0" "Sal\0" "\xc3\x87\x61r\0" "Per\0" "Cum\0" "Cmt\0" "\xc3\x87\0" "Ocak\0" "\xc5\x9eubat\0" "Mart\0" "Nisan\0" "May\xc4\xb1s\0" "Haziran\0" "Temmuz\0" "A\xc4\x9fustos\0" "Eyl\xc3\xbcl\0" "Ekim\0" "Kas\xc4\xb1m\0" "Aral\xc4\xb1k\0" "Oca\0" "\xc5\x9eub\0" "Nis\0" "Haz\0" "Tem\0" "A\xc4\x9fu\0" "Eyl\0" "Eki\0" "Kas\0" "Ara\0" "d.MM.yyyy\0" "d MMMM yyyy dddd\0" "\xd9\x82\xd8\xa8\xd9\x84 \xd8\xaf\xd9\x88\xd9\xbe\xdb\x81\xd8\xb1\0" "\xd8\xa8\xd8\xb9\xd8\xaf \xd8\xaf\xd9\x88\xd9\xbe\xdb\x81\xd8\xb1\0" "\xd8\xa7\xd8\xaa\xd9\x88\xd8\xa7\xd8\xb1\0" "\xd8\xb3\xd9\x88\xd9\x85\xd9\x88\xd8\xa7\xd8\xb1\0" "\xd9\x85\xd9\x86\xda\xaf\xd9\x84\0" "\xd8\xa8\xd8\xaf\xda\xbe\0" "\xd8\xac\xd9\x85\xd8\xb9\xd8\xb1\xd8\xa7\xd8\xaa\0" "\xd8\xac\xd9\x85\xd8\xb9\xdb\x81\0" "\xdb\x81\xd9\x81\xd8\xaa\xdb\x81\0" "\xd8\xac\xd9\x86\xd9\x88\xd8\xb1\xdb\x8c\0" "\xd9\x81\xd8\xb1\xd9\x88\xd8\xb1\xdb\x8c\0" "\xd9\x85\xd8\xa7\xd8\xb1\xda\x86\0" "\xd8\xa7\xd9\xbe\xd8\xb1\xdb\x8c\xd9\x84\0" "\xd9\x85\xd8\xa6\xdb\x8c\0" "\xd8\xac\xd9\x88\xd9\x86\0" "\xd8\xac\xd9\x88\xd9\x84\xd8\xa7\xd8\xa6\xdb\x8c\0" "\xd8\xa7\xda\xaf\xd8\xb3\xd8\xaa\0" "\xd8\xb3\xd8\xaa\xd9\x85\xd8\xa8\xd8\xb1\0" "\xd8\xa7\xda\xa9\xd8\xaa\xd9\x88\xd8\xa8\xd8\xb1\0" "\xd9\x86\xd9\x88\xd9\x85\xd8\xa8\xd8\xb1\0" "\xd8\xaf\xd8\xb3\xd9\x85\xd8\xa8\xd8\xb1\0" "dd MMMM, yyyy\0" "Minggu\0" "Senin\0" "Selasa\0" "Rabu\0" "Kamis\0" "Jumat\0" "Sabtu\0" "Min\0" "Sen\0" "Sel\0" "Rab\0" "Kam\0" "Jum\0" "Sab\0" "R\0" "Januari\0" "Februari\0" "Maret\0" "Mei\0" "Agustus\0" "Desember\0" "Agt\0" "Des\0" "dddd, dd MMMM yyyy\0" "\xd0\xb4\xd0\xbf\0" "\xd0\xbf\xd0\xbf\0" "\xd0\xbd\xd0\xb5\xd0\xb4\xd1\x96\xd0\xbb\xd1\x8f\0" "\xd0\xbf\xd0\xbe\xd0\xbd\xd0\xb5\xd0\xb4\xd1\x96\xd0\xbb\xd0\xbe\xd0\xba\0" "\xd0\xb2\xd1\x96\xd0\xb2\xd1\x82\xd0\xbe\xd1\x80\xd0\xbe\xd0\xba\0" "\xd1\x81\xd0\xb5\xd1\x80\xd0\xb5\xd0\xb4\xd0\xb0\0" "\xd1\x87\xd0\xb5\xd1\x82\xd0\xb2\xd0\xb5\xd1\x80\0" "\xd0\xbf\xca\xbc\xd1\x8f\xd1\x82\xd0\xbd\xd0\xb8\xd1\x86\xd1\x8f\0" "\xd1\x81\xd1\x83\xd0\xb1\xd0\xbe\xd1\x82\xd0\xb0\0" "\xd0\x9d\xd0\xb4\0" "\xd0\x9d\0" "\xd0\xa1\xd1\x96\xd1\x87\xd0\xb5\xd0\xbd\xd1\x8c\0" "\xd0\x9b\xd1\x8e\xd1\x82\xd0\xb8\xd0\xb9\0" "\xd0\x91\xd0\xb5\xd1\x80\xd0\xb5\xd0\xb7\xd0\xb5\xd0\xbd\xd1\x8c\0" "\xd0\x9a\xd0\xb2\xd1\x96\xd1\x82\xd0\xb5\xd0\xbd\xd1\x8c\0" "\xd0\xa2\xd1\x80\xd0\xb0\xd0\xb2\xd0\xb5\xd0\xbd\xd1\x8c\0" "\xd0\xa7\xd0\xb5\xd1\x80\xd0\xb2\xd0\xb5\xd0\xbd\xd1\x8c\0" "\xd0\x9b\xd0\xb8\xd0\xbf\xd0\xb5\xd0\xbd\xd1\x8c\0" "\xd0\xa1\xd0\xb5\xd1\x80\xd0\xbf\xd0\xb5\xd0\xbd\xd1\x8c\0" "\xd0\x92\xd0\xb5\xd1\x80\xd0\xb5\xd1\x81\xd0\xb5\xd0\xbd\xd1\x8c\0" "\xd0\x96\xd0\xbe\xd0\xb2\xd1\x82\xd0\xb5\xd0\xbd\xd1\x8c\0" "\xd0\x9b\xd0\xb8\xd1\x81\xd1\x82\xd0\xbe\xd0\xbf\xd0\xb0\xd0\xb4\0" "\xd0\x93\xd1\x80\xd1\x83\xd0\xb4\xd0\xb5\xd0\xbd\xd1\x8c\0" "\xd1\x81\xd1\x96\xd1\x87\xd0\xbd\xd1\x8f\0" "\xd0\xbb\xd1\x8e\xd1\x82\xd0\xbe\xd0\xb3\xd0\xbe\0" "\xd0\xb1\xd0\xb5\xd1\x80\xd0\xb5\xd0\xb7\xd0\xbd\xd1\x8f\0" "\xd0\xba\xd0\xb2\xd1\x96\xd1\x82\xd0\xbd\xd1\x8f\0" "\xd1\x82\xd1\x80\xd0\xb0\xd0\xb2\xd0\xbd\xd1\x8f\0" "\xd1\x87\xd0\xb5\xd1\x80\xd0\xb2\xd0\xbd\xd1\x8f\0" "\xd0\xbb\xd0\xb8\xd0\xbf\xd0\xbd\xd1\x8f\0" "\xd1\x81\xd0\xb5\xd1\x80\xd0\xbf\xd0\xbd\xd1\x8f\0" "\xd0\xb2\xd0\xb5\xd1\x80\xd0\xb5\xd1\x81\xd0\xbd\xd1\x8f\0" "\xd0\xb6\xd0\xbe\xd0\xb2\xd1\x82\xd0\xbd\xd1\x8f\0" "\xd0\xbb\xd0\xb8\xd1\x81\xd1\x82\xd0\xbe\xd0\xbf\xd0\xb0\xd0\xb4\xd0\xb0\0" "\xd0\xb3\xd1\x80\xd1\x83\xd0\xb4\xd0\xbd\xd1\x8f\0" "\xd0\xa1\xd1\x96\xd1\x87\0" "\xd0\x9b\xd1\x8e\xd1\x82\0" "\xd0\x91\xd0\xb5\xd1\x80\0" "\xd0\x9a\xd0\xb2\xd1\x96\0" "\xd0\xa2\xd1\x80\xd0\xb0\0" "\xd0\xa7\xd0\xb5\xd1\x80\0" "\xd0\x9b\xd0\xb8\xd0\xbf\0" "\xd0\xa1\xd0\xb5\xd1\x80\0" "\xd0\x92\xd0\xb5\xd1\x80\0" "\xd0\x96\xd0\xbe\xd0\xb2\0" "\xd0\x9b\xd0\xb8\xd1\x81\0" "\xd0\x93\xd1\x80\xd1\x83\0" "d MMMM yyyy' \xd1\x80.'\0" "MMMM yyyy' \xd1\x80.'\0" "\xd1\x80\xd0\xb0\xd0\xbd\xd1\x96\xd1\x86\xd1\x8b\0" "\xd0\xb2\xd0\xb5\xd1\x87\xd0\xb0\xd1\x80\xd0\xb0\0" "\xd0\xbd\xd1\x8f\xd0\xb4\xd0\xb7\xd0\xb5\xd0\xbb\xd1\x8f\0" "\xd0\xbf\xd0\xb0\xd0\xbd\xd1\x8f\xd0\xb4\xd0\xb7\xd0\xb5\xd0\xbb\xd0\xb0\xd0\xba\0" "\xd0\xb0\xd1\x9e\xd1\x82\xd0\xbe\xd1\x80\xd0\xb0\xd0\xba\0" "\xd1\x81\xd0\xb5\xd1\x80\xd0\xb0\xd0\xb4\xd0\xb0\0" "\xd1\x87\xd0\xb0\xd1\x86\xd0\xb2\xd0\xb5\xd1\x80\0" "\xd0\xbf\xd1\x8f\xd1\x82\xd0\xbd\xd1\x96\xd1\x86\xd0\xb0\0" "\xd0\xb0\xd1\x9e\0" "\xd1\x87\xd1\x86\0" "\xd0\xb0\0" "\xd1\x81\xd1\x82\xd1\x83\xd0\xb4\xd0\xb7\xd0\xb5\xd0\xbd\xd1\x8c\0" "\xd0\xbb\xd1\x8e\xd1\x82\xd1\x8b\0" "\xd1\x81\xd0\xb0\xd0\xba\xd0\xb0\xd0\xb2\xd1\x96\xd0\xba\0" "\xd0\xba\xd1\x80\xd0\xb0\xd1\x81\xd0\xb0\xd0\xb2\xd1\x96\xd0\xba\0" "\xd1\x87\xd1\x8d\xd1\x80\xd0\xb2\xd0\xb5\xd0\xbd\xd1\x8c\0" "\xd0\xbb\xd1\x96\xd0\xbf\xd0\xb5\xd0\xbd\xd1\x8c\0" "\xd0\xb6\xd0\xbd\xd1\x96\xd0\xb2\xd0\xb5\xd0\xbd\xd1\x8c\0" "\xd0\xb2\xd0\xb5\xd1\x80\xd0\xb0\xd1\x81\xd0\xb5\xd0\xbd\xd1\x8c\0" "\xd0\xba\xd0\xb0\xd1\x81\xd1\x82\xd1\x80\xd1\x8b\xd1\x87\xd0\xbd\xd1\x96\xd0\xba\0" "\xd0\xbb\xd1\x96\xd1\x81\xd1\x82\xd0\xb0\xd0\xbf\xd0\xb0\xd0\xb4\0" "\xd1\x81\xd0\xbd\xd0\xb5\xd0\xb6\xd0\xb0\xd0\xbd\xd1\x8c\0" "\xd1\x81\xd1\x82\xd1\x83\xd0\xb4\xd0\xb7\xd0\xb5\xd0\xbd\xd1\x8f\0" "\xd0\xbb\xd1\x8e\xd1\x82\xd0\xb0\xd0\xb3\xd0\xb0\0" "\xd1\x81\xd0\xb0\xd0\xba\xd0\xb0\xd0\xb2\xd1\x96\xd0\xba\xd0\xb0\0" "\xd0\xba\xd1\x80\xd0\xb0\xd1\x81\xd0\xb0\xd0\xb2\xd1\x96\xd0\xba\xd0\xb0\0" "\xd1\x87\xd1\x8d\xd1\x80\xd0\xb2\xd0\xb5\xd0\xbd\xd1\x8f\0" "\xd0\xbb\xd1\x96\xd0\xbf\xd0\xb5\xd0\xbd\xd1\x8f\0" "\xd0\xb6\xd0\xbd\xd1\x96\xd1\x9e\xd0\xbd\xd1\x8f\0" "\xd0\xb2\xd0\xb5\xd1\x80\xd0\xb0\xd1\x81\xd0\xbd\xd1\x8f\0" "\xd0\xba\xd0\xb0\xd1\x81\xd1\x82\xd1\x80\xd1\x8b\xd1\x87\xd0\xbd\xd1\x96\xd0\xba\xd0\xb0\0" "\xd0\xbb\xd1\x96\xd1\x81\xd1\x82\xd0\xb0\xd0\xbf\xd0\xb0\xd0\xb4\xd0\xb0\0" "\xd1\x81\xd0\xbd\xd0\xb5\xd0\xb6\xd0\xbd\xd1\x8f\0" "\xd1\x81\xd1\x82\xd1\x83\0" "\xd0\xbb\xd1\x8e\xd1\x82\0" "\xd1\x81\xd0\xb0\xd0\xba\0" "\xd0\xba\xd1\x80\xd0\xb0\0" "\xd1\x87\xd1\x8d\xd1\x80\0" "\xd0\xbb\xd1\x96\xd0\xbf\0" "\xd0\xb6\xd0\xbd\xd1\x96\0" "\xd0\xb2\xd0\xb5\xd1\x80\0" "\xd0\xba\xd0\xb0\xd1\x81\0" "\xd0\xbb\xd1\x96\xd1\x81\0" "\xd1\x81\xd0\xbd\xd0\xb5\0" "MMMM yyyy \xd0\xb3.\0" "dop.\0" "pop.\0" "nedelja\0" "ponedeljek\0" "torek\0" "sreda\0" "\xc4\x8d\x65trtek\0" "petek\0" "sre\0" "sob\0" "t\0" "junij\0" "julij\0" "avgust\0" "avg\0" "d. MM. yyyy\0" "dddd, dd. MMMM yyyy\0" "dd. MMMM yyyy\0" "e.k.\0" "p.k.\0" "p\xc3\xbchap\xc3\xa4\x65v\0" "esmasp\xc3\xa4\x65v\0" "teisip\xc3\xa4\x65v\0" "kolmap\xc3\xa4\x65v\0" "neljap\xc3\xa4\x65v\0" "reede\0" "laup\xc3\xa4\x65v\0" "jaanuar\0" "veebruar\0" "m\xc3\xa4rts\0" "aprill\0" "juuni\0" "juuli\0" "oktoober\0" "detsember\0" "jaan\0" "veebr\0" "sept\0" "dets\0" "H:mm.ss\0" "priek\xc5\xa1pusdien\xc4\x81\0" "p\xc4\x93\x63pusdien\xc4\x81\0" "sv\xc4\x93tdiena\0" "pirmdiena\0" "otrdiena\0" "tre\xc5\xa1\x64iena\0" "ceturtdiena\0" "piektdiena\0" "sestdiena\0" "Sv\0" "Pr\0" "Ot\0" "Tr\0" "Ce\0" "Pk\0" "Se\0" "Janv\xc4\x81ris\0" "Febru\xc4\x81ris\0" "Marts\0" "Apr\xc4\xablis\0" "Maijs\0" "J\xc5\xabnijs\0" "J\xc5\xablijs\0" "Augusts\0" "Septembris\0" "Oktobris\0" "Novembris\0" "Decembris\0" "janv\xc4\x81ris\0" "febru\xc4\x81ris\0" "apr\xc4\xablis\0" "maijs\0" "j\xc5\xabnijs\0" "j\xc5\xablijs\0" "augusts\0" "septembris\0" "oktobris\0" "novembris\0" "decembris\0" "Janv.\0" "Febr.\0" "Apr.\0" "J\xc5\xabn.\0" "J\xc5\xabl.\0" "Aug.\0" "Okt.\0" "Dec.\0" "yyyy. 'gada' d. MMM\0" "dddd, yyyy. 'gada' d. MMMM\0" "yyyy. 'gada' d. MMMM\0" "yyyy. 'g'. MMMM\0" "pr.p.\0" "sekmadienis\0" "pirmadienis\0" "antradienis\0" "tre\xc4\x8diadienis\0" "ketvirtadienis\0" "penktadienis\0" "\xc5\xa1\x65\xc5\xa1tadienis\0" "sk\0" "pr\0" "an\0" "tr\0" "kt\0" "pn\0" "A\0" "sausis\0" "vasaris\0" "kovas\0" "balandis\0" "gegu\xc5\xbe\xc4\x97\0" "bir\xc5\xbe\x65lis\0" "liepa\0" "rugpj\xc5\xabtis\0" "rugs\xc4\x97jis\0" "spalis\0" "lapkritis\0" "gruodis\0" "saus.\0" "vas.\0" "kov.\0" "bal.\0" "geg.\0" "bir\xc5\xbe.\0" "liep.\0" "rugp.\0" "rugs.\0" "spal.\0" "lapkr.\0" "gruod.\0" "yyyy 'm'. MMMM d 'd'., dddd\0" "yyyy 'm'. MMMM d 'd'.\0" "yyyy MMMM\0" "\xd0\xbf\xd0\xb5. \xd1\x87\xd0\xbe.\0" "\xd0\xbf\xd0\xb0. \xd1\x87\xd0\xbe.\0" "\xd0\xaf\xd0\xba\xd1\x88\xd0\xb0\xd0\xbd\xd0\xb1\xd0\xb5\0" "\xd0\x94\xd1\x83\xd1\x88\xd0\xb0\xd0\xbd\xd0\xb1\xd0\xb5\0" "\xd0\xa1\xd0\xb5\xd1\x88\xd0\xb0\xd0\xbd\xd0\xb1\xd0\xb5\0" "\xd0\xa7\xd0\xbe\xd1\x80\xd1\x88\xd0\xb0\xd0\xbd\xd0\xb1\xd0\xb5\0" "\xd0\x9f\xd0\xb0\xd0\xbd\xd2\xb7\xd1\x88\xd0\xb0\xd0\xbd\xd0\xb1\xd0\xb5\0" "\xd2\xb6\xd1\x83\xd0\xbc\xd1\x8a\xd0\xb0\0" "\xd0\xa8\xd0\xb0\xd0\xbd\xd0\xb1\xd0\xb5\0" "\xd0\xaf\xd1\x88\xd0\xb1\0" "\xd0\x94\xd1\x88\xd0\xb1\0" "\xd0\xa1\xd1\x88\xd0\xb1\0" "\xd0\xa7\xd1\x88\xd0\xb1\0" "\xd0\x9f\xd1\x88\xd0\xb1\0" "\xd2\xb6\xd0\xbc\xd1\x8a\0" "\xd0\xa8\xd0\xbd\xd0\xb1\0" "\xd0\xaf\xd0\xbd\xd0\xb2\xd0\xb0\xd1\x80\0" "\xd0\xa4\xd0\xb5\xd0\xb2\xd1\x80\xd0\xb0\xd0\xbb\0" "\xd0\x90\xd0\xbf\xd1\x80\xd0\xb5\xd0\xbb\0" "\xd0\x98\xd1\x8e\xd0\xbd\0" "\xd0\x98\xd1\x8e\xd0\xbb\0" "\xd0\xa1\xd0\xb5\xd0\xbd\xd1\x82\xd1\x8f\xd0\xb1\xd1\x80\0" "\xd0\x9e\xd0\xba\xd1\x82\xd1\x8f\xd0\xb1\xd1\x80\0" "\xd0\x9d\xd0\xbe\xd1\x8f\xd0\xb1\xd1\x80\0" "\xd0\x94\xd0\xb5\xd0\xba\xd0\xb0\xd0\xb1\xd1\x80\0" "\xd0\xaf\xd0\xbd\xd0\xb2\0" "\xd0\xa4\xd0\xb5\xd0\xb2\0" "\xd0\x9c\xd0\xb0\xd1\x80\0" "\xd0\x90\xd0\xbf\xd1\x80\0" "\xd0\x90\xd0\xb2\xd0\xb3\0" "\xd0\xa1\xd0\xb5\xd0\xbd\0" "\xd0\x9e\xd0\xba\xd1\x82\0" "\xd0\x9d\xd0\xbe\xd1\x8f\0" "\xd0\x94\xd0\xb5\xd0\xba\0" "d MMMM yyyy' \xd1\x81.'\0" "dd MMMM yyyy' \xd1\x81.'\0" "\xd9\x82\xd8\xa8\xd9\x84\xe2\x80\x8c\xd8\xa7\xd8\xb2\xd8\xb8\xd9\x87\xd8\xb1\0" "\xd8\xa8\xd8\xb9\xd8\xaf\xd8\xa7\xd8\xb2\xd8\xb8\xd9\x87\xd8\xb1\0" "\xdb\x8c\xda\xa9\xd8\xb4\xd9\x86\xd8\xa8\xd9\x87\0" "\xd8\xaf\xd9\x88\xd8\xb4\xd9\x86\xd8\xa8\xd9\x87\0" "\xd8\xb3\xd9\x87\xe2\x80\x8c\xd8\xb4\xd9\x86\xd8\xa8\xd9\x87\0" "\xda\x86\xd9\x87\xd8\xa7\xd8\xb1\xd8\xb4\xd9\x86\xd8\xa8\xd9\x87\0" "\xd9\xbe\xd9\x86\xd8\xac\xd8\xb4\xd9\x86\xd8\xa8\xd9\x87\0" "\xd8\xac\xd9\x85\xd8\xb9\xd9\x87\0" "\xd8\xb4\xd9\x86\xd8\xa8\xd9\x87\0" "\xdb\x8c\0" "\xd8\xaf\0" "\xd8\xb3\0" "\xda\x86\0" "\xd9\xbe\0" "\xd8\xac\0" "\xd8\xb4\0" "\xda\x98\xd8\xa7\xd9\x86\xd9\x88\xdb\x8c\xd9\x87\0" "\xd9\x81\xd9\x88\xd8\xb1\xdb\x8c\xd9\x87\0" "\xd9\x85\xd8\xa7\xd8\xb1\xd8\xb3\0" "\xd8\xa2\xd9\x88\xd8\xb1\xdb\x8c\xd9\x84\0" "\xd9\x85\xd9\x87\0" "\xda\x98\xd9\x88\xd8\xa6\xd9\x86\0" "\xda\x98\xd9\x88\xd8\xa6\xdb\x8c\xd9\x87\0" "\xd8\xa7\xd9\x88\xd8\xaa\0" "\xd8\xb3\xd9\xbe\xd8\xaa\xd8\xa7\xd9\x85\xd8\xa8\xd8\xb1\0" "\xd8\xa7\xda\xa9\xd8\xaa\xd8\xa8\xd8\xb1\0" "\xd9\x86\xd9\x88\xd8\xa7\xd9\x85\xd8\xa8\xd8\xb1\0" "\xd8\xaf\xd8\xb3\xd8\xa7\xd9\x85\xd8\xa8\xd8\xb1\0" "\xda\x98\xd8\xa7\xd9\x86\xd9\x88\xdb\x8c\xd9\x87\xd9\x94\0" "\xd9\x81\xd9\x88\xd8\xb1\xdb\x8c\xd9\x87\xd9\x94\0" "\xd9\x85\xd9\x87\xd9\x94\0" "\xda\x98\xd9\x88\xd8\xa6\xdb\x8c\xd9\x87\xd9\x94\0" "SA\0" "CH\0" "Ch\xe1\xbb\xa7 Nh\xe1\xba\xadt\0" "Th\xe1\xbb\xa9 Hai\0" "Th\xe1\xbb\xa9 Ba\0" "Th\xe1\xbb\xa9 T\xc6\xb0\0" "Th\xe1\xbb\xa9 N\xc4\x83m\0" "Th\xe1\xbb\xa9 S\xc3\xa1u\0" "Th\xe1\xbb\xa9 B\xe1\xba\xa3y\0" "CN\0" "Th 2\0" "Th 3\0" "Th 4\0" "Th 5\0" "Th 6\0" "Th 7\0" "T2\0" "T3\0" "T4\0" "T5\0" "T6\0" "T7\0" "Th\xc3\xa1ng 1\0" "Th\xc3\xa1ng 2\0" "Th\xc3\xa1ng 3\0" "Th\xc3\xa1ng 4\0" "Th\xc3\xa1ng 5\0" "Th\xc3\xa1ng 6\0" "Th\xc3\xa1ng 7\0" "Th\xc3\xa1ng 8\0" "Th\xc3\xa1ng 9\0" "Th\xc3\xa1ng 10\0" "Th\xc3\xa1ng 11\0" "Th\xc3\xa1ng 12\0" "th\xc3\xa1ng 1\0" "th\xc3\xa1ng 2\0" "th\xc3\xa1ng 3\0" "th\xc3\xa1ng 4\0" "th\xc3\xa1ng 5\0" "th\xc3\xa1ng 6\0" "th\xc3\xa1ng 7\0" "th\xc3\xa1ng 8\0" "th\xc3\xa1ng 9\0" "th\xc3\xa1ng 10\0" "th\xc3\xa1ng 11\0" "th\xc3\xa1ng 12\0" "Thg 1\0" "Thg 2\0" "Thg 3\0" "Thg 4\0" "Thg 5\0" "Thg 6\0" "Thg 7\0" "Thg 8\0" "Thg 9\0" "Thg 10\0" "Thg 11\0" "Thg 12\0" "\xd5\xaf\xd5\xa5\xd5\xbd\xd6\x85\xd6\x80\xd5\xab\xd6\x81 \xd5\xa1\xd5\xbc\xd5\xa1\xd5\xbb\0" "\xd5\xaf\xd5\xa5\xd5\xbd\xd6\x85\xd6\x80\xd5\xab\xd6\x81 \xd5\xb0\xd5\xa5\xd5\xbf\xd5\xb8\0" "\xd5\xaf\xd5\xab\xd6\x80\xd5\xa1\xd5\xaf\xd5\xab\0" "\xd5\xa5\xd6\x80\xd5\xaf\xd5\xb8\xd6\x82\xd5\xb7\xd5\xa1\xd5\xa2\xd5\xa9\xd5\xab\0" "\xd5\xa5\xd6\x80\xd5\xa5\xd6\x84\xd5\xb7\xd5\xa1\xd5\xa2\xd5\xa9\xd5\xab\0" "\xd5\xb9\xd5\xb8\xd6\x80\xd5\xa5\xd6\x84\xd5\xb7\xd5\xa1\xd5\xa2\xd5\xa9\xd5\xab\0" "\xd5\xb0\xd5\xab\xd5\xb6\xd5\xa3\xd5\xb7\xd5\xa1\xd5\xa2\xd5\xa9\xd5\xab\0" "\xd5\xb8\xd6\x82\xd6\x80\xd5\xa2\xd5\xa1\xd5\xa9\0" "\xd5\xb7\xd5\xa1\xd5\xa2\xd5\xa1\xd5\xa9\0" "\xd5\xaf\xd5\xab\xd6\x80\0" "\xd5\xa5\xd6\x80\xd5\xaf\0" "\xd5\xa5\xd6\x80\xd6\x84\0" "\xd5\xb9\xd6\x80\xd6\x84\0" "\xd5\xb0\xd5\xb6\xd5\xa3\0" "\xd5\xb8\xd6\x82\xd6\x80\0" "\xd5\xb7\xd5\xa2\xd5\xa9\0" "\xd4\xbf\0" "\xd4\xb5\0" "\xd5\x89\0" "\xd5\x80\0" "\xd5\x88\xd6\x82\0" "\xd5\x87\0" "\xd5\xb0\xd5\xb8\xd6\x82\xd5\xb6\xd5\xbe\xd5\xa1\xd6\x80\0" "\xd6\x83\xd5\xa5\xd5\xbf\xd6\x80\xd5\xbe\xd5\xa1\xd6\x80\0" "\xd5\xb4\xd5\xa1\xd6\x80\xd5\xbf\0" "\xd5\xa1\xd5\xba\xd6\x80\xd5\xab\xd5\xac\0" "\xd5\xb4\xd5\xa1\xd5\xb5\xd5\xab\xd5\xbd\0" "\xd5\xb0\xd5\xb8\xd6\x82\xd5\xb6\xd5\xab\xd5\xbd\0" "\xd5\xb0\xd5\xb8\xd6\x82\xd5\xac\xd5\xab\xd5\xbd\0" "\xd6\x85\xd5\xa3\xd5\xb8\xd5\xbd\xd5\xbf\xd5\xb8\xd5\xbd\0" "\xd5\xbd\xd5\xa5\xd5\xba\xd5\xbf\xd5\xa5\xd5\xb4\xd5\xa2\xd5\xa5\xd6\x80\0" "\xd5\xb0\xd5\xb8\xd5\xaf\xd5\xbf\xd5\xa5\xd5\xb4\xd5\xa2\xd5\xa5\xd6\x80\0" "\xd5\xb6\xd5\xb8\xd5\xb5\xd5\xa5\xd5\xb4\xd5\xa2\xd5\xa5\xd6\x80\0" "\xd5\xa4\xd5\xa5\xd5\xaf\xd5\xbf\xd5\xa5\xd5\xb4\xd5\xa2\xd5\xa5\xd6\x80\0" "\xd5\xb0\xd5\xb8\xd6\x82\xd5\xb6\xd5\xbe\xd5\xa1\xd6\x80\xd5\xab\0" "\xd6\x83\xd5\xa5\xd5\xbf\xd6\x80\xd5\xbe\xd5\xa1\xd6\x80\xd5\xab\0" "\xd5\xb4\xd5\xa1\xd6\x80\xd5\xbf\xd5\xab\0" "\xd5\xa1\xd5\xba\xd6\x80\xd5\xab\xd5\xac\xd5\xab\0" "\xd5\xb4\xd5\xa1\xd5\xb5\xd5\xab\xd5\xbd\xd5\xab\0" "\xd5\xb0\xd5\xb8\xd6\x82\xd5\xb6\xd5\xab\xd5\xbd\xd5\xab\0" "\xd5\xb0\xd5\xb8\xd6\x82\xd5\xac\xd5\xab\xd5\xbd\xd5\xab\0" "\xd6\x85\xd5\xa3\xd5\xb8\xd5\xbd\xd5\xbf\xd5\xb8\xd5\xbd\xd5\xab\0" "\xd5\xbd\xd5\xa5\xd5\xba\xd5\xbf\xd5\xa5\xd5\xb4\xd5\xa2\xd5\xa5\xd6\x80\xd5\xab\0" "\xd5\xb0\xd5\xb8\xd5\xaf\xd5\xbf\xd5\xa5\xd5\xb4\xd5\xa2\xd5\xa5\xd6\x80\xd5\xab\0" "\xd5\xb6\xd5\xb8\xd5\xb5\xd5\xa5\xd5\xb4\xd5\xa2\xd5\xa5\xd6\x80\xd5\xab\0" "\xd5\xa4\xd5\xa5\xd5\xaf\xd5\xbf\xd5\xa5\xd5\xb4\xd5\xa2\xd5\xa5\xd6\x80\xd5\xab\0" "\xd5\xb0\xd5\xb6\xd5\xbe\0" "\xd6\x83\xd5\xbf\xd5\xbe\0" "\xd5\xb4\xd6\x80\xd5\xbf\0" "\xd5\xa1\xd5\xba\xd6\x80\0" "\xd5\xb4\xd5\xb5\xd5\xbd\0" "\xd5\xb0\xd5\xb6\xd5\xbd\0" "\xd5\xb0\xd5\xac\xd5\xbd\0" "\xd6\x85\xd5\xa3\xd5\xbd\0" "\xd5\xbd\xd5\xba\xd5\xbf\0" "\xd5\xb0\xd5\xaf\xd5\xbf\0" "\xd5\xb6\xd5\xb5\xd5\xb4\0" "\xd5\xa4\xd5\xaf\xd5\xbf\0" "d/MM/yyyy\0" "d/MMM/yyyy\0" "d-MMM-yyyy\0" "dd-MMM-yyyy\0" "ddd, d-MMMM-yyyy\0" "ddd, dd-MMMM-yyyy\0" "bazar\0" "bazar ert\xc9\x99si\0" "\xc3\xa7\xc9\x99r\xc5\x9f\xc9\x99nb\xc9\x99 ax\xc5\x9f\x61m\xc4\xb1\0" "\xc3\xa7\xc9\x99r\xc5\x9f\xc9\x99nb\xc9\x99\0" "c\xc3\xbcm\xc9\x99 ax\xc5\x9f\x61m\xc4\xb1\0" "c\xc3\xbcm\xc9\x99\0" "\xc5\x9f\xc9\x99nb\xc9\x99\0" "B.\0" "B.E.\0" "\xc3\x87.A.\0" "\xc3\x87.\0" "C.A.\0" "\xc5\x9e.\0" "Yanvar\0" "Fevral\0" "Aprel\0" "\xc4\xb0yun\0" "\xc4\xb0yul\0" "Avqust\0" "Sentyabr\0" "Oktyabr\0" "Noyabr\0" "Dekabr\0" "yanvar\0" "fevral\0" "mart\0" "aprel\0" "may\0" "iyun\0" "iyul\0" "avqust\0" "sentyabr\0" "oktyabr\0" "noyabr\0" "dekabr\0" "yan\0" "iyn\0" "iyl\0" "avq\0" "sen\0" "noy\0" "dek\0" "d MMMM yyyy, dddd\0" "igandea\0" "astelehena\0" "asteartea\0" "asteazkena\0" "osteguna\0" "ostirala\0" "larunbata\0" "ig.\0" "al.\0" "ar.\0" "az.\0" "og.\0" "or.\0" "lr.\0" "I\0" "urtarrila\0" "otsaila\0" "martxoa\0" "apirila\0" "maiatza\0" "ekaina\0" "uztaila\0" "abuztua\0" "iraila\0" "urria\0" "azaroa\0" "abendua\0" "urtarrilak\0" "otsailak\0" "martxoak\0" "apirilak\0" "maiatzak\0" "ekainak\0" "uztailak\0" "abuztuak\0" "irailak\0" "urriak\0" "azaroak\0" "abenduak\0" "urt.\0" "ots.\0" "api.\0" "mai.\0" "eka.\0" "uzt.\0" "abu.\0" "ira.\0" "urr.\0" "aza.\0" "abe.\0" "yyyy MMM d\0" "yyyy('e')'ko' MMMM d, dddd\0" "yyyy('e')'ko' MMMM d\0" "yyyy('e')'ko' MMMM\0" "\xd0\xbf\xd1\x80\xd0\xb5\xd1\x82\xd0\xbf\xd0\xbb\xd0\xb0\xd0\xb4\xd0\xbd\xd0\xb5\0" "\xd0\xbf\xd0\xbe\xd0\xbf\xd0\xbb\xd0\xb0\xd0\xb4\xd0\xbd\xd0\xb5\0" "\xd0\xbd\xd0\xb5\xd0\xb4\xd0\xb5\xd0\xbb\xd0\xb0\0" "\xd1\x87\xd0\xb5\xd1\x82\xd0\xb2\xd1\x80\xd1\x82\xd0\xbe\xd0\xba\0" "\xd0\xbf\xd0\xb5\xd1\x82\xd0\xbe\xd0\xba\0" "\xd1\x81\xd0\xb0\xd0\xb1\xd0\xbe\xd1\x82\xd0\xb0\0" "\xd0\xbd\xd0\xb5\xd0\xb4.\0" "\xd0\xbf\xd0\xbe\xd0\xbd.\0" "\xd0\xb2\xd1\x82.\0" "\xd1\x81\xd1\x80\xd0\xb5.\0" "\xd1\x87\xd0\xb5\xd1\x82.\0" "\xd0\xbf\xd0\xb5\xd1\x82.\0" "\xd1\x81\xd0\xb0\xd0\xb1.\0" "\xd1\x98\xd0\xb0\xd0\xbd\xd1\x83\xd0\xb0\xd1\x80\xd0\xb8\0" "\xd0\xbc\xd0\xb0\xd1\x98\0" "\xd1\x98\xd1\x83\xd0\xbd\xd0\xb8\0" "\xd1\x98\xd1\x83\xd0\xbb\xd0\xb8\0" "\xd1\x98\xd0\xb0\xd0\xbd.\0" "\xd1\x84\xd0\xb5\xd0\xb2.\0" "\xd0\xbc\xd0\xb0\xd1\x80.\0" "\xd1\x98\xd1\x83\xd0\xbd.\0" "\xd1\x98\xd1\x83\xd0\xbb.\0" "dd.M.yyyy\0" "MMMM yyyy '\xd0\xb3'.\0" "Tshipi\0" "Mosopulogo\0" "Labobedi\0" "Laboraro\0" "Labone\0" "Labotlhano\0" "Matlhatso\0" "Tsh\0" "Mos\0" "Bed\0" "Rar\0" "Ne\0" "Tla\0" "Mat\0" "Ferikgong\0" "Tlhakole\0" "Mopitlo\0" "Moranang\0" "Motsheganang\0" "Seetebosigo\0" "Phukwi\0" "Phatwe\0" "Lwetse\0" "Diphalane\0" "Ngwanatsele\0" "Sedimonthole\0" "Fer\0" "Tlh\0" "Mop\0" "Mor\0" "Mot\0" "See\0" "Phu\0" "Pha\0" "Lwe\0" "Dip\0" "Ngw\0" "Sed\0" "yyyy MMMM d, dddd\0" "yyyy MMMM d\0" "Cawe\0" "Mvulo\0" "Lwesibini\0" "Lwesithathu\0" "Lwesine\0" "Lwesihlanu\0" "Mgqibelo\0" "Caw\0" "Mvu\0" "Bin\0" "Tha\0" "Sin\0" "Hla\0" "Mgq\0" "Janyuwari\0" "Februwari\0" "Matshi\0" "Epreli\0" "Meyi\0" "Julayi\0" "Agasti\0" "Septemba\0" "Okthoba\0" "Novemba\0" "Disemba\0" "Epr\0" "Mey\0" "Aga\0" "Dis\0" "Sonto\0" "Msombuluko\0" "Lwesibili\0" "Son\0" "Mso\0" "Bil\0" "B\0" "uJanuwari\0" "uFebruwari\0" "uMashi\0" "u-Apreli\0" "uMeyi\0" "uJuni\0" "uJulayi\0" "uAgasti\0" "uSepthemba\0" "u-Okthoba\0" "uNovemba\0" "uDisemba\0" "Januwari\0" "Mashi\0" "Apreli\0" "Septhemba\0" "Mas\0" "MMM d, yyyy\0" "vm.\0" "nm.\0" "Sondag\0" "Maandag\0" "Dinsdag\0" "Woensdag\0" "Donderdag\0" "Vrydag\0" "Saterdag\0" "Ma\0" "Wo\0" "Vr\0" "Januarie\0" "Februarie\0" "Maart\0" "Junie\0" "Julie\0" "Augustus\0" "\xe1\x83\x99\xe1\x83\x95\xe1\x83\x98\xe1\x83\xa0\xe1\x83\x90\0" "\xe1\x83\x9d\xe1\x83\xa0\xe1\x83\xa8\xe1\x83\x90\xe1\x83\x91\xe1\x83\x90\xe1\x83\x97\xe1\x83\x98\0" "\xe1\x83\xa1\xe1\x83\x90\xe1\x83\x9b\xe1\x83\xa8\xe1\x83\x90\xe1\x83\x91\xe1\x83\x90\xe1\x83\x97\xe1\x83\x98\0" "\xe1\x83\x9d\xe1\x83\x97\xe1\x83\xae\xe1\x83\xa8\xe1\x83\x90\xe1\x83\x91\xe1\x83\x90\xe1\x83\x97\xe1\x83\x98\0" "\xe1\x83\xae\xe1\x83\xa3\xe1\x83\x97\xe1\x83\xa8\xe1\x83\x90\xe1\x83\x91\xe1\x83\x90\xe1\x83\x97\xe1\x83\x98\0" "\xe1\x83\x9e\xe1\x83\x90\xe1\x83\xa0\xe1\x83\x90\xe1\x83\xa1\xe1\x83\x99\xe1\x83\x94\xe1\x83\x95\xe1\x83\x98\0" "\xe1\x83\xa8\xe1\x83\x90\xe1\x83\x91\xe1\x83\x90\xe1\x83\x97\xe1\x83\x98\0" "\xe1\x83\x99\xe1\x83\x95\xe1\x83\x98\0" "\xe1\x83\x9d\xe1\x83\xa0\xe1\x83\xa8\0" "\xe1\x83\xa1\xe1\x83\x90\xe1\x83\x9b\0" "\xe1\x83\x9d\xe1\x83\x97\xe1\x83\xae\0" "\xe1\x83\xae\xe1\x83\xa3\xe1\x83\x97\0" "\xe1\x83\x9e\xe1\x83\x90\xe1\x83\xa0\0" "\xe1\x83\xa8\xe1\x83\x90\xe1\x83\x91\0" "\xe1\x83\x99\0" "\xe1\x83\x9d\0" "\xe1\x83\xa1\0" "\xe1\x83\xae\0" "\xe1\x83\x9e\0" "\xe1\x83\xa8\0" "\xe1\x83\x98\xe1\x83\x90\xe1\x83\x9c\xe1\x83\x95\xe1\x83\x90\xe1\x83\xa0\xe1\x83\x98\0" "\xe1\x83\x97\xe1\x83\x94\xe1\x83\x91\xe1\x83\x94\xe1\x83\xa0\xe1\x83\x95\xe1\x83\x90\xe1\x83\x9a\xe1\x83\x98\0" "\xe1\x83\x9b\xe1\x83\x90\xe1\x83\xa0\xe1\x83\xa2\xe1\x83\x98\0" "\xe1\x83\x90\xe1\x83\x9e\xe1\x83\xa0\xe1\x83\x98\xe1\x83\x9a\xe1\x83\x98\0" "\xe1\x83\x9b\xe1\x83\x90\xe1\x83\x98\xe1\x83\xa1\xe1\x83\x98\0" "\xe1\x83\x98\xe1\x83\x95\xe1\x83\x9c\xe1\x83\x98\xe1\x83\xa1\xe1\x83\x98\0" "\xe1\x83\x98\xe1\x83\x95\xe1\x83\x9a\xe1\x83\x98\xe1\x83\xa1\xe1\x83\x98\0" "\xe1\x83\x90\xe1\x83\x92\xe1\x83\x95\xe1\x83\x98\xe1\x83\xa1\xe1\x83\xa2\xe1\x83\x9d\0" "\xe1\x83\xa1\xe1\x83\x94\xe1\x83\xa5\xe1\x83\xa2\xe1\x83\x94\xe1\x83\x9b\xe1\x83\x91\xe1\x83\x94\xe1\x83\xa0\xe1\x83\x98\0" "\xe1\x83\x9d\xe1\x83\xa5\xe1\x83\xa2\xe1\x83\x9d\xe1\x83\x9b\xe1\x83\x91\xe1\x83\x94\xe1\x83\xa0\xe1\x83\x98\0" "\xe1\x83\x9c\xe1\x83\x9d\xe1\x83\x94\xe1\x83\x9b\xe1\x83\x91\xe1\x83\x94\xe1\x83\xa0\xe1\x83\x98\0" "\xe1\x83\x93\xe1\x83\x94\xe1\x83\x99\xe1\x83\x94\xe1\x83\x9b\xe1\x83\x91\xe1\x83\x94\xe1\x83\xa0\xe1\x83\x98\0" "\xe1\x83\x98\xe1\x83\x90\xe1\x83\x9c\0" "\xe1\x83\x97\xe1\x83\x94\xe1\x83\x91\0" "\xe1\x83\x9b\xe1\x83\x90\xe1\x83\xa0\0" "\xe1\x83\x90\xe1\x83\x9e\xe1\x83\xa0\0" "\xe1\x83\x9b\xe1\x83\x90\xe1\x83\x98\0" "\xe1\x83\x98\xe1\x83\x95\xe1\x83\x9c\0" "\xe1\x83\x98\xe1\x83\x95\xe1\x83\x9a\0" "\xe1\x83\x90\xe1\x83\x92\xe1\x83\x95\0" "\xe1\x83\xa1\xe1\x83\x94\xe1\x83\xa5\0" "\xe1\x83\x9d\xe1\x83\xa5\xe1\x83\xa2\0" "\xe1\x83\x9c\xe1\x83\x9d\xe1\x83\x94\0" "\xe1\x83\x93\xe1\x83\x94\xe1\x83\x99\0" "d MMM, yyyy\0" "f.p.\0" "s.p.\0" "m\xc3\xa1nadagur\0" "t\xc3\xbdsdagur\0" "mikudagur\0" "h\xc3\xb3sdagur\0" "fr\xc3\xadggjadagur\0" "leygardagur\0" "sun\0" "m\xc3\xa1n\0" "t\xc3\xbds\0" "mik\0" "h\xc3\xb3s\0" "fr\xc3\xad\0" "ley\0" "\xe0\xa4\xaa\xe0\xa5\x82\xe0\xa4\xb0\xe0\xa5\x8d\xe0\xa4\xb5\0" "\xe0\xa4\x85\xe0\xa4\xaa\xe0\xa4\xb0\0" "\xe0\xa4\xb0\xe0\xa4\xb5\xe0\xa4\xbf\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xb8\xe0\xa5\x8b\xe0\xa4\xae\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xae\xe0\xa4\x82\xe0\xa4\x97\xe0\xa4\xb2\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xac\xe0\xa5\x81\xe0\xa4\xa7\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\x97\xe0\xa5\x81\xe0\xa4\xb0\xe0\xa5\x81\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xb6\xe0\xa5\x81\xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\xb0\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xb6\xe0\xa4\xa8\xe0\xa4\xbf\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xb0\xe0\xa4\xb5\xe0\xa4\xbf\0" "\xe0\xa4\xb8\xe0\xa5\x8b\xe0\xa4\xae\0" "\xe0\xa4\xae\xe0\xa4\x82\xe0\xa4\x97\xe0\xa4\xb2\0" "\xe0\xa4\xac\xe0\xa5\x81\xe0\xa4\xa7\0" "\xe0\xa4\x97\xe0\xa5\x81\xe0\xa4\xb0\xe0\xa5\x81\0" "\xe0\xa4\xb6\xe0\xa5\x81\xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\xb0\0" "\xe0\xa4\xb6\xe0\xa4\xa8\xe0\xa4\xbf\0" "\xe0\xa4\xb0\0" "\xe0\xa4\xb8\xe0\xa5\x8b\0" "\xe0\xa4\xae\xe0\xa4\x82\0" "\xe0\xa4\xac\xe0\xa5\x81\0" "\xe0\xa4\x97\xe0\xa5\x81\0" "\xe0\xa4\xb6\xe0\xa5\x81\0" "\xe0\xa4\xb6\0" "\xe0\xa4\x9c\xe0\xa4\xa8\xe0\xa4\xb5\xe0\xa4\xb0\xe0\xa5\x80\0" "\xe0\xa4\xab\xe0\xa4\xbc\xe0\xa4\xb0\xe0\xa4\xb5\xe0\xa4\xb0\xe0\xa5\x80\0" "\xe0\xa4\xae\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa5\x8d\xe0\xa4\x9a\0" "\xe0\xa4\x85\xe0\xa4\xaa\xe0\xa5\x8d\xe0\xa4\xb0\xe0\xa5\x88\xe0\xa4\xb2\0" "\xe0\xa4\xae\xe0\xa4\x88\0" "\xe0\xa4\x9c\xe0\xa5\x82\xe0\xa4\xa8\0" "\xe0\xa4\x9c\xe0\xa5\x81\xe0\xa4\xb2\xe0\xa4\xbe\xe0\xa4\x88\0" "\xe0\xa4\x85\xe0\xa4\x97\xe0\xa4\xb8\xe0\xa5\x8d\xe0\xa4\xa4\0" "\xe0\xa4\xb8\xe0\xa4\xbf\xe0\xa4\xa4\xe0\xa4\x82\xe0\xa4\xac\xe0\xa4\xb0\0" "\xe0\xa4\x85\xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\x9f\xe0\xa5\x82\xe0\xa4\xac\xe0\xa4\xb0\0" "\xe0\xa4\xa8\xe0\xa4\xb5\xe0\xa4\x82\xe0\xa4\xac\xe0\xa4\xb0\0" "\xe0\xa4\xa6\xe0\xa4\xbf\xe0\xa4\xb8\xe0\xa4\x82\xe0\xa4\xac\xe0\xa4\xb0\0" "\xe0\xa4\x9c\xe0\xa4\xa8\0" "\xe0\xa4\xab\xe0\xa4\xbc\xe0\xa4\xb0\0" "\xe0\xa4\x85\xe0\xa4\xaa\xe0\xa5\x8d\xe0\xa4\xb0\xe0\xa5\x88\0" "\xe0\xa4\x9c\xe0\xa5\x81\xe0\xa4\xb2\xe0\xa4\xbe\0" "\xe0\xa4\x85\xe0\xa4\x97\0" "\xe0\xa4\xb8\xe0\xa4\xbf\xe0\xa4\xa4\xe0\xa4\x82\0" "\xe0\xa4\x85\xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\x9f\xe0\xa5\x82\0" "\xe0\xa4\xa8\xe0\xa4\xb5\xe0\xa4\x82\0" "\xe0\xa4\xa6\xe0\xa4\xbf\xe0\xa4\xb8\xe0\xa4\x82\0" "d 'ta'\xe2\x80\x99 MMMM\0" "QN\0" "WN\0" "Il-\xc4\xa6\x61\x64\x64\0" "It-Tnejn\0" "It-Tlieta\0" "L-Erbg\xc4\xa7\x61\0" "Il-\xc4\xa6\x61mis\0" "Il-\xc4\xa0img\xc4\xa7\x61\0" "Is-Sibt\0" "\xc4\xa6\x61\x64\0" "Tne\0" "Tli\0" "Erb\0" "\xc4\xa6\x61m\0" "\xc4\xa0im\0" "Sib\0" "\xc4\xa6\0" "\xc4\xa0\0" "Jannar\0" "Frar\0" "Marzu\0" "Mejju\0" "\xc4\xa0unju\0" "Lulju\0" "Awwissu\0" "Settembru\0" "Ottubru\0" "Novembru\0" "Di\xc4\x8b\x65mbru\0" "Fra\0" "Mej\0" "\xc4\xa0un\0" "Lul\0" "Aww\0" "Set\0" "Ott\0" "Di\xc4\x8b\0" "dddd, d 'ta'\xe2\x80\x99 MMMM yyyy\0" "d 'ta'\xe2\x80\x99 MMMM yyyy\0" "MMMM 'ta'\xe2\x80\x99 yyyy\0" "i.b.\0" "e.b.\0" "sotnabeaivi\0" "vuoss\xc3\xa1rga\0" "ma\xc5\x8b\xc5\x8b\x65\x62\xc3\xa1rga\0" "gaskavahkku\0" "duorasdat\0" "bearjadat\0" "l\xc3\xa1vvardat\0" "sotn\0" "vuos\0" "ma\xc5\x8b\0" "gask\0" "duor\0" "bear\0" "l\xc3\xa1v\0" "o\xc4\x91\xc4\x91\x61jagem\xc3\xa1nnu\0" "guovvam\xc3\xa1nnu\0" "njuk\xc4\x8d\x61m\xc3\xa1nnu\0" "cuo\xc5\x8bom\xc3\xa1nnu\0" "miessem\xc3\xa1nnu\0" "geassem\xc3\xa1nnu\0" "suoidnem\xc3\xa1nnu\0" "borgem\xc3\xa1nnu\0" "\xc4\x8d\x61k\xc4\x8d\x61m\xc3\xa1nnu\0" "golggotm\xc3\xa1nnu\0" "sk\xc3\xa1\x62mam\xc3\xa1nnu\0" "juovlam\xc3\xa1nnu\0" "o\xc4\x91\xc4\x91j\0" "guov\0" "njuk\0" "cuo\0" "mies\0" "geas\0" "suoi\0" "borg\0" "\xc4\x8d\x61k\xc4\x8d\0" "golg\0" "sk\xc3\xa1\x62\0" "juov\0" "D\xc3\xa9 Domhnaigh\0" "D\xc3\xa9 Luain\0" "D\xc3\xa9 M\xc3\xa1irt\0" "D\xc3\xa9 C\xc3\xa9\x61\x64\x61oin\0" "D\xc3\xa9\x61rdaoin\0" "D\xc3\xa9 hAoine\0" "D\xc3\xa9 Sathairn\0" "Domh\0" "Luan\0" "M\xc3\xa1irt\0" "C\xc3\xa9\x61\x64\0" "D\xc3\xa9\x61r\0" "Aoine\0" "Sath\0" "Ean\xc3\xa1ir\0" "Feabhra\0" "M\xc3\xa1rta\0" "Aibre\xc3\xa1n\0" "Bealtaine\0" "Meitheamh\0" "I\xc3\xbail\0" "L\xc3\xbanasa\0" "Me\xc3\xa1n F\xc3\xb3mhair\0" "Deireadh F\xc3\xb3mhair\0" "Samhain\0" "Nollaig\0" "Ean\0" "Feabh\0" "Aib\0" "Beal\0" "Meith\0" "L\xc3\xban\0" "MF\xc3\xb3mh\0" "DF\xc3\xb3mh\0" "Samh\0" "Noll\0" "pg\0" "ptg\0" "Ahad\0" "Isnin\0" "Khamis\0" "Jumaat\0" "Ahd\0" "Isn\0" "Kha\0" "Mac\0" "Julai\0" "Ogos\0" "Disember\0" "Ogo\0" "\xd1\x82\xd2\xaf\xd1\x81\xd0\xba\xd0\xb5 \xd0\xb4\xd0\xb5\xd0\xb9\xd1\x96\xd0\xbd\0" "\xd1\x82\xd2\xaf\xd1\x81\xd1\x82\xd0\xb5\xd0\xbd \xd0\xba\xd0\xb5\xd0\xb9\xd1\x96\xd0\xbd\0" "\xd0\xb6\xd0\xb5\xd0\xba\xd1\x81\xd0\xb5\xd0\xbd\xd1\x96\0" "\xd0\xb4\xd1\x83\xd0\xb9\xd1\x81\xd0\xb5\xd0\xbd\xd0\xb1\xd1\x96\0" "\xd1\x81\xd0\xb5\xd0\xb9\xd1\x81\xd0\xb5\xd0\xbd\xd0\xb1\xd1\x96\0" "\xd1\x81\xd3\x99\xd1\x80\xd1\x81\xd0\xb5\xd0\xbd\xd0\xb1\xd1\x96\0" "\xd0\xb1\xd0\xb5\xd0\xb9\xd1\x81\xd0\xb5\xd0\xbd\xd0\xb1\xd1\x96\0" "\xd0\xb6\xd2\xb1\xd0\xbc\xd0\xb0\0" "\xd1\x81\xd0\xb5\xd0\xbd\xd0\xb1\xd1\x96\0" "\xd0\xb6\xd1\x81.\0" "\xd0\xb4\xd1\x81.\0" "\xd1\x81\xd1\x81.\0" "\xd1\x81\xd1\x80.\0" "\xd0\xb1\xd1\x81.\0" "\xd0\xb6\xd0\xbc.\0" "\xd1\x81\xd0\xb1.\0" "\xd0\x96\0" "\xd0\x94\0" "\xd0\x91\0" "\xd2\x9b\xd0\xb0\xd2\xa3\xd1\x82\xd0\xb0\xd1\x80\0" "\xd0\xb0\xd2\x9b\xd0\xbf\xd0\xb0\xd0\xbd\0" "\xd0\xbd\xd0\xb0\xd1\x83\xd1\x80\xd1\x8b\xd0\xb7\0" "\xd1\x81\xd3\x99\xd1\x83\xd1\x96\xd1\x80\0" "\xd0\xbc\xd0\xb0\xd0\xbc\xd1\x8b\xd1\x80\0" "\xd0\xbc\xd0\xb0\xd1\x83\xd1\x81\xd1\x8b\xd0\xbc\0" "\xd1\x88\xd1\x96\xd0\xbb\xd0\xb4\xd0\xb5\0" "\xd1\x82\xd0\xb0\xd0\xbc\xd1\x8b\xd0\xb7\0" "\xd2\x9b\xd1\x8b\xd1\x80\xd0\xba\xd2\xaf\xd0\xb9\xd0\xb5\xd0\xba\0" "\xd2\x9b\xd0\xb0\xd0\xb7\xd0\xb0\xd0\xbd\0" "\xd2\x9b\xd0\xb0\xd1\x80\xd0\xb0\xd1\x88\xd0\xb0\0" "\xd0\xb6\xd0\xb5\xd0\xbb\xd1\x82\xd0\xbe\xd2\x9b\xd1\x81\xd0\xb0\xd0\xbd\0" "\xd2\x9b\xd0\xb0\xd2\xa3.\0" "\xd0\xb0\xd2\x9b\xd0\xbf.\0" "\xd0\xbd\xd0\xb0\xd1\x83.\0" "\xd1\x81\xd3\x99\xd1\x83.\0" "\xd0\xbc\xd0\xb0\xd0\xbc.\0" "\xd0\xbc\xd0\xb0\xd1\x83.\0" "\xd1\x88\xd1\x96\xd0\xbb.\0" "\xd1\x82\xd0\xb0\xd0\xbc.\0" "\xd2\x9b\xd1\x8b\xd1\x80.\0" "\xd2\x9b\xd0\xb0\xd0\xb7.\0" "\xd2\x9b\xd0\xb0\xd1\x80.\0" "\xd0\xb6\xd0\xb5\xd0\xbb\xd1\x82.\0" "yyyy, dd-MMM\0" "d-MMMM\0" "\xd1\x82\xd2\xaf\xd1\x88\xd0\xba\xd3\xa9 \xd1\x87\xd0\xb5\xd0\xb9\xd0\xb8\xd0\xbd\xd0\xba\xd0\xb8\0" "\xd1\x82\xd2\xaf\xd1\x88\xd1\x82\xd3\xa9\xd0\xbd \xd0\xba\xd0\xb8\xd0\xb9\xd0\xb8\xd0\xbd\xd0\xba\xd0\xb8\0" "\xd0\x96\xd0\xb5\xd0\xba\0" "\xd0\x94\xd2\xaf\xd0\xb9\0" "\xd0\xa8\xd0\xb5\xd0\xb9\0" "\xd0\xa8\xd0\xb0\xd1\x80\0" "\xd0\x91\xd0\xb5\xd0\xb9\0" "\xd0\x96\xd1\x83\xd0\xbc\0" "\xd0\x98\xd1\x88\xd0\xbc\0" "\xd0\xa8\0" "\xd0\x98\0" "\xd1\x8f\xd0\xbd\xd0\xb2\xd0\xb0\xd1\x80\xd1\x8c\0" "\xd1\x84\xd0\xb5\xd0\xb2\xd1\x80\xd0\xb0\xd0\xbb\xd1\x8c\0" "\xd0\xb0\xd0\xbf\xd1\x80\xd0\xb5\xd0\xbb\xd1\x8c\0" "\xd0\xb8\xd1\x8e\xd0\xbd\xd1\x8c\0" "\xd0\xb8\xd1\x8e\xd0\xbb\xd1\x8c\0" "\xd1\x81\xd0\xb5\xd0\xbd\xd1\x82\xd1\x8f\xd0\xb1\xd1\x80\xd1\x8c\0" "\xd0\xbe\xd0\xba\xd1\x82\xd1\x8f\xd0\xb1\xd1\x80\xd1\x8c\0" "\xd0\xbd\xd0\xbe\xd1\x8f\xd0\xb1\xd1\x80\xd1\x8c\0" "\xd0\xb4\xd0\xb5\xd0\xba\xd0\xb0\xd0\xb1\xd1\x80\xd1\x8c\0" "\xd1\x8f\xd0\xbd\xd0\xb2.\0" "\xd0\xb8\xd1\x8e\xd0\xbd.\0" "\xd0\xb8\xd1\x8e\xd0\xbb.\0" "\xd1\x81\xd0\xb5\xd0\xbd.\0" "\xd0\xbd\xd0\xbe\xd1\x8f.\0" "d-MMM yy\0" "dd-MMMM yyyy'-\xd0\xb6.'\0" "MMMM yyyy'-\xd0\xb6.'\0" "Jumapili\0" "Jumatatu\0" "Jumanne\0" "Jumatano\0" "Alhamisi\0" "Ijumaa\0" "Jumamosi\0" "J2\0" "J3\0" "J4\0" "J5\0" "Alh\0" "Ij\0" "J1\0" "Machi\0" "Aprili\0" "Agosti\0" "Oktoba\0" "Desemba\0" "Ago\0" "yakshanba\0" "dushanba\0" "seshanba\0" "chorshanba\0" "payshanba\0" "juma\0" "shanba\0" "Yaksh\0" "Dush\0" "Sesh\0" "Chor\0" "Pay\0" "Shan\0" "Y\0" "Iyun\0" "Iyul\0" "Avgust\0" "Yanv\0" "Fev\0" "Avg\0" "Noya\0" "Dek\0" "dddd, yyyy MMMM dd\0" "\xe0\xa6\xaa\xe0\xa7\x82\xe0\xa6\xb0\xe0\xa7\x8d\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa6\xb9\xe0\xa7\x8d\xe0\xa6\xa3\0" "\xe0\xa6\x85\xe0\xa6\xaa\xe0\xa6\xb0\xe0\xa6\xbe\xe0\xa6\xb9\xe0\xa7\x8d\xe0\xa6\xa3\0" "\xe0\xa6\xb0\xe0\xa6\xac\xe0\xa6\xbf\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa6\xb0\0" "\xe0\xa6\xb8\xe0\xa7\x8b\xe0\xa6\xae\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa6\xb0\0" "\xe0\xa6\xae\xe0\xa6\x99\xe0\xa7\x8d\xe0\xa6\x97\xe0\xa6\xb2\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa6\xb0\0" "\xe0\xa6\xac\xe0\xa7\x81\xe0\xa6\xa7\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa6\xb0\0" "\xe0\xa6\xac\xe0\xa7\x83\xe0\xa6\xb9\xe0\xa6\xb7\xe0\xa7\x8d\xe0\xa6\xaa\xe0\xa6\xa4\xe0\xa6\xbf\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa6\xb0\0" "\xe0\xa6\xb6\xe0\xa7\x81\xe0\xa6\x95\xe0\xa7\x8d\xe0\xa6\xb0\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa6\xb0\0" "\xe0\xa6\xb6\xe0\xa6\xa8\xe0\xa6\xbf\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa6\xb0\0" "\xe0\xa6\xb0\xe0\xa6\xac\xe0\xa6\xbf\0" "\xe0\xa6\xb8\xe0\xa7\x8b\xe0\xa6\xae\0" "\xe0\xa6\xae\xe0\xa6\x99\xe0\xa7\x8d\xe0\xa6\x97\xe0\xa6\xb2\0" "\xe0\xa6\xac\xe0\xa7\x81\xe0\xa6\xa7\0" "\xe0\xa6\xac\xe0\xa7\x83\xe0\xa6\xb9\xe0\xa6\xb8\xe0\xa7\x8d\xe0\xa6\xaa\xe0\xa6\xa4\xe0\xa6\xbf\0" "\xe0\xa6\xb6\xe0\xa7\x81\xe0\xa6\x95\xe0\xa7\x8d\xe0\xa6\xb0\0" "\xe0\xa6\xb6\xe0\xa6\xa8\xe0\xa6\xbf\0" "\xe0\xa6\xb0\0" "\xe0\xa6\xb8\xe0\xa7\x8b\0" "\xe0\xa6\xae\0" "\xe0\xa6\xac\xe0\xa7\x81\0" "\xe0\xa6\xac\xe0\xa7\x83\0" "\xe0\xa6\xb6\xe0\xa7\x81\0" "\xe0\xa6\xb6\0" "\xe0\xa6\x9c\xe0\xa6\xbe\xe0\xa6\xa8\xe0\xa7\x81\xe0\xa6\xaf\xe0\xa6\xbc\xe0\xa6\xbe\xe0\xa6\xb0\xe0\xa7\x80\0" "\xe0\xa6\xab\xe0\xa7\x87\xe0\xa6\xac\xe0\xa7\x8d\xe0\xa6\xb0\xe0\xa7\x81\xe0\xa6\xaf\xe0\xa6\xbc\xe0\xa6\xbe\xe0\xa6\xb0\xe0\xa7\x80\0" "\xe0\xa6\xae\xe0\xa6\xbe\xe0\xa6\xb0\xe0\xa7\x8d\xe0\xa6\x9a\0" "\xe0\xa6\x8f\xe0\xa6\xaa\xe0\xa7\x8d\xe0\xa6\xb0\xe0\xa6\xbf\xe0\xa6\xb2\0" "\xe0\xa6\xae\xe0\xa7\x87\0" "\xe0\xa6\x9c\xe0\xa7\x81\xe0\xa6\xa8\0" "\xe0\xa6\x9c\xe0\xa7\x81\xe0\xa6\xb2\xe0\xa6\xbe\xe0\xa6\x87\0" "\xe0\xa6\x86\xe0\xa6\x97\xe0\xa6\xb8\xe0\xa7\x8d\xe0\xa6\x9f\0" "\xe0\xa6\xb8\xe0\xa7\x87\xe0\xa6\xaa\xe0\xa7\x8d\xe0\xa6\x9f\xe0\xa7\x87\xe0\xa6\xae\xe0\xa7\x8d\xe0\xa6\xac\xe0\xa6\xb0\0" "\xe0\xa6\x85\xe0\xa6\x95\xe0\xa7\x8d\xe0\xa6\x9f\xe0\xa7\x8b\xe0\xa6\xac\xe0\xa6\xb0\0" "\xe0\xa6\xa8\xe0\xa6\xad\xe0\xa7\x87\xe0\xa6\xae\xe0\xa7\x8d\xe0\xa6\xac\xe0\xa6\xb0\0" "\xe0\xa6\xa1\xe0\xa6\xbf\xe0\xa6\xb8\xe0\xa7\x87\xe0\xa6\xae\xe0\xa7\x8d\xe0\xa6\xac\xe0\xa6\xb0\0" "tt hh.mm\0" "tt h.mm\0" "tt hh.mm.ss\0" "tt h.mm.ss\0" "\xe0\xa8\x90\xe0\xa8\xa4\xe0\xa8\xb5\xe0\xa8\xbe\xe0\xa8\xb0\0" "\xe0\xa8\xb8\xe0\xa9\x8b\xe0\xa8\xae\xe0\xa8\xb5\xe0\xa8\xbe\xe0\xa8\xb0\0" "\xe0\xa8\xae\xe0\xa9\xb0\xe0\xa8\x97\xe0\xa8\xb2\xe0\xa8\xb5\xe0\xa8\xbe\xe0\xa8\xb0\0" "\xe0\xa8\xac\xe0\xa9\x81\xe0\xa8\xa7\xe0\xa8\xb5\xe0\xa8\xbe\xe0\xa8\xb0\0" "\xe0\xa8\xb5\xe0\xa9\x80\xe0\xa8\xb0\xe0\xa8\xb5\xe0\xa8\xbe\xe0\xa8\xb0\0" "\xe0\xa8\xb8\xe0\xa8\xbc\xe0\xa9\x81\xe0\xa9\xb1\xe0\xa8\x95\xe0\xa8\xb0\xe0\xa8\xb5\xe0\xa8\xbe\xe0\xa8\xb0\0" "\xe0\xa8\xb8\xe0\xa8\xbc\xe0\xa8\xa8\xe0\xa9\x80\xe0\xa8\xb5\xe0\xa8\xbe\xe0\xa8\xb0\0" "\xe0\xa8\x90\xe0\xa8\xa4.\0" "\xe0\xa8\xb8\xe0\xa9\x8b\xe0\xa8\xae.\0" "\xe0\xa8\xae\xe0\xa9\xb0\xe0\xa8\x97\xe0\xa8\xb2.\0" "\xe0\xa8\xac\xe0\xa9\x81\xe0\xa8\xa7.\0" "\xe0\xa8\xb5\xe0\xa9\x80\xe0\xa8\xb0.\0" "\xe0\xa8\xb8\xe0\xa8\xbc\xe0\xa9\x81\xe0\xa9\xb1\xe0\xa8\x95\xe0\xa8\xb0.\0" "\xe0\xa8\xb8\xe0\xa8\xbc\xe0\xa8\xa8\xe0\xa9\x80.\0" "\xe0\xa8\x90\0" "\xe0\xa8\xb8\xe0\xa9\x8b\0" "\xe0\xa8\xae\xe0\xa9\xb0\0" "\xe0\xa8\xac\xe0\xa9\x81\xe0\xa9\xb1\0" "\xe0\xa8\xb5\xe0\xa9\x80\0" "\xe0\xa8\xb8\xe0\xa8\xbc\xe0\xa9\x81\xe0\xa9\xb1\0" "\xe0\xa8\xb8\xe0\xa8\xbc\0" "\xe0\xa8\x9c\xe0\xa8\xa8\xe0\xa8\xb5\xe0\xa8\xb0\xe0\xa9\x80\0" "\xe0\xa8\xab\xe0\xa8\xbc\xe0\xa8\xb0\xe0\xa8\xb5\xe0\xa8\xb0\xe0\xa9\x80\0" "\xe0\xa8\xae\xe0\xa8\xbe\xe0\xa8\xb0\xe0\xa8\x9a\0" "\xe0\xa8\x85\xe0\xa8\xaa\xe0\xa9\x8d\xe0\xa8\xb0\xe0\xa9\x88\xe0\xa8\xb2\0" "\xe0\xa8\xae\xe0\xa8\x88\0" "\xe0\xa8\x9c\xe0\xa9\x82\xe0\xa8\xa8\0" "\xe0\xa8\x9c\xe0\xa9\x81\xe0\xa8\xb2\xe0\xa8\xbe\xe0\xa8\x88\0" "\xe0\xa8\x85\xe0\xa8\x97\xe0\xa8\xb8\xe0\xa8\xa4\0" "\xe0\xa8\xb8\xe0\xa8\xa4\xe0\xa9\xb0\xe0\xa8\xac\xe0\xa8\xb0\0" "\xe0\xa8\x85\xe0\xa8\x95\xe0\xa8\xa4\xe0\xa9\x82\xe0\xa8\xac\xe0\xa8\xb0\0" "\xe0\xa8\xa8\xe0\xa8\xb5\xe0\xa9\xb0\xe0\xa8\xac\xe0\xa8\xb0\0" "\xe0\xa8\xa6\xe0\xa8\xb8\xe0\xa9\xb0\xe0\xa8\xac\xe0\xa8\xb0\0" "dd MMMM yyyy dddd\0" "\xe0\xaa\xb0\xe0\xaa\xb5\xe0\xaa\xbf\xe0\xaa\xb5\xe0\xaa\xbe\xe0\xaa\xb0\0" "\xe0\xaa\xb8\xe0\xab\x8b\xe0\xaa\xae\xe0\xaa\xb5\xe0\xaa\xbe\xe0\xaa\xb0\0" "\xe0\xaa\xae\xe0\xaa\x82\xe0\xaa\x97\xe0\xaa\xb3\xe0\xaa\xb5\xe0\xaa\xbe\xe0\xaa\xb0\0" "\xe0\xaa\xac\xe0\xab\x81\xe0\xaa\xa7\xe0\xaa\xb5\xe0\xaa\xbe\xe0\xaa\xb0\0" "\xe0\xaa\x97\xe0\xab\x81\xe0\xaa\xb0\xe0\xab\x81\xe0\xaa\xb5\xe0\xaa\xbe\xe0\xaa\xb0\0" "\xe0\xaa\xb6\xe0\xab\x81\xe0\xaa\x95\xe0\xab\x8d\xe0\xaa\xb0\xe0\xaa\xb5\xe0\xaa\xbe\xe0\xaa\xb0\0" "\xe0\xaa\xb6\xe0\xaa\xa8\xe0\xaa\xbf\xe0\xaa\xb5\xe0\xaa\xbe\xe0\xaa\xb0\0" "\xe0\xaa\xb0\xe0\xaa\xb5\xe0\xaa\xbf\0" "\xe0\xaa\xb8\xe0\xab\x8b\xe0\xaa\xae\0" "\xe0\xaa\xae\xe0\xaa\x82\xe0\xaa\x97\xe0\xaa\xb3\0" "\xe0\xaa\xac\xe0\xab\x81\xe0\xaa\xa7\0" "\xe0\xaa\x97\xe0\xab\x81\xe0\xaa\xb0\xe0\xab\x81\0" "\xe0\xaa\xb6\xe0\xab\x81\xe0\xaa\x95\xe0\xab\x8d\xe0\xaa\xb0\0" "\xe0\xaa\xb6\xe0\xaa\xa8\xe0\xaa\xbf\0" "\xe0\xaa\xb0\0" "\xe0\xaa\xb8\xe0\xab\x8b\0" "\xe0\xaa\xae\xe0\xaa\x82\0" "\xe0\xaa\xac\xe0\xab\x81\0" "\xe0\xaa\x97\xe0\xab\x81\0" "\xe0\xaa\xb6\xe0\xab\x81\0" "\xe0\xaa\xb6\0" "\xe0\xaa\x9c\xe0\xaa\xbe\xe0\xaa\xa8\xe0\xab\x8d\xe0\xaa\xaf\xe0\xab\x81\xe0\xaa\x86\xe0\xaa\xb0\xe0\xab\x80\0" "\xe0\xaa\xab\xe0\xab\x87\xe0\xaa\xac\xe0\xab\x8d\xe0\xaa\xb0\xe0\xab\x81\xe0\xaa\x86\xe0\xaa\xb0\xe0\xab\x80\0" "\xe0\xaa\xae\xe0\xaa\xbe\xe0\xaa\xb0\xe0\xab\x8d\xe0\xaa\x9a\0" "\xe0\xaa\x8f\xe0\xaa\xaa\xe0\xab\x8d\xe0\xaa\xb0\xe0\xaa\xbf\xe0\xaa\xb2\0" "\xe0\xaa\xae\xe0\xab\x87\0" "\xe0\xaa\x9c\xe0\xab\x82\xe0\xaa\xa8\0" "\xe0\xaa\x9c\xe0\xab\x81\xe0\xaa\xb2\xe0\xaa\xbe\xe0\xaa\x88\0" "\xe0\xaa\x91\xe0\xaa\x97\xe0\xaa\xb8\xe0\xab\x8d\xe0\xaa\x9f\0" "\xe0\xaa\xb8\xe0\xaa\xaa\xe0\xab\x8d\xe0\xaa\x9f\xe0\xab\x87\xe0\xaa\xae\xe0\xab\x8d\xe0\xaa\xac\xe0\xaa\xb0\0" "\xe0\xaa\x91\xe0\xaa\x95\xe0\xab\x8d\xe0\xaa\x9f\xe0\xab\x8b\xe0\xaa\xac\xe0\xaa\xb0\0" "\xe0\xaa\xa8\xe0\xaa\xb5\xe0\xab\x87\xe0\xaa\xae\xe0\xab\x8d\xe0\xaa\xac\xe0\xaa\xb0\0" "\xe0\xaa\xa1\xe0\xaa\xbf\xe0\xaa\xb8\xe0\xab\x87\xe0\xaa\xae\xe0\xab\x8d\xe0\xaa\xac\xe0\xaa\xb0\0" "\xe0\xaa\x9c\xe0\xaa\xbe\xe0\xaa\xa8\xe0\xab\x8d\xe0\xaa\xaf\xe0\xab\x81\0" "\xe0\xaa\xab\xe0\xab\x87\xe0\xaa\xac\xe0\xab\x8d\xe0\xaa\xb0\xe0\xab\x81\0" "\xe0\xaa\x91\xe0\xaa\x97\0" "\xe0\xaa\xb8\xe0\xaa\xaa\xe0\xab\x8d\xe0\xaa\x9f\xe0\xab\x87\0" "\xe0\xaa\x91\xe0\xaa\x95\xe0\xab\x8d\xe0\xaa\x9f\xe0\xab\x8b\0" "\xe0\xaa\xa8\xe0\xaa\xb5\xe0\xab\x87\0" "\xe0\xaa\xa1\xe0\xaa\xbf\xe0\xaa\xb8\xe0\xab\x87\0" "pm\0" "\xe0\xac\xb0\xe0\xac\xac\xe0\xac\xbf\xe0\xac\xac\xe0\xac\xbe\xe0\xac\xb0\0" "\xe0\xac\xb8\xe0\xad\x8b\xe0\xac\xae\xe0\xac\xac\xe0\xac\xbe\xe0\xac\xb0\0" "\xe0\xac\xae\xe0\xac\x99\xe0\xad\x8d\xe0\xac\x97\xe0\xac\xb3\xe0\xac\xac\xe0\xac\xbe\xe0\xac\xb0\0" "\xe0\xac\xac\xe0\xad\x81\xe0\xac\xa7\xe0\xac\xac\xe0\xac\xbe\xe0\xac\xb0\0" "\xe0\xac\x97\xe0\xad\x81\xe0\xac\xb0\xe0\xad\x81\xe0\xac\xac\xe0\xac\xbe\xe0\xac\xb0\0" "\xe0\xac\xb6\xe0\xad\x81\xe0\xac\x95\xe0\xad\x8d\xe0\xac\xb0\xe0\xac\xac\xe0\xac\xbe\xe0\xac\xb0\0" "\xe0\xac\xb6\xe0\xac\xa8\xe0\xac\xbf\xe0\xac\xac\xe0\xac\xbe\xe0\xac\xb0\0" "\xe0\xac\xb0\xe0\xac\xac\xe0\xac\xbf\0" "\xe0\xac\xb8\xe0\xad\x8b\xe0\xac\xae\0" "\xe0\xac\xae\xe0\xac\x99\xe0\xad\x8d\xe0\xac\x97\xe0\xac\xb3\0" "\xe0\xac\xac\xe0\xad\x81\xe0\xac\xa7\0" "\xe0\xac\x97\xe0\xad\x81\xe0\xac\xb0\xe0\xad\x81\0" "\xe0\xac\xb6\xe0\xad\x81\xe0\xac\x95\xe0\xad\x8d\xe0\xac\xb0\0" "\xe0\xac\xb6\xe0\xac\xa8\xe0\xac\xbf\0" "\xe0\xac\xb0\0" "\xe0\xac\xb8\xe0\xad\x8b\0" "\xe0\xac\xae\0" "\xe0\xac\xac\xe0\xad\x81\0" "\xe0\xac\x97\xe0\xad\x81\0" "\xe0\xac\xb6\xe0\xad\x81\0" "\xe0\xac\xb6\0" "\xe0\xac\x9c\xe0\xac\xbe\xe0\xac\xa8\xe0\xad\x81\xe0\xac\x86\xe0\xac\xb0\xe0\xad\x80\0" "\xe0\xac\xab\xe0\xad\x87\xe0\xac\xac\xe0\xad\x8d\xe0\xac\xb0\xe0\xad\x81\xe0\xad\x9f\xe0\xac\xbe\xe0\xac\xb0\xe0\xad\x80\0" "\xe0\xac\xae\xe0\xac\xbe\xe0\xac\xb0\xe0\xad\x8d\xe0\xac\x9a\xe0\xad\x8d\xe0\xac\x9a\0" "\xe0\xac\x85\xe0\xac\xaa\xe0\xad\x8d\xe0\xac\xb0\xe0\xad\x87\xe0\xac\xb2\0" "\xe0\xac\xae\xe0\xad\x87\0" "\xe0\xac\x9c\xe0\xad\x81\xe0\xac\xa8\0" "\xe0\xac\x9c\xe0\xad\x81\xe0\xac\xb2\xe0\xac\xbe\xe0\xac\x87\0" "\xe0\xac\x85\xe0\xac\x97\xe0\xac\xb7\xe0\xad\x8d\xe0\xac\x9f\0" "\xe0\xac\xb8\xe0\xad\x87\xe0\xac\xaa\xe0\xad\x8d\xe0\xac\x9f\xe0\xad\x87\xe0\xac\xae\xe0\xad\x8d\xe0\xac\xac\xe0\xac\xb0\0" "\xe0\xac\x85\xe0\xac\x95\xe0\xad\x8d\xe0\xac\x9f\xe0\xad\x8b\xe0\xac\xac\xe0\xac\xb0\0" "\xe0\xac\xa8\xe0\xac\xad\xe0\xad\x87\xe0\xac\xae\xe0\xad\x8d\xe0\xac\xac\xe0\xac\xb0\0" "\xe0\xac\xa1\xe0\xac\xbf\xe0\xac\xb8\xe0\xad\x87\xe0\xac\xae\xe0\xad\x8d\xe0\xac\xac\xe0\xac\xb0\0" "\xe0\xae\xae\xe0\xaf\x81\xe0\xae\xb1\xe0\xaf\x8d\xe0\xae\xaa\xe0\xae\x95\xe0\xae\xb2\xe0\xaf\x8d\0" "\xe0\xae\xaa\xe0\xae\xbf\xe0\xae\xb1\xe0\xaf\x8d\xe0\xae\xaa\xe0\xae\x95\xe0\xae\xb2\xe0\xaf\x8d\0" "\xe0\xae\x9e\xe0\xae\xbe\xe0\xae\xaf\xe0\xae\xbf\xe0\xae\xb1\xe0\xaf\x81\0" "\xe0\xae\xa4\xe0\xae\xbf\xe0\xae\x99\xe0\xaf\x8d\xe0\xae\x95\xe0\xae\xb3\xe0\xaf\x8d\0" "\xe0\xae\x9a\xe0\xaf\x86\xe0\xae\xb5\xe0\xaf\x8d\xe0\xae\xb5\xe0\xae\xbe\xe0\xae\xaf\xe0\xaf\x8d\0" "\xe0\xae\xaa\xe0\xaf\x81\xe0\xae\xa4\xe0\xae\xa9\xe0\xaf\x8d\0" "\xe0\xae\xb5\xe0\xae\xbf\xe0\xae\xaf\xe0\xae\xbe\xe0\xae\xb4\xe0\xae\xa9\xe0\xaf\x8d\0" "\xe0\xae\xb5\xe0\xaf\x86\xe0\xae\xb3\xe0\xaf\x8d\xe0\xae\xb3\xe0\xae\xbf\0" "\xe0\xae\x9a\xe0\xae\xa9\xe0\xae\xbf\0" "\xe0\xae\x9e\xe0\xae\xbe\0" "\xe0\xae\xa4\xe0\xae\xbf\0" "\xe0\xae\x9a\xe0\xaf\x86\0" "\xe0\xae\xaa\xe0\xaf\x81\0" "\xe0\xae\xb5\xe0\xae\xbf\0" "\xe0\xae\xb5\xe0\xaf\x86\0" "\xe0\xae\x9a\0" "\xe0\xae\x9c\xe0\xae\xa9\xe0\xae\xb5\xe0\xae\xb0\xe0\xae\xbf\0" "\xe0\xae\xaa\xe0\xae\xbf\xe0\xae\xaa\xe0\xaf\x8d\xe0\xae\xb0\xe0\xae\xb5\xe0\xae\xb0\xe0\xae\xbf\0" "\xe0\xae\xae\xe0\xae\xbe\xe0\xae\xb0\xe0\xaf\x8d\xe0\xae\x9a\xe0\xaf\x8d\0" "\xe0\xae\x8f\xe0\xae\xaa\xe0\xaf\x8d\xe0\xae\xb0\xe0\xae\xb2\xe0\xaf\x8d\0" "\xe0\xae\xae\xe0\xaf\x87\0" "\xe0\xae\x9c\xe0\xaf\x82\xe0\xae\xa9\xe0\xaf\x8d\0" "\xe0\xae\x9c\xe0\xaf\x82\xe0\xae\xb2\xe0\xaf\x88\0" "\xe0\xae\x86\xe0\xae\x95\xe0\xae\xb8\xe0\xaf\x8d\xe0\xae\x9f\xe0\xaf\x81\0" "\xe0\xae\x9a\xe0\xaf\x86\xe0\xae\xaa\xe0\xaf\x8d\xe0\xae\x9f\xe0\xae\xae\xe0\xaf\x8d\xe0\xae\xaa\xe0\xae\xb0\xe0\xaf\x8d\0" "\xe0\xae\x85\xe0\xae\x95\xe0\xaf\x8d\xe0\xae\x9f\xe0\xaf\x8b\xe0\xae\xaa\xe0\xae\xb0\xe0\xaf\x8d\0" "\xe0\xae\xa8\xe0\xae\xb5\xe0\xae\xae\xe0\xaf\x8d\xe0\xae\xaa\xe0\xae\xb0\xe0\xaf\x8d\0" "\xe0\xae\x9f\xe0\xae\xbf\xe0\xae\x9a\xe0\xae\xae\xe0\xaf\x8d\xe0\xae\xaa\xe0\xae\xb0\xe0\xaf\x8d\0" "\xe0\xae\x86\xe0\xae\x95\xe0\xae\xb8\xe0\xaf\x8d\xe0\xae\x9f\xe0\xaf\x8d\0" "\xe0\xae\x9c\xe0\xae\xa9.\0" "\xe0\xae\xaa\xe0\xae\xbf\xe0\xae\xaa\xe0\xaf\x8d.\0" "\xe0\xae\xae\xe0\xae\xbe\xe0\xae\xb0\xe0\xaf\x8d.\0" "\xe0\xae\x8f\xe0\xae\xaa\xe0\xaf\x8d.\0" "\xe0\xae\x86\xe0\xae\x95.\0" "\xe0\xae\x9a\xe0\xaf\x86\xe0\xae\xaa\xe0\xaf\x8d.\0" "\xe0\xae\x85\xe0\xae\x95\xe0\xaf\x8d.\0" "\xe0\xae\xa8\xe0\xae\xb5.\0" "\xe0\xae\x9f\xe0\xae\xbf\xe0\xae\x9a.\0" "\xe0\xb0\x86\xe0\xb0\xa6\xe0\xb0\xbf\xe0\xb0\xb5\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb0\x82\0" "\xe0\xb0\xb8\xe0\xb1\x8b\xe0\xb0\xae\xe0\xb0\xb5\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb0\x82\0" "\xe0\xb0\xae\xe0\xb0\x82\xe0\xb0\x97\xe0\xb0\xb3\xe0\xb0\xb5\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb0\x82\0" "\xe0\xb0\xac\xe0\xb1\x81\xe0\xb0\xa7\xe0\xb0\xb5\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb0\x82\0" "\xe0\xb0\x97\xe0\xb1\x81\xe0\xb0\xb0\xe0\xb1\x81\xe0\xb0\xb5\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb0\x82\0" "\xe0\xb0\xb6\xe0\xb1\x81\xe0\xb0\x95\xe0\xb1\x8d\xe0\xb0\xb0\xe0\xb0\xb5\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb0\x82\0" "\xe0\xb0\xb6\xe0\xb0\xa8\xe0\xb0\xbf\xe0\xb0\xb5\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb0\x82\0" "\xe0\xb0\x86\xe0\xb0\xa6\xe0\xb0\xbf\0" "\xe0\xb0\xb8\xe0\xb1\x8b\xe0\xb0\xae\0" "\xe0\xb0\xae\xe0\xb0\x82\xe0\xb0\x97\xe0\xb0\xb3\0" "\xe0\xb0\xac\xe0\xb1\x81\xe0\xb0\xa7\0" "\xe0\xb0\x97\xe0\xb1\x81\xe0\xb0\xb0\xe0\xb1\x81\0" "\xe0\xb0\xb6\xe0\xb1\x81\xe0\xb0\x95\xe0\xb1\x8d\xe0\xb0\xb0\0" "\xe0\xb0\xb6\xe0\xb0\xa8\xe0\xb0\xbf\0" "\xe0\xb0\x86\0" "\xe0\xb0\xb8\xe0\xb1\x8b\0" "\xe0\xb0\xae\0" "\xe0\xb0\xac\xe0\xb1\x81\0" "\xe0\xb0\x97\xe0\xb1\x81\0" "\xe0\xb0\xb6\xe0\xb1\x81\0" "\xe0\xb0\xb6\0" "\xe0\xb0\x9c\xe0\xb0\xa8\xe0\xb0\xb5\xe0\xb0\xb0\xe0\xb0\xbf\0" "\xe0\xb0\xab\xe0\xb0\xbf\xe0\xb0\xac\xe0\xb1\x8d\xe0\xb0\xb0\xe0\xb0\xb5\xe0\xb0\xb0\xe0\xb0\xbf\0" "\xe0\xb0\xae\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb1\x8d\xe0\xb0\x9a\xe0\xb0\xbf\0" "\xe0\xb0\x8e\xe0\xb0\xaa\xe0\xb1\x8d\xe0\xb0\xb0\xe0\xb0\xbf\xe0\xb0\xb2\xe0\xb1\x8d\0" "\xe0\xb0\xae\xe0\xb1\x87\0" "\xe0\xb0\x9c\xe0\xb1\x82\xe0\xb0\xa8\xe0\xb1\x8d\0" "\xe0\xb0\x9c\xe0\xb1\x82\xe0\xb0\xb2\xe0\xb1\x88\0" "\xe0\xb0\x86\xe0\xb0\x97\xe0\xb0\xb8\xe0\xb1\x8d\xe0\xb0\x9f\xe0\xb1\x81\0" "\xe0\xb0\xb8\xe0\xb1\x86\xe0\xb0\xaa\xe0\xb1\x8d\xe0\xb0\x9f\xe0\xb1\x86\xe0\xb0\x82\xe0\xb0\xac\xe0\xb0\xb0\xe0\xb1\x8d\0" "\xe0\xb0\x85\xe0\xb0\x95\xe0\xb1\x8d\xe0\xb0\x9f\xe0\xb1\x8b\xe0\xb0\xac\xe0\xb0\xb0\xe0\xb1\x8d\0" "\xe0\xb0\xa8\xe0\xb0\xb5\xe0\xb0\x82\xe0\xb0\xac\xe0\xb0\xb0\xe0\xb1\x8d\0" "\xe0\xb0\xa1\xe0\xb0\xbf\xe0\xb0\xb8\xe0\xb1\x86\xe0\xb0\x82\xe0\xb0\xac\xe0\xb0\xb0\xe0\xb1\x8d\0" "\xe0\xb0\x9c\xe0\xb1\x81\xe0\xb0\xb2\xe0\xb1\x88\0" "\xe0\xb0\x9c\xe0\xb0\xa8\0" "\xe0\xb0\xab\xe0\xb0\xbf\xe0\xb0\xac\xe0\xb1\x8d\xe0\xb0\xb0\0" "\xe0\xb0\x8f\xe0\xb0\xaa\xe0\xb1\x8d\xe0\xb0\xb0\xe0\xb0\xbf\0" "\xe0\xb0\xb8\xe0\xb1\x86\xe0\xb0\xaa\xe0\xb1\x8d\xe0\xb0\x9f\xe0\xb1\x86\xe0\xb0\x82\0" "\xe0\xb0\x85\xe0\xb0\x95\xe0\xb1\x8d\xe0\xb0\x9f\xe0\xb1\x8b\0" "\xe0\xb0\xa8\xe0\xb0\xb5\xe0\xb0\x82\0" "\xe0\xb0\xa1\xe0\xb0\xbf\xe0\xb0\xb8\xe0\xb1\x86\xe0\xb0\x82\0" "\xe0\xb2\xb0\xe0\xb2\xb5\xe0\xb2\xbf\xe0\xb2\xb5\xe0\xb2\xbe\xe0\xb2\xb0\0" "\xe0\xb2\xb8\xe0\xb3\x8b\xe0\xb2\xae\xe0\xb2\xb5\xe0\xb2\xbe\xe0\xb2\xb0\0" "\xe0\xb2\xae\xe0\xb2\x82\xe0\xb2\x97\xe0\xb2\xb3\xe0\xb2\xb5\xe0\xb2\xbe\xe0\xb2\xb0\0" "\xe0\xb2\xac\xe0\xb3\x81\xe0\xb2\xa7\xe0\xb2\xb5\xe0\xb2\xbe\xe0\xb2\xb0\0" "\xe0\xb2\x97\xe0\xb3\x81\xe0\xb2\xb0\xe0\xb3\x81\xe0\xb2\xb5\xe0\xb2\xbe\xe0\xb2\xb0\0" "\xe0\xb2\xb6\xe0\xb3\x81\xe0\xb2\x95\xe0\xb3\x8d\xe0\xb2\xb0\xe0\xb2\xb5\xe0\xb2\xbe\xe0\xb2\xb0\0" "\xe0\xb2\xb6\xe0\xb2\xa8\xe0\xb2\xbf\xe0\xb2\xb5\xe0\xb2\xbe\xe0\xb2\xb0\0" "\xe0\xb2\xb0\xe0\xb2\xb5\xe0\xb2\xbf\0" "\xe0\xb2\xb8\xe0\xb3\x8b\xe0\xb2\xae\0" "\xe0\xb2\xae\xe0\xb2\x82\xe0\xb2\x97\xe0\xb2\xb3\0" "\xe0\xb2\xac\xe0\xb3\x81\xe0\xb2\xa7\0" "\xe0\xb2\x97\xe0\xb3\x81\xe0\xb2\xb0\xe0\xb3\x81\0" "\xe0\xb2\xb6\xe0\xb3\x81\xe0\xb2\x95\xe0\xb3\x8d\xe0\xb2\xb0\0" "\xe0\xb2\xb6\xe0\xb2\xa8\xe0\xb2\xbf\0" "\xe0\xb2\xb0\0" "\xe0\xb2\xb8\xe0\xb3\x8b\0" "\xe0\xb2\xae\xe0\xb2\x82\0" "\xe0\xb2\xac\xe0\xb3\x81\0" "\xe0\xb2\x97\xe0\xb3\x81\0" "\xe0\xb2\xb6\xe0\xb3\x81\0" "\xe0\xb2\xb6\0" "\xe0\xb2\x9c\xe0\xb2\xa8\xe0\xb2\xb5\xe0\xb2\xb0\xe0\xb2\xbf\0" "\xe0\xb2\xab\xe0\xb3\x86\xe0\xb2\xac\xe0\xb3\x8d\xe0\xb2\xb0\xe0\xb2\xb5\xe0\xb2\xb0\xe0\xb2\xbf\0" "\xe0\xb2\xae\xe0\xb2\xbe\xe0\xb2\xb0\xe0\xb3\x8d\xe0\xb2\x9a\xe0\xb3\x8d\0" "\xe0\xb2\x8f\xe0\xb2\xaa\xe0\xb3\x8d\xe0\xb2\xb0\xe0\xb2\xbf\xe0\xb2\xb2\xe0\xb3\x8d\0" "\xe0\xb2\xae\xe0\xb3\x87\0" "\xe0\xb2\x9c\xe0\xb3\x82\xe0\xb2\xa8\xe0\xb3\x8d\0" "\xe0\xb2\x9c\xe0\xb3\x81\xe0\xb2\xb2\xe0\xb3\x88\0" "\xe0\xb2\x86\xe0\xb2\x97\xe0\xb2\xb8\xe0\xb3\x8d\xe0\xb2\x9f\xe0\xb3\x8d\0" "\xe0\xb2\xb8\xe0\xb2\xaa\xe0\xb3\x8d\xe0\xb2\x9f\xe0\xb3\x86\xe0\xb2\x82\xe0\xb2\xac\xe0\xb2\xb0\xe0\xb3\x8d\0" "\xe0\xb2\x85\xe0\xb2\x95\xe0\xb3\x8d\xe0\xb2\x9f\xe0\xb3\x8b\xe0\xb2\xac\xe0\xb2\xb0\xe0\xb3\x8d\0" "\xe0\xb2\xa8\xe0\xb2\xb5\xe0\xb3\x86\xe0\xb2\x82\xe0\xb2\xac\xe0\xb2\xb0\xe0\xb3\x8d\0" "\xe0\xb2\xa1\xe0\xb2\xbf\xe0\xb2\xb8\xe0\xb3\x86\xe0\xb2\x82\xe0\xb2\xac\xe0\xb2\xb0\xe0\xb3\x8d\0" "\xe0\xb2\x9c\xe0\xb2\xa8.\0" "\xe0\xb2\xab\xe0\xb3\x86\xe0\xb2\xac\xe0\xb3\x8d\xe0\xb2\xb0\xe0\xb3\x81.\0" "\xe0\xb2\xae\xe0\xb2\xbe\0" "\xe0\xb2\x8f\xe0\xb2\xaa\xe0\xb3\x8d\xe0\xb2\xb0\xe0\xb2\xbf.\0" "\xe0\xb2\x9c\xe0\xb3\x82\0" "\xe0\xb2\x9c\xe0\xb3\x81.\0" "\xe0\xb2\x86\xe0\xb2\x97.\0" "\xe0\xb2\xb8\xe0\xb3\x86\xe0\xb2\xaa\xe0\xb3\x8d\xe0\xb2\x9f\xe0\xb3\x86\xe0\xb2\x82.\0" "\xe0\xb2\x85\xe0\xb2\x95\xe0\xb3\x8d\xe0\xb2\x9f\xe0\xb3\x8b.\0" "\xe0\xb2\xa8\xe0\xb2\xb5\xe0\xb3\x86\xe0\xb2\x82.\0" "\xe0\xb2\xa1\xe0\xb2\xbf\xe0\xb2\xb8\xe0\xb3\x86\xe0\xb2\x82.\0" "MMMM dd\0" "\xe0\xb4\x9e\xe0\xb4\xbe\xe0\xb4\xaf\xe0\xb4\xb1\xe0\xb4\xbe\xe0\xb4\xb4\xe0\xb5\x8d\xe2\x80\x8c\xe0\xb4\x9a\0" "\xe0\xb4\xa4\xe0\xb4\xbf\xe0\xb4\x99\xe0\xb5\x8d\xe0\xb4\x95\xe0\xb4\xb3\xe0\xb4\xbe\xe0\xb4\xb4\xe0\xb5\x8d\xe2\x80\x8c\xe0\xb4\x9a\0" "\xe0\xb4\x9a\xe0\xb5\x8a\xe0\xb4\xb5\xe0\xb5\x8d\xe0\xb4\xb5\xe0\xb4\xbe\xe0\xb4\xb4\xe0\xb5\x8d\xe0\xb4\x9a\0" "\xe0\xb4\xac\xe0\xb5\x81\xe0\xb4\xa7\xe0\xb4\xa8\xe0\xb4\xbe\xe0\xb4\xb4\xe0\xb5\x8d\xe2\x80\x8c\xe0\xb4\x9a\0" "\xe0\xb4\xb5\xe0\xb5\x8d\xe0\xb4\xaf\xe0\xb4\xbe\xe0\xb4\xb4\xe0\xb4\xbe\xe0\xb4\xb4\xe0\xb5\x8d\xe2\x80\x8c\xe0\xb4\x9a\0" "\xe0\xb4\xb5\xe0\xb5\x86\xe0\xb4\xb3\xe0\xb5\x8d\xe0\xb4\xb3\xe0\xb4\xbf\xe0\xb4\xaf\xe0\xb4\xbe\xe0\xb4\xb4\xe0\xb5\x8d\xe2\x80\x8c\xe0\xb4\x9a\0" "\xe0\xb4\xb6\xe0\xb4\xa8\xe0\xb4\xbf\xe0\xb4\xaf\xe0\xb4\xbe\xe0\xb4\xb4\xe0\xb5\x8d\xe2\x80\x8c\xe0\xb4\x9a\0" "\xe0\xb4\x9e\xe0\xb4\xbe\xe0\xb4\xaf\xe0\xb5\xbc\0" "\xe0\xb4\xa4\xe0\xb4\xbf\xe0\xb4\x99\xe0\xb5\x8d\xe0\xb4\x95\xe0\xb5\xbe\0" "\xe0\xb4\x9a\xe0\xb5\x8a\xe0\xb4\xb5\xe0\xb5\x8d\xe0\xb4\xb5\0" "\xe0\xb4\xac\xe0\xb5\x81\xe0\xb4\xa7\xe0\xb5\xbb\0" "\xe0\xb4\xb5\xe0\xb5\x8d\xe0\xb4\xaf\xe0\xb4\xbe\xe0\xb4\xb4\xe0\xb4\x82\0" "\xe0\xb4\xb5\xe0\xb5\x86\xe0\xb4\xb3\xe0\xb5\x8d\xe0\xb4\xb3\xe0\xb4\xbf\0" "\xe0\xb4\xb6\xe0\xb4\xa8\xe0\xb4\xbf\0" "\xe0\xb4\x9e\xe0\xb4\xbe\0" "\xe0\xb4\xa4\xe0\xb4\xbf\0" "\xe0\xb4\x9a\xe0\xb5\x8a\0" "\xe0\xb4\xac\xe0\xb5\x81\0" "\xe0\xb4\xb5\xe0\xb5\x8d\xe0\xb4\xaf\xe0\xb4\xbe\0" "\xe0\xb4\xb5\xe0\xb5\x86\0" "\xe0\xb4\xb6\0" "\xe0\xb4\x9c\xe0\xb4\xa8\xe0\xb5\x81\xe0\xb4\xb5\xe0\xb4\xb0\xe0\xb4\xbf\0" "\xe0\xb4\xab\xe0\xb5\x86\xe0\xb4\xac\xe0\xb5\x8d\xe0\xb4\xb0\xe0\xb5\x81\xe0\xb4\xb5\xe0\xb4\xb0\xe0\xb4\xbf\0" "\xe0\xb4\xae\xe0\xb4\xbe\xe0\xb5\xbc\xe0\xb4\x9a\xe0\xb5\x8d\xe0\xb4\x9a\xe0\xb5\x8d\0" "\xe0\xb4\x8f\xe0\xb4\xaa\xe0\xb5\x8d\xe0\xb4\xb0\xe0\xb4\xbf\xe0\xb5\xbd\0" "\xe0\xb4\xae\xe0\xb5\x87\xe0\xb4\xaf\xe0\xb5\x8d\0" "\xe0\xb4\x9c\xe0\xb5\x82\xe0\xb5\xba\0" "\xe0\xb4\x9c\xe0\xb5\x82\xe0\xb4\xb2\xe0\xb5\x88\0" "\xe0\xb4\x86\xe0\xb4\x97\xe0\xb4\xb8\xe0\xb5\x8d\xe0\xb4\xb1\xe0\xb5\x8d\xe0\xb4\xb1\xe0\xb5\x8d\0" "\xe0\xb4\xb8\xe0\xb5\x86\xe0\xb4\xaa\xe0\xb5\x8d\xe0\xb4\xb1\xe0\xb5\x8d\xe0\xb4\xb1\xe0\xb4\x82\xe0\xb4\xac\xe0\xb5\xbc\0" "\xe0\xb4\x92\xe0\xb4\x95\xe0\xb5\x8d\xe2\x80\x8c\xe0\xb4\x9f\xe0\xb5\x8b\xe0\xb4\xac\xe0\xb5\xbc\0" "\xe0\xb4\xa8\xe0\xb4\xb5\xe0\xb4\x82\xe0\xb4\xac\xe0\xb5\xbc\0" "\xe0\xb4\xa1\xe0\xb4\xbf\xe0\xb4\xb8\xe0\xb4\x82\xe0\xb4\xac\xe0\xb5\xbc\0" "\xe0\xb4\x9c\xe0\xb4\xa8\xe0\xb5\x81\0" "\xe0\xb4\xab\xe0\xb5\x86\xe0\xb4\xac\xe0\xb5\x8d\xe0\xb4\xb0\xe0\xb5\x81\0" "\xe0\xb4\xae\xe0\xb4\xbe\xe0\xb5\xbc\0" "\xe0\xb4\x8f\xe0\xb4\xaa\xe0\xb5\x8d\xe0\xb4\xb0\xe0\xb4\xbf\0" "\xe0\xb4\x93\xe0\xb4\x97\0" "\xe0\xb4\xb8\xe0\xb5\x86\xe0\xb4\xaa\xe0\xb5\x8d\xe0\xb4\xb1\xe0\xb5\x8d\xe0\xb4\xb1\xe0\xb4\x82\0" "\xe0\xb4\x92\xe0\xb4\x95\xe0\xb5\x8d\xe0\xb4\x9f\xe0\xb5\x8b\0" "\xe0\xb4\xa8\xe0\xb4\xb5\xe0\xb4\x82\0" "\xe0\xb4\xa1\xe0\xb4\xbf\xe0\xb4\xb8\xe0\xb4\x82\0" "\xe0\xa6\xaa\xe0\xa7\x82\xe0\xa7\xb0\xe0\xa7\x8d\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa6\xb9\xe0\xa7\x8d\xe0\xa6\xa3\0" "\xe0\xa6\x85\xe0\xa6\xaa\xe0\xa7\xb0\xe0\xa6\xbe\xe0\xa6\xb9\xe0\xa7\x8d\xe0\xa6\xa3\0" "\xe0\xa6\xa6\xe0\xa7\x87\xe0\xa6\x93\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa7\xb0\0" "\xe0\xa6\xb8\xe0\xa7\x8b\xe0\xa6\xae\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa7\xb0\0" "\xe0\xa6\xae\xe0\xa6\x99\xe0\xa7\x8d\xe0\xa6\x97\xe0\xa6\xb2\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa7\xb0\0" "\xe0\xa6\xac\xe0\xa7\x81\xe0\xa6\xa7\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa7\xb0\0" "\xe0\xa6\xac\xe0\xa7\x83\xe0\xa6\xb9\xe0\xa6\xb7\xe0\xa7\x8d\xe0\xa6\xaa\xe0\xa6\xa4\xe0\xa6\xbf\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa7\xb0\0" "\xe0\xa6\xb6\xe0\xa7\x81\xe0\xa6\x95\xe0\xa7\x8d\xe0\xa7\xb0\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa7\xb0\0" "\xe0\xa6\xb6\xe0\xa6\xa8\xe0\xa6\xbf\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa7\xb0\0" "\xe0\xa7\xb0\xe0\xa6\xac\xe0\xa6\xbf\0" "\xe0\xa6\xac\xe0\xa7\x83\xe0\xa6\xb9\xe0\xa6\xb7\xe0\xa7\x8d\xe0\xa6\xaa\xe0\xa6\xa4\xe0\xa6\xbf\0" "\xe0\xa6\xb6\xe0\xa7\x81\xe0\xa6\x95\xe0\xa7\x8d\xe0\xa7\xb0\0" "\xe0\xa6\x9c\xe0\xa6\xbe\xe0\xa6\xa8\xe0\xa7\x81\xe0\xa7\xb1\xe0\xa6\xbe\xe0\xa7\xb0\xe0\xa7\x80\0" "\xe0\xa6\xab\xe0\xa7\x87\xe0\xa6\xac\xe0\xa7\x8d\xe0\xa7\xb0\xe0\xa7\x81\xe0\xa7\xb1\xe0\xa6\xbe\xe0\xa7\xb0\xe0\xa7\x80\0" "\xe0\xa6\xae\xe0\xa6\xbe\xe0\xa7\xb0\xe0\xa7\x8d\xe0\xa6\x9a\0" "\xe0\xa6\x8f\xe0\xa6\xaa\xe0\xa7\x8d\xe0\xa7\xb0\xe0\xa6\xbf\xe0\xa6\xb2\0" "\xe0\xa6\x86\xe0\xa6\x97\xe0\xa6\xb7\xe0\xa7\x8d\xe0\xa6\x9f\0" "\xe0\xa6\x9b\xe0\xa7\x87\xe0\xa6\xaa\xe0\xa7\x8d\xe0\xa6\xa4\xe0\xa7\x87\xe0\xa6\xae\xe0\xa7\x8d\xe0\xa6\xac\xe0\xa7\xb0\0" "\xe0\xa6\x85\xe0\xa6\x95\xe0\xa7\x8d\xe0\xa6\x9f\xe0\xa7\x8b\xe0\xa6\xac\xe0\xa7\xb0\0" "\xe0\xa6\xa8\xe0\xa7\xb1\xe0\xa7\x87\xe0\xa6\xae\xe0\xa7\x8d\xe0\xa6\xac\xe0\xa7\xb0\0" "\xe0\xa6\xa1\xe0\xa6\xbf\xe0\xa6\x9a\xe0\xa7\x87\xe0\xa6\xae\xe0\xa7\x8d\xe0\xa6\xac\xe0\xa7\xb0\0" "\xe0\xa6\x9c\xe0\xa6\xbe\xe0\xa6\xa8\xe0\xa7\x81\0" "\xe0\xa6\xab\xe0\xa7\x87\xe0\xa6\xac\xe0\xa7\x8d\xe0\xa7\xb0\xe0\xa7\x81\0" "\xe0\xa6\x86\xe0\xa6\x97\0" "\xe0\xa6\xb8\xe0\xa7\x87\xe0\xa6\xaa\xe0\xa7\x8d\xe0\xa6\x9f\0" "\xe0\xa6\x85\xe0\xa6\x95\xe0\xa7\x8d\xe0\xa6\x9f\xe0\xa7\x8b\0" "\xe0\xa6\xa8\xe0\xa6\xad\xe0\xa7\x87\0" "\xe0\xa6\xa1\xe0\xa6\xbf\xe0\xa6\xb8\xe0\xa7\x87\0" "yyyy,MMMM dd, dddd\0" "MMMM,yy\0" "MMMM,yyyy\0" "\xe0\xa4\xae\xe0\xa4\x82\xe0\xa4\x97\xe0\xa4\xb3\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xae\xe0\xa4\x82\xe0\xa4\x97\xe0\xa4\xb3\0" "\xe0\xa4\x9c\xe0\xa4\xbe\xe0\xa4\xa8\xe0\xa5\x87\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa5\x80\0" "\xe0\xa4\xab\xe0\xa5\x87\xe0\xa4\xac\xe0\xa5\x8d\xe0\xa4\xb0\xe0\xa5\x81\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa5\x80\0" "\xe0\xa4\x8f\xe0\xa4\xaa\xe0\xa5\x8d\xe0\xa4\xb0\xe0\xa4\xbf\xe0\xa4\xb2\0" "\xe0\xa4\xae\xe0\xa5\x87\0" "\xe0\xa4\x9c\xe0\xa5\x81\xe0\xa4\xb2\xe0\xa5\x88\0" "\xe0\xa4\x91\xe0\xa4\x97\xe0\xa4\xb8\xe0\xa5\x8d\xe0\xa4\x9f\0" "\xe0\xa4\xb8\xe0\xa4\xaa\xe0\xa5\x8d\xe0\xa4\x9f\xe0\xa5\x87\xe0\xa4\x82\xe0\xa4\xac\xe0\xa4\xb0\0" "\xe0\xa4\x91\xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\x9f\xe0\xa5\x8b\xe0\xa4\xac\xe0\xa4\xb0\0" "\xe0\xa4\xa8\xe0\xa5\x8b\xe0\xa4\xb5\xe0\xa5\x8d\xe0\xa4\xb9\xe0\xa5\x87\xe0\xa4\x82\xe0\xa4\xac\xe0\xa4\xb0\0" "\xe0\xa4\xa1\xe0\xa4\xbf\xe0\xa4\xb8\xe0\xa5\x87\xe0\xa4\x82\xe0\xa4\xac\xe0\xa4\xb0\0" "\xe0\xa4\x9c\xe0\xa4\xbe\xe0\xa4\xa8\xe0\xa5\x87\0" "\xe0\xa4\xab\xe0\xa5\x87\xe0\xa4\xac\xe0\xa5\x8d\xe0\xa4\xb0\xe0\xa5\x81\0" "\xe0\xa4\x8f\xe0\xa4\xaa\xe0\xa5\x8d\xe0\xa4\xb0\xe0\xa4\xbf\0" "\xe0\xa4\x91\xe0\xa4\x97\0" "\xe0\xa4\xb8\xe0\xa4\xaa\xe0\xa5\x8d\xe0\xa4\x9f\xe0\xa5\x87\xe0\xa4\x82\0" "\xe0\xa4\x91\xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\x9f\xe0\xa5\x8b\0" "\xe0\xa4\xa8\xe0\xa5\x8b\xe0\xa4\xb5\xe0\xa5\x8d\xe0\xa4\xb9\xe0\xa5\x87\xe0\xa4\x82\0" "\xe0\xa4\xa1\xe0\xa4\xbf\xe0\xa4\xb8\xe0\xa5\x87\xe0\xa4\x82\0" "\xd2\xae\xd3\xa8\0" "\xd2\xae\xd0\xa5\0" "\xd0\xbd\xd1\x8f\xd0\xbc\0" "\xd0\xb4\xd0\xb0\xd0\xb2\xd0\xb0\xd0\xb0\0" "\xd0\xbc\xd1\x8f\xd0\xb3\xd0\xbc\xd0\xb0\xd1\x80\0" "\xd0\xbb\xd1\x85\xd0\xb0\xd0\xb3\xd0\xb2\xd0\xb0\0" "\xd0\xbf\xd2\xaf\xd1\x80\xd1\x8d\xd0\xb2\0" "\xd0\xb1\xd0\xb0\xd0\xb0\xd1\x81\xd0\xb0\xd0\xbd\0" "\xd0\xb1\xd1\x8f\xd0\xbc\xd0\xb1\xd0\xb0\0" "\xd0\x9d\xd1\x8f\0" "\xd0\x94\xd0\xb0\0" "\xd0\x9c\xd1\x8f\0" "\xd0\x9b\xd1\x85\0" "\xd0\x9f\xd2\xaf\0" "\xd0\x91\xd0\xb0\0" "\xd0\x91\xd1\x8f\0" "\xd0\x9d\xd1\x8d\xd0\xb3\xd0\xb4\xd2\xaf\xd0\xb3\xd1\x8d\xd1\x8d\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "\xd0\xa5\xd0\xbe\xd1\x91\xd1\x80\xd0\xb4\xd1\x83\xd0\xb3\xd0\xb0\xd0\xb0\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "\xd0\x93\xd1\x83\xd1\x80\xd0\xb0\xd0\xb2\xd0\xb4\xd1\x83\xd0\xb3\xd0\xb0\xd0\xb0\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "\xd0\x94\xd3\xa9\xd1\x80\xd3\xa9\xd0\xb2\xd0\xb4\xd2\xaf\xd0\xb3\xd1\x8d\xd1\x8d\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "\xd0\xa2\xd0\xb0\xd0\xb2\xd0\xb4\xd1\x83\xd0\xb3\xd0\xb0\xd0\xb0\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "\xd0\x97\xd1\x83\xd1\x80\xd0\xb3\xd0\xb0\xd0\xb4\xd1\x83\xd0\xb3\xd0\xb0\xd0\xb0\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "\xd0\x94\xd0\xbe\xd0\xbb\xd0\xb4\xd1\x83\xd0\xb3\xd0\xb0\xd0\xb0\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "\xd0\x9d\xd0\xb0\xd0\xb9\xd0\xbc\xd0\xb4\xd1\x83\xd0\xb3\xd0\xb0\xd0\xb0\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "\xd0\x95\xd1\x81\xd0\xb4\xd2\xaf\xd0\xb3\xd1\x8d\xd1\x8d\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "\xd0\x90\xd1\x80\xd0\xb0\xd0\xb2\xd0\xb4\xd1\x83\xd0\xb3\xd0\xb0\xd0\xb0\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "\xd0\x90\xd1\x80\xd0\xb2\xd0\xb0\xd0\xbd \xd0\xbd\xd1\x8d\xd0\xb3\xd0\xb4\xd2\xaf\xd0\xb3\xd1\x8d\xd1\x8d\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "\xd0\x90\xd1\x80\xd0\xb2\xd0\xb0\xd0\xbd \xd1\x85\xd0\xbe\xd1\x91\xd1\x80\xd0\xb4\xd1\x83\xd0\xb3\xd0\xb0\xd0\xb0\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "1-\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "2-\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "3-\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "4-\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "5-\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "6-\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "7-\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "8-\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "9-\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "10-\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "11-\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "12-\xd1\x80 \xd1\x81\xd0\xb0\xd1\x80\0" "dddd, yyyy '\xd0\xbe\xd0\xbd\xd1\x8b' MM '\xd1\x81\xd0\xb0\xd1\x80\xd1\x8b\xd0\xbd' d\0" "yyyy '\xd0\xbe\xd0\xbd\xd1\x8b' MM '\xd1\x81\xd0\xb0\xd1\x80\xd1\x8b\xd0\xbd' d\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8bM\xe0\xbd\x9a\xe0\xbd\xba\xe0\xbd\xa6\xe0\xbc\x8b\x64\0" "\xe0\xbd\xa6\xe0\xbe\x94\xe0\xbc\x8b\xe0\xbd\x91\xe0\xbe\xb2\xe0\xbd\xbc\xe0\xbc\x8b\0" "\xe0\xbd\x95\xe0\xbe\xb1\xe0\xbd\xb2\xe0\xbc\x8b\xe0\xbd\x91\xe0\xbe\xb2\xe0\xbd\xbc\xe0\xbc\x8b\0" "\xe0\xbd\x82\xe0\xbd\x9f\xe0\xbd\xa0\xe0\xbc\x8b\xe0\xbd\x89\xe0\xbd\xb2\xe0\xbc\x8b\xe0\xbd\x98\xe0\xbc\x8b\0" "\xe0\xbd\x82\xe0\xbd\x9f\xe0\xbd\xa0\xe0\xbc\x8b\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbd\x96\xe0\xbc\x8b\0" "\xe0\xbd\x82\xe0\xbd\x9f\xe0\xbd\xa0\xe0\xbc\x8b\xe0\xbd\x98\xe0\xbd\xb2\xe0\xbd\x82\xe0\xbc\x8b\xe0\xbd\x91\xe0\xbd\x98\xe0\xbd\xa2\xe0\xbc\x8b\0" "\xe0\xbd\x82\xe0\xbd\x9f\xe0\xbd\xa0\xe0\xbc\x8b\xe0\xbd\xa7\xe0\xbe\xb3\xe0\xbd\x82\xe0\xbc\x8b\xe0\xbd\x94\xe0\xbc\x8b\0" "\xe0\xbd\x82\xe0\xbd\x9f\xe0\xbd\xa0\xe0\xbc\x8b\xe0\xbd\x95\xe0\xbd\xb4\xe0\xbd\xa2\xe0\xbc\x8b\xe0\xbd\x96\xe0\xbd\xb4\xe0\xbc\x8b\0" "\xe0\xbd\x82\xe0\xbd\x9f\xe0\xbd\xa0\xe0\xbc\x8b\xe0\xbd\xa6\xe0\xbd\x84\xe0\xbd\xa6\xe0\xbc\x8b\0" "\xe0\xbd\x82\xe0\xbd\x9f\xe0\xbd\xa0\xe0\xbc\x8b\xe0\xbd\xa6\xe0\xbe\xa4\xe0\xbd\xba\xe0\xbd\x93\xe0\xbc\x8b\xe0\xbd\x94\xe0\xbc\x8b\0" "\xe0\xbd\x89\xe0\xbd\xb2\xe0\xbc\x8b\xe0\xbd\x98\xe0\xbc\x8b\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbd\x96\xe0\xbc\x8b\0" "\xe0\xbd\x98\xe0\xbd\xb2\xe0\xbd\x82\xe0\xbc\x8b\xe0\xbd\x91\xe0\xbd\x98\xe0\xbd\xa2\xe0\xbc\x8b\0" "\xe0\xbd\xa7\xe0\xbe\xb3\xe0\xbd\x82\xe0\xbc\x8b\xe0\xbd\x94\xe0\xbc\x8b\0" "\xe0\xbd\x95\xe0\xbd\xb4\xe0\xbd\xa2\xe0\xbc\x8b\xe0\xbd\x96\xe0\xbd\xb4\xe0\xbc\x8b\0" "\xe0\xbd\xa6\xe0\xbd\x84\xe0\xbd\xa6\xe0\xbc\x8b\0" "\xe0\xbd\xa6\xe0\xbe\xa4\xe0\xbd\xba\xe0\xbd\x93\xe0\xbc\x8b\xe0\xbd\x94\xe0\xbc\x8b\0" "\xe0\xbd\x89\xe0\xbd\xb2\0" "\xe0\xbd\x9f\xe0\xbe\xb3\0" "\xe0\xbd\x98\xe0\xbd\xb2\0" "\xe0\xbd\xa7\xe0\xbe\xb3\0" "\xe0\xbd\x95\xe0\xbd\xb4\0" "\xe0\xbd\xa6\0" "\xe0\xbd\xa6\xe0\xbe\xa4\xe0\xbd\xba\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbd\x96\xe0\xbc\x8b\xe0\xbd\x91\xe0\xbd\x84\xe0\xbc\x8b\xe0\xbd\x94\xe0\xbd\xbc\xe0\xbc\x8b\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbd\x96\xe0\xbc\x8b\xe0\xbd\x82\xe0\xbd\x89\xe0\xbd\xb2\xe0\xbd\xa6\xe0\xbc\x8b\xe0\xbd\x94\xe0\xbc\x8b\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbd\x96\xe0\xbc\x8b\xe0\xbd\xa6\xe0\xbd\xb4\xe0\xbd\x98\xe0\xbc\x8b\xe0\xbd\x94\xe0\xbc\x8b\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbd\x96\xe0\xbc\x8b\xe0\xbd\x96\xe0\xbd\x9e\xe0\xbd\xb2\xe0\xbc\x8b\xe0\xbd\x94\xe0\xbc\x8b\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbd\x96\xe0\xbc\x8b\xe0\xbd\xa3\xe0\xbe\x94\xe0\xbc\x8b\xe0\xbd\x94\xe0\xbc\x8b\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbd\x96\xe0\xbc\x8b\xe0\xbd\x91\xe0\xbe\xb2\xe0\xbd\xb4\xe0\xbd\x82\xe0\xbc\x8b\xe0\xbd\x94\xe0\xbc\x8b\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbd\x96\xe0\xbc\x8b\xe0\xbd\x96\xe0\xbd\x91\xe0\xbd\xb4\xe0\xbd\x93\xe0\xbc\x8b\xe0\xbd\x94\xe0\xbc\x8b\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbd\x96\xe0\xbc\x8b\xe0\xbd\x96\xe0\xbd\xa2\xe0\xbe\x92\xe0\xbe\xb1\xe0\xbd\x91\xe0\xbc\x8b\xe0\xbd\x94\xe0\xbc\x8b\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbd\x96\xe0\xbc\x8b\xe0\xbd\x91\xe0\xbd\x82\xe0\xbd\xb4\xe0\xbc\x8b\xe0\xbd\x94\xe0\xbc\x8b\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbd\x96\xe0\xbc\x8b\xe0\xbd\x96\xe0\xbd\x85\xe0\xbd\xb4\xe0\xbc\x8b\xe0\xbd\x94\xe0\xbc\x8b\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbd\x96\xe0\xbc\x8b\xe0\xbd\x96\xe0\xbd\x85\xe0\xbd\xb4\xe0\xbc\x8b\xe0\xbd\x82\xe0\xbd\x85\xe0\xbd\xb2\xe0\xbd\x82\xe0\xbc\x8b\xe0\xbd\x94\xe0\xbc\x8b\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbd\x96\xe0\xbc\x8b\xe0\xbd\x96\xe0\xbd\x85\xe0\xbd\xb4\xe0\xbc\x8b\xe0\xbd\x82\xe0\xbd\x89\xe0\xbd\xb2\xe0\xbd\xa6\xe0\xbc\x8b\xe0\xbd\x94\xe0\xbc\x8b\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbc\xa1\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbc\xa2\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbc\xa3\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbc\xa4\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbc\xa5\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbc\xa6\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbc\xa7\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbc\xa8\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbc\xa9\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbc\xa1\xe0\xbc\xa0\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbc\xa1\xe0\xbc\xa1\0" "\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b\xe0\xbc\xa1\xe0\xbc\xa2\0" "yyyy'\xe0\xbd\xa3\xe0\xbd\xbc\xe0\xbd\xa0\xe0\xbd\xb2\xe0\xbc\x8b\xe0\xbd\x9f\xe0\xbe\xb3' M'\xe0\xbd\x9a\xe0\xbd\xba\xe0\xbd\xa6' d\0" "yyyy'\xe0\xbd\xa3\xe0\xbd\xbc\xe0\xbd\xa0\xe0\xbd\xb2\xe0\xbc\x8b\xe0\xbd\x9f\xe0\xbe\xb3' M'\xe0\xbd\x9a\xe0\xbd\xba\xe0\xbd\xa6' d dddd\0" "yyyy\xe0\xbd\xa3\xe0\xbd\xbc\xe0\xbd\xa0\xe0\xbd\xb2\xe0\xbc\x8b\xe0\xbd\x9f\xe0\xbe\xb3 MMM d\0" "yyyy\xe0\xbd\xa3\xe0\xbd\xbc\xe0\xbd\xa0\xe0\xbd\xb2\xe0\xbc\x8b\xe0\xbd\x9f\xe0\xbe\xb3 MMM d dddd\0" "yyyy'\xe0\xbd\xa3\xe0\xbd\xbc\xe0\xbd\xa0\xe0\xbd\xb2\xe0\xbc\x8b\xe0\xbd\x9f\xe0\xbe\xb3\xe0\xbc\x8b' M\0" "Dydd Sul\0" "Dydd Llun\0" "Dydd Mawrth\0" "Dydd Mercher\0" "Dydd Iau\0" "Dydd Gwener\0" "Dydd Sadwrn\0" "Sul\0" "Llun\0" "Maw\0" "Mer\0" "Iau\0" "Gwe\0" "Sad\0" "Ll\0" "Ionawr\0" "Chwefror\0" "Mawrth\0" "Ebrill\0" "Mehefin\0" "Gorffennaf\0" "Awst\0" "Medi\0" "Hydref\0" "Tachwedd\0" "Rhagfyr\0" "Ion\0" "Chw\0" "Ebr\0" "Meh\0" "Gor\0" "Hyd\0" "Tach\0" "Rhag\0" "\xe1\x9e\x96\xe1\x9f\x92\xe1\x9e\x9a\xe1\x9e\xb9\xe1\x9e\x80\0" "\xe1\x9e\x9b\xe1\x9f\x92\xe1\x9e\x84\xe1\x9e\xb6\xe1\x9e\x85\0" "\xe1\x9e\xa2\xe1\x9e\xb6\xe1\x9e\x91\xe1\x9e\xb7\xe1\x9e\x8f\xe1\x9f\x92\xe1\x9e\x99\0" "\xe1\x9e\x85\xe1\x9e\x93\xe1\x9f\x92\xe1\x9e\x91\0" "\xe1\x9e\xa2\xe1\x9e\x84\xe1\x9f\x92\xe1\x9e\x82\xe1\x9e\xb6\xe1\x9e\x9a\0" "\xe1\x9e\x96\xe1\x9e\xbb\xe1\x9e\x92\0" "\xe1\x9e\x96\xe1\x9f\x92\xe1\x9e\x9a\xe1\x9e\xa0\xe1\x9e\x9f\xe1\x9f\x92\xe1\x9e\x94\xe1\x9e\x8f\xe1\x9e\xb7\xe1\x9f\x8d\0" "\xe1\x9e\x9f\xe1\x9e\xbb\xe1\x9e\x80\xe1\x9f\x92\xe1\x9e\x9a\0" "\xe1\x9e\x9f\xe1\x9f\x85\xe1\x9e\x9a\xe1\x9f\x8d\0" "\xe1\x9e\x98\xe1\x9e\x80\xe1\x9e\x9a\xe1\x9e\xb6\0" "\xe1\x9e\x80\xe1\x9e\xbb\xe1\x9e\x98\xe1\x9f\x92\xe1\x9e\x97\xe1\x9f\x88\0" "\xe1\x9e\x98\xe1\x9e\xb8\xe1\x9e\x93\xe1\x9e\xb6\0" "\xe1\x9e\x98\xe1\x9f\x81\xe1\x9e\x9f\xe1\x9e\xb6\0" "\xe1\x9e\xa7\xe1\x9e\x9f\xe1\x9e\x97\xe1\x9e\xb6\0" "\xe1\x9e\x98\xe1\x9e\xb7\xe1\x9e\x90\xe1\x9e\xbb\xe1\x9e\x93\xe1\x9e\xb6\0" "\xe1\x9e\x80\xe1\x9e\x80\xe1\x9f\x92\xe1\x9e\x80\xe1\x9e\x8a\xe1\x9e\xb6\0" "\xe1\x9e\x9f\xe1\x9e\xb8\xe1\x9e\xa0\xe1\x9e\xb6\0" "\xe1\x9e\x80\xe1\x9e\x89\xe1\x9f\x92\xe1\x9e\x89\xe1\x9e\xb6\0" "\xe1\x9e\x8f\xe1\x9e\xbb\xe1\x9e\x9b\xe1\x9e\xb6\0" "\xe1\x9e\x9c\xe1\x9e\xb7\xe1\x9e\x85\xe1\x9f\x92\xe1\x9e\x86\xe1\x9e\xb7\xe1\x9e\x80\xe1\x9e\xb6\0" "\xe1\x9e\x92\xe1\x9f\x92\xe1\x9e\x93\xe1\x9e\xbc\0" "'\xe1\x9e\x81\xe1\x9f\x82' MM '\xe1\x9e\x86\xe1\x9f\x92\xe1\x9e\x93\xe1\x9e\xb6\xe1\x9f\x86' yyyy\0" "\xe0\xba\x81\xe0\xbb\x88\xe0\xba\xad\xe0\xba\x99\xe0\xba\x97\xe0\xbb\x88\xe0\xba\xbd\xe0\xba\x87\0" "\xe0\xba\xab\xe0\xba\xbc\xe0\xba\xb1\xe0\xba\x87\xe0\xba\x97\xe0\xbb\x88\xe0\xba\xbd\xe0\xba\x87\0" "\xe0\xba\xa7\xe0\xba\xb1\xe0\xba\x99\xe0\xba\xad\xe0\xba\xb2\xe0\xba\x97\xe0\xba\xb4\xe0\xba\x94\0" "\xe0\xba\xa7\xe0\xba\xb1\xe0\xba\x99\xe0\xba\x88\xe0\xba\xb1\xe0\xba\x99\0" "\xe0\xba\xa7\xe0\xba\xb1\xe0\xba\x99\xe0\xba\xad\xe0\xba\xb1\xe0\xba\x87\xe0\xba\x84\xe0\xba\xb2\xe0\xba\x99\0" "\xe0\xba\xa7\xe0\xba\xb1\xe0\xba\x99\xe0\xba\x9e\xe0\xba\xb8\xe0\xba\x94\0" "\xe0\xba\xa7\xe0\xba\xb1\xe0\xba\x99\xe0\xba\x9e\xe0\xba\xb0\xe0\xba\xab\xe0\xba\xb1\xe0\xba\x94\0" "\xe0\xba\xa7\xe0\xba\xb1\xe0\xba\x99\xe0\xba\xaa\xe0\xba\xb8\xe0\xba\x81\0" "\xe0\xba\xa7\xe0\xba\xb1\xe0\xba\x99\xe0\xbb\x80\xe0\xba\xaa\xe0\xba\xbb\xe0\xba\xb2\0" "\xe0\xba\x97\0" "\xe0\xba\x88\0" "\xe0\xba\x84\0" "\xe2\x80\x8b\xe0\xba\x9e\xe0\xba\xb8\0" "\xe0\xba\x9e\0" "\xe2\x80\x8b\xe0\xba\xaa\xe0\xba\xb8\0" "\xe0\xba\xaa\0" "\xe0\xba\xa1\xe0\xba\xb1\xe0\xba\x87\xe0\xba\x81\xe0\xba\xad\xe0\xba\x99\0" "\xe0\xba\x81\xe0\xba\xb8\xe0\xba\xa1\xe0\xba\x9e\xe0\xba\xb2\0" "\xe0\xba\xa1\xe0\xba\xb5\xe0\xba\x99\xe0\xba\xb2\0" "\xe0\xbb\x80\xe0\xba\xa1\xe0\xba\xaa\xe0\xba\xb2\0" "\xe0\xba\x9e\xe0\xba\xb6\xe0\xba\x94\xe0\xba\xaa\xe0\xba\xb0\xe0\xba\x9e\xe0\xba\xb2\0" "\xe0\xba\xa1\xe0\xba\xb4\xe0\xba\x96\xe0\xba\xb8\xe0\xba\x99\xe0\xba\xb2\0" "\xe0\xba\x81\xe0\xbb\x8d\xe0\xba\xa5\xe0\xba\xb0\xe0\xba\x81\xe0\xba\xbb\xe0\xba\x94\0" "\xe0\xba\xaa\xe0\xba\xb4\xe0\xba\x87\xe0\xba\xab\xe0\xba\xb2\0" "\xe0\xba\x81\xe0\xba\xb1\xe0\xba\x99\xe0\xba\x8d\xe0\xba\xb2\0" "\xe0\xba\x95\xe0\xba\xb8\xe0\xba\xa5\xe0\xba\xb2\0" "\xe0\xba\x9e\xe0\xba\xb0\xe0\xba\x88\xe0\xba\xb4\xe0\xba\x81\0" "\xe0\xba\x97\xe0\xba\xb1\xe0\xba\x99\xe0\xba\xa7\xe0\xba\xb2\0" "\xe0\xba\xa1.\xe0\xba\x81.\0" "\xe0\xba\x81.\xe0\xba\x9e.\0" "\xe0\xba\xa1.\xe0\xba\x99.\0" "\xe0\xba\xa1.\xe0\xba\xaa.\0" "\xe0\xba\x9e.\xe0\xba\x9e.\0" "\xe0\xba\xa1\xe0\xba\xb4.\xe0\xba\x96.\0" "\xe0\xba\x81.\xe0\xba\xa5.\0" "\xe0\xba\xaa.\xe0\xba\xab.\0" "\xe0\xba\x81.\xe0\xba\x8d.\0" "\xe0\xba\x95.\xe0\xba\xa5.\0" "\xe0\xba\x9e.\xe0\xba\x88.\0" "\xe0\xba\x97.\xe0\xba\xa7.\0" "dddd \xe0\xba\x97\xe0\xba\xb5 d MMMM gg yyyy\0" "luns\0" "m\xc3\xa9rcores\0" "xoves\0" "venres\0" "Dom\0" "M\xc3\xa9r\0" "Xov\0" "Ven\0" "S\xc3\xa1\x62\0" "X\0" "Xaneiro\0" "Febreiro\0" "Maio\0" "Xu\xc3\xb1o\0" "Xullo\0" "Setembro\0" "Outubro\0" "Novembro\0" "Decembro\0" "xaneiro\0" "febreiro\0" "xu\xc3\xb1o\0" "xullo\0" "decembro\0" "Xan\0" "Abr\0" "Xu\xc3\xb1\0" "Xul\0" "Out\0" "\xe0\xa4\xae.\xe0\xa4\xaa\xe0\xa5\x82.\0" "\xe0\xa4\xae.\xe0\xa4\xa8\xe0\xa4\x82.\0" "\xe0\xa4\x86\xe0\xa4\xa6\xe0\xa4\xbf\xe0\xa4\xa4\xe0\xa5\x8d\xe0\xa4\xaf\xe0\xa4\xb5\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xae\xe0\xa4\x82\xe0\xa4\x97\xe0\xa4\xb3\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\x93\xe0\xa4\x97\xe0\xa4\xb8\xe0\xa5\x8d\xe0\xa4\x9f\0" "\xe0\xa4\xb8\xe0\xa5\x87\xe0\xa4\xaa\xe0\xa5\x8d\xe0\xa4\x9f\xe0\xa5\x87\xe0\xa4\x82\xe0\xa4\xac\xe0\xa4\xb0\0" "\xe0\xa4\x93\xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\x9f\xe0\xa5\x8b\xe0\xa4\xac\xe0\xa4\xb0\0" "\xe0\xb6\xb4\xe0\xb7\x99.\xe0\xb7\x80.\0" "\xe0\xb6\xb4.\xe0\xb7\x80.\0" "\xe0\xb6\x89\xe0\xb6\xbb\xe0\xb7\x92\xe0\xb6\xaf\xe0\xb7\x8f\0" "\xe0\xb7\x83\xe0\xb6\xb3\xe0\xb7\x94\xe0\xb6\xaf\xe0\xb7\x8f\0" "\xe0\xb6\x85\xe0\xb6\x9f\xe0\xb7\x84\xe0\xb6\xbb\xe0\xb7\x94\xe0\xb7\x80\xe0\xb7\x8f\xe0\xb6\xaf\xe0\xb7\x8f\0" "\xe0\xb6\xb6\xe0\xb6\xaf\xe0\xb7\x8f\xe0\xb6\xaf\xe0\xb7\x8f\0" "\xe0\xb6\xb6\xe0\xb7\x8a\xe2\x80\x8d\xe0\xb6\xbb\xe0\xb7\x84\xe0\xb7\x83\xe0\xb7\x8a\xe0\xb6\xb4\xe0\xb6\xad\xe0\xb7\x92\xe0\xb6\xb1\xe0\xb7\x8a\xe0\xb6\xaf\xe0\xb7\x8f\0" "\xe0\xb7\x83\xe0\xb7\x92\xe0\xb6\x9a\xe0\xb7\x94\xe0\xb6\xbb\xe0\xb7\x8f\xe0\xb6\xaf\xe0\xb7\x8f\0" "\xe0\xb7\x83\xe0\xb7\x99\xe0\xb6\xb1\xe0\xb7\x83\xe0\xb7\x94\xe0\xb6\xbb\xe0\xb7\x8f\xe0\xb6\xaf\xe0\xb7\x8f\0" "\xe0\xb6\x85\xe0\xb6\x9f\xe0\xb7\x84\0" "\xe0\xb6\xb6\xe0\xb7\x8a\xe2\x80\x8d\xe0\xb6\xbb\xe0\xb7\x84\xe0\xb7\x83\xe0\xb7\x8a\0" "\xe0\xb7\x83\xe0\xb7\x92\xe0\xb6\x9a\xe0\xb7\x94\0" "\xe0\xb7\x83\xe0\xb7\x99\xe0\xb6\xb1\0" "\xe0\xb6\x89\0" "\xe0\xb7\x83\0" "\xe0\xb6\x85\0" "\xe0\xb6\xb6\0" "\xe0\xb6\xb6\xe0\xb7\x8a\xe2\x80\x8d\xe0\xb6\xbb\0" "\xe0\xb7\x83\xe0\xb7\x92\0" "\xe0\xb7\x83\xe0\xb7\x99\0" "\xe0\xb6\xa2\xe0\xb6\xb1\xe0\xb7\x80\xe0\xb7\x8f\xe0\xb6\xbb\xe0\xb7\x92\0" "\xe0\xb6\xb4\xe0\xb7\x99\xe0\xb6\xb6\xe0\xb6\xbb\xe0\xb7\x80\xe0\xb7\x8f\xe0\xb6\xbb\xe0\xb7\x92\0" "\xe0\xb6\xb8\xe0\xb7\x8f\xe0\xb6\xbb\xe0\xb7\x8a\xe0\xb6\xad\xe0\xb7\x94\0" "\xe0\xb6\x85\xe0\xb6\xb4\xe0\xb7\x8a\xe2\x80\x8d\xe0\xb6\xbb\xe0\xb7\x9a\xe0\xb6\xbd\xe0\xb7\x8a\0" "\xe0\xb6\xb8\xe0\xb7\x90\xe0\xb6\xba\xe0\xb7\x92\0" "\xe0\xb6\xa2\xe0\xb7\x96\xe0\xb6\xb1\xe0\xb7\x92\0" "\xe0\xb6\xa2\xe0\xb7\x96\xe0\xb6\xbd\xe0\xb7\x92\0" "\xe0\xb6\x85\xe0\xb6\x9c\xe0\xb7\x9d\xe0\xb7\x83\xe0\xb7\x8a\xe0\xb6\xad\xe0\xb7\x94\0" "\xe0\xb7\x83\xe0\xb7\x90\xe0\xb6\xb4\xe0\xb7\x8a\xe0\xb6\xad\xe0\xb7\x90\xe0\xb6\xb8\xe0\xb7\x8a\xe0\xb6\xb6\xe0\xb6\xbb\xe0\xb7\x8a\0" "\xe0\xb6\x94\xe0\xb6\x9a\xe0\xb7\x8a\xe0\xb6\xad\xe0\xb7\x9d\xe0\xb6\xb6\xe0\xb6\xbb\xe0\xb7\x8a\0" "\xe0\xb6\xb1\xe0\xb7\x9c\xe0\xb7\x80\xe0\xb7\x90\xe0\xb6\xb8\xe0\xb7\x8a\xe0\xb6\xb6\xe0\xb6\xbb\xe0\xb7\x8a\0" "\xe0\xb6\xaf\xe0\xb7\x99\xe0\xb7\x83\xe0\xb7\x90\xe0\xb6\xb8\xe0\xb7\x8a\xe0\xb6\xb6\xe0\xb6\xbb\xe0\xb7\x8a\0" "\xe0\xb6\xa2\xe0\xb6\xb1\0" "\xe0\xb6\xb4\xe0\xb7\x99\xe0\xb6\xb6\0" "\xe0\xb6\xb8\xe0\xb7\x8f\xe0\xb6\xbb\xe0\xb7\x8a\0" "\xe0\xb6\x85\xe0\xb6\x9c\xe0\xb7\x9d\0" "\xe0\xb7\x83\xe0\xb7\x90\xe0\xb6\xb4\xe0\xb7\x8a\0" "\xe0\xb6\x94\xe0\xb6\x9a\xe0\xb7\x8a\0" "\xe0\xb6\xb1\xe0\xb7\x9c\xe0\xb7\x80\xe0\xb7\x90\0" "\xe0\xb6\xaf\xe0\xb7\x99\xe0\xb7\x83\xe0\xb7\x90\0" "\xe1\x8c\xa5\xe1\x8b\x8b\xe1\x89\xb5\0" "\xe1\x8a\xa8\xe1\x88\xb0\xe1\x8b\x93\xe1\x89\xb5\0" "\xe1\x8a\xa5\xe1\x88\x91\xe1\x8b\xb5\0" "\xe1\x88\xb0\xe1\x8a\x9e\0" "\xe1\x88\x9b\xe1\x8a\xad\xe1\x88\xb0\xe1\x8a\x9e\0" "\xe1\x88\xa8\xe1\x89\xa1\xe1\x8b\x95\0" "\xe1\x88\x90\xe1\x88\x99\xe1\x88\xb5\0" "\xe1\x8b\x93\xe1\x88\xad\xe1\x89\xa5\0" "\xe1\x89\x85\xe1\x8b\xb3\xe1\x88\x9c\0" "\xe1\x88\x9b\xe1\x8a\xad\xe1\x88\xb0\0" "\xe1\x8a\xa5\0" "\xe1\x88\xb0\0" "\xe1\x88\x9b\0" "\xe1\x88\xa8\0" "\xe1\x88\x90\0" "\xe1\x8b\x93\0" "\xe1\x89\x85\0" "\xe1\x8c\x83\xe1\x8a\x95\xe1\x8b\xa9\xe1\x8b\x88\xe1\x88\xaa\0" "\xe1\x8d\x8c\xe1\x89\xa5\xe1\x88\xa9\xe1\x8b\x88\xe1\x88\xaa\0" "\xe1\x88\x9b\xe1\x88\xad\xe1\x89\xbd\0" "\xe1\x8a\xa4\xe1\x8d\x95\xe1\x88\xaa\xe1\x88\x8d\0" "\xe1\x88\x9c\xe1\x8b\xad\0" "\xe1\x8c\x81\xe1\x8a\x95\0" "\xe1\x8c\x81\xe1\x88\x8b\xe1\x8b\xad\0" "\xe1\x8a\xa6\xe1\x8c\x88\xe1\x88\xb5\xe1\x89\xb5\0" "\xe1\x88\xb4\xe1\x8d\x95\xe1\x89\xb4\xe1\x88\x9d\xe1\x89\xa0\xe1\x88\xad\0" "\xe1\x8a\xa6\xe1\x8a\xad\xe1\x89\xb6\xe1\x89\xa0\xe1\x88\xad\0" "\xe1\x8a\x96\xe1\x89\xac\xe1\x88\x9d\xe1\x89\xa0\xe1\x88\xad\0" "\xe1\x8b\xb2\xe1\x88\xb4\xe1\x88\x9d\xe1\x89\xa0\xe1\x88\xad\0" "\xe1\x8a\xa6\xe1\x8a\xad\xe1\x89\xb0\xe1\x8b\x8d\xe1\x89\xa0\xe1\x88\xad\0" "\xe1\x8c\x83\xe1\x8a\x95\xe1\x8b\xa9\0" "\xe1\x8d\x8c\xe1\x89\xa5\xe1\x88\xa9\0" "\xe1\x8a\xa4\xe1\x8d\x95\xe1\x88\xaa\0" "\xe1\x8a\xa6\xe1\x8c\x88\xe1\x88\xb5\0" "\xe1\x88\xb4\xe1\x8d\x95\xe1\x89\xb4\0" "\xe1\x8a\xa6\xe1\x8a\xad\xe1\x89\xb6\0" "\xe1\x8a\x96\xe1\x89\xac\xe1\x88\x9d\0" "\xe1\x8b\xb2\xe1\x88\xb4\xe1\x88\x9d\0" "Zdat azal\0" "\xe1\xb8\x8c\x65\x66\x66ir aza\0" "Asamas\0" "Aynas\0" "Asinas\0" "Akras\0" "Akwas\0" "Asimwas\0" "Asi\xe1\xb8\x8dyas\0" "Asa\0" "Ayn\0" "Asn\0" "Akr\0" "Akw\0" "Asm\0" "As\xe1\xb8\x8d\0" "Yennayer\0" "Yebrayer\0" "Mars\0" "Ibrir\0" "Mayyu\0" "Yunyu\0" "Yulyuz\0" "\xc6\x94uct\0" "Cutanbir\0" "K\xe1\xb9\xaduber\0" "Nwanbir\0" "Dujanbir\0" "Yen\0" "Yeb\0" "Ibr\0" "Yun\0" "Yul\0" "\xc6\x94uc\0" "Cut\0" "K\xe1\xb9\xadu\0" "Nwa\0" "Duj\0" "\xe0\xa4\xaa\xe0\xa5\x82\xe0\xa4\xb0\xe0\xa5\x8d\xe0\xa4\xb5 \xe0\xa4\xae\xe0\xa4\xa7\xe0\xa5\x8d\xe0\xa4\xaf\xe0\xa4\xbe\xe0\xa4\xa8\xe0\xa5\x8d\xe0\xa4\xb9\0" "\xe0\xa4\x89\xe0\xa4\xa4\xe0\xa5\x8d\xe0\xa4\xa4\xe0\xa4\xb0 \xe0\xa4\xae\xe0\xa4\xa7\xe0\xa5\x8d\xe0\xa4\xaf\xe0\xa4\xbe\xe0\xa4\xa8\xe0\xa5\x8d\xe0\xa4\xb9\0" "\xe0\xa4\x86\xe0\xa4\x87\xe0\xa4\xa4\xe0\xa4\xac\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xb8\xe0\xa5\x8b\xe0\xa4\xae\xe0\xa4\xac\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xae\xe0\xa4\x99\xe0\xa5\x8d\xe0\xa4\x97\xe0\xa4\xb2\xe0\xa4\xac\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xac\xe0\xa5\x81\xe0\xa4\xa7\xe0\xa4\xac\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xac\xe0\xa4\xbf\xe0\xa4\xb9\xe0\xa5\x80\xe0\xa4\xac\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xb6\xe0\xa5\x81\xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\xb0\xe0\xa4\xac\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\xb6\xe0\xa4\xa8\xe0\xa4\xbf\xe0\xa4\xac\xe0\xa4\xbe\xe0\xa4\xb0\0" "\xe0\xa4\x86\xe0\xa4\x87\xe0\xa4\xa4\0" "\xe0\xa4\xae\xe0\xa4\x99\xe0\xa5\x8d\xe0\xa4\x97\xe0\xa4\xb2\0" "\xe0\xa4\xac\xe0\xa4\xbf\xe0\xa4\xb9\xe0\xa5\x80\0" "\xe0\xa4\x86\0" "\xe0\xa4\xae\0" "\xe0\xa4\xac\xe0\xa4\xbf\0" "\xe0\xa4\xab\xe0\xa5\x87\xe0\xa4\xac\xe0\xa5\x8d\xe0\xa4\xb0\xe0\xa5\x81\xe0\xa4\x85\xe0\xa4\xb0\xe0\xa5\x80\0" "\xe0\xa4\x85\xe0\xa4\xaa\xe0\xa5\x8d\xe0\xa4\xb0\xe0\xa4\xbf\xe0\xa4\xb2\0" "\xe0\xa4\x9c\xe0\xa5\x81\xe0\xa4\xa8\0" "\xe0\xa4\x85\xe0\xa4\x97\xe0\xa4\xb8\xe0\xa5\x8d\xe0\xa4\x9f\0" "\xe0\xa4\xb8\xe0\xa5\x87\xe0\xa4\xaa\xe0\xa5\x8d\xe0\xa4\x9f\xe0\xa5\x87\xe0\xa4\xae\xe0\xa5\x8d\xe0\xa4\xac\xe0\xa4\xb0\0" "\xe0\xa4\x85\xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\x9f\xe0\xa5\x8b\xe0\xa4\xac\xe0\xa4\xb0\0" "\xe0\xa4\xa8\xe0\xa5\x8b\xe0\xa4\xad\xe0\xa5\x87\xe0\xa4\xae\xe0\xa5\x8d\xe0\xa4\xac\xe0\xa4\xb0\0" "\xe0\xa4\xa1\xe0\xa4\xbf\xe0\xa4\xb8\xe0\xa5\x87\xe0\xa4\xae\xe0\xa5\x8d\xe0\xa4\xac\xe0\xa4\xb0\0" "dddd, MMMM dd, yyyy\0" "MMMM dd, yyyy\0" "\xd9\x88\xd8\xb1\xdb\x8c\0" "\xd8\xba\xd9\x88\xdb\x8c\xdb\x8c\0" "\xd8\xba\xd8\xa8\xd8\xb1\xda\xab\xd9\x88\xd9\x84\xdb\x8c\0" "\xda\x86\xd9\x86\xda\xab\xd8\xa7\xda\x9a\0" "\xd8\xb2\xd9\x85\xd8\xb1\xdb\x8c\0" "\xd9\x88\xda\x96\xdb\x8c\0" "\xd8\xaa\xd9\x84\xd9\x87\0" "\xd9\x84\xda\x93\xd9\x85\0" "\xd9\x84\xdb\x8c\xd9\x86\xd8\xaf\xdb\x8d\0" "\xd9\x85\xd8\xb1\xd8\xba\xd9\x88\xd9\x85\xdb\x8c\0" "\xd8\xb3\xd9\x84\xd9\x88\xd8\xa7\xd8\xba\xd9\x87\0" "\xda\xa9\xd8\xa8\0" "Linggo\0" "Lunes\0" "Martes\0" "Miyerkules\0" "Huwebes\0" "Biyernes\0" "Sabado\0" "Lin\0" "Miy\0" "Huw\0" "Biy\0" "Pebrero\0" "Marso\0" "Hunyo\0" "Hulyo\0" "Setyembre\0" "Oktubre\0" "Nobyembre\0" "Disyembre\0" "Ene\0" "Peb\0" "Hun\0" "Hul\0" "Nob\0" "Lahadi\0" "Litinin\0" "Talata\0" "Laraba\0" "Alhamis\0" "Jumma'a\0" "Asabar\0" "Lh\0" "Li\0" "Ta\0" "Lr\0" "Al\0" "Ju\0" "As\0" "Janairu\0" "Faburairu\0" "Maris\0" "Afirilu\0" "Mayu\0" "Yuni\0" "Yuli\0" "Agusta\0" "Satumba\0" "Nuwamba\0" "Disamba\0" "Fab\0" "Afi\0" "Agu\0" "Nuw\0" "\xc3\x80\xc3\xa1r\xe1\xbb\x8d\xcc\x80\0" "\xe1\xbb\x8c\xcc\x80s\xc3\xa1n\0" "\xe1\xbb\x8cj\xe1\xbb\x8d\xcc\x81 \xc3\x80\xc3\xack\xc3\xba\0" "\xe1\xbb\x8cj\xe1\xbb\x8d\xcc\x81 Aj\xc3\xa9\0" "\xe1\xbb\x8cj\xe1\xbb\x8d\xcc\x81 \xc3\x8cs\xe1\xba\xb9\xcc\x81gun\0" "\xe1\xbb\x8cj\xe1\xbb\x8d\xcc\x81r\xc3\xba\0" "\xe1\xbb\x8cj\xe1\xbb\x8d\xcc\x81\x62\xe1\xbb\x8d\0" "\xe1\xbb\x8cj\xe1\xbb\x8d\xcc\x81 \xe1\xba\xb8t\xc3\xac\0" "\xe1\xbb\x8cj\xe1\xbb\x8d\xcc\x81 \xc3\x80\x62\xc3\xa1m\xe1\xba\xb9\xcc\x81ta\0" "\xc3\x80\xc3\xack\xc3\xba\0" "Aj\xc3\xa9\0" "\xc3\x8cs\xe1\xba\xb9\xcc\x81gun\0" "\xe1\xba\xb8t\xc3\xac\0" "\xc3\x80\x62\xc3\xa1m\xe1\xba\xb9\xcc\x81ta\0" "O\xe1\xb9\xa3\xc3\xb9 \xe1\xb9\xa2\xe1\xba\xb9\xcc\x81r\xe1\xba\xb9\xcc\x81\0" "O\xe1\xb9\xa3\xc3\xb9 \xc3\x88r\xc3\xa8l\xc3\xa8\0" "O\xe1\xb9\xa3\xc3\xb9 \xe1\xba\xb8r\xe1\xba\xb9\xcc\x80n\xc3\xa0\0" "O\xe1\xb9\xa3\xc3\xb9 \xc3\x8cgb\xc3\xa9\0" "O\xe1\xb9\xa3\xc3\xb9 \xe1\xba\xb8\xcc\x80\x62ibi\0" "O\xe1\xb9\xa3\xc3\xb9 \xc3\x92k\xc3\xba\x64u\0" "O\xe1\xb9\xa3\xc3\xb9 Ag\xe1\xba\xb9m\xe1\xbb\x8d\0" "O\xe1\xb9\xa3\xc3\xb9 \xc3\x92g\xc3\xban\0" "O\xe1\xb9\xa3\xc3\xb9 Owewe\0" "O\xe1\xb9\xa3\xc3\xb9 \xe1\xbb\x8c\xcc\x80w\xc3\xa0r\xc3\xa0\0" "O\xe1\xb9\xa3\xc3\xb9 B\xc3\xa9l\xc3\xba\0" "O\xe1\xb9\xa3\xc3\xb9 \xe1\xbb\x8c\xcc\x80p\xe1\xba\xb9\xcc\x80\0" "\xe1\xb9\xa2\xe1\xba\xb9\xcc\x81r\xe1\xba\xb9\xcc\x81\0" "\xc3\x88r\xc3\xa8l\xc3\xa8\0" "\xe1\xba\xb8r\xe1\xba\xb9\xcc\x80n\xc3\xa0\0" "\xc3\x8cgb\xc3\xa9\0" "\xe1\xba\xb8\xcc\x80\x62ibi\0" "\xc3\x92k\xc3\xba\x64u\0" "Ag\xe1\xba\xb9m\xe1\xbb\x8d\0" "\xc3\x92g\xc3\xban\0" "Owewe\0" "\xe1\xbb\x8c\xcc\x80w\xc3\xa0r\xc3\xa0\0" "B\xc3\xa9l\xc3\xba\0" "\xe1\xbb\x8c\xcc\x80p\xe1\xba\xb9\xcc\x80\0" "Sontaga\0" "Mosupalogo\0" "Labohlano\0" "Mokibelo\0" "Mok\0" "Janaware\0" "Feberware\0" "Mat\xc5\xa1he\0" "Aporele\0" "Julae\0" "Agostose\0" "Setemere\0" "Oktobore\0" "Nofemere\0" "Disemere\0" "Apo\0" "Nof\0" "MMMM d'.-at'\0" "u.t.\0" "u.k.\0" "sabaat\0" "ataasinngorneq\0" "marlunngorneq\0" "pingasunngorneq\0" "sisamanngorneq\0" "tallimanngorneq\0" "arfininngorneq\0" "ata\0" "pin\0" "sis\0" "tal\0" "arf\0" "martsi\0" "aprili\0" "maji\0" "augustusi\0" "septemberi\0" "oktoberi\0" "novemberi\0" "decemberi\0" "MMMM d'.-at, 'yyyy\0" "A.M.\0" "P.M.\0" "Mb\xe1\xbb\x8ds\xe1\xbb\x8b \xe1\xbb\xa4ka\0" "M\xe1\xbb\x8dnde\0" "Tiuzdee\0" "Wenezdee\0" "T\xe1\xbb\x8d\xe1\xbb\x8dzdee\0" "Fra\xe1\xbb\x8b\x64\x65\x65\0" "Sat\xe1\xbb\x8d\x64\x65\x65\0" "\xe1\xbb\xa4ka\0" "M\xe1\xbb\x8dn\0" "Tiu\0" "Wen\0" "T\xe1\xbb\x8d\xe1\xbb\x8d\0" "Fra\xe1\xbb\x8b\0" "Jen\xe1\xbb\xa5war\xe1\xbb\x8b\0" "Febr\xe1\xbb\xa5war\xe1\xbb\x8b\0" "Maach\xe1\xbb\x8b\0" "Eprel\0" "Mee\0" "Juun\0" "Jula\xe1\xbb\x8b\0" "\xe1\xbb\x8cg\xe1\xbb\x8d\xe1\xbb\x8dst\0" "\xe1\xbb\x8cktoba\0" "Jen\0" "Maa\0" "Juu\0" "\xe1\xbb\x8cg\xe1\xbb\x8d\0" "\xe1\xbb\x8ckt\0" "M\xe2\x80\x99 \xea\x86\xaa\xe2\x80\x99\x64\xe2\x80\x99 \xea\x91\x8d\xe2\x80\x99\0" "\xea\x8e\xb8\xea\x84\x91\0" "\xea\x81\xaf\xea\x8b\x92\0" "\xea\x91\xad\xea\x86\x8f\xea\x91\x8d\0" "\xea\x86\x8f\xea\x8a\x82\xea\x8b\x8d\0" "\xea\x86\x8f\xea\x8a\x82\xea\x91\x8d\0" "\xea\x86\x8f\xea\x8a\x82\xea\x8c\x95\0" "\xea\x86\x8f\xea\x8a\x82\xea\x87\x96\0" "\xea\x86\x8f\xea\x8a\x82\xea\x89\xac\0" "\xea\x86\x8f\xea\x8a\x82\xea\x83\x98\0" "\xea\x91\xad\xea\x86\x8f\0" "\xea\x86\x8f\xea\x8b\x8d\0" "\xea\x86\x8f\xea\x91\x8d\0" "\xea\x86\x8f\xea\x8c\x95\0" "\xea\x86\x8f\xea\x87\x96\0" "\xea\x86\x8f\xea\x89\xac\0" "\xea\x86\x8f\xea\x83\x98\0" "\xea\x86\x8f\0" "\xea\x8b\x8d\0" "\xea\x91\x8d\0" "\xea\x8c\x95\0" "\xea\x87\x96\0" "\xea\x89\xac\0" "\xea\x83\x98\0" "\xea\x8b\x8d\xea\x86\xaa\0" "\xea\x91\x8d\xea\x86\xaa\0" "\xea\x8c\x95\xea\x86\xaa\0" "\xea\x87\x96\xea\x86\xaa\0" "\xea\x89\xac\xea\x86\xaa\0" "\xea\x83\x98\xea\x86\xaa\0" "\xea\x8f\x83\xea\x86\xaa\0" "\xea\x89\x86\xea\x86\xaa\0" "\xea\x88\xac\xea\x86\xaa\0" "\xea\x8a\xb0\xea\x86\xaa\0" "\xea\x8a\xb0\xea\x8a\xaa\xea\x86\xaa\0" "\xea\x8a\xb0\xea\x91\x8b\xea\x86\xaa\0" "yyyy'\xea\x88\x8e' M'\xea\x86\xaa' d'\xea\x91\x8d'\0" "dddd, yyyy'\xea\x88\x8e' M'\xea\x86\xaa' d'\xea\x91\x8d'\0" "yyyy'\xea\x88\x8e' M'\xea\x86\xaa' d'\xea\x91\x8d', dddd\0" "yyyy\xea\x88\x8e MMM d\xea\x91\x8d\0" "dddd, yyyy\xea\x88\x8e MMM d\xea\x91\x8d\0" "yyyy'\xea\x88\x8e' M'\xea\x86\xaa'\0" "Meurzh\0" "Merc\xca\xbcher\0" "Yaou\0" "Gwener\0" "Sadorn\0" "sul\0" "meu.\0" "yaou\0" "gwe.\0" "sad.\0" "lu\0" "mz\0" "mc\0" "ya\0" "gw\0" "sa\0" "Genver\0" "C\xca\xbchwevrer\0" "Ebrel\0" "Mae\0" "Mezheven\0" "Gouere\0" "Eost\0" "Gwengolo\0" "Here\0" "Du\0" "Kerzu\0" "Gen\0" "C\xca\xbchwe\0" "Meur\0" "Mezh\0" "Goue\0" "Gwen\0" "Ker\0" "v.m.\0" "n.m.\0" "Sunntig\0" "M\xc3\xa4\xc3\xa4ntig\0" "Ziischtig\0" "Mittwuch\0" "Dunschtig\0" "Friitig\0" "Samschtig\0" "Su.\0" "M\xc3\xa4.\0" "Zi.\0" "Mi.\0" "Du.\0" "Fr.\0" "Sa.\0" "Auguscht\0" "Sept\xc3\xa4mber\0" "Oktoober\0" "Nov\xc3\xa4mber\0" "Dez\xc3\xa4mber\0" "MMMM d \xd0\xba\xd2\xaf\xd0\xbd\xd1\x8d\0" "\xd0\xad\xd0\x98\0" "\xd0\xad\xd0\x9a\0" "\xd0\x91\xd0\xb0\xd1\x81\xd0\xba\xd1\x8b\xd2\xbb\xd1\x8b\xd0\xb0\xd0\xbd\xd0\xbd\xd1\x8c\xd0\xb0\0" "\xd0\x91\xd1\x8d\xd0\xbd\xd0\xb8\xd0\xb4\xd0\xb8\xd1\x8d\xd0\xbb\xd0\xb8\xd0\xbd\xd0\xbd\xd1\x8c\xd0\xb8\xd0\xba\0" "\xd0\x9e\xd0\xbf\xd1\x82\xd1\x83\xd0\xbe\xd1\x80\xd1\x83\xd0\xbd\xd0\xbd\xd1\x8c\xd1\x83\xd0\xba\0" "\xd0\xa1\xd1\x8d\xd1\x80\xd1\x8d\xd0\xb4\xd1\x8d\0" "\xd0\xa7\xd1\x8d\xd0\xbf\xd0\xbf\xd0\xb8\xd1\x8d\xd1\x80\0" "\xd0\x91\xd1\x8d\xd1\x8d\xd1\x82\xd0\xb8\xd2\xa5\xd1\x81\xd1\x8d\0" "\xd0\xa1\xd1\x83\xd0\xb1\xd1\x83\xd0\xbe\xd1\x82\xd0\xb0\0" "\xd0\x91\xd1\x81\0" "\xd0\x91\xd0\xbd\0" "\xd0\x9e\xd0\xbf\0" "\xd0\xa1\xd1\x8d\0" "\xd0\xa7\xd0\xbf\0" "\xd0\x91\xd1\x8d\0" "\xd0\x9e\0" "\xd0\xa2\xd0\xbe\xd1\x85\xd1\x81\xd1\x83\xd0\xbd\xd0\xbd\xd1\x8c\xd1\x83\0" "\xd0\x9e\xd0\xbb\xd1\x83\xd0\xbd\xd0\xbd\xd1\x8c\xd1\x83\0" "\xd0\x9a\xd1\x83\xd0\xbb\xd1\x83\xd0\xbd \xd1\x82\xd1\x83\xd1\x82\xd0\xb0\xd1\x80\0" "\xd0\x9c\xd1\x83\xd1\x83\xd1\x81 \xd1\x83\xd1\x81\xd1\x82\xd0\xb0\xd1\x80\0" "\xd0\xab\xd0\xb0\xd0\xbc \xd1\x8b\xd0\xb9\xd1\x8b\xd0\xbd\0" "\xd0\x91\xd1\x8d\xd1\x81 \xd1\x8b\xd0\xb9\xd1\x8b\xd0\xbd\0" "\xd0\x9e\xd1\x82 \xd1\x8b\xd0\xb9\xd1\x8b\xd0\xbd\0" "\xd0\x90\xd1\x82\xd1\x8b\xd1\x80\xd0\xb4\xd1\x8c\xd1\x8b\xd1\x85 \xd1\x8b\xd0\xb9\xd1\x8b\xd0\xbd\0" "\xd0\x91\xd0\xb0\xd0\xbb\xd0\xb0\xd2\x95\xd0\xb0\xd0\xbd \xd1\x8b\xd0\xb9\xd1\x8b\xd0\xbd\0" "\xd0\x90\xd0\xbb\xd1\x82\xd1\x8b\xd0\xbd\xd0\xbd\xd1\x8c\xd1\x8b\0" "\xd0\xa1\xd1\x8d\xd1\x82\xd0\xb8\xd0\xbd\xd0\xbd\xd1\x8c\xd0\xb8\0" "\xd0\x90\xd1\x85\xd1\x81\xd1\x8b\xd0\xbd\xd0\xbd\xd1\x8c\xd1\x8b\0" "\xd0\xa2\xd0\xbe\xd1\x85\xd1\x81\0" "\xd0\x9e\xd0\xbb\xd1\x83\xd0\xbd\0" "\xd0\x9a\xd0\xbb\xd0\xbd_\xd1\x82\xd1\x82\xd1\x80\0" "\xd0\x9c\xd1\x83\xd1\x81_\xd1\x83\xd1\x81\xd1\x82\0" "\xd0\xab\xd0\xb0\xd0\xbc_\xd0\xb9\xd0\xbd\0" "\xd0\x91\xd1\x8d\xd1\x81_\xd0\xb9\xd0\xbd\0" "\xd0\x9e\xd1\x82_\xd0\xb9\xd0\xbd\0" "\xd0\x90\xd1\x82\xd1\x80\xd0\xb4\xd1\x8c_\xd0\xb9\xd0\xbd\0" "\xd0\x91\xd0\xbb\xd2\x95\xd0\xbd_\xd0\xb9\xd0\xbd\0" "\xd0\x90\xd0\xbb\xd1\x82\0" "\xd0\xa1\xd1\x8d\xd1\x82\0" "\xd0\x90\xd1\x85\xd1\x81\0" "yyyy MM d\0" "dd yyyy MM d\0" "dddd, yyyy '\xd1\x81.' MMMM d '\xd0\xba\xd2\xaf\xd0\xbd\xd1\x8d'\0" "yyyy '\xd1\x81.' MMMM d '\xd0\xba\xd2\xaf\xd0\xbd\xd1\x8d'\0" "dddd, MMMM d '\xd0\xba\xd2\xaf\xd0\xbd\xd1\x8d' yyyy '\xd1\x81.'\0" "yyyy '\xd1\x81.' MMMM\0" "Ku cyumweru\0" "Kuwa mbere\0" "Kuwa kabiri\0" "Kuwa gatatu\0" "Kuwa kane\0" "Kuwa gatanu\0" "Kuwa gatandatu\0" "cyu.\0" "mbe.\0" "kab.\0" "gtu.\0" "kan.\0" "gnu.\0" "gnd.\0" "Mutarama\0" "Gashyantare\0" "Werurwe\0" "Mata\0" "Gicuransi\0" "Kamena\0" "Nyakanga\0" "Kanama\0" "Nzeli\0" "Ukwakira\0" "Ugushyingo\0" "Ukuboza\0" "mut.\0" "gas.\0" "wer.\0" "mat.\0" "gic.\0" "kam.\0" "nya.\0" "nze.\0" "ukw.\0" "ugu.\0" "uku.\0" "d'mh' MMMM\0" "m\0" "f\0" "DiD\xc3\xb2mhnaich\0" "DiLuain\0" "DiM\xc3\xa0irt\0" "DiCiadain\0" "Diardaoin\0" "DihAoine\0" "DiSathairne\0" "DiD\0" "DiL\0" "DiM\0" "DiC\0" "Dia\0" "Dih\0" "DiS\0" "Am Faoilleach\0" "An Gearran\0" "Am M\xc3\xa0rt\0" "An Giblean\0" "An C\xc3\xa8itean\0" "An t-\xc3\x92gmhios\0" "An t-Iuchar\0" "An L\xc3\xb9nastal\0" "An t-Sultain\0" "An D\xc3\xa0mhair\0" "An t-Samhain\0" "An D\xc3\xb9\x62hlachd\0" "Faoi\0" "Gearr\0" "M\xc3\xa0rt\0" "Gibl\0" "C\xc3\xa8it\0" "\xc3\x92gmh\0" "Iuch\0" "L\xc3\xb9na\0" "Sult\0" "D\xc3\xa0mh\0" "D\xc3\xb9\x62h\0" "dddd, d'mh' MMMM yyyy\0" "d'mh' MMMM yyyy\0" "\xe9\x80\xb1\xe6\x97\xa5\0" "\xe9\x80\xb1\xe4\xb8\x80\0" "\xe9\x80\xb1\xe4\xba\x8c\0" "\xe9\x80\xb1\xe4\xb8\x89\0" "\xe9\x80\xb1\xe5\x9b\x9b\0" "\xe9\x80\xb1\xe4\xba\x94\0" "\xe9\x80\xb1\xe5\x85\xad\0" "dddd yyyy\xe5\xb9\xb4MMMd\xe6\x97\xa5\0" "\xd8\xb5\0" "\xd9\x85\0" "\xd8\xa7\xd9\x84\xd8\xa3\xd8\xad\xd8\xaf\0" "\xd8\xa7\xd9\x84\xd8\xa7\xd8\xab\xd9\x86\xd9\x8a\xd9\x86\0" "\xd8\xa7\xd9\x84\xd8\xab\xd9\x84\xd8\xa7\xd8\xab\xd8\xa7\xd8\xa1\0" "\xd8\xa7\xd9\x84\xd8\xa3\xd8\xb1\xd8\xa8\xd8\xb9\xd8\xa7\xd8\xa1\0" "\xd8\xa7\xd9\x84\xd8\xae\xd9\x85\xd9\x8a\xd8\xb3\0" "\xd8\xa7\xd9\x84\xd8\xac\xd9\x85\xd8\xb9\xd8\xa9\0" "\xd8\xa7\xd9\x84\xd8\xb3\xd8\xa8\xd8\xaa\0" "\xd8\xad\0" "\xd9\x86\0" "\xd8\xab\0" "\xd8\xb1\0" "\xd8\xae\0" "\xd9\x83\xd8\xa7\xd9\x86\xd9\x88\xd9\x86 \xd8\xa7\xd9\x84\xd8\xab\xd8\xa7\xd9\x86\xd9\x8a\0" "\xd8\xb4\xd8\xa8\xd8\xa7\xd8\xb7\0" "\xd8\xa2\xd8\xb0\xd8\xa7\xd8\xb1\0" "\xd9\x86\xd9\x8a\xd8\xb3\xd8\xa7\xd9\x86\0" "\xd8\xa3\xd9\x8a\xd8\xa7\xd8\xb1\0" "\xd8\xad\xd8\xb2\xd9\x8a\xd8\xb1\xd8\xa7\xd9\x86\0" "\xd8\xaa\xd9\x85\xd9\x88\xd8\xb2\0" "\xd8\xa2\xd8\xa8\0" "\xd8\xa3\xd9\x8a\xd9\x84\xd9\x88\xd9\x84\0" "\xd8\xaa\xd8\xb4\xd8\xb1\xd9\x8a\xd9\x86 \xd8\xa7\xd9\x84\xd8\xa3\xd9\x88\xd9\x84\0" "\xd8\xaa\xd8\xb4\xd8\xb1\xd9\x8a\xd9\x86 \xd8\xa7\xd9\x84\xd8\xab\xd8\xa7\xd9\x86\xd9\x8a\0" "\xd9\x83\xd8\xa7\xd9\x86\xd9\x88\xd9\x86 \xd8\xa7\xd9\x84\xd8\xa3\xd9\x88\xd9\x84\0" "dd.MMMM.\0" "dom.\0" "mi\xc3\xa9.\0" "jue.\0" "vie\0" "s\xc3\xa1\x62.\0" "en.\0" "mzo.\0" "my.\0" "dic.\0" "dd.MMMM\0" "MMMM.yyyy\0" "H.mm' u.'\0" "f.m.\0" "e.m.\0" "tysdag\0" "laurdag\0" "tys\0" "lau\0" "Janeiro\0" "Fevereiro\0" "Mar\xc3\xa7o\0" "Junho\0" "Julho\0" "Dezembro\0" "yy.MM.dd\0" "\xd0\xb1\xd0\xb0\xd0\xb7\xd0\xb0\xd1\x80\0" "\xd0\xb1\xd0\xb0\xd0\xb7\xd0\xb0\xd1\x80 \xd0\xb5\xd1\x80\xd1\x82\xd3\x99\xd1\x81\xd0\xb8\0" "\xd1\x87\xd3\x99\xd1\x80\xd1\x88\xd3\x99\xd0\xbd\xd0\xb1\xd3\x99 \xd0\xb0\xd1\x85\xd1\x88\xd0\xb0\xd0\xbc\xd1\x8b\0" "\xd1\x87\xd3\x99\xd1\x80\xd1\x88\xd3\x99\xd0\xbd\xd0\xb1\xd3\x99\0" "\xd2\xb9\xd2\xaf\xd0\xbc\xd3\x99 \xd0\xb0\xd1\x85\xd1\x88\xd0\xb0\xd0\xbc\xd1\x8b\0" "\xd2\xb9\xd2\xaf\xd0\xbc\xd3\x99\0" "\xd1\x88\xd3\x99\xd0\xbd\xd0\xb1\xd3\x99\0" "\xd1\x98\xd0\xb0\xd0\xbd\xd0\xb2\xd0\xb0\xd1\x80\0" "\xd1\x84\xd0\xb5\xd0\xb2\xd1\x80\xd0\xb0\xd0\xbb\0" "\xd0\xb0\xd0\xbf\xd1\x80\xd0\xb5\xd0\xbb\0" "\xd0\xb8\xd1\x98\xd1\x83\xd0\xbd\0" "\xd0\xb8\xd1\x98\xd1\x83\xd0\xbb\0" "\xd1\x81\xd0\xb5\xd0\xbd\xd1\x82\xd1\x98\xd0\xb0\xd0\xb1\xd1\x80\0" "\xd0\xbe\xd0\xba\xd1\x82\xd1\x98\xd0\xb0\xd0\xb1\xd1\x80\0" "\xd0\xbd\xd0\xbe\xd1\x98\xd0\xb0\xd0\xb1\xd1\x80\0" "\xd0\xb4\xd0\xb5\xd0\xba\xd0\xb0\xd0\xb1\xd1\x80\0" "\xd1\x8f\xd0\xba\xd1\x88\xd0\xb0\xd0\xbd\xd0\xb1\xd0\xb0\0" "\xd0\xb4\xd1\x83\xd1\x88\xd0\xb0\xd0\xbd\xd0\xb1\xd0\xb0\0" "\xd1\x81\xd0\xb5\xd1\x88\xd0\xb0\xd0\xbd\xd0\xb1\xd0\xb0\0" "\xd1\x87\xd0\xbe\xd1\x80\xd1\x88\xd0\xb0\xd0\xbd\xd0\xb1\xd0\xb0\0" "\xd0\xbf\xd0\xb0\xd0\xb9\xd1\x88\xd0\xb0\xd0\xbd\xd0\xb1\xd0\xb0\0" "\xd0\xb6\xd1\x83\xd0\xbc\xd0\xb0\0" "\xd1\x88\xd0\xb0\xd0\xbd\xd0\xb1\xd0\xb0\0" "\xd0\xaf\xd0\xba\xd1\x88\0" "\xd0\x94\xd1\x83\xd1\x88\0" "\xd0\xa1\xd0\xb5\xd1\x88\0" "\xd0\xa7\xd0\xbe\xd1\x80\0" "\xd0\x9f\xd0\xb0\xd0\xb9\0" "\xd0\xa8\xd0\xb0\xd0\xbd\0" "\xd0\xaf\0" "\xd9\x8a\xd9\x86\xd8\xa7\xd9\x8a\xd8\xb1\0" "\xd9\x81\xd8\xa8\xd8\xb1\xd8\xa7\xd9\x8a\xd8\xb1\0" "\xd8\xa3\xd8\xa8\xd8\xb1\xd9\x8a\xd9\x84\0" "\xd9\x85\xd8\xa7\xd9\x8a\xd9\x88\0" "\xd9\x8a\xd9\x88\xd9\x86\xd9\x8a\xd9\x88\0" "\xd9\x8a\xd9\x88\xd9\x84\xd9\x8a\xd9\x88\0" "\xd8\xa3\xd8\xba\xd8\xb3\xd8\xb7\xd8\xb3\0" "\xd8\xb3\xd8\xa8\xd8\xaa\xd9\x85\xd8\xa8\xd8\xb1\0" "\xd8\xa3\xd9\x83\xd8\xaa\xd9\x88\xd8\xa8\xd8\xb1\0" "\xd9\x86\xd9\x88\xd9\x81\xd9\x85\xd8\xa8\xd8\xb1\0" "\xd8\xaf\xd9\x8a\xd8\xb3\xd9\x85\xd8\xa8\xd8\xb1\0" "J\xc3\xa4nner\0" "J\xc3\xa4n\0" "yy MM dd\0" "MMMM d'. b.'\0" "aejlege\0" "m\xc3\xa5\x61nta\0" "d\xc3\xa4jsta\0" "gaskevahkoe\0" "d\xc3\xa5\x61rsta\0" "bearjadahke\0" "laavadahke\0" "o\xc4\x91\xc4\x91\x61jage\0" "guovva\0" "njuk\xc4\x8d\x61\0" "cuo\xc5\x8bo\0" "miesse\0" "geasse\0" "suoidne\0" "borge\0" "\xc4\x8d\x61k\xc4\x8d\x61\0" "golggot\0" "sk\xc3\xa1\x62ma\0" "juovla\0" "dddd', 'MMMM d'. b. 'yyyy\0" "MMMM d'. b. 'yyyy\0" "M/dd/yy\0" "MMMM-dd-yy\0" "dd-MMMM\0" "dddd, d 'de' MMMM 'de' yyyy\0" "d 'de' MMMM 'de' yyyy\0" "d. MMM yyyy.\0" "MMMM yyyy.\0" "\xd8\xac\xd8\xa7\xd9\x86\xd9\x81\xd9\x8a\0" "\xd9\x81\xd9\x8a\xd9\x81\xd8\xb1\xd9\x8a\0" "\xd8\xa3\xd9\x81\xd8\xb1\xd9\x8a\xd9\x84\0" "\xd9\x85\xd8\xa7\xd9\x8a\0" "\xd8\xac\xd9\x88\xd8\xa7\xd9\x86\0" "\xd8\xac\xd9\x88\xd9\x8a\xd9\x84\xd9\x8a\xd8\xa9\0" "\xd8\xa3\xd9\x88\xd8\xaa\0" "dddd yyyy'\xe5\xb9\xb4'M'\xe6\x9c\x88'd'\xe6\x97\xa5'\0" "dddd yyyy MM dd\0" "d/MMMM\0" "MMMM/yyyy\0" "pre podne\0" "popodne\0" "septembar\0" "oktobar\0" "novembar\0" "decembar\0" "dd. MMM. yyyy.\0" "dddd, dd. MMMM yyyy.\0" "\xd9\x8a\xd9\x88\xd9\x84\xd9\x8a\xd9\x88\xd8\xb2\0" "\xd8\xba\xd8\xb4\xd8\xaa\0" "\xd8\xb4\xd8\xaa\xd9\x86\xd8\xa8\xd8\xb1\0" "\xd9\x86\xd9\x88\xd9\x86\xd8\xa8\xd8\xb1\0" "\xd8\xaf\xd8\xac\xd9\x86\xd8\xa8\xd8\xb1\0" "MMMM/dd\0" "ponedeljak\0" "\xd0\xbf\xd1\x80\xd0\xb5 \xd0\xbf\xd0\xbe\xd0\xb4\xd0\xbd\xd0\xb5\0" "\xd0\xbf\xd0\xbe\xd0\xbf\xd0\xbe\xd0\xb4\xd0\xbd\xd0\xb5\0" "\xd0\xbd\xd0\xb5\xd0\xb4\xd0\xb5\xd1\x99\xd0\xb0\0" "\xd0\xbf\xd0\xbe\xd0\xbd\xd0\xb5\xd0\xb4\xd0\xb5\xd1\x99\xd0\xb0\xd0\xba\0" "\xd1\x83\xd1\x82\xd0\xbe\xd1\x80\xd0\xb0\xd0\xba\0" "\xd1\x81\xd1\x80\xd0\xb8\xd1\x98\xd0\xb5\xd0\xb4\xd0\xb0\0" "\xd1\x87\xd0\xb5\xd1\x82\xd0\xb2\xd1\x80\xd1\x82\xd0\xb0\xd0\xba\0" "\xd0\xbf\xd0\xb5\xd1\x82\xd0\xb0\xd0\xba\0" "\xd0\xbd\xd0\xb5\xd0\xb4\0" "\xd0\xbf\xd0\xbe\xd0\xbd\0" "\xd1\x83\xd1\x82\xd0\xbe\0" "\xd1\x81\xd1\x80\xd0\xb8\0" "\xd1\x87\xd0\xb5\xd1\x82\0" "\xd0\xbf\xd0\xb5\xd1\x82\0" "\xd1\x81\xd1\x83\xd0\xb1\0" "\xd1\x83\0" "\xd1\x98\xd0\xb0\xd0\xbd\xd1\x83\xd0\xb0\xd1\x80\0" "\xd1\x84\xd0\xb5\xd0\xb1\xd1\x80\xd1\x83\xd0\xb0\xd1\x80\0" "\xd1\x81\xd0\xb5\xd0\xbf\xd1\x82\xd0\xb5\xd0\xbc\xd0\xb1\xd0\xb0\xd1\x80\0" "\xd0\xbe\xd0\xba\xd1\x82\xd0\xbe\xd0\xb1\xd0\xb0\xd1\x80\0" "\xd0\xbd\xd0\xbe\xd0\xb2\xd0\xb5\xd0\xbc\xd0\xb1\xd0\xb0\xd1\x80\0" "\xd0\xb4\xd0\xb5\xd1\x86\xd0\xb5\xd0\xbc\xd0\xb1\xd0\xb0\xd1\x80\0" "\xd1\x98\xd0\xb0\xd0\xbd\0" "\xd1\x84\xd0\xb5\xd0\xb1\0" "\xd0\xbc\xd0\xb0\xd1\x80\0" "\xd0\xb0\xd0\xbf\xd1\x80\0" "\xd1\x98\xd1\x83\xd0\xbd\0" "\xd1\x98\xd1\x83\xd0\xbb\0" "\xd0\xb0\xd0\xb2\xd0\xb3\0" "\xd1\x81\xd0\xb5\xd0\xbf\0" "\xd0\xbe\xd0\xba\xd1\x82\0" "\xd0\xbd\xd0\xbe\xd0\xb2\0" "\xd0\xb4\xd0\xb5\xd1\x86\0" "d. M. yy\0" "dd. MM. yy\0" "\xd1\x81\xd1\x80\xd0\xb5\0" "MMMM-yyyy\0" "dd MMM,yyyy\0" "yyyy-MM-dd.\0" "h.mm.ss tt\0" "dddd dd 'de' MMMM 'de' yyyy\0" "dd 'de' MMMM 'de' yyyy\0" ",\0" "\xd8\xb1.\xd8\xb3.\xe2\x80\x8f\0" "\xd9\xaa\0" "\xd9\x84\xd9\x8a\xd8\xb3\xc2\xa0\xd8\xb1\xd9\x82\xd9\x85\0" "\xd8\x89\0" "-Infinity\0" "Infinity\0" "\xe2\x80\x8f+\0" "\xc2\xa0\0" "\xd0\xbb\xd0\xb2.\0" "%\0" "NaN\0" "\xe2\x80\xb0\0" "+\0" "\xe2\x82\xac\0" "-Infinit\0" "Infinit\0" "\xc2\xa5\0" "K\xc4\x8d\0" "-nekone\xc4\x8dno\0" "+nekone\xc4\x8dno\0" "kr\0" "-unendlich\0" "+unendlich\0" "-\xce\x86\xcf\x80\xce\xb5\xce\xb9\xcf\x81\xce\xbf\0" "\xce\x86\xcf\x80\xce\xb5\xce\xb9\xcf\x81\xce\xbf\0" "$\0" "-Infinito\0" "Infinito\0" "ep\xc3\xa4luku\0" "-Infini\0" "+Infini\0" "\xe2\x82\xaa\0" "\xe2\x80\x8e+\0" "Ft\0" "+Infinito\0" "\xef\xbf\xa5\0" "\xe2\x82\xa9\0" "-oneindig\0" "oneindig\0" "z\xc5\x82\0" "-niesko\xc5\x84\x63zono\xc5\x9b\xc4\x87\0" "+niesko\xc5\x84\x63zono\xc5\x9b\xc4\x87\0" "R$\0" "\xe2\x80\x99\0" "CHF\0" "-infinit\0" "+infinit\0" "\xd1\x80\xd1\x83\xd0\xb1.\0" "\xd0\xbd\xd0\xb5\xc2\xa0\xd1\x87\xd0\xb8\xd1\x81\xd0\xbb\xd0\xbe\0" "-\xd0\xb1\xd0\xb5\xd1\x81\xd0\xba\xd0\xbe\xd0\xbd\xd0\xb5\xd1\x87\xd0\xbd\xd0\xbe\xd1\x81\xd1\x82\xd1\x8c\0" "\xd0\xb1\xd0\xb5\xd1\x81\xd0\xba\xd0\xbe\xd0\xbd\xd0\xb5\xd1\x87\xd0\xbd\xd0\xbe\xd1\x81\xd1\x82\xd1\x8c\0" "kn\0" "Lek\xc3\xab\0" "\xc2\xa4\xc2\xa4\xc2\xa4\0" "\xe0\xb8\xbf\0" "\xe2\x82\xba\0" "Rs\0" "\xdb\x8c\xdb\x81\xc2\xa0\xd8\xb9\xd8\xaf\xd8\xaf\xc2\xa0\xd9\x86\xdb\x81\xdb\x8c\xda\xba\0" "\xe2\x80\x8e-\xe2\x80\x8eInfinity\0" "\xe2\x80\x8e-\xe2\x80\x8e\0" "\xe2\x80\x8e+\xe2\x80\x8e\0" "Rp\0" "\xe2\x82\xb4\0" "\xd0\x9d\xd0\xb5\xc2\xa0\xd1\x87\xd0\xb8\xd1\x81\xd0\xbb\xd0\xbe\0" "\xd1\x80.\0" "-neskon\xc4\x8dnost\0" "neskon\xc4\x8dnost\0" "nav\xc2\xa0skaitlis\0" "-bezgal\xc4\xab\x62\x61\0" "bezgal\xc4\xab\x62\x61\0" "Lt\0" "-begalyb\xc4\x97\0" "begalyb\xc4\x97\0" "\xd8\xb1\xdb\x8c\xd8\xa7\xd9\x84\0" "\xd9\x86\xd8\xa7\xd8\xb9\xd8\xaf\xd8\xaf\0" "\xe2\x80\x8e\xe2\x88\x92Infinity\0" "\xe2\x80\x8e\xe2\x88\x92\0" "\xe2\x82\xab\0" "\xd5\xa4\xd6\x80.\0" "-Infinitu\0" "Infinitu\0" "\xd0\xb4\xd0\xb5\xd0\xbd\0" "I-NaN\0" "\xe1\x83\x90\xe1\x83\xa0\xc2\xa0\xe1\x83\x90\xe1\x83\xa0\xe1\x83\x98\xe1\x83\xa1\xc2\xa0\xe1\x83\xa0\xe1\x83\x98\xe1\x83\xaa\xe1\x83\xae\xe1\x83\x95\xe1\x83\x98\0" "\xe2\x82\xb9\0" "RM\0" "\xd1\x81\xd0\xb0\xd0\xbd\xc2\xa0\xd1\x8d\xd0\xbc\xd0\xb5\xd1\x81\0" "Ksh\0" "\xe0\xa6\x9f\xe0\xa6\xbe\0" "\xe0\xa6\xb8\xe0\xa6\x82\xe0\xa6\x96\xe0\xa7\x8d\xe0\xa6\xaf\xe0\xa6\xbe\xc2\xa0\xe0\xa6\xa8\xe0\xa6\xbe\0" "`\0" "\xc2\xa3\0" "\xe1\x9f\x9b\0" "\xe2\x82\xad\0" "\xe0\xba\x9a\xe0\xbb\x8d\xe0\xbb\x88\xe0\xbb\x81\xe0\xba\xa1\xe0\xbb\x88\xe0\xba\x99\xe0\xbb\x82\xe0\xba\x95\xe0\xbb\x80\xe0\xba\xa5\xe0\xba\x81\0" "\xe0\xb6\xbb\xe0\xb7\x94.\0" "\xe1\x89\xa5\xe1\x88\xad\0" "\xe0\xa4\xa8\xe0\xa5\x87\xe0\xa4\xb0\xe0\xa5\x82\0" "\xd8\x8b\0" "\xe2\x82\xb1\0" "\xe2\x82\xa6\0" "RF\0" "NT$\0" "\xe9\x9d\x9e\xe6\x95\xb8\xe5\x80\xbc\0" "\xd1\x81\xd0\xbe\xd0\xbc\0" "man.\0" "so\xca\xbbm\0" "\xd8\xaf.\xd8\xb9.\xe2\x80\x8f\0" "'\0" "\xd0\xbc\xd0\xb0\xd0\xbd.\0" "\xd1\x81\xd1\x9e\xd0\xbc\0" "\xe0\xa7\xb3\0" "\xd8\xac.\xd9\x85.\xe2\x80\x8f\0" "\xd8\xaf.\xd9\x84.\xe2\x80\x8f\0" "KM\0" "\xd8\xaf.\xd8\xac.\xe2\x80\x8f\0" "MOP$\0" "\xe2\x82\xa1\0" "\xd8\xaf.\xd9\x85.\xe2\x80\x8f\0" "B/.\0" "\xd8\xaf.\xd8\xaa.\xe2\x80\x8f\0" "\xd0\x9a\xd0\x9c\0" "\xd8\xb1.\xd8\xb9.\xe2\x80\x8f\0" "Bs.\0" "\xd8\xb1.\xd9\x8a.\xe2\x80\x8f\0" "din.\0" "\xd9\x84.\xd8\xb3.\xe2\x80\x8f\0" "S/.\0" "\xd0\xb4\xd0\xb8\xd0\xbd.\0" "\xd8\xaf.\xd8\xa3.\xe2\x80\x8f\0" "\xd9\x84.\xd9\x84.\xe2\x80\x8f\0" "\xd8\xaf.\xd9\x83.\xe2\x80\x8f\0" "\xd8\xaf.\xd8\xa5.\xe2\x80\x8f\0" "\xd8\xaf.\xd8\xa8.\xe2\x80\x8f\0" "\xe2\x82\xb2\0" "\xd8\xb1.\xd9\x82.\xe2\x80\x8f\0" "Bs\0" "C$\0" "\xd0\x94\xd0\xb8\xd0\xbd.\0" "Din.\0" "HK$\0" "ar\0" "Arabic\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9\0" "ARA\0" "ara\0" "\xd8\xa7\xd9\x84\xd8\xaa\xd9\x82\xd9\x88\xd9\x8a\xd9\x85 \xd8\xa7\xd9\x84\xd9\x87\xd8\xac\xd8\xb1\xd9\x8a\0" "bg\0" "Bulgarian\0" "\xd0\xb1\xd1\x8a\xd0\xbb\xd0\xb3\xd0\xb0\xd1\x80\xd1\x81\xd0\xba\xd0\xb8\0" "BGR\0" "bul\0" "\xd0\x93\xd1\x80\xd0\xb8\xd0\xb3\xd0\xbe\xd1\x80\xd0\xb8\xd0\xb0\xd0\xbd\xd1\x81\xd0\xba\xd0\xb8 \xd0\xba\xd0\xb0\xd0\xbb\xd0\xb5\xd0\xbd\xd0\xb4\xd0\xb0\xd1\x80\0" "ca\0" "Catalan\0" "catal\xc3\xa0\0" "CAT\0" "cat\0" "calendari gregori\xc3\xa0\0" "zh-CHS\0" "Chinese (Simplified) Legacy\0" "\xe4\xb8\xad\xe6\x96\x87\0" "CHS\0" "zho\0" "zh\0" "\xe5\x85\xac\xe5\x8e\x86\0" "zh-Hans\0" "Chinese (Simplified)\0" "cs\0" "Czech\0" "\xc4\x8d\x65\xc5\xa1tina\0" "CSY\0" "ces\0" "Gregori\xc3\xa1nsk\xc3\xbd kalend\xc3\xa1\xc5\x99\0" "da\0" "Danish\0" "dansk\0" "DAN\0" "dan\0" "gregoriansk kalender\0" "de\0" "German\0" "Deutsch\0" "DEU\0" "deu\0" "Gregorianischer Kalender\0" "el\0" "Greek\0" "\xce\x95\xce\xbb\xce\xbb\xce\xb7\xce\xbd\xce\xb9\xce\xba\xce\xac\0" "ELL\0" "ell\0" "\xce\x93\xcf\x81\xce\xb7\xce\xb3\xce\xbf\xcf\x81\xce\xb9\xce\xb1\xce\xbd\xcf\x8c \xce\xb7\xce\xbc\xce\xb5\xcf\x81\xce\xbf\xce\xbb\xcf\x8c\xce\xb3\xce\xb9\xce\xbf\0" "en\0" "English\0" "ENU\0" "eng\0" "Gregorian Calendar\0" "es\0" "Spanish\0" "espa\xc3\xb1ol\0" "ESP\0" "spa\0" "calendario gregoriano\0" "fi\0" "Finnish\0" "suomi\0" "FIN\0" "fin\0" "gregoriaaninen kalenteri\0" "fr\0" "French\0" "fran\xc3\xa7\x61is\0" "FRA\0" "fra\0" "calendrier gr\xc3\xa9gorien\0" "he\0" "Hebrew\0" "\xd7\xa2\xd7\x91\xd7\xa8\xd7\x99\xd7\xaa\0" "HEB\0" "heb\0" "\xd7\x9c\xd7\x95\xd7\x97 \xd7\xa9\xd7\xa0\xd7\x94 \xd7\x92\xd7\xa8\xd7\x92\xd7\x95\xd7\xa8\xd7\x99\xd7\x90\xd7\xa0\xd7\x99\0" "hu\0" "Hungarian\0" "magyar\0" "HUN\0" "hun\0" "Gergely-napt\xc3\xa1r\0" "is\0" "Icelandic\0" "\xc3\xadslenska\0" "ISL\0" "isl\0" "Gregor\xc3\xadskt dagatal\0" "it\0" "Italian\0" "italiano\0" "ITA\0" "ita\0" "Calendario gregoriano\0" "ja\0" "Japanese\0" "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e\0" "JPN\0" "jpn\0" "\xe8\xa5\xbf\xe6\x9a\xa6(\xe3\x82\xb0\xe3\x83\xac\xe3\x82\xb4\xe3\x83\xaa\xe3\x82\xaa\xe6\x9a\xa6)\0" "ko\0" "Korean\0" "\xed\x95\x9c\xea\xb5\xad\xec\x96\xb4\0" "KOR\0" "kor\0" "\xed\x83\x9c\xec\x96\x91\xeb\xa0\xa5\0" "nl\0" "Dutch\0" "Nederlands\0" "NLD\0" "nld\0" "Gregoriaanse kalender\0" "no\0" "Norwegian\0" "norsk\0" "NOR\0" "nob\0" "nb\0" "pl\0" "Polish\0" "polski\0" "PLK\0" "pol\0" "kalendarz gregoria\xc5\x84ski\0" "pt\0" "Portuguese\0" "portugu\xc3\xaas\0" "PTB\0" "por\0" "Calend\xc3\xa1rio Gregoriano\0" "rm\0" "Romansh\0" "rumantsch\0" "RMC\0" "roh\0" "chalender gregorian\0" "ro\0" "Romanian\0" "rom\xc3\xa2n\xc4\x83\0" "ROM\0" "ron\0" "calendar gregorian\0" "ru\0" "Russian\0" "\xd1\x80\xd1\x83\xd1\x81\xd1\x81\xd0\xba\xd0\xb8\xd0\xb9\0" "RUS\0" "rus\0" "\xd0\x93\xd1\x80\xd0\xb8\xd0\xb3\xd0\xbe\xd1\x80\xd0\xb8\xd0\xb0\xd0\xbd\xd1\x81\xd0\xba\xd0\xb8\xd0\xb9 \xd0\xba\xd0\xb0\xd0\xbb\xd0\xb5\xd0\xbd\xd0\xb4\xd0\xb0\xd1\x80\xd1\x8c\0" "hr\0" "Croatian\0" "hrvatski\0" "HRV\0" "hrv\0" "gregorijanski kalendar\0" "Slovak\0" "sloven\xc4\x8dina\0" "SKY\0" "slk\0" "Gregori\xc3\xa1nsky kalend\xc3\xa1r\0" "sq\0" "Albanian\0" "Shqip\0" "SQI\0" "sqi\0" "Kalendari Gregorian\0" "sv\0" "Swedish\0" "svenska\0" "SVE\0" "swe\0" "th\0" "Thai\0" "\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0" "THA\0" "tha\0" "\xe0\xb8\x9b\xe0\xb8\x8f\xe0\xb8\xb4\xe0\xb8\x97\xe0\xb8\xb4\xe0\xb8\x99\xe0\xb8\x9e\xe0\xb8\xb8\xe0\xb8\x97\xe0\xb8\x98\0" "Turkish\0" "T\xc3\xbcrk\xc3\xa7\x65\0" "TRK\0" "tur\0" "Miladi Takvim\0" "ur\0" "Urdu\0" "\xd8\xa7\xd8\xb1\xd8\xaf\xd9\x88\0" "URD\0" "urd\0" "\xd8\xac\xd8\xa7\xd8\xb1\xd8\xac\xdb\x8c\xd8\xa7\xd8\xa6\xdb\x8c \xda\xa9\xdb\x8c\xd9\x84\xd9\x86\xda\x88\xd8\xb1\0" "id\0" "Indonesian\0" "Bahasa Indonesia\0" "IND\0" "ind\0" "Kalender Gregorian\0" "uk\0" "Ukrainian\0" "\xd1\x83\xd0\xba\xd1\x80\xd0\xb0\xd1\x97\xd0\xbd\xd1\x81\xd1\x8c\xd0\xba\xd0\xb0\0" "UKR\0" "ukr\0" "\xd0\x93\xd1\x80\xd0\xb8\xd0\xb3\xd0\xbe\xd1\x80\xd1\x96\xd0\xb0\xd0\xbd\xd1\x81\xd1\x8c\xd0\xba\xd0\xb8\xd0\xb9 \xd0\xba\xd0\xb0\xd0\xbb\xd0\xb5\xd0\xbd\xd0\xb4\xd0\xb0\xd1\x80\0" "be\0" "Belarusian\0" "\xd0\xb1\xd0\xb5\xd0\xbb\xd0\xb0\xd1\x80\xd1\x83\xd1\x81\xd0\xba\xd0\xb0\xd1\x8f\0" "BEL\0" "bel\0" "\xd0\xb3\xd1\x80\xd1\x8d\xd0\xb3\xd0\xb0\xd1\x80\xd1\x8b\xd1\x8f\xd0\xbd\xd1\x81\xd0\xba\xd1\x96 \xd0\xba\xd0\xb0\xd0\xbb\xd1\x8f\xd0\xbd\xd0\xb4\xd0\xb0\xd1\x80\0" "sl\0" "Slovenian\0" "sloven\xc5\xa1\xc4\x8dina\0" "SLV\0" "slv\0" "gregorijanski koledar\0" "et\0" "Estonian\0" "eesti\0" "ETI\0" "est\0" "Gregoriuse kalender\0" "lv\0" "Latvian\0" "latvie\xc5\xa1u\0" "LVI\0" "lav\0" "Gregora kalend\xc4\x81rs\0" "lt\0" "Lithuanian\0" "lietuvi\xc5\xb3\0" "LTH\0" "lit\0" "Grigaliaus kalendorius\0" "tg\0" "Tajik\0" "\xd0\xa2\xd0\xbe\xd2\xb7\xd0\xb8\xd0\xba\xd3\xa3\0" "TAJ\0" "tgk\0" "fa\0" "Persian\0" "\xd9\x81\xd8\xa7\xd8\xb1\xd8\xb3\xdb\x8c\0" "FAR\0" "fas\0" "\xd8\xaa\xd9\x82\xd9\x88\xdb\x8c\xd9\x85 \xd9\x85\xdb\x8c\xd9\x84\xd8\xa7\xd8\xaf\xdb\x8c\0" "vi\0" "Vietnamese\0" "Ti\xe1\xba\xbfng Vi\xe1\xbb\x87t\0" "VIT\0" "L\xe1\xbb\x8b\x63h Gregory\0" "hy\0" "Armenian\0" "\xd5\xb0\xd5\xa1\xd5\xb5\xd5\xa5\xd6\x80\xd5\xa5\xd5\xb6\0" "HYE\0" "hye\0" "\xd4\xb3\xd6\x80\xd5\xab\xd5\xa3\xd5\xb8\xd6\x80\xd5\xb5\xd5\xa1\xd5\xb6 \xd5\xbf\xd5\xb8\xd5\xb4\xd5\xa1\xd6\x80\0" "az\0" "Azerbaijani\0" "az\xc9\x99rbaycan\0" "AZE\0" "aze\0" "Qreqorian T\xc9\x99qvimi\0" "eu\0" "Basque\0" "euskara\0" "EUQ\0" "eus\0" "Egutegi gregoriarra\0" "mk\0" "Macedonian\0" "\xd0\xbc\xd0\xb0\xd0\xba\xd0\xb5\xd0\xb4\xd0\xbe\xd0\xbd\xd1\x81\xd0\xba\xd0\xb8\0" "MKI\0" "mkd\0" "\xd0\x93\xd1\x80\xd0\xb5\xd0\xb3\xd0\xbe\xd1\x80\xd0\xb8\xd1\x98\xd0\xb0\xd0\xbd\xd1\x81\xd0\xba\xd0\xb8 \xd0\xba\xd0\xb0\xd0\xbb\xd0\xb5\xd0\xbd\xd0\xb4\xd0\xb0\xd1\x80\0" "tn\0" "Tswana\0" "Setswana\0" "TSN\0" "tsn\0" "xh\0" "Xhosa\0" "isiXhosa\0" "XHO\0" "xho\0" "zu\0" "Zulu\0" "isiZulu\0" "ZUL\0" "zul\0" "i-Gregorian Calender\0" "af\0" "Afrikaans\0" "AFK\0" "afr\0" "Gregoriese kalender\0" "ka\0" "Georgian\0" "\xe1\x83\xa5\xe1\x83\x90\xe1\x83\xa0\xe1\x83\x97\xe1\x83\xa3\xe1\x83\x9a\xe1\x83\x98\0" "KAT\0" "kat\0" "\xe1\x83\x92\xe1\x83\xa0\xe1\x83\x98\xe1\x83\x92\xe1\x83\x9d\xe1\x83\xa0\xe1\x83\x98\xe1\x83\x90\xe1\x83\x9c\xe1\x83\xa3\xe1\x83\x9a\xe1\x83\x98 \xe1\x83\x99\xe1\x83\x90\xe1\x83\x9a\xe1\x83\x94\xe1\x83\x9c\xe1\x83\x93\xe1\x83\x90\xe1\x83\xa0\xe1\x83\x98\0" "fo\0" "Faroese\0" "f\xc3\xb8royskt\0" "FOS\0" "fao\0" "hi\0" "Hindi\0" "\xe0\xa4\xb9\xe0\xa4\xbf\xe0\xa4\x82\xe0\xa4\xa6\xe0\xa5\x80\0" "HIN\0" "hin\0" "\xe0\xa4\x97\xe0\xa5\x8d\xe0\xa4\xb0\xe0\xa5\x87\xe0\xa4\x97\xe0\xa5\x8b\xe0\xa4\xb0\xe0\xa4\xbf\xe0\xa4\xaf\xe0\xa4\xa8 \xe0\xa4\x95\xe0\xa5\x88\xe0\xa4\xb2\xe0\xa5\x87\xe0\xa4\x82\xe0\xa4\xa1\xe0\xa4\xb0\0" "mt\0" "Maltese\0" "Malti\0" "MLT\0" "mlt\0" "Kalendarju Gregorjan\0" "se\0" "Northern Sami\0" "davvis\xc3\xa1megiella\0" "SME\0" "sme\0" "gregoria kaleander\0" "ga\0" "Irish\0" "Gaeilge\0" "IRE\0" "gle\0" "F\xc3\xa9ilire Greag\xc3\xb3rach\0" "ms\0" "Malay\0" "Bahasa Melayu\0" "MSL\0" "msa\0" "Kalendar Gregory\0" "kk\0" "Kazakh\0" "\xd2\x9b\xd0\xb0\xd0\xb7\xd0\xb0\xd2\x9b \xd1\x82\xd1\x96\xd0\xbb\xd1\x96\0" "KKZ\0" "kaz\0" "\xd0\x93\xd1\x80\xd0\xb5\xd0\xb3\xd0\xbe\xd1\x80\xd0\xb8\xd0\xb0\xd0\xbd\xd0\xb4\xd1\x8b\xd2\x9b \xd0\xba\xd2\xaf\xd0\xbd\xd1\x82\xd1\x96\xd0\xb7\xd0\xb1\xd0\xb5\0" "ky\0" "Kyrgyz\0" "\xd0\xba\xd1\x8b\xd1\x80\xd0\xb3\xd1\x8b\xd0\xb7\xd1\x87\xd0\xb0\0" "KYR\0" "kir\0" "\xd0\x93\xd1\x80\xd0\xb8\xd0\xb3\xd0\xbe\xd1\x80\xd0\xb8\xd0\xb0\xd0\xbd \xd0\xba\xd0\xb0\xd0\xbb\xd0\xb5\xd0\xbd\xd0\xb4\xd0\xb0\xd1\x80\xd1\x8b\0" "sw\0" "Swahili\0" "Kiswahili\0" "SWK\0" "swa\0" "Kalenda ya Kigregori\0" "uz\0" "Uzbek\0" "o\xca\xbbzbekcha\0" "UZB\0" "uzb\0" "Grigorian kalendari\0" "bn\0" "Bengali\0" "\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa6\x82\xe0\xa6\xb2\xe0\xa6\xbe\0" "BNG\0" "bng\0" "\xe0\xa6\x97\xe0\xa7\x8d\xe0\xa6\xb0\xe0\xa6\xbf\xe0\xa6\x97\xe0\xa7\x8b\xe0\xa6\xb0\xe0\xa6\xbf\xe0\xa6\xaf\xe0\xa6\xbc\xe0\xa6\xbe\xe0\xa6\xa8 \xe0\xa6\xac\xe0\xa6\xb0\xe0\xa7\x8d\xe0\xa6\xb7\xe0\xa6\xaa\xe0\xa6\x9e\xe0\xa7\x8d\xe0\xa6\x9c\xe0\xa7\x80\0" "pa\0" "Punjabi\0" "\xe0\xa8\xaa\xe0\xa9\xb0\xe0\xa8\x9c\xe0\xa8\xbe\xe0\xa8\xac\xe0\xa9\x80\0" "PAN\0" "pan\0" "\xe0\xa8\x97\xe0\xa8\xb0\xe0\xa9\x80\xe0\xa8\x9c\xe0\xa9\x8b\xe0\xa8\xb0\xe0\xa9\x80\xe0\xa8\x85\xe0\xa8\xa8 \xe0\xa8\x95\xe0\xa9\x88\xe0\xa8\xb2\xe0\xa9\xb0\xe0\xa8\xa1\xe0\xa8\xb0\0" "gu\0" "Gujarati\0" "\xe0\xaa\x97\xe0\xab\x81\xe0\xaa\x9c\xe0\xaa\xb0\xe0\xaa\xbe\xe0\xaa\xa4\xe0\xab\x80\0" "GUJ\0" "guj\0" "\xe0\xaa\x97\xe0\xab\x8d\xe0\xaa\xb0\xe0\xab\x87\xe0\xaa\x97\xe0\xab\x8b\xe0\xaa\xb0\xe0\xaa\xbf\xe0\xaa\xaf\xe0\xaa\xa8 \xe0\xaa\x95\xe0\xab\x87\xe0\xaa\xb2\xe0\xab\x87\xe0\xaa\xa8\xe0\xab\x8d\xe0\xaa\xa1\xe0\xaa\xb0\0" "or\0" "Oriya\0" "\xe0\xac\x93\xe0\xac\xa1\xe0\xac\xbc\xe0\xac\xbf\xe0\xac\x86\0" "ORI\0" "ori\0" "ta\0" "Tamil\0" "\xe0\xae\xa4\xe0\xae\xae\xe0\xae\xbf\xe0\xae\xb4\xe0\xaf\x8d\0" "TAM\0" "tam\0" "\xe0\xae\x95\xe0\xae\xbf\xe0\xae\xb0\xe0\xae\xbf\xe0\xae\x95\xe0\xaf\x8b\xe0\xae\xb0\xe0\xae\xbf\xe0\xae\xaf\xe0\xae\xa9\xe0\xaf\x8d \xe0\xae\xa8\xe0\xae\xbe\xe0\xae\xb3\xe0\xaf\x8d\xe0\xae\x95\xe0\xae\xbe\xe0\xae\x9f\xe0\xaf\x8d\xe0\xae\x9f\xe0\xae\xbf\0" "te\0" "Telugu\0" "\xe0\xb0\xa4\xe0\xb1\x86\xe0\xb0\xb2\xe0\xb1\x81\xe0\xb0\x97\xe0\xb1\x81\0" "TEL\0" "tel\0" "\xe0\xb0\x97\xe0\xb1\x8d\xe0\xb0\xb0\xe0\xb1\x87\xe0\xb0\x97\xe0\xb1\x8b\xe0\xb0\xb0\xe0\xb0\xbf\xe0\xb0\xaf\xe0\xb0\xa8\xe0\xb1\x8d \xe0\xb0\x95\xe0\xb1\x8d\xe0\xb0\xaf\xe0\xb0\xbe\xe0\xb0\xb2\xe0\xb1\x86\xe0\xb0\x82\xe0\xb0\xa1\xe0\xb0\xb0\xe0\xb1\x8d\0" "Kannada\0" "\xe0\xb2\x95\xe0\xb2\xa8\xe0\xb3\x8d\xe0\xb2\xa8\xe0\xb2\xa1\0" "KDI\0" "kan\0" "\xe0\xb2\x97\xe0\xb3\x8d\xe0\xb2\xb0\xe0\xb2\xbf\xe0\xb2\x97\xe0\xb3\x8b\xe0\xb2\xb0\xe0\xb2\xbf\xe0\xb2\xaf\xe0\xb2\xa8\xe0\xb3\x8d \xe0\xb2\x95\xe0\xb3\x8d\xe0\xb2\xaf\xe0\xb2\xbe\xe0\xb2\xb2\xe0\xb3\x86\xe0\xb2\x82\xe0\xb2\xa1\xe0\xb2\xb0\xe0\xb3\x8d\0" "ml\0" "Malayalam\0" "\xe0\xb4\xae\xe0\xb4\xb2\xe0\xb4\xaf\xe0\xb4\xbe\xe0\xb4\xb3\xe0\xb4\x82\0" "MYM\0" "mym\0" "\xe0\xb4\x87\xe0\xb4\x82\xe0\xb4\x97\xe0\xb5\x8d\xe0\xb4\xb2\xe0\xb5\x80\xe0\xb4\xb7\xe0\xb5\x8d \xe0\xb4\x95\xe0\xb4\xb2\xe0\xb4\xa3\xe0\xb5\x8d\xe0\xb4\x9f\xe0\xb5\xbc\0" "as\0" "Assamese\0" "\xe0\xa6\x85\xe0\xa6\xb8\xe0\xa6\xae\xe0\xa7\x80\xe0\xa6\xaf\xe0\xa6\xbc\xe0\xa6\xbe\0" "ASM\0" "asm\0" "\xe0\xa6\x97\xe0\xa7\x8d\xe0\xa7\xb0\xe0\xa6\xbf\xe0\xa6\x97\xe0\xa7\x8b\xe0\xa7\xb0\xe0\xa7\x80\xe0\xa6\xaf\xe0\xa6\xbc \xe0\xa6\xaa\xe0\xa6\x9e\xe0\xa7\x8d\xe0\xa6\x9c\xe0\xa6\xbf\xe0\xa6\x95\xe0\xa6\xbe\0" "mr\0" "Marathi\0" "\xe0\xa4\xae\xe0\xa4\xb0\xe0\xa4\xbe\xe0\xa4\xa0\xe0\xa5\x80\0" "MAR\0" "\xe0\xa4\x97\xe0\xa5\x8d\xe0\xa4\xb0\xe0\xa5\x87\xe0\xa4\x97\xe0\xa5\x8b\xe0\xa4\xb0\xe0\xa4\xbf\xe0\xa4\xaf\xe0\xa4\xa8 \xe0\xa4\xa6\xe0\xa4\xbf\xe0\xa4\xa8\xe0\xa4\xa6\xe0\xa4\xb0\xe0\xa5\x8d\xe0\xa4\xb6\xe0\xa4\xbf\xe0\xa4\x95\xe0\xa4\xbe\0" "mn\0" "Mongolian\0" "\xd0\xbc\xd0\xbe\xd0\xbd\xd0\xb3\xd0\xbe\xd0\xbb\0" "MON\0" "mon\0" "\xd0\xb3\xd1\x80\xd0\xb5\xd0\xb3\xd0\xbe\xd1\x80\xd0\xb8\xd0\xb9\xd0\xbd \xd1\x85\xd1\x83\xd0\xb0\xd0\xbd\xd0\xbb\xd0\xb8\0" "bo\0" "Tibetan\0" "\xe0\xbd\x94\xe0\xbd\xbc\xe0\xbd\x91\xe0\xbc\x8b\xe0\xbd\xa6\xe0\xbe\x90\xe0\xbd\x91\xe0\xbc\x8b\0" "BOB\0" "bod\0" "cy\0" "Welsh\0" "Cymraeg\0" "CYM\0" "cym\0" "Calendr Gregori\0" "km\0" "Khmer\0" "\xe1\x9e\x81\xe1\x9f\x92\xe1\x9e\x98\xe1\x9f\x82\xe1\x9e\x9a\0" "KHM\0" "khm\0" "\xe1\x9e\x94\xe1\x9f\x92\xe1\x9e\x9a\xe1\x9e\x8f\xe1\x9e\xb7\xe1\x9e\x91\xe1\x9e\xb7\xe1\x9e\x93\xe2\x80\x8b\xe1\x9e\xa0\xe1\x9f\x92\xe1\x9e\x9f\xe1\x9e\x80\xe1\x9e\xa0\xe1\x9f\x92\xe1\x9e\x9f\xe1\x9f\x8a\xe1\x9e\xb8\0" "lo\0" "Lao\0" "\xe0\xba\xa5\xe0\xba\xb2\xe0\xba\xa7\0" "LAO\0" "lao\0" "\xe0\xba\x9b\xe0\xba\xb0\xe0\xba\x95\xe0\xba\xb4\xe0\xba\x97\xe0\xba\xb4\xe0\xba\x99\xe0\xbb\x80\xe0\xba\x81\xe0\xba\xa3\xe0\xbb\x82\xe0\xba\x81\xe0\xba\xa3\xe0\xba\xbd\xe0\xba\x99\0" "gl\0" "Galician\0" "galego\0" "GLC\0" "glg\0" "kok\0" "Konkani\0" "\xe0\xa4\x95\xe0\xa5\x8b\xe0\xa4\x82\xe0\xa4\x95\xe0\xa4\xa3\xe0\xa5\x80\0" "KNK\0" "si\0" "Sinhala\0" "\xe0\xb7\x83\xe0\xb7\x92\xe0\xb6\x82\xe0\xb7\x84\xe0\xb6\xbd\0" "SIN\0" "sin\0" "\xe0\xb6\x9c\xe0\xb7\x8a\xe2\x80\x8d\xe0\xb6\xbb\xe0\xb7\x99\xe0\xb6\x9c\xe0\xb6\xbb\xe0\xb7\x92\xe0\xb6\xba\xe0\xb7\x8f\xe0\xb6\xb1\xe0\xb7\x94 \xe0\xb6\xaf\xe0\xb7\x92\xe0\xb6\xb1\xe0\xb6\xaf\xe0\xb7\x83\xe0\xb7\x94\xe0\xb6\xb1\0" "Amharic\0" "\xe1\x8a\xa0\xe1\x88\x9b\xe1\x88\xad\xe1\x8a\x9b\0" "AMH\0" "amh\0" "\xe1\x8b\xa8\xe1\x8c\x8d\xe1\x88\xaa\xe1\x8c\x8e\xe1\x88\xaa\xe1\x8b\xab\xe1\x8a\x95 \xe1\x89\x80\xe1\x8a\x95 \xe1\x8a\xa0\xe1\x89\x86\xe1\x8c\xa3\xe1\x8c\xa0\xe1\x88\xad\0" "tzm\0" "Central Atlas Tamazight\0" "Tamazi\xc9\xa3t\0" "TZM\0" "Nepali\0" "\xe0\xa4\xa8\xe0\xa5\x87\xe0\xa4\xaa\xe0\xa4\xbe\xe0\xa4\xb2\xe0\xa5\x80\0" "NEP\0" "nep\0" "\xe0\xa4\x97\xe0\xa5\x8d\xe0\xa4\xb0\xe0\xa5\x87\xe0\xa4\x97\xe0\xa5\x8b\xe0\xa4\xb0\xe0\xa4\xbf\xe0\xa4\xaf\xe0\xa4\xa8 \xe0\xa4\xaa\xe0\xa4\xbe\xe0\xa4\xa4\xe0\xa5\x8d\xe0\xa4\xb0\xe0\xa5\x8b\0" "ps\0" "Pashto\0" "\xd9\xbe\xda\x9a\xd8\xaa\xd9\x88\0" "PAS\0" "pus\0" "fil\0" "Filipino\0" "FPO\0" "Kalendaryong Gregorian\0" "ha\0" "Hausa\0" "HAU\0" "hau\0" "yo\0" "Yoruba\0" "\xc3\x88\x64\xc3\xa8 Yor\xc3\xb9\x62\xc3\xa1\0" "YOR\0" "yor\0" "nso\0" "Northern Sotho\0" "Sesotho sa Leboa\0" "NSO\0" "kl\0" "Kalaallisut\0" "kalaallisut\0" "KAL\0" "kal\0" "gregorianskit ullorsiutaat\0" "ig\0" "Igbo\0" "IBO\0" "ibo\0" "ii\0" "Sichuan Yi\0" "\xea\x86\x88\xea\x8c\xa0\xea\x89\x99\0" "III\0" "iii\0" "\xea\x84\x89\xea\x89\xbb\xea\x83\x85\xea\x91\x8d\0" "br\0" "Breton\0" "brezhoneg\0" "BRE\0" "bre\0" "deiziadur gregorian\0" "gsw\0" "Swiss German\0" "Schwiizert\xc3\xbc\xc3\xbctsch\0" "GSW\0" "Gregoriaanisch Kal\xc3\xa4nder\0" "sah\0" "Sakha\0" "\xd1\x81\xd0\xb0\xd1\x85\xd0\xb0 \xd1\x82\xd1\x8b\xd0\xbb\xd0\xb0\0" "SAH\0" "rw\0" "Kinyarwanda\0" "KIN\0" "kin\0" "gd\0" "Scottish Gaelic\0" "G\xc3\xa0idhlig\0" "GLA\0" "gla\0" "Am M\xc3\xacosachan Griogarach\0" "ar-SA\0" "Arabic (Saudi Arabia)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd9\x85\xd9\x85\xd9\x84\xd9\x83\xd8\xa9 \xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 \xd8\xa7\xd9\x84\xd8\xb3\xd8\xb9\xd9\x88\xd8\xaf\xd9\x8a\xd8\xa9)\0" "bg-BG\0" "Bulgarian (Bulgaria)\0" "\xd0\xb1\xd1\x8a\xd0\xbb\xd0\xb3\xd0\xb0\xd1\x80\xd1\x81\xd0\xba\xd0\xb8 (\xd0\x91\xd1\x8a\xd0\xbb\xd0\xb3\xd0\xb0\xd1\x80\xd0\xb8\xd1\x8f)\0" "BG\0" "ca-ES\0" "Catalan (Spain)\0" "catal\xc3\xa0 (Espanya)\0" "ES\0" "zh-TW\0" "Chinese (Traditional)\0" "\xe4\xb8\xad\xe6\x96\x87 (\xe5\x8f\xb0\xe6\xb9\xbe)\0" "CHT\0" "TW\0" "\xe5\x85\xac\xe6\x9b\x86\0" "cs-CZ\0" "Czech (Czech Republic)\0" "\xc4\x8d\x65\xc5\xa1tina (\xc4\x8c\x65sk\xc3\xa1 republika)\0" "CZ\0" "da-DK\0" "Danish (Denmark)\0" "dansk (Danmark)\0" "DK\0" "de-DE\0" "German (Germany)\0" "Deutsch (Deutschland)\0" "DE\0" "el-GR\0" "Greek (Greece)\0" "\xce\x95\xce\xbb\xce\xbb\xce\xb7\xce\xbd\xce\xb9\xce\xba\xce\xac (\xce\x95\xce\xbb\xce\xbb\xce\xac\xce\xb4\xce\xb1)\0" "GR\0" "en-US\0" "English (United States)\0" "US\0" "fi-FI\0" "Finnish (Finland)\0" "suomi (Suomi)\0" "FI\0" "fr-FR\0" "French (France)\0" "fran\xc3\xa7\x61is (France)\0" "FR\0" "he-IL\0" "Hebrew (Israel)\0" "\xd7\xa2\xd7\x91\xd7\xa8\xd7\x99\xd7\xaa (\xd7\x99\xd7\xa9\xd7\xa8\xd7\x90\xd7\x9c)\0" "IL\0" "hu-HU\0" "Hungarian (Hungary)\0" "magyar (Magyarorsz\xc3\xa1g)\0" "HU\0" "is-IS\0" "Icelandic (Iceland)\0" "\xc3\xadslenska (\xc3\x8dsland)\0" "IS\0" "it-IT\0" "Italian (Italy)\0" "italiano (Italia)\0" "IT\0" "ja-JP\0" "Japanese (Japan)\0" "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (\xe6\x97\xa5\xe6\x9c\xac)\0" "JP\0" "ko-KR\0" "Korean (South Korea)\0" "\xed\x95\x9c\xea\xb5\xad\xec\x96\xb4 (\xeb\x8c\x80\xed\x95\x9c\xeb\xaf\xbc\xea\xb5\xad)\0" "KR\0" "nl-NL\0" "Dutch (Netherlands)\0" "Nederlands (Nederland)\0" "NL\0" "nb-NO\0" "Norwegian Bokm\xc3\xa5l (Norway)\0" "norsk bokm\xc3\xa5l (Norge)\0" "NO\0" "pl-PL\0" "Polish (Poland)\0" "polski (Polska)\0" "PL\0" "pt-BR\0" "Portuguese (Brazil)\0" "portugu\xc3\xaas (Brasil)\0" "BR\0" "rm-CH\0" "Romansh (Switzerland)\0" "rumantsch (Svizra)\0" "ro-RO\0" "Romanian (Romania)\0" "rom\xc3\xa2n\xc4\x83 (Rom\xc3\xa2nia)\0" "RO\0" "ru-RU\0" "Russian (Russia)\0" "\xd1\x80\xd1\x83\xd1\x81\xd1\x81\xd0\xba\xd0\xb8\xd0\xb9 (\xd0\xa0\xd0\xbe\xd1\x81\xd1\x81\xd0\xb8\xd1\x8f)\0" "RU\0" "hr-HR\0" "Croatian (Croatia)\0" "hrvatski (Hrvatska)\0" "HR\0" "sk-SK\0" "Slovak (Slovakia)\0" "sloven\xc4\x8dina (Slovensko)\0" "SK\0" "sq-AL\0" "Albanian (Albania)\0" "Shqip (Shqip\xc3\xabri)\0" "AL\0" "sv-SE\0" "Swedish (Sweden)\0" "svenska (Sverige)\0" "SE\0" "th-TH\0" "Thai (Thailand)\0" "\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2 (\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2)\0" "TH\0" "tr-TR\0" "Turkish (Turkey)\0" "T\xc3\xbcrk\xc3\xa7\x65 (T\xc3\xbcrkiye)\0" "TR\0" "ur-PK\0" "Urdu (Pakistan)\0" "\xd8\xa7\xd8\xb1\xd8\xaf\xd9\x88 (\xd9\xbe\xd8\xa7\xda\xa9\xd8\xb3\xd8\xaa\xd8\xa7\xd9\x86)\0" "PK\0" "id-ID\0" "Indonesian (Indonesia)\0" "Bahasa Indonesia (Indonesia)\0" "ID\0" "uk-UA\0" "Ukrainian (Ukraine)\0" "\xd1\x83\xd0\xba\xd1\x80\xd0\xb0\xd1\x97\xd0\xbd\xd1\x81\xd1\x8c\xd0\xba\xd0\xb0 (\xd0\xa3\xd0\xba\xd1\x80\xd0\xb0\xd1\x97\xd0\xbd\xd0\xb0)\0" "UA\0" "be-BY\0" "Belarusian (Belarus)\0" "\xd0\xb1\xd0\xb5\xd0\xbb\xd0\xb0\xd1\x80\xd1\x83\xd1\x81\xd0\xba\xd0\xb0\xd1\x8f (\xd0\x91\xd0\xb5\xd0\xbb\xd0\xb0\xd1\x80\xd1\x83\xd1\x81\xd1\x8c)\0" "BY\0" "sl-SI\0" "Slovenian (Slovenia)\0" "sloven\xc5\xa1\xc4\x8dina (Slovenija)\0" "SI\0" "et-EE\0" "Estonian (Estonia)\0" "eesti (Eesti)\0" "EE\0" "lv-LV\0" "Latvian (Latvia)\0" "latvie\xc5\xa1u (Latvija)\0" "LV\0" "lt-LT\0" "Lithuanian (Lithuania)\0" "lietuvi\xc5\xb3 (Lietuva)\0" "LT\0" "tg-Cyrl-TJ\0" "Tajik (Cyrillic, Tajikistan)\0" "\xd0\xa2\xd0\xbe\xd2\xb7\xd0\xb8\xd0\xba\xd3\xa3 (\xd0\xa2\xd0\xbe\xd2\xb7\xd0\xb8\xd0\xba\xd0\xb8\xd1\x81\xd1\x82\xd0\xbe\xd0\xbd)\0" "TJ\0" "fa-IR\0" "Persian (Iran)\0" "\xd9\x81\xd8\xa7\xd8\xb1\xd8\xb3\xdb\x8c (\xd8\xa7\xdb\x8c\xd8\xb1\xd8\xa7\xd9\x86)\0" "IR\0" "vi-VN\0" "Vietnamese (Vietnam)\0" "Ti\xe1\xba\xbfng Vi\xe1\xbb\x87t (Vi\xe1\xbb\x87t Nam)\0" "VN\0" "hy-AM\0" "Armenian (Armenia)\0" "\xd5\xb0\xd5\xa1\xd5\xb5\xd5\xa5\xd6\x80\xd5\xa5\xd5\xb6 (\xd5\x80\xd5\xa1\xd5\xb5\xd5\xa1\xd5\xbd\xd5\xbf\xd5\xa1\xd5\xb6)\0" "az-Latn-AZ\0" "Azerbaijani (Latin, Azerbaijan)\0" "az\xc9\x99rbaycan (Az\xc9\x99rbaycan)\0" "AZ\0" "eu-ES\0" "Basque (Spain)\0" "euskara (Espainia)\0" "mk-MK\0" "Macedonian (Macedonia)\0" "\xd0\xbc\xd0\xb0\xd0\xba\xd0\xb5\xd0\xb4\xd0\xbe\xd0\xbd\xd1\x81\xd0\xba\xd0\xb8 (\xd0\x9c\xd0\xb0\xd0\xba\xd0\xb5\xd0\xb4\xd0\xbe\xd0\xbd\xd0\xb8\xd1\x98\xd0\xb0)\0" "MK\0" "tn-ZA\0" "Tswana (South Africa)\0" "ZA\0" "xh-ZA\0" "Xhosa (South Africa)\0" "zu-ZA\0" "Zulu (South Africa)\0" "isiZulu (i-South Africa)\0" "af-ZA\0" "Afrikaans (South Africa)\0" "Afrikaans (Suid-Afrika)\0" "ka-GE\0" "Georgian (Georgia)\0" "\xe1\x83\xa5\xe1\x83\x90\xe1\x83\xa0\xe1\x83\x97\xe1\x83\xa3\xe1\x83\x9a\xe1\x83\x98 (\xe1\x83\xa1\xe1\x83\x90\xe1\x83\xa5\xe1\x83\x90\xe1\x83\xa0\xe1\x83\x97\xe1\x83\x95\xe1\x83\x94\xe1\x83\x9a\xe1\x83\x9d)\0" "GE\0" "fo-FO\0" "Faroese (Faroe Islands)\0" "f\xc3\xb8royskt (F\xc3\xb8royar)\0" "FO\0" "hi-IN\0" "Hindi (India)\0" "\xe0\xa4\xb9\xe0\xa4\xbf\xe0\xa4\x82\xe0\xa4\xa6\xe0\xa5\x80 (\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa4\xa4)\0" "IN\0" "mt-MT\0" "Maltese (Malta)\0" "Malti (Malta)\0" "MT\0" "se-NO\0" "Northern Sami (Norway)\0" "davvis\xc3\xa1megiella (Norga)\0" "sw-KE\0" "Swahili (Kenya)\0" "Kiswahili (Kenya)\0" "KE\0" "uz-Latn-UZ\0" "Uzbek (Latin, Uzbekistan)\0" "o\xca\xbbzbekcha (O\xca\xbbzbekiston)\0" "UZ\0" "bn-IN\0" "Bengali (India)\0" "\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa6\x82\xe0\xa6\xb2\xe0\xa6\xbe (\xe0\xa6\xad\xe0\xa6\xbe\xe0\xa6\xb0\xe0\xa6\xa4)\0" "gu-IN\0" "Gujarati (India)\0" "\xe0\xaa\x97\xe0\xab\x81\xe0\xaa\x9c\xe0\xaa\xb0\xe0\xaa\xbe\xe0\xaa\xa4\xe0\xab\x80 (\xe0\xaa\xad\xe0\xaa\xbe\xe0\xaa\xb0\xe0\xaa\xa4)\0" "or-IN\0" "Oriya (India)\0" "\xe0\xac\x93\xe0\xac\xa1\xe0\xac\xbc\xe0\xac\xbf\xe0\xac\x86 (\xe0\xac\xad\xe0\xac\xbe\xe0\xac\xb0\xe0\xac\xa4)\0" "ta-IN\0" "Tamil (India)\0" "\xe0\xae\xa4\xe0\xae\xae\xe0\xae\xbf\xe0\xae\xb4\xe0\xaf\x8d (\xe0\xae\x87\xe0\xae\xa8\xe0\xaf\x8d\xe0\xae\xa4\xe0\xae\xbf\xe0\xae\xaf\xe0\xae\xbe)\0" "te-IN\0" "Telugu (India)\0" "\xe0\xb0\xa4\xe0\xb1\x86\xe0\xb0\xb2\xe0\xb1\x81\xe0\xb0\x97\xe0\xb1\x81 (\xe0\xb0\xad\xe0\xb0\xbe\xe0\xb0\xb0\xe0\xb0\xa4 \xe0\xb0\xa6\xe0\xb1\x87\xe0\xb0\xb6\xe0\xb0\x82)\0" "kn-IN\0" "Kannada (India)\0" "\xe0\xb2\x95\xe0\xb2\xa8\xe0\xb3\x8d\xe0\xb2\xa8\xe0\xb2\xa1 (\xe0\xb2\xad\xe0\xb2\xbe\xe0\xb2\xb0\xe0\xb2\xa4)\0" "ml-IN\0" "Malayalam (India)\0" "\xe0\xb4\xae\xe0\xb4\xb2\xe0\xb4\xaf\xe0\xb4\xbe\xe0\xb4\xb3\xe0\xb4\x82 (\xe0\xb4\x87\xe0\xb4\xa8\xe0\xb5\x8d\xe0\xb4\xa4\xe0\xb5\x8d\xe0\xb4\xaf)\0" "as-IN\0" "Assamese (India)\0" "\xe0\xa6\x85\xe0\xa6\xb8\xe0\xa6\xae\xe0\xa7\x80\xe0\xa6\xaf\xe0\xa6\xbc\xe0\xa6\xbe (\xe0\xa6\xad\xe0\xa6\xbe\xe0\xa7\xb0\xe0\xa6\xa4)\0" "mr-IN\0" "Marathi (India)\0" "\xe0\xa4\xae\xe0\xa4\xb0\xe0\xa4\xbe\xe0\xa4\xa0\xe0\xa5\x80 (\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa4\xa4)\0" "bo-CN\0" "Tibetan (China)\0" "\xe0\xbd\x94\xe0\xbd\xbc\xe0\xbd\x91\xe0\xbc\x8b\xe0\xbd\xa6\xe0\xbe\x90\xe0\xbd\x91\xe0\xbc\x8b (\xe0\xbd\xa2\xe0\xbe\x92\xe0\xbe\xb1\xe0\xbc\x8b\xe0\xbd\x93\xe0\xbd\x82)\0" "cy-GB\0" "Welsh (United Kingdom)\0" "Cymraeg (Y Deyrnas Unedig)\0" "GB\0" "km-KH\0" "Khmer (Cambodia)\0" "\xe1\x9e\x81\xe1\x9f\x92\xe1\x9e\x98\xe1\x9f\x82\xe1\x9e\x9a (\xe1\x9e\x80\xe1\x9e\x98\xe1\x9f\x92\xe1\x9e\x96\xe1\x9e\xbb\xe1\x9e\x87\xe1\x9e\xb6)\0" "KH\0" "lo-LA\0" "Lao (Laos)\0" "\xe0\xba\xa5\xe0\xba\xb2\xe0\xba\xa7 (\xe0\xba\xa5\xe0\xba\xb2\xe0\xba\xa7)\0" "LA\0" "gl-ES\0" "Galician (Spain)\0" "galego (Espa\xc3\xb1\x61)\0" "kok-IN\0" "Konkani (India)\0" "\xe0\xa4\x95\xe0\xa5\x8b\xe0\xa4\x82\xe0\xa4\x95\xe0\xa4\xa3\xe0\xa5\x80 (\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa4\xa4)\0" "si-LK\0" "Sinhala (Sri Lanka)\0" "\xe0\xb7\x83\xe0\xb7\x92\xe0\xb6\x82\xe0\xb7\x84\xe0\xb6\xbd (\xe0\xb7\x81\xe0\xb7\x8a\xe2\x80\x8d\xe0\xb6\xbb\xe0\xb7\x93 \xe0\xb6\xbd\xe0\xb6\x82\xe0\xb6\x9a\xe0\xb7\x8f\xe0\xb7\x80)\0" "LK\0" "am-ET\0" "Amharic (Ethiopia)\0" "\xe1\x8a\xa0\xe1\x88\x9b\xe1\x88\xad\xe1\x8a\x9b (\xe1\x8a\xa2\xe1\x89\xb5\xe1\x8b\xae\xe1\x8c\xb5\xe1\x8b\xab)\0" "ET\0" "ne-NP\0" "Nepali (Nepal)\0" "\xe0\xa4\xa8\xe0\xa5\x87\xe0\xa4\xaa\xe0\xa4\xbe\xe0\xa4\xb2\xe0\xa5\x80 (\xe0\xa4\xa8\xe0\xa5\x87\xe0\xa4\xaa\xe0\xa4\xbe\xe0\xa4\xb2)\0" "NP\0" "ps-AF\0" "Pashto (Afghanistan)\0" "\xd9\xbe\xda\x9a\xd8\xaa\xd9\x88 (\xd8\xa7\xd9\x81\xd8\xba\xd8\xa7\xd9\x86\xd8\xb3\xd8\xaa\xd8\xa7\xd9\x86)\0" "AF\0" "fil-PH\0" "Filipino (Philippines)\0" "Filipino (Pilipinas)\0" "PH\0" "ha-Latn-NG\0" "Hausa (Latin, Nigeria)\0" "Hausa (Najeriya)\0" "NG\0" "yo-NG\0" "Yoruba (Nigeria)\0" "\xc3\x88\x64\xc3\xa8 Yor\xc3\xb9\x62\xc3\xa1 (Or\xc3\xadl\xe1\xba\xb9\xcc\x81\xc3\xa8\x64\x65 N\xc3\xa0\xc3\xacj\xc3\xadr\xc3\xad\xc3\xa0)\0" "nso-ZA\0" "Northern Sotho (South Africa)\0" "kl-GL\0" "Kalaallisut (Greenland)\0" "kalaallisut (Kalaallit Nunaat)\0" "GL\0" "ig-NG\0" "Igbo (Nigeria)\0" "ii-CN\0" "Sichuan Yi (China)\0" "\xea\x86\x88\xea\x8c\xa0\xea\x89\x99 (\xea\x8d\x8f\xea\x87\xa9)\0" "br-FR\0" "Breton (France)\0" "brezhoneg (Fra\xc3\xb1s)\0" "sah-RU\0" "Sakha (Russia)\0" "rw-RW\0" "Kinyarwanda (Rwanda)\0" "RW\0" "gd-GB\0" "Scottish Gaelic (United Kingdom)\0" "G\xc3\xa0idhlig (An R\xc3\xacoghachd Aonaichte)\0" "ar-IQ\0" "Arabic (Iraq)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa7\xd9\x82)\0" "ARI\0" "IQ\0" "\xd8\xa7\xd9\x84\xd8\xaa\xd9\x82\xd9\x88\xd9\x8a\xd9\x85 \xd8\xa7\xd9\x84\xd9\x85\xd9\x8a\xd9\x84\xd8\xa7\xd8\xaf\xd9\x8a\0" "zh-CN\0" "\xe4\xb8\xad\xe6\x96\x87 (\xe4\xb8\xad\xe5\x9b\xbd)\0" "de-CH\0" "German (Switzerland)\0" "Deutsch (Schweiz)\0" "DES\0" "en-GB\0" "English (United Kingdom)\0" "ENG\0" "es-MX\0" "Spanish (Mexico)\0" "espa\xc3\xb1ol (M\xc3\xa9xico)\0" "ESM\0" "MX\0" "fr-BE\0" "French (Belgium)\0" "fran\xc3\xa7\x61is (Belgique)\0" "FRB\0" "BE\0" "it-CH\0" "Italian (Switzerland)\0" "italiano (Svizzera)\0" "ITS\0" "nl-BE\0" "Dutch (Belgium)\0" "Nederlands (Belgi\xc3\xab)\0" "NLB\0" "nn-NO\0" "Norwegian Nynorsk (Norway)\0" "nynorsk (Noreg)\0" "NON\0" "nno\0" "nn\0" "pt-PT\0" "Portuguese (Portugal)\0" "portugu\xc3\xaas (Portugal)\0" "PTG\0" "PT\0" "sv-FI\0" "Swedish (Finland)\0" "svenska (Finland)\0" "SVF\0" "az-Cyrl-AZ\0" "Azerbaijani (Cyrillic, Azerbaijan)\0" "AZC\0" "ga-IE\0" "Irish (Ireland)\0" "Gaeilge (\xc3\x89ire)\0" "IE\0" "uz-Cyrl-UZ\0" "Uzbek (Cyrillic, Uzbekistan)\0" "\xd0\x93\xd1\x80\xd0\xb8\xd0\xb3\xd0\xbe\xd1\x80\xd0\xb8\xd0\xb0\xd0\xbd \xd0\xba\xd0\xb0\xd0\xbb\xd0\xb5\xd0\xbd\xd0\xb4\xd0\xb0\xd1\x80\xd0\xb8\0" "bn-BD\0" "Bengali (Bangladesh)\0" "\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa6\x82\xe0\xa6\xb2\xe0\xa6\xbe (\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa6\x82\xe0\xa6\xb2\xe0\xa6\xbe\xe0\xa6\xa6\xe0\xa7\x87\xe0\xa6\xb6)\0" "BNB\0" "BD\0" "ar-EG\0" "Arabic (Egypt)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd9\x85\xd8\xb5\xd8\xb1)\0" "ARE\0" "EG\0" "zh-HK\0" "Chinese (Traditional, Hong Kong SAR China)\0" "\xe4\xb8\xad\xe6\x96\x87 (\xe4\xb8\xad\xe5\x9b\xbd\xe9\xa6\x99\xe6\xb8\xaf\xe7\x89\xb9\xe5\x88\xab\xe8\xa1\x8c\xe6\x94\xbf\xe5\x8c\xba)\0" "ZHH\0" "HK\0" "de-AT\0" "German (Austria)\0" "Deutsch (\xc3\x96sterreich)\0" "DEA\0" "AT\0" "en-AU\0" "English (Australia)\0" "ENA\0" "AU\0" "es-ES\0" "Spanish (Spain)\0" "espa\xc3\xb1ol (Espa\xc3\xb1\x61)\0" "ESN\0" "fr-CA\0" "French (Canada)\0" "fran\xc3\xa7\x61is (Canada)\0" "FRC\0" "CA\0" "Calendrier gr\xc3\xa9gorien\0" "se-FI\0" "Northern Sami (Finland)\0" "davvis\xc3\xa1megiella (Suopma)\0" "SMG\0" "smg\0" "ar-LY\0" "Arabic (Libya)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd9\x84\xd9\x8a\xd8\xa8\xd9\x8a\xd8\xa7)\0" "ARL\0" "LY\0" "zh-SG\0" "Chinese (Simplified, Singapore)\0" "\xe4\xb8\xad\xe6\x96\x87 (\xe6\x96\xb0\xe5\x8a\xa0\xe5\x9d\xa1)\0" "ZHI\0" "SG\0" "de-LU\0" "German (Luxembourg)\0" "Deutsch (Luxemburg)\0" "DEL\0" "LU\0" "en-CA\0" "English (Canada)\0" "ENC\0" "es-GT\0" "Spanish (Guatemala)\0" "espa\xc3\xb1ol (Guatemala)\0" "ESG\0" "GT\0" "fr-CH\0" "French (Switzerland)\0" "fran\xc3\xa7\x61is (Suisse)\0" "FRS\0" "hr-BA\0" "Croatian (Bosnia and Herzegovina)\0" "hrvatski (Bosna i Hercegovina)\0" "HRB\0" "hrb\0" "BA\0" "ar-DZ\0" "Arabic (Algeria)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd8\xac\xd8\xb2\xd8\xa7\xd8\xa6\xd8\xb1)\0" "ARG\0" "DZ\0" "zh-MO\0" "Chinese (Traditional, Macau SAR China)\0" "\xe4\xb8\xad\xe6\x96\x87 (\xe4\xb8\xad\xe5\x9b\xbd\xe6\xbe\xb3\xe9\x97\xa8\xe7\x89\xb9\xe5\x88\xab\xe8\xa1\x8c\xe6\x94\xbf\xe5\x8c\xba)\0" "ZHM\0" "MO\0" "de-LI\0" "German (Liechtenstein)\0" "Deutsch (Liechtenstein)\0" "DEC\0" "LI\0" "en-NZ\0" "English (New Zealand)\0" "ENZ\0" "NZ\0" "es-CR\0" "Spanish (Costa Rica)\0" "espa\xc3\xb1ol (Costa Rica)\0" "ESC\0" "CR\0" "fr-LU\0" "French (Luxembourg)\0" "fran\xc3\xa7\x61is (Luxembourg)\0" "FRL\0" "bs-Latn-BA\0" "Bosnian (Latin, Bosnia and Herzegovina)\0" "bosanski (Bosna i Hercegovina)\0" "BSB\0" "bsb\0" "bs\0" "Gregorijanski kalendar\0" "ar-MA\0" "Arabic (Morocco)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd9\x85\xd8\xba\xd8\xb1\xd8\xa8)\0" "ARM\0" "MA\0" "en-IE\0" "English (Ireland)\0" "ENI\0" "es-PA\0" "Spanish (Panama)\0" "espa\xc3\xb1ol (Panam\xc3\xa1)\0" "ESA\0" "PA\0" "fr-MC\0" "French (Monaco)\0" "fran\xc3\xa7\x61is (Monaco)\0" "FRM\0" "MC\0" "sr-Latn-BA\0" "Serbian (Latin, Bosnia and Herzegovina)\0" "\xd0\xa1\xd1\x80\xd0\xbf\xd1\x81\xd0\xba\xd0\xb8 (\xd0\x91\xd0\xbe\xd1\x81\xd0\xbd\xd0\xb0 \xd0\xb8 \xd0\xa5\xd0\xb5\xd1\x80\xd1\x86\xd0\xb5\xd0\xb3\xd0\xbe\xd0\xb2\xd0\xb8\xd0\xbd\xd0\xb0)\0" "SRS\0" "srs\0" "sr\0" "ar-TN\0" "Arabic (Tunisia)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xaa\xd9\x88\xd9\x86\xd8\xb3)\0" "ART\0" "TN\0" "en-ZA\0" "English (South Africa)\0" "ENS\0" "es-DO\0" "Spanish (Dominican Republic)\0" "espa\xc3\xb1ol (Rep\xc3\xba\x62lica Dominicana)\0" "ESD\0" "DO\0" "sr-Cyrl-BA\0" "Serbian (Cyrillic, Bosnia and Herzegovina)\0" "SRN\0" "srn\0" "ar-OM\0" "Arabic (Oman)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xb9\xd9\x8f\xd9\x85\xd8\xa7\xd9\x86)\0" "ARO\0" "OM\0" "en-JM\0" "English (Jamaica)\0" "ENJ\0" "JM\0" "es-VE\0" "Spanish (Venezuela)\0" "espa\xc3\xb1ol (Venezuela)\0" "ESV\0" "VE\0" "bs-Cyrl-BA\0" "Bosnian (Cyrillic, Bosnia and Herzegovina)\0" "BSC\0" "bsc\0" "ar-YE\0" "Arabic (Yemen)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd9\x8a\xd9\x85\xd9\x86)\0" "ARY\0" "YE\0" "es-CO\0" "Spanish (Colombia)\0" "espa\xc3\xb1ol (Colombia)\0" "ESO\0" "CO\0" "sr-Latn-RS\0" "Serbian (Latin, Serbia)\0" "\xd0\xa1\xd1\x80\xd0\xbf\xd1\x81\xd0\xba\xd0\xb8 (\xd0\xa1\xd1\x80\xd0\xb1\xd0\xb8\xd1\x98\xd0\xb0)\0" "SRM\0" "RS\0" "ar-SY\0" "Arabic (Syria)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xb3\xd9\x88\xd8\xb1\xd9\x8a\xd8\xa7)\0" "ARS\0" "SY\0" "en-BZ\0" "English (Belize)\0" "ENL\0" "BZ\0" "es-PE\0" "Spanish (Peru)\0" "espa\xc3\xb1ol (Per\xc3\xba)\0" "ESR\0" "PE\0" "sr-Cyrl-RS\0" "Serbian (Cyrillic, Serbia)\0" "SRO\0" "ar-JO\0" "Arabic (Jordan)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd8\xa3\xd8\xb1\xd8\xaf\xd9\x86)\0" "ARJ\0" "JO\0" "en-TT\0" "English (Trinidad and Tobago)\0" "ENT\0" "TT\0" "es-AR\0" "Spanish (Argentina)\0" "espa\xc3\xb1ol (Argentina)\0" "ESS\0" "AR\0" "sr-Latn-ME\0" "Serbian (Latin, Montenegro)\0" "\xd0\xa1\xd1\x80\xd0\xbf\xd1\x81\xd0\xba\xd0\xb8 (\xd0\xa6\xd1\x80\xd0\xbd\xd0\xb0 \xd0\x93\xd0\xbe\xd1\x80\xd0\xb0)\0" "SRP\0" "ME\0" "ar-LB\0" "Arabic (Lebanon)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd9\x84\xd8\xa8\xd9\x86\xd8\xa7\xd9\x86)\0" "ARB\0" "LB\0" "en-ZW\0" "English (Zimbabwe)\0" "ENW\0" "ZW\0" "es-EC\0" "Spanish (Ecuador)\0" "espa\xc3\xb1ol (Ecuador)\0" "ESF\0" "EC\0" "sr-Cyrl-ME\0" "Serbian (Cyrillic, Montenegro)\0" "SRQ\0" "ar-KW\0" "Arabic (Kuwait)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd9\x83\xd9\x88\xd9\x8a\xd8\xaa)\0" "ARK\0" "KW\0" "en-PH\0" "English (Philippines)\0" "ENP\0" "es-CL\0" "Spanish (Chile)\0" "espa\xc3\xb1ol (Chile)\0" "ESL\0" "CL\0" "ar-AE\0" "Arabic (United Arab Emirates)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd8\xa5\xd9\x85\xd8\xa7\xd8\xb1\xd8\xa7\xd8\xaa \xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 \xd8\xa7\xd9\x84\xd9\x85\xd8\xaa\xd8\xad\xd8\xaf\xd8\xa9)\0" "ARU\0" "AE\0" "es-UY\0" "Spanish (Uruguay)\0" "espa\xc3\xb1ol (Uruguay)\0" "ESY\0" "UY\0" "ar-BH\0" "Arabic (Bahrain)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd8\xa7\xd9\x84\xd8\xa8\xd8\xad\xd8\xb1\xd9\x8a\xd9\x86)\0" "ARH\0" "BH\0" "es-PY\0" "Spanish (Paraguay)\0" "espa\xc3\xb1ol (Paraguay)\0" "ESZ\0" "PY\0" "ar-QA\0" "Arabic (Qatar)\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 (\xd9\x82\xd8\xb7\xd8\xb1)\0" "ARQ\0" "QA\0" "en-IN\0" "English (India)\0" "ENN\0" "es-BO\0" "Spanish (Bolivia)\0" "espa\xc3\xb1ol (Bolivia)\0" "ESB\0" "BO\0" "es-SV\0" "Spanish (El Salvador)\0" "espa\xc3\xb1ol (El Salvador)\0" "ESE\0" "SV\0" "en-SG\0" "English (Singapore)\0" "ENE\0" "es-HN\0" "Spanish (Honduras)\0" "espa\xc3\xb1ol (Honduras)\0" "ESH\0" "HN\0" "es-NI\0" "Spanish (Nicaragua)\0" "espa\xc3\xb1ol (Nicaragua)\0" "ESI\0" "NI\0" "es-PR\0" "Spanish (Puerto Rico)\0" "espa\xc3\xb1ol (Puerto Rico)\0" "ESU\0" "PR\0" "es-US\0" "Spanish (United States)\0" "espa\xc3\xb1ol (Estados Unidos)\0" "EST\0" "bs-Cyrl\0" "Bosnian (Cyrillic)\0" "bosanski\0" "bs-Latn\0" "Bosnian (Latin)\0" "sr-Cyrl\0" "Serbian (Cyrillic)\0" "\xd0\xa1\xd1\x80\xd0\xbf\xd1\x81\xd0\xba\xd0\xb8\0" "sr-Latn\0" "Serbian (Latin)\0" "az-Cyrl\0" "Azerbaijani (Cyrillic)\0" "Norwegian Nynorsk\0" "nynorsk\0" "Bosnian\0" "az-Latn\0" "Azerbaijani (Latin)\0" "uz-Cyrl\0" "Uzbek (Cyrillic)\0" "mn-Cyrl\0" "Mongolian (Cyrillic)\0" "MNN\0" "zh-Hant\0" "zh-CHT\0" "Chinese (Traditional) Legacy\0" "Norwegian Bokm\xc3\xa5l\0" "norsk bokm\xc3\xa5l\0" "Serbian\0" "SRB\0" "tg-Cyrl\0" "Tajik (Cyrillic)\0" "uz-Latn\0" "Uzbek (Latin)\0" "tzm-Latn\0" "Central Atlas Tamazight (Latin)\0" "ha-Latn\0" "Hausa (Latin)\0" "af-za\0" "am-et\0" "ar-ae\0" "ar-bh\0" "ar-dz\0" "ar-eg\0" "ar-iq\0" "ar-jo\0" "ar-kw\0" "ar-lb\0" "ar-ly\0" "ar-ma\0" "ar-om\0" "ar-qa\0" "ar-sa\0" "ar-sy\0" "ar-tn\0" "ar-ye\0" "as-in\0" "az-cyrl\0" "az-cyrl-az\0" "az-latn\0" "az-latn-az\0" "be-by\0" "bg-bg\0" "bn-bd\0" "bn-in\0" "bo-cn\0" "br-fr\0" "bs-cyrl\0" "bs-cyrl-ba\0" "bs-latn\0" "bs-latn-ba\0" "ca-es\0" "cs-cz\0" "cy-gb\0" "da-dk\0" "de-at\0" "de-ch\0" "de-de\0" "de-li\0" "de-lu\0" "el-gr\0" "en-au\0" "en-bz\0" "en-ca\0" "en-gb\0" "en-ie\0" "en-in\0" "en-jm\0" "en-nz\0" "en-ph\0" "en-sg\0" "en-tt\0" "en-us\0" "en-za\0" "en-zw\0" "es-ar\0" "es-bo\0" "es-cl\0" "es-co\0" "es-cr\0" "es-do\0" "es-ec\0" "es-es\0" "es-gt\0" "es-hn\0" "es-mx\0" "es-ni\0" "es-pa\0" "es-pe\0" "es-pr\0" "es-py\0" "es-sv\0" "es-us\0" "es-uy\0" "es-ve\0" "et-ee\0" "eu-es\0" "fa-ir\0" "fi-fi\0" "fil-ph\0" "fo-fo\0" "fr-be\0" "fr-ca\0" "fr-ch\0" "fr-fr\0" "fr-lu\0" "fr-mc\0" "ga-ie\0" "gd-gb\0" "gl-es\0" "gu-in\0" "ha-latn\0" "ha-latn-ng\0" "he-il\0" "hi-in\0" "hr-ba\0" "hr-hr\0" "hu-hu\0" "hy-am\0" "id-id\0" "ig-ng\0" "ii-cn\0" "is-is\0" "it-ch\0" "it-it\0" "ja-jp\0" "ka-ge\0" "kl-gl\0" "km-kh\0" "kn-in\0" "ko-kr\0" "kok-in\0" "lo-la\0" "lt-lt\0" "lv-lv\0" "mk-mk\0" "ml-in\0" "mn-cyrl\0" "mr-in\0" "mt-mt\0" "nb-no\0" "ne-np\0" "nl-be\0" "nl-nl\0" "nn-no\0" "nso-za\0" "or-in\0" "pl-pl\0" "ps-af\0" "pt-br\0" "pt-pt\0" "rm-ch\0" "ro-ro\0" "ru-ru\0" "rw-rw\0" "sah-ru\0" "se-fi\0" "se-no\0" "si-lk\0" "sk-sk\0" "sl-si\0" "sq-al\0" "sr-cyrl\0" "sr-cyrl-ba\0" "sr-cyrl-me\0" "sr-cyrl-rs\0" "sr-latn\0" "sr-latn-ba\0" "sr-latn-me\0" "sr-latn-rs\0" "sv-fi\0" "sv-se\0" "sw-ke\0" "ta-in\0" "te-in\0" "tg-cyrl\0" "tg-cyrl-tj\0" "th-th\0" "tn-za\0" "tr-tr\0" "tzm-latn\0" "uk-ua\0" "ur-pk\0" "uz-cyrl\0" "uz-cyrl-uz\0" "uz-latn\0" "uz-latn-uz\0" "vi-vn\0" "xh-za\0" "yo-ng\0" "zh-chs\0" "zh-cht\0" "zh-cn\0" "zh-hans\0" "zh-hant\0" "zh-hk\0" "zh-mo\0" "zh-sg\0" "zh-tw\0" "zu-za\0" "United Arab Emirates\0" "\xd8\xa7\xd9\x84\xd8\xa5\xd9\x85\xd8\xa7\xd8\xb1\xd8\xa7\xd8\xaa \xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 \xd8\xa7\xd9\x84\xd9\x85\xd8\xaa\xd8\xad\xd8\xaf\xd8\xa9\0" "AED\0" "United Arab Emirates Dirham\0" "\xd8\xaf\xd8\xb1\xd9\x87\xd9\x85 \xd8\xa5\xd9\x85\xd8\xa7\xd8\xb1\xd8\xa7\xd8\xaa\xd9\x8a\0" "AFG\0" "Afghanistan\0" "\xd8\xa7\xd9\x81\xd8\xba\xd8\xa7\xd9\x86\xd8\xb3\xd8\xaa\xd8\xa7\xd9\x86\0" "AFN\0" "Afghan Afghani\0" "\xd8\xa7\xd9\x81\xd8\xba\xd8\xa7\xd9\x86\xdb\x8d\0" "ALB\0" "Albania\0" "Shqip\xc3\xabri\0" "ALL\0" "Albanian Lek\0" "Leku shqiptar\0" "Armenia\0" "\xd5\x80\xd5\xa1\xd5\xb5\xd5\xa1\xd5\xbd\xd5\xbf\xd5\xa1\xd5\xb6\0" "AMD\0" "Armenian Dram\0" "\xd5\x80\xd5\xa1\xd5\xb5\xd5\xaf\xd5\xa1\xd5\xaf\xd5\xa1\xd5\xb6 \xd5\xa4\xd6\x80\xd5\xa1\xd5\xb4\0" "Argentina\0" "Argentine Peso\0" "peso argentino\0" "AUT\0" "Austria\0" "\xc3\x96sterreich\0" "EUR\0" "Euro\0" "AUS\0" "Australia\0" "AUD\0" "Australian Dollar\0" "Azerbaijan\0" "Az\xc9\x99rbaycan\0" "AZN\0" "Azerbaijani Manat\0" "Az\xc9\x99rbaycan Manat\xc4\xb1\0" "BIH\0" "Bosnia and Herzegovina\0" "Bosna i Hercegovina\0" "BAM\0" "Bosnia-Herzegovina Convertible Mark\0" "konvertibilna marka\0" "BGD\0" "Bangladesh\0" "\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa6\x82\xe0\xa6\xb2\xe0\xa6\xbe\xe0\xa6\xa6\xe0\xa7\x87\xe0\xa6\xb6\0" "BDT\0" "Bangladeshi Taka\0" "\xe0\xa6\xac\xe0\xa6\xbe\xe0\xa6\x82\xe0\xa6\xb2\xe0\xa6\xbe\xe0\xa6\xa6\xe0\xa7\x87\xe0\xa6\xb6\xe0\xa7\x80 \xe0\xa6\x9f\xe0\xa6\xbe\xe0\xa6\x95\xe0\xa6\xbe\0" "Belgium\0" "Belgique\0" "euro\0" "Bulgaria\0" "\xd0\x91\xd1\x8a\xd0\xbb\xd0\xb3\xd0\xb0\xd1\x80\xd0\xb8\xd1\x8f\0" "BGN\0" "Bulgarian Lev\0" "\xd0\x91\xd1\x8a\xd0\xbb\xd0\xb3\xd0\xb0\xd1\x80\xd1\x81\xd0\xba\xd0\xb8 \xd0\xbb\xd0\xb5\xd0\xb2\0" "BHR\0" "Bahrain\0" "\xd8\xa7\xd9\x84\xd8\xa8\xd8\xad\xd8\xb1\xd9\x8a\xd9\x86\0" "BHD\0" "Bahraini Dinar\0" "\xd8\xaf\xd9\x8a\xd9\x86\xd8\xa7\xd8\xb1 \xd8\xa8\xd8\xad\xd8\xb1\xd9\x8a\xd9\x86\xd9\x8a\0" "BOL\0" "Bolivia\0" "Bolivian Boliviano\0" "boliviano\0" "BRA\0" "Brazil\0" "Brasil\0" "BRL\0" "Brazilian Real\0" "Real brasileiro\0" "BLR\0" "Belarus\0" "\xd0\x91\xd0\xb5\xd0\xbb\xd0\xb0\xd1\x80\xd1\x83\xd1\x81\xd1\x8c\0" "BYR\0" "Belarusian Ruble\0" "\xd0\xb1\xd0\xb5\xd0\xbb\xd0\xb0\xd1\x80\xd1\x83\xd1\x81\xd0\xba\xd1\x96 \xd1\x80\xd1\x83\xd0\xb1\xd0\xb5\xd0\xbb\xd1\x8c\0" "BLZ\0" "Belize\0" "BZD\0" "Belize Dollar\0" "CAN\0" "Canada\0" "CAD\0" "Canadian Dollar\0" "dollar canadien\0" "CHE\0" "Switzerland\0" "Svizra\0" "Swiss Franc\0" "franc svizzer\0" "CHL\0" "Chile\0" "CLP\0" "Chilean Peso\0" "peso chileno\0" "CHN\0" "China\0" "\xe0\xbd\xa2\xe0\xbe\x92\xe0\xbe\xb1\xe0\xbc\x8b\xe0\xbd\x93\xe0\xbd\x82\0" "CNY\0" "Chinese Yuan\0" "\xe0\xbd\xa1\xe0\xbd\xb4\xe0\xbc\x8b\xe0\xbd\xa8\xe0\xbd\x93\xe0\xbc\x8b\0" "COL\0" "Colombia\0" "COP\0" "Colombian Peso\0" "peso colombiano\0" "CRI\0" "Costa Rica\0" "CRC\0" "Costa Rican Col\xc3\xb3n\0" "col\xc3\xb3n costarricense\0" "CZE\0" "Czech Republic\0" "\xc4\x8c\x65sk\xc3\xa1 republika\0" "CZK\0" "Czech Republic Koruna\0" "\xc4\x8d\x65sk\xc3\xa1 koruna\0" "Germany\0" "Deutschland\0" "DNK\0" "Denmark\0" "Danmark\0" "DKK\0" "Danish Krone\0" "Dansk krone\0" "DOM\0" "Dominican Republic\0" "Rep\xc3\xba\x62lica Dominicana\0" "DOP\0" "Dominican Peso\0" "peso dominicano\0" "DZA\0" "Algeria\0" "\xd8\xa7\xd9\x84\xd8\xac\xd8\xb2\xd8\xa7\xd8\xa6\xd8\xb1\0" "DZD\0" "Algerian Dinar\0" "\xd8\xaf\xd9\x8a\xd9\x86\xd8\xa7\xd8\xb1 \xd8\xac\xd8\xb2\xd8\xa7\xd8\xa6\xd8\xb1\xd9\x8a\0" "ECU\0" "Ecuador\0" "USD\0" "US Dollar\0" "d\xc3\xb3lar estadounidense\0" "Estonia\0" "Eesti\0" "EGY\0" "Egypt\0" "\xd9\x85\xd8\xb5\xd8\xb1\0" "EGP\0" "Egyptian Pound\0" "\xd8\xac\xd9\x86\xd9\x8a\xd9\x87 \xd9\x85\xd8\xb5\xd8\xb1\xd9\x8a\0" "Spain\0" "Espanya\0" "ETH\0" "Ethiopia\0" "\xe1\x8a\xa2\xe1\x89\xb5\xe1\x8b\xae\xe1\x8c\xb5\xe1\x8b\xab\0" "ETB\0" "Ethiopian Birr\0" "\xe1\x8b\xa8\xe1\x8a\xa2\xe1\x89\xb5\xe1\x8b\xae\xe1\x8c\xb5\xe1\x8b\xab \xe1\x89\xa5\xe1\x88\xad\0" "Finland\0" "Suomi\0" "FRO\0" "Faroe Islands\0" "F\xc3\xb8royar\0" "donsk kr\xc3\xb3na\0" "France\0" "GBR\0" "United Kingdom\0" "Y Deyrnas Unedig\0" "GBP\0" "British Pound Sterling\0" "Punt Sterling Prydain\0" "GEO\0" "Georgia\0" "\xe1\x83\xa1\xe1\x83\x90\xe1\x83\xa5\xe1\x83\x90\xe1\x83\xa0\xe1\x83\x97\xe1\x83\x95\xe1\x83\x94\xe1\x83\x9a\xe1\x83\x9d\0" "GEL\0" "Georgian Lari\0" "\xe1\x83\xa5\xe1\x83\x90\xe1\x83\xa0\xe1\x83\x97\xe1\x83\xa3\xe1\x83\x9a\xe1\x83\x98 \xe1\x83\x9a\xe1\x83\x90\xe1\x83\xa0\xe1\x83\x98\0" "GRL\0" "Greenland\0" "Kalaallit Nunaat\0" "danmarkimut koruuni\0" "GRC\0" "Greece\0" "\xce\x95\xce\xbb\xce\xbb\xce\xac\xce\xb4\xce\xb1\0" "\xce\x95\xcf\x85\xcf\x81\xcf\x8e\0" "GTM\0" "Guatemala\0" "GTQ\0" "Guatemalan Quetzal\0" "quetzal guatemalteco\0" "HKG\0" "Hong Kong SAR China\0" "\xe4\xb8\xad\xe5\x9b\xbd\xe9\xa6\x99\xe6\xb8\xaf\xe7\x89\xb9\xe5\x88\xab\xe8\xa1\x8c\xe6\x94\xbf\xe5\x8c\xba\0" "HKD\0" "Hong Kong Dollar\0" "\xe6\xb8\xaf\xe5\x85\x83\0" "HND\0" "Honduras\0" "HNL\0" "Honduran Lempira\0" "lempira hondure\xc3\xb1o\0" "Croatia\0" "Hrvatska\0" "HRK\0" "Croatian Kuna\0" "hrvatska kuna\0" "Hungary\0" "Magyarorsz\xc3\xa1g\0" "HUF\0" "Hungarian Forint\0" "magyar forint\0" "IDN\0" "Indonesia\0" "IDR\0" "Indonesian Rupiah\0" "Rupiah Indonesia\0" "IRL\0" "Ireland\0" "\xc3\x89ire\0" "ISR\0" "Israel\0" "\xd7\x99\xd7\xa9\xd7\xa8\xd7\x90\xd7\x9c\0" "ILS\0" "Israeli New Sheqel\0" "\xd7\xa9\xd7\xb4\xd7\x97\0" "India\0" "\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa4\xa4\0" "INR\0" "Indian Rupee\0" "\xe0\xa4\xad\xe0\xa4\xbe\xe0\xa4\xb0\xe0\xa4\xa4\xe0\xa5\x80\xe0\xa4\xaf \xe0\xa4\xb0\xe0\xa5\x81\xe0\xa4\xaa\xe0\xa4\xaf\xe0\xa4\xbe\0" "IRQ\0" "Iraq\0" "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa7\xd9\x82\0" "IQD\0" "Iraqi Dinar\0" "\xd8\xaf\xd9\x8a\xd9\x86\xd8\xa7\xd8\xb1 \xd8\xb9\xd8\xb1\xd8\xa7\xd9\x82\xd9\x8a\0" "IRN\0" "Iran\0" "\xd8\xa7\xdb\x8c\xd8\xb1\xd8\xa7\xd9\x86\0" "IRR\0" "Iranian Rial\0" "\xd8\xb1\xdb\x8c\xd8\xa7\xd9\x84 \xd8\xa7\xdb\x8c\xd8\xb1\xd8\xa7\xd9\x86\0" "Iceland\0" "\xc3\x8dsland\0" "ISK\0" "Icelandic Kr\xc3\xb3na\0" "\xc3\x8dslensk kr\xc3\xb3na\0" "Italy\0" "Italia\0" "JAM\0" "Jamaica\0" "JMD\0" "Jamaican Dollar\0" "JOR\0" "Jordan\0" "\xd8\xa7\xd9\x84\xd8\xa3\xd8\xb1\xd8\xaf\xd9\x86\0" "JOD\0" "Jordanian Dinar\0" "\xd8\xaf\xd9\x8a\xd9\x86\xd8\xa7\xd8\xb1 \xd8\xa3\xd8\xb1\xd8\xaf\xd9\x86\xd9\x8a\0" "Japan\0" "\xe6\x97\xa5\xe6\x9c\xac\0" "JPY\0" "Japanese Yen\0" "\xe6\x97\xa5\xe6\x9c\xac\xe5\x86\x86\0" "KEN\0" "Kenya\0" "KES\0" "Kenyan Shilling\0" "shilingi ya Kenya\0" "Cambodia\0" "\xe1\x9e\x80\xe1\x9e\x98\xe1\x9f\x92\xe1\x9e\x96\xe1\x9e\xbb\xe1\x9e\x87\xe1\x9e\xb6\0" "KHR\0" "Cambodian Riel\0" "\xe1\x9e\x9a\xe1\x9f\x80\xe1\x9e\x9b \xe1\x9e\x80\xe1\x9e\x98\xe1\x9f\x92\xe1\x9e\x96\xe1\x9e\xbb\xe1\x9e\x87\xe1\x9e\xb6\0" "South Korea\0" "\xeb\x8c\x80\xed\x95\x9c\xeb\xaf\xbc\xea\xb5\xad\0" "KRW\0" "South Korean Won\0" "\xeb\x8c\x80\xed\x95\x9c\xeb\xaf\xbc\xea\xb5\xad \xec\x9b\x90\0" "KWT\0" "Kuwait\0" "\xd8\xa7\xd9\x84\xd9\x83\xd9\x88\xd9\x8a\xd8\xaa\0" "KWD\0" "Kuwaiti Dinar\0" "\xd8\xaf\xd9\x8a\xd9\x86\xd8\xa7\xd8\xb1 \xd9\x83\xd9\x88\xd9\x8a\xd8\xaa\xd9\x8a\0" "Laos\0" "LAK\0" "Laotian Kip\0" "\xe0\xba\x81\xe0\xba\xb5\xe0\xba\x9a \xe0\xba\xa5\xe0\xba\xb2\xe0\xba\xa7\0" "LBN\0" "Lebanon\0" "\xd9\x84\xd8\xa8\xd9\x86\xd8\xa7\xd9\x86\0" "LBP\0" "Lebanese Pound\0" "\xd8\xac\xd9\x86\xd9\x8a\xd8\xa9 \xd9\x84\xd8\xa8\xd9\x86\xd8\xa7\xd9\x86\xd9\x8a\0" "LIE\0" "Liechtenstein\0" "Schweizer Franken\0" "LKA\0" "Sri Lanka\0" "\xe0\xb7\x81\xe0\xb7\x8a\xe2\x80\x8d\xe0\xb6\xbb\xe0\xb7\x93 \xe0\xb6\xbd\xe0\xb6\x82\xe0\xb6\x9a\xe0\xb7\x8f\xe0\xb7\x80\0" "LKR\0" "Sri Lankan Rupee\0" "\xe0\xb7\x81\xe0\xb7\x8a\xe2\x80\x8d\xe0\xb6\xbb\xe0\xb7\x93 \xe0\xb6\xbd\xe0\xb6\x82\xe0\xb6\x9a\xe0\xb7\x8f \xe0\xb6\xbb\xe0\xb7\x94\xe0\xb6\xb4\xe0\xb7\x92\xe0\xb6\xba\xe0\xb6\xbd\0" "LTU\0" "Lithuania\0" "Lietuva\0" "LTL\0" "Lithuanian Litas\0" "Lietuvos litas\0" "LUX\0" "Luxembourg\0" "Luxemburg\0" "LVA\0" "Latvia\0" "Latvija\0" "eiro\0" "LBY\0" "Libya\0" "\xd9\x84\xd9\x8a\xd8\xa8\xd9\x8a\xd8\xa7\0" "LYD\0" "Libyan Dinar\0" "\xd8\xaf\xd9\x8a\xd9\x86\xd8\xa7\xd8\xb1 \xd9\x84\xd9\x8a\xd8\xa8\xd9\x8a\0" "Morocco\0" "\xd8\xa7\xd9\x84\xd9\x85\xd8\xba\xd8\xb1\xd8\xa8\0" "MAD\0" "Moroccan Dirham\0" "\xd8\xaf\xd8\xb1\xd9\x87\xd9\x85 \xd9\x85\xd8\xba\xd8\xb1\xd8\xa8\xd9\x8a\0" "MCO\0" "Monaco\0" "MNE\0" "Montenegro\0" "\xd0\xa6\xd1\x80\xd0\xbd\xd0\xb0 \xd0\x93\xd0\xbe\xd1\x80\xd0\xb0\0" "Evro\0" "MKD\0" "Macedonia\0" "\xd0\x9c\xd0\xb0\xd0\xba\xd0\xb5\xd0\xb4\xd0\xbe\xd0\xbd\xd0\xb8\xd1\x98\xd0\xb0\0" "Macedonian Denar\0" "\xd0\x9c\xd0\xb0\xd0\xba\xd0\xb5\xd0\xb4\xd0\xbe\xd0\xbd\xd1\x81\xd0\xba\xd0\xb8 \xd0\xb4\xd0\xb5\xd0\xbd\xd0\xb0\xd1\x80\0" "MAC\0" "Macau SAR China\0" "\xe4\xb8\xad\xe5\x9b\xbd\xe6\xbe\xb3\xe9\x97\xa8\xe7\x89\xb9\xe5\x88\xab\xe8\xa1\x8c\xe6\x94\xbf\xe5\x8c\xba\0" "MOP\0" "Macanese Pataca\0" "\xe6\xbe\xb3\xe9\x96\x80\xe5\x85\x83\0" "Malta\0" "Ewro\0" "MEX\0" "Mexico\0" "M\xc3\xa9xico\0" "MXN\0" "Mexican Peso\0" "peso mexicano\0" "NGA\0" "Nigeria\0" "Najeriya\0" "NGN\0" "Nigerian Naira\0" "Naira\0" "NIC\0" "Nicaragua\0" "NIO\0" "Nicaraguan C\xc3\xb3rdoba\0" "c\xc3\xb3rdoba nicarag\xc3\xbc\x65nse\0" "Netherlands\0" "Nederland\0" "Norway\0" "Norge\0" "NOK\0" "Norwegian Krone\0" "norske kroner\0" "NPL\0" "Nepal\0" "\xe0\xa4\xa8\xe0\xa5\x87\xe0\xa4\xaa\xe0\xa4\xbe\xe0\xa4\xb2\0" "NPR\0" "Nepalese Rupee\0" "\xe0\xa4\xa8\xe0\xa5\x87\xe0\xa4\xaa\xe0\xa4\xbe\xe0\xa4\xb2\xe0\xa5\x80 \xe0\xa4\xb0\xe0\xa5\x82\xe0\xa4\xaa\xe0\xa5\x88\xe0\xa4\xaf\xe0\xa4\xbe\xe0\xa4\x81\0" "NZL\0" "New Zealand\0" "NZD\0" "New Zealand Dollar\0" "OMN\0" "Oman\0" "\xd8\xb9\xd9\x8f\xd9\x85\xd8\xa7\xd9\x86\0" "OMR\0" "Omani Rial\0" "\xd8\xb1\xd9\x8a\xd8\xa7\xd9\x84 \xd8\xb9\xd9\x85\xd8\xa7\xd9\x86\xd9\x8a\0" "Panama\0" "Panam\xc3\xa1\0" "PAB\0" "Panamanian Balboa\0" "balboa paname\xc3\xb1o\0" "PER\0" "Peru\0" "Per\xc3\xba\0" "PEN\0" "Peruvian Nuevo Sol\0" "nuevo sol peruano\0" "PHL\0" "Philippines\0" "Pilipinas\0" "PHP\0" "Philippine Peso\0" "PAK\0" "Pakistan\0" "\xd9\xbe\xd8\xa7\xda\xa9\xd8\xb3\xd8\xaa\xd8\xa7\xd9\x86\0" "PKR\0" "Pakistani Rupee\0" "\xd9\xbe\xd8\xa7\xda\xa9\xd8\xb3\xd8\xaa\xd8\xa7\xd9\x86\xdb\x8c \xd8\xb1\xd9\x88\xd9\xbe\xdb\x8c\xdb\x81\0" "POL\0" "Poland\0" "Polska\0" "PLN\0" "Polish Zloty\0" "z\xc5\x82oty polski\0" "PRI\0" "Puerto Rico\0" "PRT\0" "Portugal\0" "PRY\0" "Paraguay\0" "PYG\0" "Paraguayan Guarani\0" "guaran\xc3\xad paraguayo\0" "QAT\0" "Qatar\0" "\xd9\x82\xd8\xb7\xd8\xb1\0" "QAR\0" "Qatari Rial\0" "\xd8\xb1\xd9\x8a\xd8\xa7\xd9\x84 \xd9\x82\xd8\xb7\xd8\xb1\xd9\x8a\0" "ROU\0" "Romania\0" "Rom\xc3\xa2nia\0" "RON\0" "Romanian Leu\0" "leu rom\xc3\xa2nesc\0" "Serbia\0" "\xd0\xa1\xd1\x80\xd0\xb1\xd0\xb8\xd1\x98\xd0\xb0\0" "RSD\0" "Serbian Dinar\0" "Srpski dinar\0" "Russia\0" "\xd0\xa0\xd0\xbe\xd1\x81\xd1\x81\xd0\xb8\xd1\x8f\0" "RUB\0" "Russian Ruble\0" "\xd0\xa0\xd0\xbe\xd1\x81\xd1\x81\xd0\xb8\xd0\xb9\xd1\x81\xd0\xba\xd0\xb8\xd0\xb9 \xd1\x80\xd1\x83\xd0\xb1\xd0\xbb\xd1\x8c\0" "RWA\0" "Rwanda\0" "RWF\0" "Rwandan Franc\0" "SAU\0" "Saudi Arabia\0" "\xd8\xa7\xd9\x84\xd9\x85\xd9\x85\xd9\x84\xd9\x83\xd8\xa9 \xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9 \xd8\xa7\xd9\x84\xd8\xb3\xd8\xb9\xd9\x88\xd8\xaf\xd9\x8a\xd8\xa9\0" "SAR\0" "Saudi Riyal\0" "\xd8\xb1\xd9\x8a\xd8\xa7\xd9\x84 \xd8\xb3\xd8\xb9\xd9\x88\xd8\xaf\xd9\x8a\0" "SWE\0" "Sweden\0" "Sverige\0" "SEK\0" "Swedish Krona\0" "svensk krona\0" "SGP\0" "Singapore\0" "\xe6\x96\xb0\xe5\x8a\xa0\xe5\x9d\xa1\0" "SGD\0" "Singapore Dollar\0" "\xe6\x96\xb0\xe5\x8a\xa0\xe5\x9d\xa1\xe5\x85\x83\0" "SVN\0" "Slovenia\0" "Slovenija\0" "evro\0" "SVK\0" "Slovakia\0" "Slovensko\0" "El Salvador\0" "SYR\0" "Syria\0" "\xd8\xb3\xd9\x88\xd8\xb1\xd9\x8a\xd8\xa7\0" "SYP\0" "Syrian Pound\0" "\xd9\x84\xd9\x8a\xd8\xb1\xd8\xa9 \xd8\xb3\xd9\x88\xd8\xb1\xd9\x8a\xd8\xa9\0" "Thailand\0" "THB\0" "Thai Baht\0" "\xe0\xb8\x9a\xe0\xb8\xb2\xe0\xb8\x97\xe0\xb9\x84\xe0\xb8\x97\xe0\xb8\xa2\0" "TJK\0" "Tajikistan\0" "\xd0\xa2\xd0\xbe\xd2\xb7\xd0\xb8\xd0\xba\xd0\xb8\xd1\x81\xd1\x82\xd0\xbe\xd0\xbd\0" "TJS\0" "Tajikistani Somoni\0" "\xd0\xa1\xd0\xbe\xd0\xbc\xd0\xbe\xd0\xbd\xd3\xa3\0" "TUN\0" "Tunisia\0" "\xd8\xaa\xd9\x88\xd9\x86\xd8\xb3\0" "TND\0" "Tunisian Dinar\0" "\xd8\xaf\xd9\x8a\xd9\x86\xd8\xa7\xd8\xb1\xd8\xaa\xd9\x88\xd9\x86\xd8\xb3\xd9\x8a\0" "TUR\0" "Turkey\0" "T\xc3\xbcrkiye\0" "TRY\0" "Turkish Lira\0" "T\xc3\xbcrk Liras\xc4\xb1\0" "TTO\0" "Trinidad and Tobago\0" "TTD\0" "Trinidad and Tobago Dollar\0" "TWN\0" "Taiwan\0" "\xe5\x8f\xb0\xe6\xb9\xbe\0" "TWD\0" "New Taiwan Dollar\0" "\xe6\x96\xb0\xe8\x87\xba\xe5\xb9\xa3\0" "Ukraine\0" "\xd0\xa3\xd0\xba\xd1\x80\xd0\xb0\xd1\x97\xd0\xbd\xd0\xb0\0" "UAH\0" "Ukrainian Hryvnia\0" "\xd1\x83\xd0\xba\xd1\x80\xd0\xb0\xd1\x97\xd0\xbd\xd1\x81\xd1\x8c\xd0\xba\xd0\xb0 \xd0\xb3\xd1\x80\xd0\xb8\xd0\xb2\xd0\xbd\xd1\x8f\0" "USA\0" "United States\0" "URY\0" "Uruguay\0" "UYU\0" "Uruguayan Peso\0" "peso uruguayo\0" "Uzbekistan\0" "O\xca\xbbzbekiston\0" "UZS\0" "Uzbekistan Som\0" "O\xca\xbbzbekiston so\xca\xbbm\0" "VEN\0" "Venezuela\0" "VEF\0" "Venezuelan Bol\xc3\xadvar\0" "bol\xc3\xadvar venezolano\0" "VNM\0" "Vietnam\0" "Vi\xe1\xbb\x87t Nam\0" "VND\0" "Vietnamese Dong\0" "\xc4\x90\xe1\xbb\x93ng Vi\xe1\xbb\x87t Nam\0" "YEM\0" "Yemen\0" "\xd8\xa7\xd9\x84\xd9\x8a\xd9\x85\xd9\x86\0" "YER\0" "Yemeni Rial\0" "\xd8\xb1\xd9\x8a\xd8\xa7\xd9\x84 \xd9\x8a\xd9\x85\xd9\x86\xd9\x8a\0" "ZAF\0" "South Africa\0" "ZAR\0" "South African Rand\0" "ZWE\0" "Zimbabwe\0" }; #endif #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Globalization/RegionInfo.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Globalization/CultureInfoInternals.h" #include "icalls/mscorlib/System.Globalization/CultureInfoTables.h" #include "icalls/mscorlib/System.Globalization/RegionInfo.h" #include "utils/StringUtils.h" #include "vm/String.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Globalization { static bool ConstructRegion(Il2CppRegionInfo* regionInfo, const RegionInfoEntry* ri) { #if NET_4_0 regionInfo->geo_id = ri->geo_id; #else regionInfo->region_id = ri->region_id; #endif IL2CPP_OBJECT_SETREF(regionInfo, iso2name, vm::String::New(idx2string(ri->iso2name))); IL2CPP_OBJECT_SETREF(regionInfo, iso3name, vm::String::New(idx2string(ri->iso3name))); IL2CPP_OBJECT_SETREF(regionInfo, win3name, vm::String::New(idx2string(ri->win3name))); IL2CPP_OBJECT_SETREF(regionInfo, english_name, vm::String::New(idx2string(ri->english_name))); IL2CPP_OBJECT_SETREF(regionInfo, currency_symbol, vm::String::New(idx2string(ri->currency_symbol))); IL2CPP_OBJECT_SETREF(regionInfo, iso_currency_symbol, vm::String::New(idx2string(ri->iso_currency_symbol))); IL2CPP_OBJECT_SETREF(regionInfo, currency_english_name, vm::String::New(idx2string(ri->currency_english_name))); return true; } static int RegionNameLocator(const void *a, const void *b) { const char* aa = (const char*)a; const RegionInfoNameEntry* bb = (const RegionInfoNameEntry*)b; return strcmp(aa, idx2string(bb->name)); } bool RegionInfo::construct_internal_region_from_name(Il2CppRegionInfo* regionInfo, Il2CppString* name) { std::string n = utils::StringUtils::Utf16ToUtf8(utils::StringUtils::GetChars(name)); RegionInfoNameEntry* nameEntry = (RegionInfoNameEntry*)bsearch(n.c_str(), region_name_entries, NUM_REGION_ENTRIES, sizeof(RegionInfoNameEntry), RegionNameLocator); if (nameEntry == NULL) return false; return ConstructRegion(regionInfo, ®ion_entries[nameEntry->region_entry_index]); } } /* namespace Globalization */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Globalization/RegionInfo.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Globalization { class LIBIL2CPP_CODEGEN_API RegionInfo { public: static bool construct_internal_region_from_name(Il2CppRegionInfo* regionInfo, Il2CppString* name); }; } /* namespace Globalization */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.IO/DriveInfo.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.IO/DriveInfo.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace IO { bool DriveInfo::GetDiskFreeSpaceInternal(Il2CppString* pathName, uint64_t* freeBytesAvail, uint64_t* totalNumberOfBytes, uint64_t* totalNumberOfFreeBytes, MonoIOError* error) { NOT_SUPPORTED_IL2CPP(DriveInfo::GetDiskFreeSpaceInternal, "This icall is not supported by il2cpp."); return false; } uint32_t DriveInfo::GetDriveTypeInternal(Il2CppString* rootPathName) { NOT_SUPPORTED_IL2CPP(DriveInfo::GetDriveTypeInternal, "This icall is not supported by il2cpp."); return 0; } #if NET_4_0 Il2CppString* DriveInfo::GetDriveFormat(Il2CppString* rootPathName) { NOT_IMPLEMENTED_ICALL(DriveInfo::GetDriveFormat); IL2CPP_UNREACHABLE; return NULL; } #endif } /* namespace IO */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.IO/DriveInfo.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; typedef int32_t MonoIOError; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace IO { class LIBIL2CPP_CODEGEN_API DriveInfo { public: static uint32_t GetDriveTypeInternal(Il2CppString* rootPathName); static bool GetDiskFreeSpaceInternal(Il2CppString* pathName, uint64_t* freeBytesAvail, uint64_t* totalNumberOfBytes, uint64_t* totalNumberOfFreeBytes, MonoIOError* error); #if NET_4_0 static Il2CppString* GetDriveFormat(Il2CppString* rootPathName); #endif }; } /* namespace IO */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.IO/MonoIO.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "icalls/mscorlib/System.IO/MonoIO.h" #include "os/Directory.h" #include "os/ErrorCodes.h" #include "os/File.h" #include "utils/PathUtils.h" #include "vm/Array.h" #include "vm/Class.h" #include "vm/Path.h" #include "vm/String.h" #include "vm/Exception.h" #include "utils/Memory.h" #include "utils/StringUtils.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace IO { Il2CppChar MonoIO::get_AltDirectorySeparatorChar(void) { #if IL2CPP_COMPILER_MSVC return '/'; /* forward slash */ #else return '/'; /* slash, same as DirectorySeparatorChar */ #endif } bool MonoIO::Close(Il2CppIntPtr handle, int *error) { il2cpp::os::FileHandle* fileHandle = (il2cpp::os::FileHandle*)handle.m_value; return il2cpp::os::File::Close(fileHandle, error); } bool MonoIO::CopyFile(Il2CppString *src, Il2CppString *dest, bool overwrite, int *error) { const std::string srcString(il2cpp::utils::StringUtils::Utf16ToUtf8(src->chars)); const std::string destString(il2cpp::utils::StringUtils::Utf16ToUtf8(dest->chars)); return il2cpp::os::File::CopyFile(srcString, destString, overwrite, error); } Il2CppIntPtr MonoIO::get_ConsoleError(void) { Il2CppIntPtr ret; ret.m_value = il2cpp::os::File::GetStdError(); return ret; } Il2CppIntPtr MonoIO::get_ConsoleInput(void) { Il2CppIntPtr ret; ret.m_value = il2cpp::os::File::GetStdInput(); return ret; } Il2CppIntPtr MonoIO::get_ConsoleOutput(void) { Il2CppIntPtr ret; ret.m_value = il2cpp::os::File::GetStdOutput(); return ret; } bool MonoIO::CreateDirectory(Il2CppString* path, int32_t* error) { return il2cpp::os::Directory::Create(il2cpp::utils::StringUtils::Utf16ToUtf8(path->chars), error); } bool MonoIO::DeleteFile(Il2CppString *path, int *error) { return il2cpp::os::File::DeleteFile(il2cpp::utils::StringUtils::Utf16ToUtf8(path->chars), error); } Il2CppChar MonoIO::get_DirectorySeparatorChar(void) { return IL2CPP_DIR_SEPARATOR; } Il2CppString * MonoIO::GetCurrentDirectory(int *error) { return vm::String::New(il2cpp::os::Directory::GetCurrent(error).c_str()); } int MonoIO::GetFileAttributes(Il2CppString* path, int* error) { return il2cpp::os::File::GetFileAttributes(il2cpp::utils::StringUtils::Utf16ToUtf8(path->chars), error); } bool MonoIO::GetFileStat(Il2CppString* path, FileStat * stat, int32_t* error) { os::FileStat fileStat; const bool ret = il2cpp::os::File::GetFileStat(il2cpp::utils::StringUtils::Utf16ToUtf8(path->chars), &fileStat, error); if (ret) { #if !NET_4_0 stat->name = vm::String::New(fileStat.name.c_str()); #endif stat->attributes = fileStat.attributes; stat->length = fileStat.length; stat->creation_time = fileStat.creation_time; stat->last_access_time = fileStat.last_access_time; stat->last_write_time = fileStat.last_write_time; } return ret; } int MonoIO::GetFileType(Il2CppIntPtr handle, int *error) { il2cpp::os::FileHandle* h = (il2cpp::os::FileHandle*)handle.m_value; return il2cpp::os::File::GetFileType(h); } int64_t MonoIO::GetLength(Il2CppIntPtr handle, int *error) { il2cpp::os::FileHandle* h = (il2cpp::os::FileHandle*)handle.m_value; return il2cpp::os::File::GetLength(h, error); } Il2CppIntPtr MonoIO::Open(Il2CppString *filename, int mode, int access_mode, int share, int options, int *error) { Il2CppIntPtr ret; ret.m_value = il2cpp::os::File::Open(il2cpp::utils::StringUtils::Utf16ToUtf8(filename->chars), mode, access_mode, share, options, error); return ret; } Il2CppChar MonoIO::get_PathSeparator(void) { #if IL2CPP_COMPILER_MSVC return ';'; /* semicolon */ #else return ':'; /* colon */ #endif } int MonoIO::Read(Il2CppIntPtr handle, Il2CppArray *dest, int dest_offset, int count, int *error) { IL2CPP_ASSERT(dest != NULL); *error = 0; // ERROR_SUCCESS if (((uint32_t)dest_offset + count) > il2cpp::vm::Array::GetLength(dest)) return 0; il2cpp::os::FileHandle* h = (il2cpp::os::FileHandle*)handle.m_value; char *buffer = il2cpp_array_addr(dest, char, dest_offset); return il2cpp::os::File::Read(h, buffer, count, error); } bool MonoIO::SetCurrentDirectory(Il2CppString* path, int* error) { return il2cpp::os::Directory::SetCurrent(il2cpp::utils::StringUtils::Utf16ToUtf8(path->chars), error); } bool MonoIO::SetLength(Il2CppIntPtr handle, int64_t length, int *error) { il2cpp::os::FileHandle* fileHandle = (il2cpp::os::FileHandle*)handle.m_value; return il2cpp::os::File::SetLength(fileHandle, length, error); } int64_t MonoIO::Seek(Il2CppIntPtr handle, int64_t offset, int origin, int *error) { il2cpp::os::FileHandle* fileHandle = (il2cpp::os::FileHandle*)handle.m_value; return il2cpp::os::File::Seek(fileHandle, offset, origin, error); } int MonoIO::Write(Il2CppIntPtr handle, Il2CppArray * src, int src_offset, int count, int * error) { IL2CPP_ASSERT(src != NULL); *error = 0; // ERROR_SUCCESS if ((uint32_t)(src_offset + count) > il2cpp::vm::Array::GetLength(src)) return 0; il2cpp::os::FileHandle* h = (il2cpp::os::FileHandle*)handle.m_value; char *buffer = il2cpp_array_addr(src, char, src_offset); return il2cpp::os::File::Write(h, buffer, count, error); } Il2CppChar MonoIO::get_VolumeSeparatorChar(void) { #if IL2CPP_COMPILER_MSVC return ':'; /* colon */ #else return '/'; /* forward slash */ #endif } bool MonoIO::RemoveDirectory(Il2CppString* path, MonoIOError* error) { return il2cpp::os::Directory::Remove(il2cpp::utils::StringUtils::Utf16ToUtf8(path->chars), error); } Il2CppArray* MonoIO::GetFileSystemEntries(Il2CppString* path, Il2CppString* path_with_pattern, int32_t attrs, int32_t mask, MonoIOError* error) { const std::string pathString(il2cpp::utils::StringUtils::Utf16ToUtf8(path->chars)); const std::string pathPatternString(il2cpp::utils::StringUtils::Utf16ToUtf8(path_with_pattern->chars)); const std::set entries(il2cpp::os::Directory::GetFileSystemEntries(pathString, pathPatternString, attrs, mask, error)); Il2CppClass *klass = il2cpp::vm::Class::GetArrayClass(il2cpp_defaults.string_class, 1); Il2CppArray* array = (Il2CppArray*)il2cpp::vm::Array::NewSpecific(klass, (il2cpp_array_size_t)entries.size()); size_t index = 0; for (std::set::const_iterator entry = entries.begin(), end = entries.end(); entry != end; ++entry) il2cpp_array_setref(array, index++, il2cpp::vm::String::New(entry->c_str())); return array; } bool MonoIO::MoveFile(Il2CppString* src, Il2CppString* dest, MonoIOError* error) { const std::string srcString(il2cpp::utils::StringUtils::Utf16ToUtf8(src->chars)); const std::string destString(il2cpp::utils::StringUtils::Utf16ToUtf8(dest->chars)); return il2cpp::os::File::MoveFile(srcString, destString, error); } bool MonoIO::ReplaceFile(Il2CppString* sourceFileName, Il2CppString* destinationFileName, Il2CppString* destinationBackupFileName, bool ignoreMetadataErrors, MonoIOError* error) { const std::string srcString(il2cpp::utils::StringUtils::Utf16ToUtf8(sourceFileName->chars)); const std::string destString(il2cpp::utils::StringUtils::Utf16ToUtf8(destinationFileName->chars)); const std::string destBackupString(destinationBackupFileName ? il2cpp::utils::StringUtils::Utf16ToUtf8(destinationBackupFileName->chars) : ""); return il2cpp::os::File::ReplaceFile(srcString, destString, destBackupString, ignoreMetadataErrors, error); } bool MonoIO::SetFileAttributes(Il2CppString* path, FileAttributes attrs, MonoIOError* error) { return il2cpp::os::File::SetFileAttributes(il2cpp::utils::StringUtils::Utf16ToUtf8(path->chars), (UnityPalFileAttributes)attrs, error); } bool MonoIO::Flush(Il2CppIntPtr handle, MonoIOError* error) { il2cpp::os::FileHandle* fileHandle = (il2cpp::os::FileHandle*)handle.m_value; return il2cpp::os::File::Flush(fileHandle, error); } bool MonoIO::SetFileTime(Il2CppIntPtr handle, int64_t creation_time, int64_t last_access_time, int64_t last_write_time, MonoIOError* error) { il2cpp::os::FileHandle* fileHandle = (il2cpp::os::FileHandle*)handle.m_value; return il2cpp::os::File::SetFileTime(fileHandle, creation_time, last_access_time, last_write_time, error); } void MonoIO::Lock(Il2CppIntPtr handle, int64_t position, int64_t length, MonoIOError* error) { il2cpp::os::FileHandle* fileHandle = (il2cpp::os::FileHandle*)handle.m_value; return il2cpp::os::File::Lock(fileHandle, position, length, error); } void MonoIO::Unlock(Il2CppIntPtr handle, int64_t position, int64_t length, MonoIOError* error) { il2cpp::os::FileHandle* fileHandle = (il2cpp::os::FileHandle*)handle.m_value; return il2cpp::os::File::Unlock(fileHandle, position, length, error); } bool MonoIO::CreatePipe(Il2CppIntPtr* read_handle, Il2CppIntPtr* write_handle) { MonoIOError error; return CreatePipe40(read_handle, write_handle, &error); } bool MonoIO::DuplicateHandle(Il2CppIntPtr source_process_handle, Il2CppIntPtr source_handle, Il2CppIntPtr target_process_handle, Il2CppIntPtr* target_handle, int32_t access, int32_t inherit, int32_t options) { MonoIOError error; return DuplicateHandle40(source_process_handle, source_handle, target_process_handle, target_handle, access, inherit, options, &error); } // This is never called from Mono. int32_t MonoIO::GetTempPath(Il2CppString** path) { const std::string tempPath(il2cpp::vm::Path::GetTempPath()); *path = vm::String::New(tempPath.c_str()); return utils::StringUtils::GetLength(*path); } bool MonoIO::CreatePipe40(Il2CppIntPtr* read_handle, Il2CppIntPtr* write_handle, MonoIOError* error) { il2cpp::os::FileHandle** input = (il2cpp::os::FileHandle**)&read_handle->m_value; il2cpp::os::FileHandle** output = (il2cpp::os::FileHandle**)&write_handle->m_value; #if IL2CPP_TARGET_WINRT || IL2CPP_TARGET_XBOXONE vm::Exception::Raise(vm::Exception::GetNotSupportedException("Pipes are not supported on WinRT based platforms.")); #else return il2cpp::os::File::CreatePipe(input, output, error); #endif } bool MonoIO::DuplicateHandle40(Il2CppIntPtr source_process_handle, Il2CppIntPtr source_handle, Il2CppIntPtr target_process_handle, Il2CppIntPtr* target_handle, int32_t access, int32_t inherit, int32_t options, MonoIOError* error) { il2cpp::os::FileHandle* spHandle = (il2cpp::os::FileHandle*)source_process_handle.m_value; il2cpp::os::FileHandle* sHandle = (il2cpp::os::FileHandle*)source_handle.m_value; il2cpp::os::FileHandle* tpHandle = (il2cpp::os::FileHandle*)target_process_handle.m_value; il2cpp::os::FileHandle** tHandle = (il2cpp::os::FileHandle**)&target_handle->m_value; return il2cpp::os::File::DuplicateHandle(spHandle, sHandle, tpHandle, tHandle, access, inherit, options, error); } bool MonoIO::RemapPath(Il2CppString* path, Il2CppString** newPath) { *newPath = NULL; return false; } #if NET_4_0 static int32_t CloseFindHandle(os::Directory::FindHandle* findHandle) { int32_t result = findHandle->CloseOSHandle(); findHandle->~FindHandle(); utils::Memory::Free(findHandle); return result; } int32_t MonoIO::FindClose(Il2CppIntPtr handle) { return CloseFindHandle(static_cast(handle.m_value)); } Il2CppString* PrepareFindResult(os::Directory::FindHandle* findHandle, Il2CppNativeString& fileName, int32_t* resultAttributes, MonoIOError* error) { while (fileName.empty() || fileName == IL2CPP_NATIVE_STRING(".") || fileName == IL2CPP_NATIVE_STRING("..")) { os::ErrorCode findError = os::Directory::FindNextFile(findHandle, &fileName, resultAttributes); if (findError != os::kErrorCodeSuccess) { if (findError != os::kErrorCodeNoMoreFiles) *error = findError; return NULL; } } // Convert file name to UTF16 DECLARE_NATIVE_STRING_AS_STRING_VIEW_OF_IL2CPP_CHARS(fileNameIl2CppChars, fileName); DECLARE_NATIVE_STRING_AS_STRING_VIEW_OF_IL2CPP_CHARS(directoryNameIl2CppChars, findHandle->directoryPath); // Allocate result string Il2CppString* result = vm::String::NewSize(static_cast(directoryNameIl2CppChars.Length() + fileNameIl2CppChars.Length() + 1)); Il2CppChar* targetBuffer = utils::StringUtils::GetChars(result); // Copy in directory name memcpy(targetBuffer, directoryNameIl2CppChars.Str(), sizeof(Il2CppChar) * directoryNameIl2CppChars.Length()); // Copy in directory separator targetBuffer[directoryNameIl2CppChars.Length()] = IL2CPP_DIR_SEPARATOR; // Copy in file name memcpy(targetBuffer + directoryNameIl2CppChars.Length() + 1, fileNameIl2CppChars.Str(), sizeof(Il2CppChar) * fileNameIl2CppChars.Length()); *error = os::kErrorCodeSuccess; return result; } Il2CppString* MonoIO::FindFirst(Il2CppString* path, Il2CppString* pathWithPattern, int32_t* resultAttributes, MonoIOError* error, Il2CppIntPtr* handle) { DECLARE_IL2CPP_STRING_AS_STRING_VIEW_OF_NATIVE_CHARS(pathWithPatternNative, pathWithPattern); os::Directory::FindHandle* findHandle = new(utils::Memory::Malloc(sizeof(os::Directory::FindHandle))) os::Directory::FindHandle(pathWithPatternNative); Il2CppNativeString fileName; os::ErrorCode findError = os::Directory::FindFirstFile(findHandle, pathWithPatternNative, &fileName, resultAttributes); if (findError != os::kErrorCodeSuccess) { // mscorlib expects no error if we didn't find any files if (findError != os::kErrorCodeFileNotFound && findError != os::kErrorCodeNoMoreFiles) *error = findError; return NULL; } handle->m_value = findHandle; Il2CppString* result = PrepareFindResult(findHandle, fileName, resultAttributes, error); if (result == NULL) { handle->m_value = NULL; CloseFindHandle(findHandle); } return result; } Il2CppString* MonoIO::FindNext(Il2CppIntPtr handle, int32_t* resultAttributes, MonoIOError* error) { Il2CppNativeString fileName; os::Directory::FindHandle* findHandle = static_cast(handle.m_value); return PrepareFindResult(findHandle, fileName, resultAttributes, error); } void MonoIO::DumpHandles() { NOT_IMPLEMENTED_ICALL(MonoIO::DumpHandles); IL2CPP_UNREACHABLE; } #endif } /* namespace IO */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.IO/MonoIO.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppArray; struct Il2CppString; typedef int32_t MonoIOError; typedef int32_t FileAttributes; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace IO { struct FileStat { #if !NET_4_0 Il2CppString *name; #endif int32_t attributes; int64_t length; int64_t creation_time; int64_t last_access_time; int64_t last_write_time; }; class LIBIL2CPP_CODEGEN_API MonoIO { public: static bool Close(Il2CppIntPtr handle, int *error); static bool CopyFile(Il2CppString* src, Il2CppString* dest, bool overwrite, MonoIOError* error); static bool CreateDirectory(Il2CppString* path, MonoIOError* error); static bool CreatePipe(Il2CppIntPtr* read_handle, Il2CppIntPtr* write_handle); static bool DeleteFile(Il2CppString* path, MonoIOError* error); static bool DuplicateHandle(Il2CppIntPtr source_process_handle, Il2CppIntPtr source_handle, Il2CppIntPtr target_process_handle, Il2CppIntPtr* target_handle, int32_t access, int32_t inherit, int32_t options); static bool Flush(Il2CppIntPtr handle, MonoIOError* error); static Il2CppString* GetCurrentDirectory(MonoIOError* error); static FileAttributes GetFileAttributes(Il2CppString* path, MonoIOError* error); static bool GetFileStat(Il2CppString* path, FileStat * stat, int32_t* error); static Il2CppArray* GetFileSystemEntries(Il2CppString* path, Il2CppString* path_with_pattern, int32_t attrs, int32_t mask, MonoIOError* error); static int GetFileType(Il2CppIntPtr handle, int *error); static int64_t GetLength(Il2CppIntPtr handle, int *error); static int32_t GetTempPath(Il2CppString** path); static void Lock(Il2CppIntPtr handle, int64_t position, int64_t length, MonoIOError* error); static bool MoveFile(Il2CppString* src, Il2CppString* dest, MonoIOError* error); static Il2CppIntPtr Open(Il2CppString *filename, int mode, int access_mode, int share, int options, int *error); static int Read(Il2CppIntPtr handle, Il2CppArray *dest, int dest_offset, int count, int *error); static bool RemoveDirectory(Il2CppString* path, MonoIOError* error); static bool ReplaceFile(Il2CppString* sourceFileName, Il2CppString* destinationFileName, Il2CppString* destinationBackupFileName, bool ignoreMetadataErrors, MonoIOError* error); static int64_t Seek(Il2CppIntPtr handle, int64_t offset, int origin, int *error); static bool SetCurrentDirectory(Il2CppString* path, int* error); static bool SetFileAttributes(Il2CppString* path, FileAttributes attrs, MonoIOError* error); static bool SetFileTime(Il2CppIntPtr handle, int64_t creation_time, int64_t last_access_time, int64_t last_write_time, MonoIOError* error); static bool SetLength(Il2CppIntPtr handle, int64_t length, int *error); static void Unlock(Il2CppIntPtr handle, int64_t position, int64_t length, MonoIOError* error); static int Write(Il2CppIntPtr handle, Il2CppArray * src, int src_offset, int count, int * error); static Il2CppChar get_AltDirectorySeparatorChar(void); static Il2CppIntPtr get_ConsoleError(void); static Il2CppIntPtr get_ConsoleInput(void); static Il2CppIntPtr get_ConsoleOutput(void); static Il2CppChar get_DirectorySeparatorChar(void); static Il2CppChar get_PathSeparator(void); static Il2CppChar get_VolumeSeparatorChar(void); static bool CreatePipe40(Il2CppIntPtr* read_handle, Il2CppIntPtr* write_handle, MonoIOError* error); static bool DuplicateHandle40(Il2CppIntPtr source_process_handle, Il2CppIntPtr source_handle, Il2CppIntPtr target_process_handle, Il2CppIntPtr* target_handle, int32_t access, int32_t inherit, int32_t options, MonoIOError* error); static bool RemapPath(Il2CppString* path, Il2CppString** newPath); #if NET_4_0 static int32_t FindClose(Il2CppIntPtr handle); static Il2CppString* FindFirst(Il2CppString* path, Il2CppString* pathWithPattern, int32_t* resultAttributes, MonoIOError* error, Il2CppIntPtr* handle); static Il2CppString* FindNext(Il2CppIntPtr handle, int32_t* result_attr, MonoIOError* error); static void DumpHandles(); #endif }; } /* namespace IO */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.IO/Path.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.IO/Path.h" #include "vm/Path.h" #include "vm/String.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace IO { Il2CppString* Path::get_temp_path() { return il2cpp::vm::String::New(il2cpp::vm::Path::GetTempPath().c_str()); } } /* namespace IO */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.IO/Path.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace IO { class LIBIL2CPP_CODEGEN_API Path { public: static Il2CppString* get_temp_path(); }; } /* namespace IO */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/Assembly.cpp ================================================ #include "il2cpp-config.h" #include #include #include #include "icalls/mscorlib/System.Reflection/Assembly.h" #include "icalls/mscorlib/System.Reflection/Module.h" #include "utils/StringUtils.h" #include "utils/PathUtils.h" #include "os/File.h" #include "os/MemoryMappedFile.h" #include "os/Mutex.h" #include "os/Path.h" #include "utils/Memory.h" #include "utils/Runtime.h" #include "vm/Array.h" #include "vm/Assembly.h" #include "vm/AssemblyName.h" #include "vm/Class.h" #include "vm/Exception.h" #include "vm/Field.h" #include "vm/Image.h" #include "vm/MetadataCache.h" #include "vm/Object.h" #include "vm/Reflection.h" #include "vm/Runtime.h" #include "vm/String.h" #include "vm/Type.h" #include "vm/Array.h" #include "class-internals.h" #include using namespace il2cpp::vm; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { Il2CppString* Assembly::get_fullname(Il2CppReflectionAssembly *assembly) { return vm::String::New(vm::AssemblyName::AssemblyNameToString(assembly->assembly->aname).c_str()); } Il2CppString* Assembly::get_location(Il2CppReflectionAssembly *assembly) { NOT_IMPLEMENTED_ICALL_NO_ASSERT(Assembly::get_location, "Assembly::get_location is not functional on il2cpp"); return vm::String::New(""); } Il2CppReflectionAssembly* Assembly::GetEntryAssembly() { NOT_IMPLEMENTED_ICALL_NO_ASSERT(Assembly::GetEntryAssembly, "In the case of Unity this is always NULL. For a normal exe this is the assembly with Main."); return NULL; } Il2CppReflectionAssembly* Assembly::GetExecutingAssembly() { return vm::Reflection::GetAssemblyObject(MetadataCache::GetAssemblyFromIndex(vm::Image::GetExecutingImage()->assemblyIndex)); } #define CHECK_IF_NULL(v) \ if ( (v) == NULL && throwOnError ) \ Exception::Raise (Exception::GetTypeLoadException ()); \ if ( (v) == NULL ) \ return NULL; Il2CppReflectionType* Assembly::InternalGetType(Il2CppReflectionAssembly *assembly, mscorlib_System_Reflection_Module *, Il2CppString* name, bool throwOnError, bool ignoreCase) { std::string str = utils::StringUtils::Utf16ToUtf8(utils::StringUtils::GetChars(name)); il2cpp::vm::TypeNameParseInfo info; il2cpp::vm::TypeNameParser parser(str, info, false); if (!parser.Parse()) { if (throwOnError) Exception::Raise(Exception::GetTypeLoadException()); else return NULL; } CHECK_IF_NULL(assembly); Il2CppImage *image = (Il2CppImage*)vm::Assembly::GetImage(assembly->assembly); CHECK_IF_NULL(image); Il2CppClass *klass = Image::FromTypeNameParseInfo(image, info, ignoreCase); CHECK_IF_NULL(klass); il2cpp::vm::Class::Init(klass); const Il2CppType *type = Class::GetType(klass, info); CHECK_IF_NULL(type); return il2cpp::vm::Reflection::GetTypeObject(type); } Il2CppReflectionAssembly* Assembly::load_with_partial_name(Il2CppString* name, mscorlib_System_Security_Policy_Evidence* evidence) { const Il2CppAssembly* assembly = vm::Assembly::GetLoadedAssembly(il2cpp::utils::StringUtils::Utf16ToUtf8(name->chars).c_str()); if (assembly != NULL) return vm::Reflection::GetAssemblyObject(assembly); return NULL; } void Assembly::FillName(Il2CppReflectionAssembly * ass, mscorlib_System_Reflection_AssemblyName * aname) { Il2CppObject* assemblyNameObject = reinterpret_cast(aname); Il2CppClass* assemblyNameType = assemblyNameObject->klass; const Il2CppAssemblyName* assemblyName = &ass->assembly->aname; // System.Reflection.AssemblyName is not protected from stripping. Since this call will be used // very rarely, instead of including that type to stripper excludes, let's instead set fields only // if they're there. FieldInfo* assemblyNameField = Class::GetFieldFromName(assemblyNameType, "name"); FieldInfo* codebaseField = Class::GetFieldFromName(assemblyNameType, "codebase"); if (assemblyNameField != NULL) Field::SetValue(assemblyNameObject, assemblyNameField, String::New(MetadataCache::GetStringFromIndex(assemblyName->nameIndex))); if (codebaseField != NULL) Field::SetValue(assemblyNameObject, codebaseField, get_code_base(ass, false)); FieldInfo* field = Class::GetFieldFromName(assemblyNameType, "major"); if (field != NULL) { int32_t major = assemblyName->major; Field::SetValue(assemblyNameObject, field, &major); } field = Class::GetFieldFromName(assemblyNameType, "minor"); if (field != NULL) { int32_t minor = assemblyName->minor; Field::SetValue(assemblyNameObject, field, &minor); } field = Class::GetFieldFromName(assemblyNameType, "build"); if (field != NULL) { int32_t build = assemblyName->build; Field::SetValue(assemblyNameObject, field, &build); } field = Class::GetFieldFromName(assemblyNameType, "revision"); if (field != NULL) { int32_t revision = assemblyName->revision; Field::SetValue(assemblyNameObject, field, &revision); } field = Class::GetFieldFromName(assemblyNameType, "cultureinfo"); if (field != NULL) { Il2CppClass* cultureInfoType = Class::FromIl2CppType(field->type); FieldInfo* invariantCultureField = Class::GetFieldFromName(cultureInfoType, "invariant_culture_info"); Il2CppObject* invariantCulture = NULL; if (invariantCultureField != NULL) Field::StaticGetValue(invariantCultureField, &invariantCulture); Field::SetValue(assemblyNameObject, field, invariantCulture); } field = Class::GetFieldFromName(assemblyNameType, "flags"); if (field != NULL) Field::SetValue(assemblyNameObject, field, const_cast((const void*)&assemblyName->flags)); field = Class::GetFieldFromName(assemblyNameType, "hashalg"); if (field != NULL) Field::SetValue(assemblyNameObject, field, const_cast((const void*)&assemblyName->hash_alg)); field = Class::GetFieldFromName(assemblyNameType, "keypair"); if (field != NULL) Field::SetValue(assemblyNameObject, field, NULL); field = Class::GetFieldFromName(assemblyNameType, "publicKey"); if (field != NULL) Field::SetValue(assemblyNameObject, field, Array::New(il2cpp_defaults.byte_class, 0)); field = Class::GetFieldFromName(assemblyNameType, "keyToken"); if (field != NULL) { Il2CppArray* keyTokenManaged = NULL; // Set it to non-null only if public key token is not all zeroes for (int i = 0; i < kPublicKeyByteLength; i++) { if (assemblyName->publicKeyToken[i] != 0) { keyTokenManaged = Array::New(il2cpp_defaults.byte_class, kPublicKeyByteLength); memcpy(il2cpp::vm::Array::GetFirstElementAddress(keyTokenManaged), assemblyName->publicKeyToken, kPublicKeyByteLength); break; } } Field::SetValue(assemblyNameObject, field, keyTokenManaged); } field = Class::GetFieldFromName(assemblyNameType, "versioncompat"); if (field != NULL) { int32_t kSameProcess = 2; Field::SetValue(assemblyNameObject, field, &kSameProcess); } field = Class::GetFieldFromName(assemblyNameType, "version"); if (field != NULL) { Il2CppClass* versionType = Class::FromIl2CppType(field->type); Il2CppObject* version = Object::New(versionType); FieldInfo* versionField = Class::GetFieldFromName(versionType, "_Major"); if (versionField != NULL) { int32_t major = assemblyName->major; Field::SetValue(version, versionField, &major); } versionField = Class::GetFieldFromName(versionType, "_Minor"); if (versionField != NULL) { int32_t minor = assemblyName->minor; Field::SetValue(version, versionField, &minor); } versionField = Class::GetFieldFromName(versionType, "_Build"); if (versionField != NULL) { int32_t build = assemblyName->build; Field::SetValue(version, versionField, &build); } versionField = Class::GetFieldFromName(versionType, "_Revision"); if (versionField != NULL) { int32_t revision = assemblyName->revision; Field::SetValue(version, versionField, &revision); } Field::SetValue(assemblyNameObject, field, version); } field = Class::GetFieldFromName(assemblyNameType, "processor_architecture"); if (field != NULL) { int32_t kMSILArchitecture = 1; Field::SetValue(assemblyNameObject, field, &kMSILArchitecture); } } Il2CppArray* Assembly::GetModulesInternal(Il2CppReflectionAssembly * thisPtr) { Il2CppArray* arr = vm::Array::New(il2cpp_defaults.module_class, 1); il2cpp_array_setref(arr, 0, vm::Reflection::GetModuleObject(vm::Assembly::GetImage(thisPtr->assembly))); return arr; } bool Assembly::LoadPermissions(mscorlib_System_Reflection_Assembly * a, Il2CppIntPtr* minimum, int32_t* minLength, Il2CppIntPtr* optional, int32_t* optLength, Il2CppIntPtr* refused, int32_t* refLength) { NOT_IMPLEMENTED_ICALL(Assembly::LoadPermissions); return false; } Il2CppReflectionAssembly* Assembly::GetCallingAssembly() { return vm::Reflection::GetAssemblyObject(MetadataCache::GetAssemblyFromIndex(Image::GetCallingImage()->assemblyIndex)); } Il2CppString* Assembly::get_code_base(Il2CppReflectionAssembly * assembly, bool escaped) { std::string executableDirectory = utils::PathUtils::DirectoryName(os::Path::GetExecutablePath()); std::replace(executableDirectory.begin(), executableDirectory.end(), '\\', '/'); return vm::String::New(utils::StringUtils::Printf("file://%s/%s.dll", executableDirectory.c_str(), MetadataCache::GetStringFromIndex(assembly->assembly->aname.nameIndex)).c_str()); } Il2CppArray* Assembly::GetTypes(Il2CppReflectionAssembly* thisPtr, bool exportedOnly) { const Il2CppImage* image = MetadataCache::GetImageFromIndex(thisPtr->assembly->imageIndex); return Module::InternalGetTypes(vm::Reflection::GetModuleObject(image)); } Il2CppString* Assembly::InternalImageRuntimeVersion(Il2CppAssembly* self) { NOT_SUPPORTED_IL2CPP(Assembly::InternalImageRuntimeVersion, "This icall is not supported by il2cpp."); return 0; } Il2CppReflectionMethod* Assembly::get_EntryPoint(Il2CppReflectionAssembly* self) { const MethodInfo* method = Image::GetEntryPoint(MetadataCache::GetImageFromIndex(self->assembly->imageIndex)); if (method == NULL) return NULL; return il2cpp::vm::Reflection::GetMethodObject(method, NULL); } bool Assembly::get_global_assembly_cache(Il2CppAssembly* self) { return false; } Il2CppObject* Assembly::GetFilesInternal(Il2CppAssembly* self, Il2CppString* name, bool getResourceModules) { // Some code paths in mscorlib (e.g. Encoding.GetEncoding) will expect this icall to return NULL. If it // instead throws a NotSupportedException, the mscorlib code path changes, and we see some IL2CPP-specific bugs. return NULL; } void Assembly::InternalGetAssemblyName(Il2CppString* assemblyFile, Il2CppAssemblyName* aname) { NOT_SUPPORTED_IL2CPP(Assembly::InternalGetAssemblyName, "This icall is not supported by il2cpp."); } Il2CppReflectionAssembly* Assembly::LoadFrom(Il2CppString* assemblyFile, bool refonly) { assert(!refonly && "This icall is not supported by il2cpp when refonly=true"); // Our implementation is going to behave a bit different. We can't actually load any assembly. If we didn't know about the assembly at conversion time, // then we won't be able to do anything. // On the other hand, if the name of the assembly matches the name of an assembly that we converted, then lets return the assembly that we know about. std::string utf8Path = utils::StringUtils::Utf16ToUtf8(utils::StringUtils::GetChars(assemblyFile)); std::string fileName = utils::PathUtils::BasenameNoExtension(utf8Path); const Il2CppAssembly* foundAssembly = MetadataCache::GetAssemblyByName(fileName); if (!foundAssembly) { vm::Exception::Raise(vm::Exception::GetFileLoadException(fileName.c_str())); IL2CPP_UNREACHABLE; } return vm::Reflection::GetAssemblyObject(foundAssembly); } Il2CppArray* Assembly::GetNamespaces(Il2CppAssembly* self) { NOT_SUPPORTED_IL2CPP(Assembly::GetNamespaces, "This icall is not supported by il2cpp."); return 0; } Il2CppArray* Assembly::GetReferencedAssemblies(Il2CppReflectionAssembly* self) { vm::AssemblyNameVector referencedAssemblies; vm::Assembly::GetReferencedAssemblies(self->assembly, &referencedAssemblies); Il2CppArray* result = Array::New(il2cpp_defaults.assembly_name_class, (il2cpp_array_size_t)referencedAssemblies.size()); size_t index = 0; for (vm::AssemblyNameVector::const_iterator aname = referencedAssemblies.begin(); aname != referencedAssemblies.end(); ++aname) { Il2CppReflectionAssemblyName* reflectionAssemblyName = vm::Reflection::GetAssemblyNameObject(*aname); il2cpp_array_set(result, Il2CppReflectionAssemblyName*, index, reflectionAssemblyName); index++; } return result; } static void* LoadResourceFile(Il2CppReflectionAssembly* assembly) { std::string resourcesDirectory = utils::PathUtils::Combine(utils::Runtime::GetDataDir(), utils::StringView("Resources")); std::string resourceFileName(MetadataCache::GetImageFromIndex(assembly->assembly->imageIndex)->name); resourceFileName += "-resources.dat"; std::string resourceFilePath = utils::PathUtils::Combine(resourcesDirectory, resourceFileName); int error = 0; os::FileHandle* handle = os::File::Open(resourceFilePath, kFileModeOpen, kFileAccessRead, kFileShareRead, kFileOptionsNone, &error); if (error != 0) return NULL; void* fileBuffer = os::MemoryMappedFile::Map(handle); os::File::Close(handle, &error); if (error != 0) { os::MemoryMappedFile::Unmap(fileBuffer); fileBuffer = NULL; return NULL; } return fileBuffer; } static os::Mutex s_ResourceDataMutex; static void* LoadResourceData(Il2CppReflectionAssembly* assembly, EmbeddedResourceRecord record) { os::AutoLock lock(&s_ResourceDataMutex); void* resourceData = vm::Image::GetCachedResourceData(record.image, record.name); if (resourceData != NULL) return resourceData; void* fileBuffer = vm::Image::GetCachedMemoryMappedResourceFile(assembly); if (fileBuffer == NULL) { fileBuffer = LoadResourceFile(assembly); if (fileBuffer == NULL) return NULL; vm::Image::CacheMemoryMappedResourceFile(assembly, fileBuffer); } resourceData = (uint8_t*)fileBuffer + record.offset; vm::Image::CacheResourceData(record, resourceData); return resourceData; } static int ReadFromBuffer(uint8_t* buffer, int offset, int size, void* output) { memcpy(output, buffer + offset, size); return size; } static std::vector GetResourceRecords(Il2CppReflectionAssembly* assembly) { std::vector resourceRecords; void* fileBuffer = vm::Image::GetCachedMemoryMappedResourceFile(assembly); if (fileBuffer == NULL) { fileBuffer = LoadResourceFile(assembly); if (fileBuffer == NULL) return resourceRecords; vm::Image::CacheMemoryMappedResourceFile(assembly, fileBuffer); } int32_t resourceRecordsSize = 0; uint32_t bytesRead = ReadFromBuffer((uint8_t*)fileBuffer, 0, sizeof(int32_t), &resourceRecordsSize); int32_t currentResourceDataOffset = bytesRead + resourceRecordsSize; int32_t numberOfResources = 0; bytesRead += ReadFromBuffer((uint8_t*)fileBuffer, bytesRead, sizeof(int32_t), &numberOfResources); for (int resourceIndex = 0; resourceIndex < numberOfResources; ++resourceIndex) { uint32_t resourceDataSize = 0; bytesRead += ReadFromBuffer((uint8_t*)fileBuffer, bytesRead, sizeof(int32_t), &resourceDataSize); int32_t resourceNameSize = 0; bytesRead += ReadFromBuffer((uint8_t*)fileBuffer, bytesRead, sizeof(int32_t), &resourceNameSize); std::vector resourceName(resourceNameSize); bytesRead += ReadFromBuffer((uint8_t*)fileBuffer, bytesRead, resourceNameSize, &resourceName[0]); resourceRecords.push_back(EmbeddedResourceRecord(MetadataCache::GetImageFromIndex(assembly->assembly->imageIndex), std::string(resourceName.begin(), resourceName.end()), currentResourceDataOffset, resourceDataSize)); currentResourceDataOffset += resourceDataSize; } return resourceRecords; } Il2CppArray* Assembly::GetManifestResourceNames(Il2CppReflectionAssembly* assembly) { std::vector resourceRecords = GetResourceRecords(assembly); IL2CPP_ASSERT(resourceRecords.size() <= static_cast(std::numeric_limits::max())); Il2CppArray* resourceNameArray = vm::Array::New(il2cpp_defaults.string_class, static_cast(resourceRecords.size())); for (size_t i = 0; i < resourceRecords.size(); ++i) il2cpp_array_setref(resourceNameArray, i, vm::String::New(resourceRecords[i].name.c_str())); return resourceNameArray; } class ResourceNameMatcher { public: ResourceNameMatcher(const std::string& resourceNameToFind) : needle(resourceNameToFind) {} bool operator()(const EmbeddedResourceRecord& data) const { return data.name == needle; } private: std::string needle; }; bool Assembly::GetManifestResourceInfoInternal(Il2CppReflectionAssembly* assembly, Il2CppString* name, Il2CppManifestResourceInfo* info) { std::vector resourceRecords = GetResourceRecords(assembly); if (std::find_if(resourceRecords.begin(), resourceRecords.end(), ResourceNameMatcher(utils::StringUtils::Utf16ToUtf8(name->chars))) != resourceRecords.end()) { info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST; NOT_IMPLEMENTED_ICALL_NO_ASSERT(Assembly::GetManifestResourceInfoInternal, "We have not yet implemented file or assembly resources."); return true; } return false; } Il2CppIntPtr Assembly::GetManifestResourceInternal(Il2CppReflectionAssembly* assembly, Il2CppString* name, int* size, Il2CppReflectionModule** module) { std::vector resourceRecords = GetResourceRecords(assembly); std::vector::iterator resource = std::find_if(resourceRecords.begin(), resourceRecords.end(), ResourceNameMatcher(utils::StringUtils::Utf16ToUtf8(name->chars))); if (resource != resourceRecords.end()) { *module = vm::Reflection::GetModuleObject(MetadataCache::GetImageFromIndex(assembly->assembly->imageIndex)); *size = resource->size; Il2CppIntPtr result; result.m_value = LoadResourceData(assembly, *resource); return result; } return Il2CppIntPtr::Zero; } int32_t Assembly::MonoDebugger_GetMethodToken(void* /* System.Reflection.MethodBase */ method) { NOT_SUPPORTED_IL2CPP(Assembly::MonoDebugger_GetMethodToken, "This icall is not supported by il2cpp."); return 0; } Il2CppReflectionModule* Assembly::GetManifestModuleInternal(Il2CppAssembly* self) { NOT_SUPPORTED_IL2CPP(Assembly::GetManifestModuleInternal, "This icall is not supported by il2cpp."); return 0; } bool Assembly::get_ReflectionOnly(Il2CppAssembly* self) { // It doesn't mean anything to have a reflection only assembly in il2cpp since we can't load a managed assembly that we didn't convert. So let's always return false. return false; } #if NET_4_0 Il2CppString* Assembly::GetAotId() { return NULL; } #endif } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/Assembly.h ================================================ #pragma once #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppString; struct Il2CppAssemblyName; struct Il2CppReflectionAssembly; struct mscorlib_System_Reflection_Assembly; struct mscorlib_System_Reflection_Module; struct mscorlib_System_Security_Policy_Evidence; struct mscorlib_System_Reflection_AssemblyName; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { class LIBIL2CPP_CODEGEN_API Assembly { public: static Il2CppReflectionAssembly* GetExecutingAssembly(); static Il2CppReflectionAssembly* GetEntryAssembly(); static Il2CppReflectionAssembly* GetCallingAssembly(); static void FillName(Il2CppReflectionAssembly* ass, mscorlib_System_Reflection_AssemblyName* aname); static Il2CppObject* GetFilesInternal(Il2CppAssembly* self, Il2CppString* name, bool getResourceModules); static Il2CppReflectionModule* GetManifestModuleInternal(Il2CppAssembly* self); static bool GetManifestResourceInfoInternal(Il2CppReflectionAssembly* assembly, Il2CppString* name, Il2CppManifestResourceInfo* info); static Il2CppIntPtr GetManifestResourceInternal(Il2CppReflectionAssembly* assembly, Il2CppString* name, int* size, Il2CppReflectionModule** module); static Il2CppArray* GetManifestResourceNames(Il2CppReflectionAssembly* assembly); static Il2CppArray* GetModulesInternal(Il2CppReflectionAssembly* thisPtr); static Il2CppArray* GetNamespaces(Il2CppAssembly* self); static Il2CppArray* GetReferencedAssemblies(Il2CppReflectionAssembly* self); static void InternalGetAssemblyName(Il2CppString* assemblyFile, Il2CppAssemblyName* aname); static Il2CppReflectionType* InternalGetType(Il2CppReflectionAssembly* , mscorlib_System_Reflection_Module* , Il2CppString* , bool, bool); static Il2CppString* InternalImageRuntimeVersion(Il2CppAssembly* self); static Il2CppReflectionAssembly* LoadFrom(Il2CppString* assemblyFile, bool refonly); static bool LoadPermissions(mscorlib_System_Reflection_Assembly* a, Il2CppIntPtr* minimum, int32_t* minLength, Il2CppIntPtr* optional, int32_t* optLength, Il2CppIntPtr* refused, int32_t* refLength); static int32_t MonoDebugger_GetMethodToken(void* /* System.Reflection.MethodBase */ method); static Il2CppReflectionMethod* get_EntryPoint(Il2CppReflectionAssembly* self); static bool get_ReflectionOnly(Il2CppAssembly* self); static Il2CppString* get_code_base(Il2CppReflectionAssembly* assembly, bool escaped); static Il2CppString* get_fullname(Il2CppReflectionAssembly *ass); static bool get_global_assembly_cache(Il2CppAssembly* self); static Il2CppString* get_location(Il2CppReflectionAssembly *assembly); static Il2CppReflectionAssembly* load_with_partial_name(Il2CppString* name, mscorlib_System_Security_Policy_Evidence* evidence); static Il2CppArray* GetTypes(Il2CppReflectionAssembly* thisPtr, bool exportedOnly); #if NET_4_0 static Il2CppString* GetAotId(); #endif }; } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/AssemblyName.cpp ================================================ #include "il2cpp-config.h" #include "object-internals.h" #include "mono-structs.h" #include "icalls/mscorlib/System.Reflection/AssemblyName.h" #include "vm/Array.h" #include "vm/Class.h" #include "vm/Exception.h" #include "vm/Object.h" #include "vm/Runtime.h" #include "vm/String.h" #include "vm/Type.h" #include "vm/Reflection.h" #include "vm/AssemblyName.h" #include "utils/StringUtils.h" #include "vm-utils/VmStringUtils.h" using il2cpp::vm::Array; using il2cpp::vm::Class; using il2cpp::vm::Object; using il2cpp::vm::Runtime; using il2cpp::vm::String; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { bool AssemblyName::ParseName(Il2CppReflectionAssemblyName* aname, Il2CppString* assemblyName) { return vm::AssemblyName::ParseName(aname, utils::StringUtils::Utf16ToUtf8(utils::StringUtils::GetChars(assemblyName))); } #if NET_4_0 void AssemblyName::get_public_token(uint8_t* token, uint8_t* pubkey, int32_t len) { NOT_IMPLEMENTED_ICALL(AssemblyName::get_public_token); IL2CPP_UNREACHABLE; } char hexChar(uint8_t value) { if (value < 10) return '0' + value; else return 'A' + (value - 10); } Il2CppMonoAssemblyName* AssemblyName::GetNativeName(Il2CppIntPtr assembly_ptr) { Il2CppAssembly *assembly = (Il2CppAssembly*)assembly_ptr.m_value; Il2CppMonoAssemblyName *aname = (Il2CppMonoAssemblyName*)il2cpp::vm::Reflection::GetMonoAssemblyName(assembly); if (aname) { return aname; } else { aname = (Il2CppMonoAssemblyName*)IL2CPP_MALLOC_ZERO(sizeof(Il2CppMonoAssemblyName)); aname->name.m_value = (void*)il2cpp::vm::MetadataCache::GetStringFromIndex(assembly->aname.nameIndex); aname->culture.m_value = (void*)il2cpp::vm::MetadataCache::GetStringFromIndex(assembly->aname.cultureIndex); aname->hash_value.m_value = (void*)il2cpp::vm::MetadataCache::GetStringFromIndex(assembly->aname.hashValueIndex); aname->public_key.m_value = (void*)il2cpp::vm::MetadataCache::GetStringFromIndex(assembly->aname.publicKeyIndex); aname->hash_alg = assembly->aname.hash_alg; aname->hash_len = assembly->aname.hash_len; aname->flags = assembly->aname.flags; aname->major = assembly->aname.major; aname->minor = assembly->aname.minor; aname->build = assembly->aname.build; aname->revision = assembly->aname.revision; //Mono public key token is stored as hexadecimal characters if (assembly->aname.publicKeyToken[0]) { int j = 0; for (int i = 0; i < kPublicKeyByteLength; ++i) { uint8_t value = assembly->aname.publicKeyToken[i]; aname->public_key_token.padding[j++] = hexChar((value & 0xF0) >> 4); aname->public_key_token.padding[j++] = hexChar(value & 0x0F); } } il2cpp::vm::Reflection::SetMonoAssemblyName(assembly, aname); return aname; } } bool AssemblyName::ParseAssemblyName(Il2CppIntPtr namePtr, Il2CppMonoAssemblyName* aname, bool* is_version_defined, bool* is_token_defined) { std::string name((char*)namePtr.m_value); il2cpp::vm::TypeNameParseInfo info; il2cpp::vm::TypeNameParser parser(name, info, false); if (!parser.ParseAssembly()) return false; if (is_version_defined) { *is_version_defined = false; size_t index = name.find("Version"); if (index != std::string::npos) *is_version_defined = true; } if (is_token_defined) { *is_token_defined = false; size_t index = name.find("PublicKeyToken"); if (index != std::string::npos) *is_token_defined = true; } const il2cpp::vm::TypeNameParseInfo::AssemblyName& parsedName = info.assembly_name(); aname->name.m_value = il2cpp::utils::StringUtils::StringDuplicate(parsedName.name.c_str()); if (utils::VmStringUtils::CaseInsensitiveEquals(parsedName.culture.c_str(), "neutral")) // culture names are case insensitive aname->culture.m_value = NULL; else aname->culture.m_value = il2cpp::utils::StringUtils::StringDuplicate(parsedName.culture.c_str()); aname->hash_value.m_value = il2cpp::utils::StringUtils::StringDuplicate(parsedName.hash_value.c_str()); aname->public_key.m_value = il2cpp::utils::StringUtils::StringDuplicate(parsedName.public_key.c_str()); for (int i = 0; i < il2cpp::vm::kPublicKeyTokenLength; ++i) aname->public_key_token.padding[i] = parsedName.public_key_token[i]; aname->hash_alg = parsedName.hash_alg; aname->hash_len = parsedName.hash_len; aname->flags = parsedName.flags; aname->major = parsedName.major; aname->minor = parsedName.minor; aname->build = parsedName.build; aname->revision = parsedName.revision; return true; } #endif } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/AssemblyName.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppString; struct Il2CppReflectionAssemblyName; struct Il2CppMonoAssemblyName; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { class LIBIL2CPP_CODEGEN_API AssemblyName { public: static bool ParseName(Il2CppReflectionAssemblyName* aname, Il2CppString* assemblyName); #if NET_4_0 static void get_public_token(uint8_t* token, uint8_t* pubkey, int32_t len); static Il2CppMonoAssemblyName* GetNativeName(Il2CppIntPtr assembly_ptr); static bool ParseAssemblyName(Il2CppIntPtr name, Il2CppMonoAssemblyName* aname, bool* is_version_defined, bool* is_token_defined); #endif }; } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/CustomAttributeData.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "CustomAttributeData.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { void CustomAttributeData::ResolveArgumentsInternal(Il2CppObject* ctor, Il2CppObject* assembly, Il2CppIntPtr data, uint32_t data_length, Il2CppArray** ctorArgs, Il2CppArray** namedArgs) { NOT_IMPLEMENTED_ICALL(CustomAttributeData::ResolveArgumentsInternal); IL2CPP_UNREACHABLE; } } // namespace Reflection } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/CustomAttributeData.h ================================================ #if NET_4_0 #pragma once #include "object-internals.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { class LIBIL2CPP_CODEGEN_API CustomAttributeData { public: static void ResolveArgumentsInternal(Il2CppObject* ctor, Il2CppObject* assembly, Il2CppIntPtr data, uint32_t data_length, Il2CppArray** ctorArgs, Il2CppArray** namedArgs); }; } // namespace Reflection } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/EventInfo.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "class-internals.h" #include "il2cpp-api.h" #include "EventInfo.h" #include "vm/Class.h" #include "vm/Reflection.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { Il2CppReflectionEvent* EventInfo::internal_from_handle_type(Il2CppIntPtr handlePtr, Il2CppIntPtr typePtr) { Il2CppClass *klass; IL2CPP_ASSERT(handlePtr.m_value); ::EventInfo *handle = (::EventInfo*)handlePtr.m_value; Il2CppType *type = (Il2CppType*)typePtr.m_value; if (!type) { klass = handle->parent; } else { klass = il2cpp_class_from_il2cpp_type(type); bool found = klass == handle->parent || il2cpp::vm::Class::HasParent(klass, handle->parent); if (!found) /* Managed code will throw an exception */ return NULL; } Il2CppReflectionEvent *result = il2cpp::vm::Reflection::GetEventObject(klass, handle); return result; } } // namespace Reflection } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/EventInfo.h ================================================ #pragma once #if NET_4_0 #include "object-internals.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { class LIBIL2CPP_CODEGEN_API EventInfo { public: static Il2CppReflectionEvent* internal_from_handle_type(Il2CppIntPtr event_handle, Il2CppIntPtr type_handle); }; } // namespace Reflection } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/FieldInfo.cpp ================================================ #include "il2cpp-config.h" #include #include "icalls/mscorlib/System.Reflection/FieldInfo.h" #include "class-internals.h" #include "object-internals.h" #include "vm/Class.h" #include "vm/Exception.h" #include "vm/Reflection.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { Il2CppArray* FieldInfo::GetTypeModifiers(Il2CppReflectionField* field, bool optional) { NOT_SUPPORTED_IL2CPP(FieldInfo::GetTypeModifiers, "GetOptionalCustomModifiers and GetRequiredCustomModifiers are not supported."); return NULL; } Il2CppReflectionMarshal* FieldInfo::GetUnmanagedMarshal(Il2CppReflectionField* field) { NOT_IMPLEMENTED_ICALL_NO_ASSERT(FieldInfo::GetUnmanagedMarshal, "This should only be needed for types with a MarshalAsAttribute"); return NULL; } Il2CppReflectionField* FieldInfo::internal_from_handle_type(Il2CppIntPtr field_handle, Il2CppIntPtr type_handle) { ::FieldInfo* fieldInfo = (::FieldInfo*)field_handle.m_value; Il2CppType* il2cppType = (Il2CppType*)type_handle.m_value; if (il2cppType == NULL) return vm::Reflection::GetFieldObject(fieldInfo->parent, fieldInfo); for (Il2CppClass* k = vm::Class::FromIl2CppType(il2cppType); k; k = k->parent) { if (k == fieldInfo->parent) return vm::Reflection::GetFieldObject(fieldInfo->parent, fieldInfo); } return NULL; } #if NET_4_0 Il2CppObject* FieldInfo::get_marshal_info(Il2CppObject* _this) { NOT_IMPLEMENTED_ICALL_NO_ASSERT(FieldInfo::get_marshal_info, "We currently don't store marshal information in metadata"); return NULL; } #endif } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/FieldInfo.h ================================================ #pragma once #include "object-internals.h" #include "il2cpp-config.h" struct Il2CppReflectionField; struct Il2CppReflectionMarshal; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { class LIBIL2CPP_CODEGEN_API FieldInfo { public: static Il2CppReflectionMarshal* GetUnmanagedMarshal(Il2CppReflectionField* field); static Il2CppReflectionField* internal_from_handle_type(Il2CppIntPtr field_handle, Il2CppIntPtr type_handle); static Il2CppArray* GetTypeModifiers(Il2CppReflectionField* field, bool optional); #if NET_4_0 static Il2CppObject* get_marshal_info(Il2CppObject* _this); #endif }; } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/MemberInfo.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Reflection/MemberInfo.h" #include "vm/Exception.h" #include "object-internals.h" #include "vm/Reflection.h" #include "vm/Field.h" #include "vm/Property.h" #include "vm/Method.h" #include "vm/Event.h" #include "vm/Type.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { int32_t MemberInfo::get_MetadataToken(Il2CppObject* /* System.Reflection.MemberInfo */ self) { if (vm::Reflection::IsField(self)) { Il2CppReflectionField* field = (Il2CppReflectionField*)self; return vm::Field::GetToken(field->field); } else if (vm::Reflection::IsAnyMethod(self)) { Il2CppReflectionMethod* method = (Il2CppReflectionMethod*)self; return vm::Method::GetToken(method->method); } else if (vm::Reflection::IsProperty(self)) { Il2CppReflectionProperty* prop = (Il2CppReflectionProperty*)self; return vm::Property::GetToken(prop->property); } else if (vm::Reflection::IsEvent(self)) { Il2CppReflectionMonoEvent* eventInfo = (Il2CppReflectionMonoEvent*)self; return vm::Event::GetToken(eventInfo->eventInfo); } else if (vm::Reflection::IsType(self)) { Il2CppReflectionType* type = (Il2CppReflectionType*)self; return vm::Type::GetToken(type->type); } else { NOT_SUPPORTED_IL2CPP(MemberInfo::get_MetadataToken, "This icall is not supported by il2cpp."); } return 0; } } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/MemberInfo.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { class LIBIL2CPP_CODEGEN_API MemberInfo { public: static int32_t get_MetadataToken(Il2CppObject* /* System.Reflection.MemberInfo */ self); }; } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/MethodBase.cpp ================================================ #include "il2cpp-config.h" #include #include "icalls/mscorlib/System.Reflection/MethodBase.h" #include "class-internals.h" #include "il2cpp-api.h" #include "vm/Class.h" #include "vm/Exception.h" #include "vm/GenericClass.h" #include "vm/Reflection.h" #include "vm/StackTrace.h" #include "vm/MetadataCache.h" #include "metadata/GenericMetadata.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { static Il2CppClass* il2cpp_class_get_generic_type_definition(Il2CppClass *klass) { return klass->generic_class ? il2cpp::vm::GenericClass::GetTypeDefinition(klass->generic_class) : klass; } Il2CppReflectionMethod * MethodBase::GetMethodFromHandleInternalType(Il2CppIntPtr method, Il2CppIntPtr type) { Il2CppClass *klass = NULL; MethodInfo* methodInfo = (MethodInfo*)method.m_value; if (type.m_value) { klass = vm::Class::FromIl2CppType((Il2CppType*)type.m_value); if (il2cpp_class_get_generic_type_definition(methodInfo->declaring_type) != il2cpp_class_get_generic_type_definition(klass)) return NULL; // See the VerifyTwoArgumentGetMethodFromHandleWithGenericType for the failing test. Once we have support for inflating methods // we can implement this case as well and make that test pass. if (methodInfo->declaring_type != klass) NOT_IMPLEMENTED_ICALL(MethodBase::GetMethodFromHandleInternalType); } else { klass = methodInfo->declaring_type; } return il2cpp::vm::Reflection::GetMethodObject(methodInfo, klass); } Il2CppReflectionMethod* MethodBase::GetCurrentMethod() { NOT_SUPPORTED_IL2CPP(MethodBase::GetCurrentMethod, "This icall is not supported by il2cpp. Use the il2cpp_codegen_get_method_object intrinsic instead."); return NULL; } void* /* System.Reflection.MethodBody */ MethodBase::GetMethodBodyInternal(Il2CppIntPtr handle) { NOT_SUPPORTED_IL2CPP(MethodBase::GetMethodBodyInternal, "This icall is not supported by il2cpp."); return 0; } #if NET_4_0 static const MethodInfo* il2cpp_method_get_equivalent_method(const MethodInfo *method, Il2CppClass *klass) { int offset = -1, i; if (method->is_inflated) { const Il2CppGenericContext *context = il2cpp::vm::MetadataCache::GetMethodGenericContext(method); if (context->method_inst) { const MethodInfo *result; //MonoMethodInflated *inflated = (MonoMethodInflated*)method; //method is inflated, we should inflate it on the other class Il2CppGenericContext newCtx; newCtx.method_inst = context->method_inst; newCtx.class_inst = context->class_inst; if (klass->generic_class) { newCtx.class_inst = klass->generic_class->context.class_inst; } else if (klass->genericContainerIndex != kGenericContainerIndexInvalid) { NOT_IMPLEMENTED(il2cpp_method_get_equivalent_method: generic_container_case); //const Il2CppGenericContainer *genericContainer = il2cpp::vm::MetadataCache::GetGenericContainerFromIndex(klass->genericContainerIndex); //newCtx.class_inst = genericContainer->context.class_inst; } result = il2cpp::metadata::GenericMetadata::Inflate(method, klass, &newCtx); return result; } } il2cpp::vm::Class::SetupMethods(method->declaring_type); for (i = 0; i < method->declaring_type->method_count; ++i) { if (method->declaring_type->methods[i] == method) { offset = i; break; } } il2cpp::vm::Class::SetupMethods(klass); IL2CPP_ASSERT(offset >= 0 && offset < klass->method_count); return klass->methods[offset]; } Il2CppReflectionMethod* MethodBase::GetMethodFromHandleInternalType_native(Il2CppIntPtr method_handle, Il2CppIntPtr type_handle, bool genericCheck) { Il2CppReflectionMethod *res = NULL; Il2CppClass *klass; const MethodInfo *method = (const MethodInfo*)method_handle.m_value; if (type_handle.m_value && genericCheck) { klass = il2cpp_class_from_il2cpp_type((Il2CppType*)type_handle.m_value); if (il2cpp_class_get_generic_type_definition(method->declaring_type) != il2cpp_class_get_generic_type_definition(klass)) return NULL; if (method->declaring_type != klass) { method = il2cpp_method_get_equivalent_method(method, klass); if (!method) return NULL; } } else if (type_handle.m_value) klass = il2cpp_class_from_il2cpp_type((Il2CppType*)type_handle.m_value); else klass = method->declaring_type; res = il2cpp_method_get_object(method, klass); return res; } #endif } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/MethodBase.h ================================================ #pragma once #include "il2cpp-config.h" #include "object-internals.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { class LIBIL2CPP_CODEGEN_API MethodBase { public: static Il2CppReflectionMethod* GetCurrentMethod(); static void* /* System.Reflection.MethodBody */ GetMethodBodyInternal(Il2CppIntPtr handle); static Il2CppReflectionMethod* GetMethodFromHandleInternalType(Il2CppIntPtr method, Il2CppIntPtr type); #if NET_4_0 static Il2CppReflectionMethod* GetMethodFromHandleInternalType_native(Il2CppIntPtr method_handle, Il2CppIntPtr type_handle, bool genericCheck); #endif }; } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/Module.cpp ================================================ #include "il2cpp-config.h" #include #include "icalls/mscorlib/System.Reflection/Module.h" #include "vm/Exception.h" #include "vm/Module.h" #include "vm/Image.h" #include "vm/Array.h" #include "class-internals.h" #include "vm/Reflection.h" #include "vm/String.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { Il2CppArray* Module::InternalGetTypes(Il2CppReflectionModule * self) { vm::TypeVector types; vm::Image::GetTypes(self->image, true, &types); Il2CppArray* result = vm::Array::New(il2cpp_defaults.monotype_class, (il2cpp_array_size_t)types.size()); size_t index = 0; for (vm::TypeVector::const_iterator type = types.begin(); type != types.end(); ++type) { Il2CppReflectionType* reflectionType = vm::Reflection::GetTypeObject((*type)->byval_arg); il2cpp_array_set(result, Il2CppReflectionType*, index, reflectionType); index++; } return result; } Il2CppString* Module::GetGuidInternal(mscorlib_System_Reflection_Module * thisPtr) { return il2cpp::vm::String::New("00000000-0000-0000-0000-000000000000"); } Il2CppIntPtr Module::GetHINSTANCE(mscorlib_System_Reflection_Module * thisPtr) { NOT_IMPLEMENTED_ICALL(Module::GetHINSTANCE); return Il2CppIntPtr(); } int32_t Module::get_MetadataToken(Il2CppReflectionModule* self) { return vm::Module::GetToken(self->image); } int32_t Module::GetMDStreamVersion(Il2CppIntPtr module_handle) { NOT_SUPPORTED_IL2CPP(Module::GetMDStreamVersion, "This icall is not supported by il2cpp."); return 0; } Il2CppReflectionType* Module::GetGlobalType(Il2CppReflectionModule* self) { NOT_SUPPORTED_IL2CPP(Module::GetGlobalType, "This icall is not supported by il2cpp."); return 0; } Il2CppIntPtr Module::ResolveTypeToken(Il2CppIntPtr module, int32_t token, Il2CppArray* type_args, Il2CppArray* method_args, ResolveTokenError* error) { NOT_SUPPORTED_IL2CPP(Module::ResolveTypeToken, "This icall is not supported by il2cpp."); return Il2CppIntPtr(); } Il2CppIntPtr Module::ResolveMethodToken(Il2CppIntPtr module, int32_t token, Il2CppArray* type_args, Il2CppArray* method_args, ResolveTokenError* error) { NOT_SUPPORTED_IL2CPP(Module::ResolveMethodToken, "This icall is not supported by il2cpp."); return Il2CppIntPtr(); } Il2CppIntPtr Module::ResolveFieldToken(Il2CppIntPtr module, int32_t token, Il2CppArray* type_args, Il2CppArray* method_args, ResolveTokenError* error) { NOT_SUPPORTED_IL2CPP(Module::ResolveFieldToken, "This icall is not supported by il2cpp."); return Il2CppIntPtr(); } Il2CppString* Module::ResolveStringToken(Il2CppIntPtr module, int32_t token, ResolveTokenError* error) { NOT_SUPPORTED_IL2CPP(Module::ResolveStringToken, "This icall is not supported by il2cpp."); return 0; } void* /* System.Reflection.MemberInfo */ Module::ResolveMemberToken(Il2CppIntPtr module, int32_t token, Il2CppArray* type_args, Il2CppArray* method_args, ResolveTokenError* error) { NOT_SUPPORTED_IL2CPP(Module::ResolveMemberToken, "This icall is not supported by il2cpp."); return 0; } Il2CppArray* Module::ResolveSignature(Il2CppIntPtr module, int32_t metadataToken, ResolveTokenError* error) { NOT_SUPPORTED_IL2CPP(Module::ResolveSignature, "This icall is not supported by il2cpp."); return 0; } void Module::GetPEKind(Il2CppIntPtr module, PortableExecutableKinds* peKind, ImageFileMachine* machine) { NOT_SUPPORTED_IL2CPP(Module::GetPEKind, "This icall is not supported by il2cpp."); } } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/Module.h ================================================ #pragma once #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppArray; struct Il2CppString; struct mscorlib_System_Reflection_Module; typedef int32_t PortableExecutableKinds; typedef int32_t ImageFileMachine; typedef int32_t ResolveTokenError; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { class LIBIL2CPP_CODEGEN_API Module { public: static Il2CppReflectionType* GetGlobalType(Il2CppReflectionModule* self); static Il2CppString* GetGuidInternal(mscorlib_System_Reflection_Module * thisPtr); static int32_t GetMDStreamVersion(Il2CppIntPtr module_handle); static void GetPEKind(Il2CppIntPtr module, PortableExecutableKinds* peKind, ImageFileMachine* machine); static Il2CppArray* InternalGetTypes(Il2CppReflectionModule * self); static Il2CppIntPtr ResolveFieldToken(Il2CppIntPtr module, int32_t token, Il2CppArray* type_args, Il2CppArray* method_args, ResolveTokenError* error); static void* /* System.Reflection.MemberInfo */ ResolveMemberToken(Il2CppIntPtr module, int32_t token, Il2CppArray* type_args, Il2CppArray* method_args, ResolveTokenError* error); static Il2CppIntPtr ResolveMethodToken(Il2CppIntPtr module, int32_t token, Il2CppArray* type_args, Il2CppArray* method_args, ResolveTokenError* error); static Il2CppArray* ResolveSignature(Il2CppIntPtr module, int32_t metadataToken, ResolveTokenError* error); static Il2CppString* ResolveStringToken(Il2CppIntPtr module, int32_t token, ResolveTokenError* error); static Il2CppIntPtr ResolveTypeToken(Il2CppIntPtr module, int32_t token, Il2CppArray* type_args, Il2CppArray* method_args, ResolveTokenError* error); static int32_t get_MetadataToken(Il2CppReflectionModule* self); static Il2CppIntPtr GetHINSTANCE(mscorlib_System_Reflection_Module * thisPtr); }; } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/MonoCMethod.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Reflection/MonoCMethod.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { Il2CppObject* MonoCMethod::InternalInvoke(void* /* System.Reflection.MonoCMethod */ self, Il2CppObject* obj, Il2CppArray* parameters, Il2CppException** exc) { NOT_SUPPORTED_IL2CPP(MonoCMethod::InternalInvoke, "This icall is not supported by il2cpp."); return 0; } #if NET_4_0 int32_t MonoCMethod::get_core_clr_security_level(Il2CppObject* _this) { NOT_IMPLEMENTED_ICALL(MonoCMethod::get_core_clr_security_level); IL2CPP_UNREACHABLE; return 0; } #endif } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/MonoCMethod.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { class LIBIL2CPP_CODEGEN_API MonoCMethod { public: static Il2CppObject* InternalInvoke(void* /* System.Reflection.MonoCMethod */ self, Il2CppObject* obj, Il2CppArray* parameters, Il2CppException** exc); #if NET_4_0 static int32_t get_core_clr_security_level(Il2CppObject* _this); #endif }; } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/MonoEventInfo.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "object-internals.h" #include #include "icalls/mscorlib/System.Reflection/MonoEventInfo.h" #include "vm/Array.h" #include "vm/Class.h" #include "vm/Reflection.h" #include "vm/String.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { void MonoEventInfo::get_event_info(Il2CppReflectionMonoEvent* event, Il2CppReflectionMonoEventInfo* eventInfo) { eventInfo->declaringType = vm::Reflection::GetTypeObject(event->eventInfo->parent->byval_arg); eventInfo->reflectedType = event->reflectedType; eventInfo->name = vm::String::New(event->eventInfo->name); Il2CppClass* reflectedTypeInfo = vm::Class::FromIl2CppType(event->reflectedType->type); eventInfo->addMethod = event->eventInfo->add != NULL ? vm::Reflection::GetMethodObject(event->eventInfo->add, reflectedTypeInfo) : NULL; eventInfo->removeMethod = event->eventInfo->remove != NULL ? vm::Reflection::GetMethodObject(event->eventInfo->remove, reflectedTypeInfo) : NULL; eventInfo->raiseMethod = event->eventInfo->raise != NULL ? vm::Reflection::GetMethodObject(event->eventInfo->raise, reflectedTypeInfo) : NULL; eventInfo->eventAttributes = event->eventInfo->eventType->attrs; eventInfo->otherMethods = vm::Array::NewCached(il2cpp_defaults.method_info_class, 0); // Empty for now } } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/MonoEventInfo.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppReflectionMonoEvent; struct Il2CppReflectionMonoEventInfo; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { class LIBIL2CPP_CODEGEN_API MonoEventInfo { public: static void get_event_info(Il2CppReflectionMonoEvent* event, Il2CppReflectionMonoEventInfo* eventInfo); }; } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/MonoField.cpp ================================================ #include "il2cpp-config.h" #include #include "icalls/mscorlib/System.Reflection/MonoField.h" #include "utils/StringUtils.h" #include "vm/Class.h" #include "vm/Field.h" #include "vm/Object.h" #include "vm/Reflection.h" #include "vm/Runtime.h" #include "vm/Type.h" #include "vm/Exception.h" #include "class-internals.h" #include "tabledefs.h" #include "vm-utils/BlobReader.h" using namespace il2cpp::vm; using il2cpp::utils::StringUtils; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { Il2CppReflectionType * MonoField::GetParentType(Il2CppReflectionField * field, bool declaring) { Il2CppClass *parent; parent = declaring ? field->field->parent : field->klass; return il2cpp::vm::Reflection::GetTypeObject(parent->byval_arg); } int32_t MonoField::GetFieldOffset(Il2CppReflectionField * field) { return field->field->offset - sizeof(Il2CppObject); } Il2CppObject* MonoField::GetValueInternal(Il2CppReflectionField * field, Il2CppObject * obj) { return vm::Field::GetValueObject(field->field, obj); } void MonoField::SetValueInternal(Il2CppReflectionField* field, Il2CppObject* obj, Il2CppObject* value) { FieldInfo* fieldInfo = field->field; Il2CppClass* fieldType = Class::FromIl2CppType(fieldInfo->type); #ifndef NET_4_0 //This check is done in managed code in .NET 4.5+ if (value != NULL && !Class::IsAssignableFrom(fieldType, value->klass)) { Exception::Raise(Exception::GetArgumentException("value", utils::StringUtils::Printf("Object of type '%s' cannot be converted to type '%s'.", Type::GetName(value->klass->byval_arg, IL2CPP_TYPE_NAME_FORMAT_FULL_NAME).c_str(), Type::GetName(fieldInfo->type, IL2CPP_TYPE_NAME_FORMAT_FULL_NAME).c_str() ).c_str())); } #endif uint8_t* fieldAddress; if (fieldInfo->type->attrs & FIELD_ATTRIBUTE_STATIC) { if (fieldInfo->offset == THREAD_STATIC_FIELD_OFFSET) { NOT_IMPLEMENTED(Field::StaticSetValue); } Runtime::ClassInit(fieldInfo->parent); fieldAddress = static_cast(fieldInfo->parent->static_fields) + fieldInfo->offset; } else { IL2CPP_ASSERT(obj); fieldAddress = reinterpret_cast(obj) + fieldInfo->offset; } if (fieldType->valuetype) { if (!Class::IsNullable(fieldType)) { uint32_t fieldSize = Class::GetInstanceSize(fieldType) - sizeof(Il2CppObject); if (value != NULL) { memcpy(fieldAddress, Object::Unbox(value), fieldSize); } else { // Setting value type to null is defined to zero it out memset(fieldAddress, 0, fieldSize); } } else { Il2CppClass* nullableArg = Class::GetNullableArgument(fieldType); uint32_t valueSize = Class::GetInstanceSize(nullableArg) - sizeof(Il2CppObject); if (value != NULL) { memcpy(fieldAddress, Object::Unbox(value), valueSize); *(fieldAddress + valueSize) = true; } else { *(fieldAddress + valueSize) = false; } } } else { memcpy(fieldAddress, &value, sizeof(Il2CppObject*)); } } Il2CppObject* MonoField::GetRawConstantValue(Il2CppReflectionField* field) { FieldInfo* fieldInfo = field->field; if (!(fieldInfo->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) Exception::Raise(Exception::GetInvalidOperationException(NULL)); const Il2CppType* type = NULL; const char* data = Class::GetFieldDefaultValue(fieldInfo, &type); switch (type->type) { case IL2CPP_TYPE_U1: case IL2CPP_TYPE_I1: case IL2CPP_TYPE_BOOLEAN: case IL2CPP_TYPE_U2: case IL2CPP_TYPE_I2: case IL2CPP_TYPE_CHAR: case IL2CPP_TYPE_U4: case IL2CPP_TYPE_I4: case IL2CPP_TYPE_R4: case IL2CPP_TYPE_U8: case IL2CPP_TYPE_I8: case IL2CPP_TYPE_R8: { Il2CppObject* obj = Object::New(Class::FromIl2CppType(type)); utils::BlobReader::GetConstantValueFromBlob(type->type, data, Object::Unbox(obj)); return obj; } case IL2CPP_TYPE_STRING: case IL2CPP_TYPE_CLASS: case IL2CPP_TYPE_OBJECT: case IL2CPP_TYPE_GENERICINST: { Il2CppObject* obj = NULL; utils::BlobReader::GetConstantValueFromBlob(type->type, data, &obj); return obj; } default: Exception::Raise(Exception::GetInvalidOperationException(StringUtils::Printf("Attempting to get raw constant value for field of type %d", type).c_str())); } return NULL; } #if NET_4_0 int32_t MonoField::get_core_clr_security_level(Il2CppObject* _this) { NOT_IMPLEMENTED_ICALL(MonoField::get_core_clr_security_level); IL2CPP_UNREACHABLE; return 0; } Il2CppObject* MonoField::ResolveType(Il2CppObject* _this) { NOT_IMPLEMENTED_ICALL(MonoField::ResolveType); IL2CPP_UNREACHABLE; return NULL; } #endif } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/MonoField.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct mscorlib_System_Reflection_FieldInfo; struct mscorlib_System_Reflection_Emit_UnmanagedMarshal; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { class LIBIL2CPP_CODEGEN_API MonoField { public: static int32_t GetFieldOffset(Il2CppReflectionField * thisPtr); static Il2CppReflectionType * GetParentType(Il2CppReflectionField * field, bool declaring); static Il2CppObject* GetRawConstantValue(Il2CppReflectionField* field); static Il2CppObject * GetValueInternal(Il2CppReflectionField * thisPtr, Il2CppObject * obj); static void SetValueInternal(Il2CppReflectionField * fi, Il2CppObject * obj, Il2CppObject * value); #if NET_4_0 static int32_t get_core_clr_security_level(Il2CppObject* _this); static Il2CppObject* ResolveType(Il2CppObject* _this); #endif }; } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/MonoGenericCMethod.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Reflection/MonoGenericCMethod.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { Il2CppReflectionType* MonoGenericCMethod::get_ReflectedType(void* /* System.Reflection.MonoGenericCMethod */ self) { NOT_SUPPORTED_IL2CPP(MonoGenericCMethod::get_ReflectedType, "This icall is not supported by il2cpp."); return 0; } } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/MonoGenericCMethod.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { class LIBIL2CPP_CODEGEN_API MonoGenericCMethod { public: static Il2CppReflectionType* get_ReflectedType(void* /* System.Reflection.MonoGenericCMethod */ self); }; } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/MonoGenericClass.cpp ================================================ #include "il2cpp-config.h" #include #include "icalls/mscorlib/System.Reflection/MonoGenericClass.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { void MonoGenericClass::initialize(mscorlib_System_Reflection_MonoGenericClass * thisPtr, Il2CppArray* methods, Il2CppArray* ctors, Il2CppArray* fields, Il2CppArray* properties, Il2CppArray* events) { NOT_IMPLEMENTED_ICALL(MonoGenericClass::initialize); } #if NET_4_0 void MonoGenericClass::initialize40(Il2CppObject* _this, Il2CppArray* fields) { NOT_IMPLEMENTED_ICALL(MonoGenericClass::initialize40); IL2CPP_UNREACHABLE; } void MonoGenericClass::register_with_runtime(Il2CppObject* type) { NOT_IMPLEMENTED_ICALL(MonoGenericClass::register_with_runtime); IL2CPP_UNREACHABLE; } #endif } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/MonoGenericClass.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppArray; struct mscorlib_System_Reflection_MonoGenericClass; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { class LIBIL2CPP_CODEGEN_API MonoGenericClass { public: static void initialize(mscorlib_System_Reflection_MonoGenericClass * thisPtr, Il2CppArray* methods, Il2CppArray* ctors, Il2CppArray* fields, Il2CppArray* properties, Il2CppArray* events); #if NET_4_0 static void initialize40(Il2CppObject* _this, Il2CppArray* fields); static void register_with_runtime(Il2CppObject* type); #endif }; } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/MonoGenericMethod.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Reflection/MonoGenericMethod.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { Il2CppReflectionType* MonoGenericMethod::get_ReflectedType(void* /* System.Reflection.MonoGenericMethod */ self) { NOT_SUPPORTED_IL2CPP(MonoGenericMethod::get_ReflectedType, "This icall is not supported by il2cpp."); return 0; } } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/MonoGenericMethod.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { class LIBIL2CPP_CODEGEN_API MonoGenericMethod { public: static Il2CppReflectionType* get_ReflectedType(void* /* System.Reflection.MonoGenericMethod */ self); }; } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/MonoMethod.cpp ================================================ #include "il2cpp-config.h" #include #include #include #include "icalls/mscorlib/System.Reflection/MonoMethod.h" #include "tabledefs.h" #include "class-internals.h" #include "metadata/Il2CppTypeVector.h" #include "vm/Array.h" #include "vm/Class.h" #include "vm/Exception.h" #include "vm/GenericContainer.h" #include "vm/MetadataCache.h" #include "vm/Method.h" #include "vm/Object.h" #include "vm/Reflection.h" #include "vm/Runtime.h" #include "vm/String.h" #include "vm/Reflection.h" #include "vm/Type.h" #include "vm/GenericClass.h" using namespace il2cpp::vm; using il2cpp::metadata::Il2CppTypeVector; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { Il2CppReflectionMethod* MonoMethod::get_base_definition(Il2CppReflectionMethod *m) { const MethodInfo *method = m->method; Il2CppClass *klass = method->declaring_type; if (klass == NULL) return m; if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) || Class::IsInterface(klass) || method->flags & METHOD_ATTRIBUTE_NEW_SLOT) return m; /*if(klass->generic_class) klass = klass->generic_class->container_class;*/ for (Il2CppClass* parent = klass->parent; parent != NULL; parent = parent->parent) { if (parent->vtable_count <= method->slot) break; klass = parent; } if (klass == method->declaring_type) return m; il2cpp::vm::Class::Init(klass); const MethodInfo *result = klass->vtable[method->slot].method; if (result == NULL) { void *iterator = NULL; for (result = Class::GetMethods(klass, &iterator); result != NULL; result = Class::GetMethods(klass, &iterator)) if (result->slot == method->slot) break; } if (result == NULL) return m; return il2cpp::vm::Reflection::GetMethodObject(result, klass); } bool MonoMethod::get_IsGenericMethod(Il2CppReflectionMethod* method) { // if we are a generic method definition if (method->method->is_generic) return true; // is_inflated is true when a method is a generic instance or it's declaring type is a generic instance type. // Only return true here if we are a generic instance method if (method->method->is_inflated) { const Il2CppGenericContext* context = MetadataCache::GetMethodGenericContext(method->method); return context != NULL && context->method_inst != NULL; } return false; } Il2CppString * MonoMethod::get_name(Il2CppReflectionMethod * m) { const MethodInfo *method = m->method; IL2CPP_OBJECT_SETREF(m, name, String::New(method->name)); return m->name; } mscorlib_System_Runtime_InteropServices_DllImportAttribute * MonoMethod::GetDllImportAttribute(Il2CppIntPtr) { //Todo: [DllImport] is an pseudo attribute. it doesn't exist in the metadata as an attribute, but as a flag on a method. //however, if you use reflection to ask for attributes, it does get reported, so what needs to happen is we create an attribute //instanec on the fly and populate it with the data in the metadata. Turns out that if you call GetCustomAttributes() that ends //up calling this function. For now, we will just return an attribute, but not yet populate it with the correct data. Il2CppClass* typeInfo = Class::FromName(il2cpp_defaults.corlib, "System.Runtime.InteropServices", "DllImportAttribute"); IL2CPP_ASSERT(typeInfo != NULL); return (mscorlib_System_Runtime_InteropServices_DllImportAttribute*)il2cpp::vm::Object::New(typeInfo); } Il2CppArray* MonoMethod::GetGenericArguments(Il2CppReflectionMethod* method) { uint32_t count = 0; Il2CppArray* res = NULL; const MethodInfo* methodInfo = method->method; if (methodInfo->is_inflated) { const Il2CppGenericContext* context = MetadataCache::GetMethodGenericContext(methodInfo); if (context && context->method_inst) { const Il2CppGenericInst *inst = context->method_inst; count = inst->type_argc; res = Array::New(il2cpp_defaults.systemtype_class, count); for (uint32_t i = 0; i < count; i++) il2cpp_array_setref(res, i, il2cpp::vm::Reflection::GetTypeObject(inst->type_argv[i])); return res; } // method is inflated because it's owner is a generic instance type, extract method definition out of the method IL2CPP_ASSERT(methodInfo->is_generic); methodInfo = methodInfo->genericMethod->methodDefinition; } const Il2CppGenericContainer *container = MetadataCache::GetMethodGenericContainer(methodInfo); count = container != NULL ? container->type_argc : 0; res = Array::New(il2cpp_defaults.systemtype_class, count); for (uint32_t i = 0; i < count; i++) { const Il2CppGenericParameter *param = GenericContainer::GetGenericParameter(container, i); Il2CppClass *pklass = Class::FromGenericParameter(param); il2cpp_array_setref(res, i, il2cpp::vm::Reflection::GetTypeObject(pklass->byval_arg)); } return res; } Il2CppObject * MonoMethod::InternalInvoke(Il2CppReflectionMethod * method, Il2CppObject * thisPtr, Il2CppArray * params, Il2CppObject * * exc) { NOT_IMPLEMENTED_ICALL_NO_ASSERT(MonoMethod::InternalInvoke, "Audit and look over commented code. Work in progress."); /* * Invoke from reflection is supposed to always be a virtual call (the API * is stupid), mono_runtime_invoke_*() calls the provided method, allowing * greater flexibility. */ const MethodInfo *m = method->method; int pcount; void *obj = thisPtr; *exc = NULL; if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) { if (thisPtr) { //if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) { // mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass)); // return NULL; //} if (!Object::IsInst(thisPtr, m->declaring_type)) { IL2CPP_ASSERT(0); //mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type.")); return NULL; } m = Object::GetVirtualMethod(thisPtr, m); } else #if IL2CPP_ENABLE_MONO_BUG_EMULATION // Mono doesn't throw on null 'this' if it's an instance constructor, and class libs depend on this behaviour if (strcmp(m->name, ".ctor")) #endif { Exception::Raise(Exception::GetTargetException("Non-static method requires a target")); } } pcount = params ? il2cpp::vm::Array::GetLength(params) : 0; if (pcount != m->parameters_count) { IL2CPP_ASSERT(0); //mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException")); return NULL; } // TODO: Add check for abstract once types have flags //if ((m->declaring_type->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) { // mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class.")); // return NULL; //} if (m->declaring_type->rank && !strcmp(m->name, ".ctor")) { int i; il2cpp_array_size_t *lengths; il2cpp_array_size_t *lower_bounds; pcount = il2cpp::vm::Array::GetLength(params); lengths = (il2cpp_array_size_t*)alloca(sizeof(il2cpp_array_size_t) * pcount); for (i = 0; i < pcount; ++i) lengths[i] = *(il2cpp_array_size_t*)((char*)il2cpp_array_get(params, void*, i) + sizeof(Il2CppObject)); if (m->declaring_type->rank == pcount) { /* Only lengths provided. */ lower_bounds = NULL; } else { IL2CPP_ASSERT(pcount == (m->declaring_type->rank * 2)); /* lower bounds are first. */ lower_bounds = lengths; lengths += m->declaring_type->rank; } return (Il2CppObject*)il2cpp::vm::Array::NewFull(m->declaring_type, lengths, lower_bounds); } // If a managed exception was thrown, we need raise it here because Runtime::Invoke catches the exception and returns a pointer to it. Il2CppException* exception = NULL; Il2CppObject *result = il2cpp::vm::Runtime::InvokeArray(m, obj, params, &exception); if (exception) Exception::Raise(exception); return result; } bool MonoMethod::get_IsGenericMethodDefinition(Il2CppReflectionMethod* method) { return method->method->is_generic; } static std::string FormatExceptionMessageForNonConstructableGenericMethod(const MethodInfo* method, const Il2CppTypeVector& genericArguments) { std::string message; message += "Failed to construct generic method '"; message += Type::GetName(method->declaring_type->byval_arg, IL2CPP_TYPE_NAME_FORMAT_FULL_NAME); message += "::"; message += Method::GetName(method); message += "' with generic arguments ["; for (Il2CppTypeVector::const_iterator iter = genericArguments.begin(); iter != genericArguments.end(); ++iter) { if (iter != genericArguments.begin()) message += ", "; message += Type::GetName(*iter, IL2CPP_TYPE_NAME_FORMAT_FULL_NAME); } message += "] at runtime."; return message; } Il2CppReflectionMethod* MonoMethod::MakeGenericMethod_impl(Il2CppReflectionMethod* method, Il2CppArray* genericArgumentTypes) { const MethodInfo* genericMethodDefinition = method->method; if (!genericMethodDefinition->is_generic) { std::string message; // what's the point of this ? Exception::Raise(Exception::GetInvalidOperationException(message.c_str())); } uint32_t arrayLength = Array::GetLength(genericArgumentTypes); Il2CppTypeVector genericArguments; genericArguments.reserve(arrayLength); for (uint32_t i = 0; i < arrayLength; i++) { Il2CppReflectionType* genericArgumentType = il2cpp_array_get(genericArgumentTypes, Il2CppReflectionType*, i); genericArguments.push_back(genericArgumentType->type); } const MethodInfo* genericInstanceMethod = MetadataCache::GetGenericInstanceMethod(genericMethodDefinition, genericArguments); if (!genericInstanceMethod) { Exception::Raise(Exception::GetNotSupportedException(FormatExceptionMessageForNonConstructableGenericMethod(genericMethodDefinition, genericArguments).c_str())); return NULL; } return il2cpp::vm::Reflection::GetMethodObject(genericInstanceMethod, NULL); } Il2CppReflectionMethod* MonoMethod::GetGenericMethodDefinition_impl(Il2CppReflectionMethod* method) { if (method->method->is_generic) return method; if (!method->method->is_inflated) return NULL; const MethodInfo* methodDefinition = MetadataCache::GetGenericMethodDefinition(method->method); IL2CPP_ASSERT(methodDefinition); if (!methodDefinition->is_generic) return NULL; const Il2CppGenericContext* methodContext = MetadataCache::GetMethodGenericContext(method->method); IL2CPP_ASSERT(methodContext); if (methodContext->class_inst) { NOT_IMPLEMENTED_ICALL(MonoMethod::GetGenericMethodDefinition_impl); } return il2cpp::vm::Reflection::GetMethodObject(const_cast(methodDefinition), NULL); } #if NET_4_0 int32_t MonoMethod::get_core_clr_security_level(Il2CppObject* _this) { NOT_IMPLEMENTED_ICALL(MonoMethod::get_core_clr_security_level); IL2CPP_UNREACHABLE; return 0; } Il2CppReflectionMethod* MonoMethod::get_base_method(Il2CppReflectionMethod* method, bool definition) { // On the C# side, MonoMethod.GetBaseDefinition is the only caller of this icall that passes definition=true, // so we can do the equivalent call that net20 would do, which would be to call get_base_definition. // // When definition=false. This is called by MonoMethod.GetBaseMethod, which is internal, and seems to // only be called by some GetCustomAttributes(true) calls. There is only a small difference in the behavior of this method // when definition is false. const MethodInfo *method2 = method->method; Il2CppClass *klass = method2->declaring_type; if (klass == NULL) return method; if (!(method2->flags & METHOD_ATTRIBUTE_VIRTUAL) || Class::IsInterface(klass) || method2->flags & METHOD_ATTRIBUTE_NEW_SLOT) return method; /*if(klass->generic_class) klass = klass->generic_class->container_class;*/ if (definition) { for (Il2CppClass* parent = klass->parent; parent != NULL; parent = parent->parent) { if (parent->vtable_count <= method2->slot) break; klass = parent; } } else { if (!klass->parent) { IL2CPP_ASSERT(klass == il2cpp_defaults.object_class); return method; } klass = klass->parent; } if (klass == method2->declaring_type) return method; il2cpp::vm::Class::Init(klass); const MethodInfo *result = klass->vtable[method2->slot].method; if (result == NULL) { void *iterator = NULL; for (result = Class::GetMethods(klass, &iterator); result != NULL; result = Class::GetMethods(klass, &iterator)) if (result->slot == method2->slot) break; } if (result == NULL) return method; return il2cpp::vm::Reflection::GetMethodObject(result, klass); } void MonoMethod::GetPInvoke(Il2CppReflectionMethod* _this, int32_t* flags, Il2CppString** entryPoint, Il2CppString** dllName) { // we don't keep these around in metadata *flags = 0; *dllName = *entryPoint = vm::String::Empty(); // TODO: Write barrier here! } #endif } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/MonoMethod.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct mscorlib_System_Runtime_InteropServices_DllImportAttribute; struct mscorlib_System_Reflection_MethodInfo; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { class LIBIL2CPP_CODEGEN_API MonoMethod { public: static mscorlib_System_Runtime_InteropServices_DllImportAttribute * GetDllImportAttribute(Il2CppIntPtr); static Il2CppArray * GetGenericArguments(Il2CppReflectionMethod *); static Il2CppReflectionMethod* GetGenericMethodDefinition_impl(Il2CppReflectionMethod* method); static Il2CppObject * InternalInvoke(Il2CppReflectionMethod * method, Il2CppObject * thisPtr, Il2CppArray * params, Il2CppObject * * exc); static bool get_IsGenericMethod(Il2CppReflectionMethod *); static bool get_IsGenericMethodDefinition(Il2CppReflectionMethod *); static Il2CppReflectionMethod* get_base_definition(Il2CppReflectionMethod *); static Il2CppString * get_name(Il2CppReflectionMethod * m); static Il2CppReflectionMethod* MakeGenericMethod_impl(Il2CppReflectionMethod *, Il2CppArray *); #if NET_4_0 static int32_t get_core_clr_security_level(Il2CppObject* _this); static Il2CppReflectionMethod* get_base_method(Il2CppReflectionMethod* method, bool definition); static void GetPInvoke(Il2CppReflectionMethod* _this, int32_t* flags, Il2CppString** entryPoint, Il2CppString** dllName); #endif }; } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/MonoMethodInfo.cpp ================================================ #include "il2cpp-config.h" #include #include "icalls/mscorlib/System.Reflection/MonoMethodInfo.h" #include "class-internals.h" #include "vm/Class.h" #include "vm/Reflection.h" #include "vm/Exception.h" using namespace il2cpp::vm; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { void MonoMethodInfo::get_method_info(Il2CppIntPtr methodPtr, Il2CppMethodInfo *info) { NOT_IMPLEMENTED_ICALL_NO_ASSERT(MonoMethodInfo::get_method_info, "Audit and look over commented code. Work in progress."); MethodInfo* method = (MethodInfo*)methodPtr.m_value; //MonoMethodSignature* sig; //sig = mono_method_signature (method); //if (!sig) { // IL2CPP_ASSERT(mono_loader_get_last_error ()); // mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ())); //} IL2CPP_STRUCT_SETREF(info, parent, il2cpp::vm::Reflection::GetTypeObject(method->declaring_type->byval_arg)); if (method->return_type) IL2CPP_STRUCT_SETREF(info, ret, il2cpp::vm::Reflection::GetTypeObject(method->return_type)); info->attrs = method->flags; info->implattrs = method->iflags; //if (sig->call_convention == MONO_CALL_DEFAULT) // info->callconv = sig->sentinelpos >= 0 ? 2 : 1; //else { // if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0) // info->callconv = 2; // else // info->callconv = 1; //} //info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6); } Il2CppArray * MonoMethodInfo::get_parameter_info(Il2CppIntPtr methodPtr, Il2CppReflectionMethod *member) { MethodInfo* method = (MethodInfo*)methodPtr.m_value; return il2cpp::vm::Reflection::GetParamObjects(method, member->reftype ? Class::FromIl2CppType(member->reftype->type) : NULL); } void* /* System.Reflection.Emit.UnmanagedMarshal */ MonoMethodInfo::get_retval_marshal(Il2CppIntPtr handle) { NOT_IMPLEMENTED_ICALL_NO_ASSERT(MonoMethodInfo::get_retval_marshal, "This icall is not supported by il2cpp."); return NULL; } #if NET_4_0 int32_t MonoMethodInfo::get_method_attributes(Il2CppIntPtr methodPtr) { MethodInfo* method = (MethodInfo*)methodPtr.m_value; return method->flags; } #endif } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/MonoMethodInfo.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { class LIBIL2CPP_CODEGEN_API MonoMethodInfo { public: static void get_method_info(Il2CppIntPtr methodPtr, Il2CppMethodInfo* info); static void* /* System.Reflection.Emit.UnmanagedMarshal */ get_retval_marshal(Il2CppIntPtr handle); static Il2CppArray* get_parameter_info(Il2CppIntPtr methodPtr, Il2CppReflectionMethod* member); #if NET_4_0 static int32_t get_method_attributes(Il2CppIntPtr methodPtr); #endif }; } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/MonoPropertyInfo.cpp ================================================ #include "il2cpp-config.h" #include #include "icalls/mscorlib/System.Reflection/MonoPropertyInfo.h" #include "class-internals.h" #include "object-internals.h" #include "vm/Reflection.h" #include "vm/String.h" #include "vm/Exception.h" using namespace il2cpp::vm; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { void MonoPropertyInfo::get_property_info(Il2CppReflectionProperty *property, Il2CppPropertyInfo *info, PInfo req_info) { if ((req_info & PInfo_ReflectedType) != 0) IL2CPP_STRUCT_SETREF(info, parent, vm::Reflection::GetTypeObject(property->klass->byval_arg)); else if ((req_info & PInfo_DeclaringType) != 0) { #if !NET_4_0 IL2CPP_STRUCT_SETREF(info, parent, vm::Reflection::GetTypeObject(property->property->parent->byval_arg)); #else IL2CPP_STRUCT_SETREF(info, declaringType, vm::Reflection::GetTypeObject(property->property->parent->byval_arg)); #endif } if ((req_info & PInfo_Name) != 0) IL2CPP_STRUCT_SETREF(info, name, vm::String::New(property->property->name)); if ((req_info & PInfo_Attributes) != 0) info->attrs = property->property->attrs; if ((req_info & PInfo_GetMethod) != 0) IL2CPP_STRUCT_SETREF(info, get, property->property->get ? vm::Reflection::GetMethodObject(property->property->get, property->klass) : NULL); if ((req_info & PInfo_SetMethod) != 0) IL2CPP_STRUCT_SETREF(info, set, property->property->set ? vm::Reflection::GetMethodObject(property->property->set, property->klass) : NULL); /* * There may be other methods defined for properties, though, it seems they are not exposed * in the reflection API */ } Il2CppArray* MonoPropertyInfo::GetTypeModifiers(void* /* System.Reflection.MonoProperty */ prop, bool optional) { NOT_SUPPORTED_IL2CPP(MonoPropertyInfo::GetTypeModifiers, "This icall is not supported by il2cpp."); return 0; } #if NET_4_0 Il2CppObject* MonoPropertyInfo::get_default_value(Il2CppReflectionProperty* prop) { NOT_IMPLEMENTED_ICALL(MonoPropertyInfo::get_default_value); IL2CPP_UNREACHABLE; return NULL; } #endif } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/MonoPropertyInfo.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppReflectionProperty; struct Il2CppPropertyInfo; struct Il2CppArray; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { typedef enum { PInfo_Attributes = 1, PInfo_GetMethod = 1 << 1, PInfo_SetMethod = 1 << 2, PInfo_ReflectedType = 1 << 3, PInfo_DeclaringType = 1 << 4, PInfo_Name = 1 << 5 } PInfo; class LIBIL2CPP_CODEGEN_API MonoPropertyInfo { public: static Il2CppArray* GetTypeModifiers(void* /* System.Reflection.MonoProperty */ prop, bool optional); static void get_property_info(Il2CppReflectionProperty *property, Il2CppPropertyInfo *info, PInfo req_info); #if NET_4_0 static Il2CppObject* get_default_value(Il2CppReflectionProperty* prop); #endif }; } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/ParameterInfo.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Reflection/ParameterInfo.h" #include "vm/Exception.h" #include "object-internals.h" #include "class-internals.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { int32_t ParameterInfo::GetMetadataToken(Il2CppReflectionParameter* self) { //ReturnParameter Parameter infos are constructed at runtime. if (self->PositionImpl == -1) return 0x8000000; // This is what mono returns as a fixed value. Il2CppReflectionMethod* method = (Il2CppReflectionMethod*)self->MemberImpl; const ::ParameterInfo* info = &method->method->parameters[self->PositionImpl]; return (int32_t)info->token; } Il2CppArray* ParameterInfo::GetTypeModifiers(void* /* System.Reflection.ParameterInfo */ self, bool optional) { NOT_SUPPORTED_IL2CPP(ParameterInfo::GetTypeModifiers, "This icall is not supported by il2cpp."); return 0; } } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/ParameterInfo.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { class LIBIL2CPP_CODEGEN_API ParameterInfo { public: static Il2CppArray* GetTypeModifiers(void* /* System.Reflection.ParameterInfo */ self, bool optional); static int32_t GetMetadataToken(Il2CppReflectionParameter* self); }; } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/PropertyInfo.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "il2cpp-api.h" #include "PropertyInfo.h" #include "vm/Class.h" #include "vm/Reflection.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { Il2CppReflectionProperty* PropertyInfo::internal_from_handle_type(Il2CppIntPtr handlePtr, Il2CppIntPtr typePtr) { Il2CppClass *klass; IL2CPP_ASSERT(handlePtr.m_value); ::PropertyInfo *handle = (::PropertyInfo*)handlePtr.m_value; Il2CppType *type = (Il2CppType*)typePtr.m_value; if (!type) { klass = handle->parent; } else { klass = il2cpp_class_from_il2cpp_type(type); bool found = klass == handle->parent || il2cpp::vm::Class::HasParent(klass, handle->parent); if (!found) /* Managed code will throw an exception */ return NULL; } Il2CppReflectionProperty *result = il2cpp::vm::Reflection::GetPropertyObject(klass, handle); return result; } } // namespace Reflection } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/PropertyInfo.h ================================================ #pragma once #if NET_4_0 #include "object-internals.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { class LIBIL2CPP_CODEGEN_API PropertyInfo { public: static Il2CppReflectionProperty* internal_from_handle_type(Il2CppIntPtr event_handle, Il2CppIntPtr type_handle); }; } // namespace Reflection } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/RtFieldInfo.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "RtFieldInfo.h" #include "icalls/mscorlib/System.Reflection/MonoField.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { Il2CppObject* RtFieldInfo::UnsafeGetValue(Il2CppReflectionField* _this, Il2CppObject* obj) { // In mono's icall-def.h file, this maps to the same icall as MonoField.GetValueInternal // so our implementation will do the same return MonoField::GetValueInternal(_this, obj); } } // namespace Reflection } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection/RtFieldInfo.h ================================================ #pragma once #if NET_4_0 #include "object-internals.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { class LIBIL2CPP_CODEGEN_API RtFieldInfo { public: static Il2CppObject* UnsafeGetValue(Il2CppReflectionField* _this, Il2CppObject* obj); }; } // namespace Reflection } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection.Emit/AssemblyBuilder.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Reflection.Emit/AssemblyBuilder.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { namespace Emit { void AssemblyBuilder::basic_init(mscorlib_System_Reflection_Emit_AssemblyBuilder *) { NOT_SUPPORTED_SRE(AssemblyBuilder::basic_init); } mscorlib_System_Reflection_Module* AssemblyBuilder::InternalAddModule(mscorlib_System_Reflection_Emit_AssemblyBuilder * thisPtr, Il2CppString* fileName) { NOT_SUPPORTED_SRE(AssemblyBuilder::InternalAddModule); return NULL; } } /* namespace Emit */ } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection.Emit/AssemblyBuilder.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppString; struct mscorlib_System_Reflection_Emit_AssemblyBuilder; struct mscorlib_System_Reflection_Module; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { namespace Emit { class LIBIL2CPP_CODEGEN_API AssemblyBuilder { public: static void basic_init(mscorlib_System_Reflection_Emit_AssemblyBuilder*); static mscorlib_System_Reflection_Module* InternalAddModule(mscorlib_System_Reflection_Emit_AssemblyBuilder * thisPtr, Il2CppString* fileName); }; } /* namespace Emit */ } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection.Emit/CustomAttributeBuilder.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Reflection.Emit/CustomAttributeBuilder.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { namespace Emit { Il2CppArray* CustomAttributeBuilder::GetBlob(Il2CppAssembly* asmb, void* /* System.Reflection.ConstructorInfo */ con, Il2CppArray* constructorArgs, Il2CppArray* namedProperties, Il2CppArray* propertyValues, Il2CppArray* namedFields, Il2CppArray* fieldValues) { NOT_SUPPORTED_SRE(CustomAttributeBuilder::GetBlob); return NULL; } } /* namespace Emit */ } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection.Emit/CustomAttributeBuilder.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { namespace Emit { class LIBIL2CPP_CODEGEN_API CustomAttributeBuilder { public: static Il2CppArray* GetBlob(Il2CppAssembly* asmb, void* /* System.Reflection.ConstructorInfo */ con, Il2CppArray* constructorArgs, Il2CppArray* namedProperties, Il2CppArray* propertyValues, Il2CppArray* namedFields, Il2CppArray* fieldValues); }; } /* namespace Emit */ } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection.Emit/DerivedType.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Reflection.Emit/DerivedType.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { namespace Emit { void DerivedType::create_unmanaged_type(Il2CppReflectionType* type) { NOT_SUPPORTED_SRE(DerivedType::create_unmanaged_type); } } /* namespace Emit */ } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection.Emit/DerivedType.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppReflectionType; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { namespace Emit { class LIBIL2CPP_CODEGEN_API DerivedType { public: static void create_unmanaged_type(Il2CppReflectionType* type); }; } /* namespace Emit */ } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection.Emit/DynamicMethod.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Reflection.Emit/DynamicMethod.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { namespace Emit { void DynamicMethod::create_dynamic_method(Il2CppReflectionDynamicMethod*, Il2CppReflectionDynamicMethod*) { NOT_SUPPORTED_SRE(DynamicMethod::create_dynamic_method); } void DynamicMethod::destroy_dynamic_method(Il2CppReflectionDynamicMethod*, Il2CppReflectionDynamicMethod*) { NOT_SUPPORTED_SRE(DynamicMethod::destroy_dynamic_method); } } /* namespace Emit */ } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection.Emit/DynamicMethod.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppReflectionDynamicMethod; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { namespace Emit { class LIBIL2CPP_CODEGEN_API DynamicMethod { public: static void create_dynamic_method(Il2CppReflectionDynamicMethod*, Il2CppReflectionDynamicMethod*); static void destroy_dynamic_method(Il2CppReflectionDynamicMethod*, Il2CppReflectionDynamicMethod*); }; } /* namespace Emit */ } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection.Emit/EnumBuilder.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Reflection.Emit/EnumBuilder.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { namespace Emit { void EnumBuilder::setup_enum_type(Il2CppReflectionType *enumtype, Il2CppReflectionType* t) { NOT_SUPPORTED_SRE(EnumBuilder::setup_enum_type); } } /* namespace Emit */ } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection.Emit/EnumBuilder.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppReflectionType; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { namespace Emit { class LIBIL2CPP_CODEGEN_API EnumBuilder { public: static void setup_enum_type(Il2CppReflectionType *enumtype, Il2CppReflectionType* t); }; } /* namespace Emit */ } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection.Emit/GenericTypeParameterBuilder.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Reflection.Emit/GenericTypeParameterBuilder.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { namespace Emit { void GenericTypeParameterBuilder::initialize(Il2CppReflectionGenericParam* genericParameter) { NOT_SUPPORTED_SRE(GenericTypeParameterBuilder::initialize); } } /* namespace Emit */ } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection.Emit/GenericTypeParameterBuilder.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppReflectionGenericParam; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { namespace Emit { class LIBIL2CPP_CODEGEN_API GenericTypeParameterBuilder { public: static void initialize(Il2CppReflectionGenericParam* genericParameter); }; } /* namespace Emit */ } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection.Emit/MethodBuilder.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Reflection.Emit/MethodBuilder.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { namespace Emit { Il2CppReflectionMethod* MethodBuilder::MakeGenericMethod(Il2CppReflectionMethod*, Il2CppArray*) { NOT_SUPPORTED_SRE(MethodBuilder::MakeGenericMethod); return NULL; } } /* namespace Emit */ } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection.Emit/MethodBuilder.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppArray; struct Il2CppReflectionMethod; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { namespace Emit { class LIBIL2CPP_CODEGEN_API MethodBuilder { public: static Il2CppReflectionMethod* MakeGenericMethod(Il2CppReflectionMethod*, Il2CppArray*); }; } /* namespace Emit */ } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection.Emit/ModuleBuilder.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Reflection.Emit/ModuleBuilder.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { namespace Emit { void ModuleBuilder::basic_init(Il2CppReflectionModuleBuilder*) { NOT_SUPPORTED_SRE(ModuleBuilder::basic_init); } void ModuleBuilder::RegisterToken(Il2CppReflectionModuleBuilder*, Il2CppObject*, int) { NOT_SUPPORTED_SRE(ModuleBuilder::RegisterToken); } void ModuleBuilder::set_wrappers_type(Il2CppReflectionModuleBuilder*, Il2CppReflectionType*) { NOT_SUPPORTED_SRE(ModuleBuilder::set_wrappers_type); } Il2CppReflectionType * ModuleBuilder::create_modified_type(Il2CppReflectionTypeBuilder*, Il2CppString*) { NOT_SUPPORTED_SRE(ModuleBuilder::create_modified_type); return NULL; } int32_t ModuleBuilder::getUSIndex(Il2CppReflectionModuleBuilder*, Il2CppString* str) { NOT_SUPPORTED_SRE(ModuleBuilder::getUSIndex); return 0; } int32_t ModuleBuilder::getToken(Il2CppReflectionModuleBuilder*, Il2CppObject * obj) { NOT_SUPPORTED_SRE(ModuleBuilder::getToken); return 0; } int32_t ModuleBuilder::getMethodToken(Il2CppReflectionModuleBuilder*, Il2CppReflectionMethod*, Il2CppArray*) { NOT_SUPPORTED_SRE(ModuleBuilder::getMethodToken); return 0; } void ModuleBuilder::build_metadata(Il2CppReflectionModuleBuilder*) { NOT_SUPPORTED_SRE(ModuleBuilder::build_metadata); } void ModuleBuilder::WriteToFile(Il2CppReflectionModuleBuilder*, Il2CppIntPtr) { NOT_SUPPORTED_SRE(ModuleBuilder::WriteToFile); } #if NET_4_0 int32_t ModuleBuilder::getMethodToken40(Il2CppObject* mb, Il2CppObject* method, Il2CppArray* opt_param_types) { NOT_IMPLEMENTED_ICALL(ModuleBuilder::getMethodToken40); IL2CPP_UNREACHABLE; return 0; } int32_t ModuleBuilder::getToken40(Il2CppObject* mb, Il2CppObject* obj, bool create_open_instance) { NOT_IMPLEMENTED_ICALL(ModuleBuilder::getToken40); IL2CPP_UNREACHABLE; return 0; } Il2CppObject* ModuleBuilder::GetRegisteredToken(Il2CppObject* _this, int32_t token) { NOT_IMPLEMENTED_ICALL(ModuleBuilder::GetRegisteredToken); IL2CPP_UNREACHABLE; return NULL; } #endif } /* namespace Emit */ } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection.Emit/ModuleBuilder.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; struct Il2CppArray; struct Il2CppString; struct Il2CppReflectionMethod; struct Il2CppReflectionModuleBuilder; struct Il2CppReflectionTypeBuilder; struct Il2CppReflectionType; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { namespace Emit { class LIBIL2CPP_CODEGEN_API ModuleBuilder { public: static void RegisterToken(Il2CppReflectionModuleBuilder*, Il2CppObject*, int); static void WriteToFile(Il2CppReflectionModuleBuilder*, Il2CppIntPtr); static void basic_init(Il2CppReflectionModuleBuilder*); static void build_metadata(Il2CppReflectionModuleBuilder*); static Il2CppReflectionType * create_modified_type(Il2CppReflectionTypeBuilder*, Il2CppString*); static int32_t getToken(Il2CppReflectionModuleBuilder*, Il2CppObject*); static int32_t getUSIndex(Il2CppReflectionModuleBuilder*, Il2CppString*); static void set_wrappers_type(Il2CppReflectionModuleBuilder*, Il2CppReflectionType*); static int32_t getMethodToken(Il2CppReflectionModuleBuilder*, Il2CppReflectionMethod*, Il2CppArray*); #if NET_4_0 static int32_t getMethodToken40(Il2CppObject* mb, Il2CppObject* method, Il2CppArray* opt_param_types); static int32_t getToken40(Il2CppObject* mb, Il2CppObject* obj, bool create_open_instance); static Il2CppObject* GetRegisteredToken(Il2CppObject* _this, int32_t token); #endif }; } /* namespace Emit */ } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection.Emit/SignatureHelper.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Reflection.Emit/SignatureHelper.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { namespace Emit { Il2CppArray* SignatureHelper::get_signature_local(Il2CppReflectionSigHelper*) { NOT_SUPPORTED_SRE(SignatureHelper::get_signature_local); return NULL; } Il2CppArray* SignatureHelper::get_signature_field(Il2CppReflectionSigHelper*) { NOT_SUPPORTED_SRE(SignatureHelper::get_signature_field); return NULL; } } /* namespace Emit */ } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection.Emit/SignatureHelper.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppArray; struct Il2CppReflectionSigHelper; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { namespace Emit { class LIBIL2CPP_CODEGEN_API SignatureHelper { public: static Il2CppArray* get_signature_field(Il2CppReflectionSigHelper*); static Il2CppArray* get_signature_local(Il2CppReflectionSigHelper*); }; } /* namespace Emit */ } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection.Emit/SymbolType.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "SymbolType.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { namespace Emit { void SymbolType::create_unmanaged_type(Il2CppObject* type) { NOT_IMPLEMENTED_ICALL(SymbolType::create_unmanaged_type); IL2CPP_UNREACHABLE; } } // namespace Emit } // namespace Reflection } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection.Emit/SymbolType.h ================================================ #if NET_4_0 #pragma once namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { namespace Emit { class LIBIL2CPP_CODEGEN_API SymbolType { public: static void create_unmanaged_type(Il2CppObject* type); }; } // namespace Emit } // namespace Reflection } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection.Emit/TypeBuilder.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Reflection.Emit/TypeBuilder.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { namespace Emit { void TypeBuilder::create_generic_class(Il2CppReflectionTypeBuilder*) { NOT_SUPPORTED_SRE(TypeBuilder::create_generic_class); } Il2CppReflectionType* TypeBuilder::create_runtime_class(Il2CppReflectionTypeBuilder*, Il2CppReflectionTypeBuilder*) { NOT_SUPPORTED_SRE(TypeBuilder::create_runtime_class); return NULL; } Il2CppReflectionEvent* TypeBuilder::get_event_info(Il2CppReflectionTypeBuilder*, Il2CppReflectionEventBuilder*) { NOT_SUPPORTED_SRE(TypeBuilder::get_event_info); return NULL; } bool TypeBuilder::get_IsGenericParameter(Il2CppReflectionTypeBuilder*) { NOT_SUPPORTED_SRE(TypeBuilder::get_IsGenericParameter); return false; } void TypeBuilder::setup_internal_class(Il2CppReflectionTypeBuilder*, Il2CppReflectionTypeBuilder*) { NOT_SUPPORTED_SRE(TypeBuilder::setup_internal_class); } void TypeBuilder::create_internal_class(Il2CppReflectionTypeBuilder* tb) { NOT_SUPPORTED_SRE(TypeBuilder::create_internal_class); } void TypeBuilder::setup_generic_class(Il2CppReflectionTypeBuilder*) { NOT_SUPPORTED_SRE(TypeBuilder::setup_generic_class); } } /* namespace Emit */ } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Reflection.Emit/TypeBuilder.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppReflectionEvent; struct Il2CppReflectionEventBuilder; struct Il2CppReflectionType; struct Il2CppReflectionTypeBuilder; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Reflection { namespace Emit { class LIBIL2CPP_CODEGEN_API TypeBuilder { public: static void create_generic_class(Il2CppReflectionTypeBuilder*); static void create_internal_class(Il2CppReflectionTypeBuilder*); static Il2CppReflectionType* create_runtime_class(Il2CppReflectionTypeBuilder*, Il2CppReflectionTypeBuilder*); static bool get_IsGenericParameter(Il2CppReflectionTypeBuilder*); static Il2CppReflectionEvent* get_event_info(Il2CppReflectionTypeBuilder*, Il2CppReflectionEventBuilder*); static void setup_generic_class(Il2CppReflectionTypeBuilder*); static void setup_internal_class(Il2CppReflectionTypeBuilder*, Il2CppReflectionTypeBuilder*); }; } /* namespace Emit */ } /* namespace Reflection */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Runtime.CompilerServices/RuntimeHelpers.cpp ================================================ #include "il2cpp-config.h" #include #include "object-internals.h" #include "class-internals.h" #include "tabledefs.h" #include "vm/Array.h" #include "vm/Class.h" #include "vm/Exception.h" #include "vm/Field.h" #include "vm/Runtime.h" #include "vm/Type.h" #include "icalls/mscorlib/System.Runtime.CompilerServices/RuntimeHelpers.h" using namespace il2cpp::vm; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Runtime { namespace CompilerServices { int RuntimeHelpers::get_OffsetToStringData(void) { return offsetof(Il2CppString, chars); } void RuntimeHelpers::InitializeArray(Il2CppArray * array, Il2CppIntPtr ptr) { FieldInfo* field_handle = (FieldInfo*)ptr.m_value; Il2CppClass *klass = array->klass; uint32_t size = Array::GetElementSize(klass); const Il2CppType *type = Type::GetUnderlyingType(klass->element_class->byval_arg); const char *field_data; if (Type::IsReference(type) || (type->type == IL2CPP_TYPE_VALUETYPE && (!Type::GetClass(type) || Type::GetClass(type)->has_references))) { Il2CppException *exc = Exception::GetArgumentException("array", "Cannot initialize array containing references"); Exception::Raise(exc); } if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) { Il2CppException *exc = Exception::GetArgumentException("field_handle", "Field doesn't have an RVA"); Exception::Raise(exc); } size *= array->max_length; field_data = Field::GetData(field_handle); NOT_IMPLEMENTED_ICALL_NO_ASSERT(RuntimeHelpers::InitializeArray, "Check type size"); //int align; //if (size > mono_type_size (field_handle->type, &align)) { // MonoException *exc = mono_get_exception_argument("field_handle", // "Field not large enough to fill array"); // mono_raise_exception (exc); //} NOT_IMPLEMENTED_ICALL_NO_ASSERT(RuntimeHelpers::InitializeArray, "Ignoring Endianess"); memcpy(il2cpp_array_addr(array, char, 0), field_data, size); } Il2CppObject* RuntimeHelpers::GetObjectValue(Il2CppObject* obj) { NOT_SUPPORTED_IL2CPP(RuntimeHelpers::GetObjectValue, "This icall is not supported by il2cpp."); return 0; } void RuntimeHelpers::RunClassConstructor(Il2CppIntPtr type) { IL2CPP_CHECK_ARG_NULL(type.m_value); Il2CppClass* klass = Class::FromIl2CppType((const Il2CppType*)type.m_value); //MONO_CHECK_ARG(handle, klass); il2cpp::vm::Runtime::ClassInit(klass); } void RuntimeHelpers::RunModuleConstructor(Il2CppIntPtr module) { NOT_SUPPORTED_IL2CPP(RuntimeHelpers::RunModuleConstructor, "This icall is not supported by il2cpp."); } #if NET_4_0 bool RuntimeHelpers::SufficientExecutionStack() { NOT_IMPLEMENTED_ICALL(RuntimeHelpers::SufficientExecutionStack); IL2CPP_UNREACHABLE; return false; } #endif } /* namespace CompilerServices */ } /* namespace Runtime */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Runtime.CompilerServices/RuntimeHelpers.h ================================================ #pragma once #include "il2cpp-config.h" #include "object-internals.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Runtime { namespace CompilerServices { class LIBIL2CPP_CODEGEN_API RuntimeHelpers { public: static Il2CppObject* GetObjectValue(Il2CppObject* obj); static void RunClassConstructor(Il2CppIntPtr type); static void RunModuleConstructor(Il2CppIntPtr module); static int get_OffsetToStringData(void); static void InitializeArray(Il2CppArray* arr, Il2CppIntPtr ptr); #if NET_4_0 static bool SufficientExecutionStack(); #endif }; } /* namespace CompilerServices */ } /* namespace Runtime */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Runtime.InteropServices/GCHandle.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "icalls/mscorlib/System.Runtime.InteropServices/GCHandle.h" #include "gc/GCHandle.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Runtime { namespace InteropServices { bool GCHandle::CheckCurrentDomain(int32_t handle) { return true; // il2cpp doesn't support multiple domains } void GCHandle::FreeHandle(int32_t handle) { gc::GCHandle::Free(handle); } static inline Il2CppIntPtr MakeIntPtr(uint8_t* value) { Il2CppIntPtr ptr; ptr.m_value = reinterpret_cast(value); return ptr; } // Returns -2 if gchandle is not pinned Il2CppIntPtr GCHandle::GetAddrOfPinnedObject(int32_t handle) { gc::GCHandleType type = gc::GCHandle::GetHandleType(handle); if (type != gc::HANDLE_PINNED) return MakeIntPtr(reinterpret_cast(-2)); // mscorlib on managed land expects us to return "-2" as IntPtr if this condition occurs Il2CppObject* obj = gc::GCHandle::GetTarget(handle); if (obj == NULL) return MakeIntPtr(NULL); ptrdiff_t offset; if (obj->klass->rank > 0) { // Pointer to first array element offset = kIl2CppSizeOfArray; } else if (obj->klass->byval_arg->type == IL2CPP_TYPE_STRING) { // Pointer to first character offset = offsetof(Il2CppString, chars); } else { // Pointer to struct in boxed object offset = sizeof(Il2CppObject); } return MakeIntPtr(reinterpret_cast(obj) + offset); } Il2CppObject* GCHandle::GetTarget(int32_t handle) { return gc::GCHandle::GetTarget(handle); } static inline bool IsObjectPinnable(Il2CppObject* obj) { if (obj == NULL) return true; Il2CppClass* klass = obj->klass; if (klass->byval_arg->type == IL2CPP_TYPE_ARRAY || klass->byval_arg->type == IL2CPP_TYPE_SZARRAY) { Il2CppClass* elementClass = klass->element_class; return elementClass->is_blittable || elementClass->byval_arg->type == IL2CPP_TYPE_CHAR || // while "char" and "bool" are not blittable, we can still pin their arrays elementClass->byval_arg->type == IL2CPP_TYPE_BOOLEAN; } if (klass->byval_arg->type == IL2CPP_TYPE_CHAR || klass->byval_arg->type == IL2CPP_TYPE_BOOLEAN || klass->byval_arg->type == IL2CPP_TYPE_STRING) return true; return klass->is_blittable; } int32_t GCHandle::GetTargetHandle(Il2CppObject* obj, int32_t handle, int32_t type) { if (type == gc::HANDLE_PINNED && !IsObjectPinnable(obj)) { Il2CppException* ex = vm::Exception::GetArgumentException(NULL, "Object contains non-primitive or non-blittable data."); vm::Exception::Raise(ex); } return gc::GCHandle::GetTargetHandle(obj, handle, type); } } /* namespace InteropServices */ } /* namespace Runtime */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Runtime.InteropServices/GCHandle.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Runtime { namespace InteropServices { class LIBIL2CPP_CODEGEN_API GCHandle { public: static bool CheckCurrentDomain(int32_t handle); static void FreeHandle(int32_t handle); static Il2CppIntPtr GetAddrOfPinnedObject(int32_t handle); static Il2CppObject * GetTarget(int32_t handle); static int32_t GetTargetHandle(Il2CppObject * obj, int32_t handle, int32_t type); }; } /* namespace InteropServices */ } /* namespace Runtime */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Runtime.InteropServices/Marshal.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Runtime.InteropServices/Marshal.h" #include "class-internals.h" #include "tabledefs.h" #include "gc/GarbageCollector.h" #include "metadata/FieldLayout.h" #include "vm/Array.h" #include "vm/Class.h" #include "vm/Exception.h" #include "vm/Field.h" #include "vm/Image.h" #include "vm/LastError.h" #include "vm/MarshalAlloc.h" #include "vm/Object.h" #include "vm/PlatformInvoke.h" #include "vm/RCW.h" #include "vm/String.h" #include "vm/Type.h" #include "utils/MarshalingUtils.h" #include "utils/StringUtils.h" #include #include #include #include using namespace il2cpp::vm; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Runtime { namespace InteropServices { int32_t Marshal::AddRefInternal(Il2CppIntPtr pUnk) { return static_cast(pUnk.m_value)->AddRef(); } Il2CppIntPtr Marshal::AllocCoTaskMem(int32_t size) { Il2CppIntPtr result; result.m_value = MarshalAlloc::Allocate(size); return result; } Il2CppIntPtr Marshal::AllocHGlobal(Il2CppIntPtr size) { Il2CppIntPtr result; result.m_value = MarshalAlloc::AllocateHGlobal((size_t)size.m_value); return result; } void Marshal::copy_from_unmanaged(Il2CppIntPtr source, int startIndex, Il2CppArray * destination, int length) { uint32_t element_size = (uint32_t)il2cpp_array_element_size(destination->klass); memcpy(il2cpp_array_addr_with_size(destination, element_size, startIndex), source.m_value, length * element_size); } void Marshal::copy_to_unmanaged(Il2CppArray * source, int32_t startIndex, Il2CppIntPtr destination, int32_t length) { uint32_t element_size = (uint32_t)il2cpp_array_element_size(source->klass); memcpy(destination.m_value, il2cpp_array_addr_with_size(source, element_size, startIndex), length * element_size); } void Marshal::FreeBSTR(Il2CppIntPtr ptr) { NOT_SUPPORTED_IL2CPP(Marshal::StringToBSTR, "BSTR icalls are not supported."); } void Marshal::FreeCoTaskMem(Il2CppIntPtr ptr) { MarshalAlloc::Free(ptr.m_value); } void Marshal::FreeHGlobal(Il2CppIntPtr hglobal) { MarshalAlloc::FreeHGlobal(hglobal.m_value); } bool Marshal::IsComObject(Il2CppObject* o) { return o->klass->is_import_or_windows_runtime; } Il2CppIntPtr Marshal::GetCCW(Il2CppObject* o, Il2CppReflectionType * T) { NOT_SUPPORTED_IL2CPP(Marshal::GetCCW, "COM icalls are not supported."); return Il2CppIntPtr::Zero; } int32_t Marshal::GetComSlotForMethodInfoInternal(mscorlib_System_Reflection_MemberInfo * m) { NOT_SUPPORTED_IL2CPP(Marshal::GetComSlotForMethodInfoInternal, "COM icalls are not supported."); return 0; } Il2CppDelegate* Marshal::GetDelegateForFunctionPointerInternal(Il2CppIntPtr ptr, Il2CppReflectionType* t) { Il2CppClass* delegateType = il2cpp::vm::Class::FromIl2CppType(t->type); return PlatformInvoke::MarshalFunctionPointerToDelegate(ptr.m_value, delegateType); } Il2CppIntPtr Marshal::GetFunctionPointerForDelegateInternal(Il2CppDelegate* d) { return vm::PlatformInvoke::MarshalDelegate(d); } Il2CppIntPtr Marshal::GetIDispatchForObjectInternal(Il2CppObject* o) { NOT_SUPPORTED_IL2CPP(Marshal::GetIDispatchForObjectInternal, "COM icalls are not supported."); return Il2CppIntPtr::Zero; } Il2CppIntPtr Marshal::GetIUnknownForObjectInternal(Il2CppObject* o) { NOT_SUPPORTED_IL2CPP(Marshal::GetIUnknownForObjectInternal, "This icall is not supported by il2cpp. Use the il2cpp_codegen_com_get_iunknown_for_object intrinsic instead."); return Il2CppIntPtr::Zero; } Il2CppObject* Marshal::GetObjectForCCW(Il2CppIntPtr pUnk) { if (pUnk.m_value == NULL) return NULL; return RCW::GetOrCreateFromIUnknown(static_cast(pUnk.m_value), il2cpp_defaults.il2cpp_com_object_class); } Il2CppString* Marshal::PtrToStringBSTR(Il2CppIntPtr ptr) { NOT_SUPPORTED_IL2CPP(Marshal::PtrToStringBSTR, "COM icalls are not supported."); return 0; } Il2CppString* Marshal::PtrToStringAnsi_mscorlib_System_String_mscorlib_System_IntPtr(Il2CppIntPtr ptr) { char* value = (char*)ptr.m_value; if (value == NULL) return NULL; return String::New(value); } Il2CppString* Marshal::PtrToStringAnsi_mscorlib_System_String_mscorlib_System_IntPtr_mscorlib_System_Int32(Il2CppIntPtr ptr, int32_t len) { char* value = (char*)ptr.m_value; if (value == NULL) Exception::Raise(Exception::GetArgumentNullException("ptr")); return String::NewLen(value, len); } Il2CppString* Marshal::PtrToStringUni_mscorlib_System_String_mscorlib_System_IntPtr(Il2CppIntPtr ptr) { Il2CppChar* value = static_cast(ptr.m_value); if (value == NULL) return NULL; int32_t len = 0; Il2CppChar* t = value; while (*t++) len++; return String::NewUtf16(value, len); } Il2CppString* Marshal::PtrToStringUni_mscorlib_System_String_mscorlib_System_IntPtr_mscorlib_System_Int32(Il2CppIntPtr ptr, int32_t len) { Il2CppChar* value = static_cast(ptr.m_value); if (value == NULL) Exception::Raise(Exception::GetArgumentNullException("ptr")); return String::NewUtf16(value, len); } Il2CppObject* Marshal::PtrToStructure(Il2CppIntPtr ptr, Il2CppReflectionType* structureType) { if (ptr.m_value == NULL) return NULL; if (structureType == NULL) Exception::Raise(Exception::GetArgumentNullException("structureType")); Il2CppClass* type = Class::FromIl2CppType(structureType->type); Il2CppTypeEnum typeType = structureType->type->type; if (typeType == IL2CPP_TYPE_STRING || typeType == IL2CPP_TYPE_SZARRAY || (typeType == IL2CPP_TYPE_CLASS && !Class::HasDefaultConstructor(type))) { Exception::Raise(Exception::GetMissingMethodException("No parameterless constructor defined for this object.")); } if (type->interopData != NULL && type->interopData->pinvokeMarshalFromNativeFunction != NULL) { Il2CppObject* result = Object::New(type); if (typeType == IL2CPP_TYPE_CLASS) { typedef void (*Constructor)(Il2CppObject*); Constructor ctor = reinterpret_cast(Class::GetMethodFromName(type, ".ctor", 0)->methodPointer); ctor(result); utils::MarshalingUtils::MarshalStructFromNative(ptr.m_value, result, type->interopData); } else { utils::MarshalingUtils::MarshalStructFromNative(ptr.m_value, Object::Unbox(result), type->interopData); } return result; } // If there's no custom marshal function, it means it's either a primitive, or invalid argument if (type->native_size != -1) { // We may also need to throw a NotSupportedException for an ArgIterator. if (structureType->type->type == IL2CPP_TYPE_VOID) Exception::Raise(Exception::GetNotSupportedException("Cannot dynamically create an instance of System.Void.")); // PtrToStructure is supposed to throw on enums if (!type->enumtype) { Il2CppObject* result = Object::New(type); memcpy(Object::Unbox(result), ptr.m_value, type->native_size); return result; } } // If we got this far, throw an exception if (type->generic_class != NULL || type->is_generic) Exception::Raise(Exception::GetArgumentException("structure", "The specified object must not be an instance of a generic type.")); Exception::Raise(Exception::GetArgumentException("structure", "The specified structure must be blittable or have layout information.")); return NULL; } void Marshal::PtrToStructureObject(Il2CppIntPtr ptr, Il2CppObject* structure) { if (ptr.m_value == NULL) return; if (structure == NULL) Exception::Raise(Exception::GetArgumentNullException("structure")); Il2CppClass* type = structure->klass; // This is only legal for classes. if (type->byval_arg->type != IL2CPP_TYPE_CLASS) { Exception::Raise(Exception::GetArgumentException("structure", "The specified structure must be an instance of a formattable class.")); } if (type->interopData != NULL && type->interopData->pinvokeMarshalFromNativeFunction != NULL) { utils::MarshalingUtils::MarshalStructFromNative(ptr.m_value, structure, type->interopData); return; } if (type->generic_class || type->is_generic) Exception::Raise(Exception::GetArgumentException("structure", "The specified object must not be an instance of a generic type.")); Exception::Raise(Exception::GetArgumentException("structure", "The specified structure must be blittable or have layout information.")); } int32_t Marshal::QueryInterfaceInternal(Il2CppIntPtr pUnk, mscorlib_System_Guid * iid, Il2CppIntPtr* ppv) { NOT_SUPPORTED_IL2CPP(Marshal::QueryInterfaceInternal, "COM icalls are not supported."); return 0; } template static inline T ReadValue(Il2CppIntPtr ptr, int32_t offset) { return *reinterpret_cast(static_cast(ptr.m_value) + offset); } uint8_t Marshal::ReadByte(Il2CppIntPtr ptr, int32_t ofs) { return ReadValue(ptr, ofs); } int16_t Marshal::ReadInt16(Il2CppIntPtr ptr, int32_t ofs) { return ReadValue(ptr, ofs); } int32_t Marshal::ReadInt32(Il2CppIntPtr ptr, int32_t ofs) { return ReadValue(ptr, ofs); } int64_t Marshal::ReadInt64(Il2CppIntPtr ptr, int32_t ofs) { return ReadValue(ptr, ofs); } Il2CppIntPtr Marshal::ReadIntPtr(Il2CppIntPtr ptr, int32_t ofs) { return ReadValue(ptr, ofs); } int32_t Marshal::ReleaseInternal(Il2CppIntPtr pUnk) { return static_cast(pUnk.m_value)->Release(); } int32_t Marshal::ReleaseComObjectInternal(Il2CppObject* co) { // There's a check in mscorlib before calling this internal icall, so assert instead of full check is OK here. IL2CPP_ASSERT(co->klass->is_import_or_windows_runtime); // We can't really release the COM object directly, because it might have additional // fields that cache different interfaces. So let's just call its finalizer here. // In order to deal with the fact that this may get called from different threads // at the same time, we (atomically) register a NULL finalizer, and if another finalizer // was already registered, we call it. If there was no finalizer registered, it means // that we lost the race and we should just carry on. gc::GarbageCollector::FinalizerCallback oldFinalizer = gc::GarbageCollector::RegisterFinalizerWithCallback(co, NULL); if (oldFinalizer != NULL) oldFinalizer(co, NULL); return 0; } int Marshal::SizeOf(Il2CppReflectionType* rtype) { if (rtype == NULL) Exception::Raise(Exception::GetArgumentNullException("t")); Il2CppClass* typeInfo = Class::FromIl2CppType(rtype->type); if (typeInfo->native_size != -1) { // SizeOf "cannot" get size of enums and strings if (!typeInfo->enumtype && rtype->type->type != IL2CPP_TYPE_STRING) return typeInfo->native_size; } // If we get to here, type does not have a native size // So let's figure what kind of exception to throw if (typeInfo->generic_class != NULL || typeInfo->is_generic) Exception::Raise(Exception::GetArgumentException("t", "The t parameter is a generic type.")); std::string exceptionMessage = utils::StringUtils::Printf("Type \'%s\' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.", Type::GetName(rtype->type, IL2CPP_TYPE_NAME_FORMAT_FULL_NAME).c_str()); Exception::Raise(Exception::GetArgumentException(NULL, exceptionMessage.c_str())); return 0; } Il2CppIntPtr Marshal::StringToBSTR(Il2CppString* s) { NOT_SUPPORTED_IL2CPP(Marshal::StringToBSTR, "BSTR icalls are not supported."); return Il2CppIntPtr::Zero; } Il2CppIntPtr Marshal::StringToHGlobalUni(Il2CppString* s) { if (s == NULL) return Il2CppIntPtr::Zero; int32_t size = utils::StringUtils::GetLength(s); const Il2CppChar* utf16 = utils::StringUtils::GetChars(s); size_t bytes = (size + 1) * 2; Il2CppChar* cstr = static_cast(MarshalAlloc::AllocateHGlobal(bytes)); memcpy(cstr, utf16, bytes); Il2CppIntPtr result; result.m_value = cstr; return result; } Il2CppIntPtr Marshal::StringToHGlobalAnsi(Il2CppString* s) { if (s == NULL) return Il2CppIntPtr::Zero; const Il2CppChar* utf16 = utils::StringUtils::GetChars(s); std::string str = il2cpp::utils::StringUtils::Utf16ToUtf8(utf16); char *cstr = (char*)MarshalAlloc::AllocateHGlobal(str.size() + 1); strcpy(cstr, str.c_str()); Il2CppIntPtr result; result.m_value = cstr; return result; } void Marshal::StructureToPtr(Il2CppObject* structure, Il2CppIntPtr ptr, bool deleteOld) { if (structure == NULL) Exception::Raise(Exception::GetArgumentNullException("structure")); if (ptr.m_value == NULL) Exception::Raise(Exception::GetArgumentNullException("ptr")); Il2CppClass* type = structure->klass; if (type->interopData != NULL && type->interopData->pinvokeMarshalToNativeFunction != NULL) { if (deleteOld) utils::MarshalingUtils::MarshalFreeStruct(ptr.m_value, type->interopData); void* objectPtr = (type->byval_arg->type == IL2CPP_TYPE_CLASS) ? structure : Object::Unbox(structure); utils::MarshalingUtils::MarshalStructToNative(objectPtr, ptr.m_value, type->interopData); return; } // If there's no custom marshal function, it means it's either a primitive, or invalid argument if (type->native_size != -1) { // StructureToPtr is supposed to throw on strings and enums if (!type->enumtype && type->byval_arg->type != IL2CPP_TYPE_STRING) { memcpy(ptr.m_value, Object::Unbox(structure), type->native_size); return; } } // If we got this far, throw an exception Il2CppException* exception; if (type->generic_class != NULL || type->is_generic) { exception = Exception::GetArgumentException("structure", "The specified object must not be an instance of a generic type."); } else { exception = Exception::GetArgumentException("structure", "The specified structure must be blittable or have layout information."); } Exception::Raise(exception); } template static inline void WriteValue(Il2CppIntPtr ptr, int32_t offset, T value) { *reinterpret_cast(static_cast(ptr.m_value) + offset) = value; } void Marshal::WriteByte(Il2CppIntPtr ptr, int32_t ofs, uint8_t val) { WriteValue(ptr, ofs, val); } void Marshal::WriteInt16(Il2CppIntPtr ptr, int32_t ofs, int16_t val) { WriteValue(ptr, ofs, val); } void Marshal::WriteInt32(Il2CppIntPtr ptr, int32_t ofs, int32_t val) { WriteValue(ptr, ofs, val); } void Marshal::WriteInt64(Il2CppIntPtr ptr, int32_t ofs, int64_t val) { WriteValue(ptr, ofs, val); } void Marshal::WriteIntPtr(Il2CppIntPtr ptr, int32_t ofs, Il2CppIntPtr val) { WriteValue(ptr, ofs, val); } void Marshal::DestroyStructure(Il2CppIntPtr ptr, Il2CppReflectionType* structureType) { if (ptr.m_value == NULL) Exception::Raise(Exception::GetArgumentNullException("ptr")); if (structureType == NULL) Exception::Raise(Exception::GetArgumentNullException("structureType")); Il2CppClass* type = Class::FromIl2CppType(structureType->type); // If cleanup function exists, it will call it and return true // In that case, we're done. if (utils::MarshalingUtils::MarshalFreeStruct(ptr.m_value, type->interopData)) return; if (type->is_generic) { Exception::Raise(Exception::GetArgumentException("structureType", "The specified type must not be an instance of a generic type.")); } // Enums are blittable, but they don't have layout information, therefore Marshal.DestroyStructure is supposed to throw if (!type->enumtype) { // Char and Boolean are not blittable, but they should not raise this exception, as we can call DestroyStructure on them without problems. if (type->is_blittable || structureType->type->type == IL2CPP_TYPE_CHAR || structureType->type->type == IL2CPP_TYPE_BOOLEAN) return; } // If we got this far, throw an exception Exception::Raise(Exception::GetArgumentException("structureType", "The specified type must be blittable or have layout information.")); } int32_t Marshal::GetLastWin32Error() { return vm::LastError::GetLastError(); } static size_t RoundUpToMultiple(size_t numToRound, size_t multiple) { if (multiple == 0) return numToRound; size_t remainder = numToRound % multiple; if (remainder == 0) return numToRound; return numToRound + multiple - remainder; } Il2CppIntPtr Marshal::OffsetOf(Il2CppReflectionType* t, Il2CppString* fieldName) { std::string fieldNameToFind = utils::StringUtils::Utf16ToUtf8(fieldName->chars); Il2CppClass* type = Class::FromIl2CppType(t->type); FieldInfo* field = vm::Class::GetFieldFromName(type, fieldNameToFind.c_str()); if (field == NULL || (vm::Field::GetFlags(field) & FIELD_ATTRIBUTE_STATIC)) { std::stringstream message; message << "Field '" << fieldNameToFind << "' is not a marshaled member of the type '" << type->name << "'"; vm::Exception::Raise(vm::Exception::GetArgumentException("fieldName", message.str().c_str())); } // Order the base classes so the most base class is first. std::deque inheritanceHierarchy; while (type) { inheritanceHierarchy.push_front(type); type = type->parent; } bool fieldFound = false; size_t offset = 0; FieldInfo* previousField = NULL; for (std::deque::iterator it = inheritanceHierarchy.begin(); it < inheritanceHierarchy.end(); ++it) { type = *it; void* iter = NULL; while ((field = vm::Class::GetFields(type, &iter))) { if (vm::Field::GetFlags(field) & FIELD_ATTRIBUTE_STATIC) continue; // Determine how much the previous field added to the offset. if (previousField != NULL) { if (!Type::IsStruct(previousField->type)) { size_t managedOffset = field->offset - previousField->offset; if (type->packingSize == 0) offset += managedOffset; else if (managedOffset != 0) // overlapping fields have a zero offset { offset += vm::Class::GetFieldMarshaledSize(previousField); offset = RoundUpToMultiple(offset, std::min((int)type->packingSize, vm::Class::GetFieldMarshaledSize(field))); } } else { offset += Class::FromIl2CppType(previousField->type)->native_size; } } previousField = field; if (fieldNameToFind == vm::Field::GetName(field)) { fieldFound = true; break; } } if (fieldFound) break; } Il2CppIntPtr offsetPtr; offsetPtr.m_value = (void*)(offset); return offsetPtr; } void Marshal::Prelink(Il2CppReflectionMethod* m) { NOT_SUPPORTED_IL2CPP(Marshal::Prelink, "This icall is not supported by il2cpp."); } void Marshal::PrelinkAll(Il2CppReflectionType* c) { NOT_SUPPORTED_IL2CPP(Marshal::PrelinkAll, "This icall is not supported by il2cpp."); } Il2CppIntPtr Marshal::ReAllocCoTaskMem(Il2CppIntPtr ptr, int32_t size) { Il2CppIntPtr result; result.m_value = MarshalAlloc::ReAlloc(ptr.m_value, size); return result; } Il2CppIntPtr Marshal::ReAllocHGlobal(Il2CppIntPtr ptr, Il2CppIntPtr size) { if (ptr.m_value == NULL) Exception::RaiseOutOfMemoryException(); Il2CppIntPtr result; result.m_value = MarshalAlloc::ReAllocHGlobal(ptr.m_value, (size_t)size.m_value); return result; } Il2CppIntPtr Marshal::UnsafeAddrOfPinnedArrayElement(Il2CppArray* arr, int32_t index) { Il2CppIntPtr address; address.m_value = il2cpp_array_addr_with_size(arr, il2cpp_array_element_size(arr->klass), index); return address; } #if NET_4_0 Il2CppIntPtr Marshal::BufferToBSTR(Il2CppArray* ptr, int32_t slen) { NOT_IMPLEMENTED_ICALL(Marshal::BufferToBSTR); IL2CPP_UNREACHABLE; } int32_t Marshal::GetHRForException_WinRT(Il2CppException* e) { NOT_IMPLEMENTED_ICALL(Marshal::GetHRForException_WinRT); IL2CPP_UNREACHABLE; } Il2CppIntPtr Marshal::GetRawIUnknownForComObjectNoAddRef(Il2CppObject* o) { IL2CPP_ASSERT(o->klass->is_import_or_windows_runtime); Il2CppIntPtr result = { static_cast(o)->identity }; return result; } Il2CppObject* Marshal::GetNativeActivationFactory(Il2CppObject* type) { NOT_IMPLEMENTED_ICALL(Marshal::GetNativeActivationFactory); IL2CPP_UNREACHABLE; } #endif } /* namespace InteropServices */ } /* namespace Runtime */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Runtime.InteropServices/Marshal.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct mscorlib_System_Guid; struct mscorlib_System_Reflection_MemberInfo; struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppString; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Runtime { namespace InteropServices { class LIBIL2CPP_CODEGEN_API Marshal { public: static int32_t GetLastWin32Error(); static int32_t AddRefInternal(Il2CppIntPtr pUnk); static Il2CppIntPtr AllocCoTaskMem(int32_t size); static Il2CppIntPtr AllocHGlobal(Il2CppIntPtr size); static void DestroyStructure(Il2CppIntPtr ptr, Il2CppReflectionType* structureType); static void FreeBSTR(Il2CppIntPtr ptr); static void FreeCoTaskMem(Il2CppIntPtr ptr); static void FreeHGlobal(Il2CppIntPtr hglobal); static Il2CppIntPtr GetCCW(Il2CppObject* o, Il2CppReflectionType * T); static int32_t GetComSlotForMethodInfoInternal(mscorlib_System_Reflection_MemberInfo * m); static Il2CppDelegate* GetDelegateForFunctionPointerInternal(Il2CppIntPtr ptr, Il2CppReflectionType* t); static Il2CppIntPtr GetFunctionPointerForDelegateInternal(Il2CppDelegate* d); static Il2CppIntPtr GetIDispatchForObjectInternal(Il2CppObject* o); static Il2CppIntPtr GetIUnknownForObjectInternal(Il2CppObject* o); static Il2CppObject* GetObjectForCCW(Il2CppIntPtr pUnk); static bool IsComObject(Il2CppObject* o); static Il2CppIntPtr OffsetOf(Il2CppReflectionType* t, Il2CppString* fieldName); static void Prelink(Il2CppReflectionMethod* m); static void PrelinkAll(Il2CppReflectionType* c); static Il2CppString* PtrToStringAnsi_mscorlib_System_String_mscorlib_System_IntPtr(Il2CppIntPtr ptr); static Il2CppString* PtrToStringAnsi_mscorlib_System_String_mscorlib_System_IntPtr_mscorlib_System_Int32(Il2CppIntPtr ptr, int32_t len); static Il2CppString* PtrToStringBSTR(Il2CppIntPtr ptr); static Il2CppString* PtrToStringUni_mscorlib_System_String_mscorlib_System_IntPtr(Il2CppIntPtr ptr); static Il2CppString* PtrToStringUni_mscorlib_System_String_mscorlib_System_IntPtr_mscorlib_System_Int32(Il2CppIntPtr ptr, int32_t len); static Il2CppObject* PtrToStructure(Il2CppIntPtr ptr, Il2CppReflectionType * structureType); static void PtrToStructureObject(Il2CppIntPtr ptr, Il2CppObject* structure); static int32_t QueryInterfaceInternal(Il2CppIntPtr pUnk, mscorlib_System_Guid * iid, Il2CppIntPtr* ppv); static Il2CppIntPtr ReAllocCoTaskMem(Il2CppIntPtr ptr, int32_t size); static Il2CppIntPtr ReAllocHGlobal(Il2CppIntPtr ptr, Il2CppIntPtr size); static uint8_t ReadByte(Il2CppIntPtr ptr, int32_t ofs); static int16_t ReadInt16(Il2CppIntPtr ptr, int32_t ofs); static int32_t ReadInt32(Il2CppIntPtr ptr, int32_t ofs); static int64_t ReadInt64(Il2CppIntPtr ptr, int32_t ofs); static Il2CppIntPtr ReadIntPtr(Il2CppIntPtr ptr, int32_t ofs); static int32_t ReleaseComObjectInternal(Il2CppObject* co); static int32_t ReleaseInternal(Il2CppIntPtr pUnk); static int SizeOf(Il2CppReflectionType * rtype); static Il2CppIntPtr StringToBSTR(Il2CppString* s); static Il2CppIntPtr StringToHGlobalAnsi(Il2CppString* s); static Il2CppIntPtr StringToHGlobalUni(Il2CppString* s); static void StructureToPtr(Il2CppObject* structure, Il2CppIntPtr ptr, bool deleteOld); static Il2CppIntPtr UnsafeAddrOfPinnedArrayElement(Il2CppArray* arr, int32_t index); static void WriteByte(Il2CppIntPtr ptr, int32_t ofs, uint8_t val); static void WriteInt16(Il2CppIntPtr ptr, int32_t ofs, int16_t val); static void WriteInt32(Il2CppIntPtr ptr, int32_t ofs, int32_t val); static void WriteInt64(Il2CppIntPtr ptr, int32_t ofs, int64_t val); static void copy_from_unmanaged(Il2CppIntPtr, int, Il2CppArray *, int); static void copy_to_unmanaged(Il2CppArray * source, int32_t startIndex, Il2CppIntPtr destination, int32_t length); static void WriteIntPtr(Il2CppIntPtr ptr, int32_t ofs, Il2CppIntPtr val); #if NET_4_0 static Il2CppIntPtr BufferToBSTR(Il2CppArray* ptr, int32_t slen); #endif #if NET_4_0 static int32_t GetHRForException_WinRT(Il2CppException* e); static Il2CppIntPtr GetRawIUnknownForComObjectNoAddRef(Il2CppObject* o); static Il2CppObject* GetNativeActivationFactory(Il2CppObject* type); #endif }; } /* namespace InteropServices */ } /* namespace Runtime */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Runtime.InteropServices.WindowsRuntime/UnsafeNativeMethods.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "UnsafeNativeMethods.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Runtime { namespace InteropServices { namespace WindowsRuntime { bool UnsafeNativeMethods::RoOriginateLanguageException(int32_t error, Il2CppString* message, Il2CppIntPtr languageException) { NOT_IMPLEMENTED_ICALL(UnsafeNativeMethods::RoOriginateLanguageException); IL2CPP_UNREACHABLE; } Il2CppChar* UnsafeNativeMethods::WindowsGetStringRawBuffer(Il2CppIntPtr hstring, uint32_t* length) { NOT_IMPLEMENTED_ICALL(UnsafeNativeMethods::WindowsGetStringRawBuffer); IL2CPP_UNREACHABLE; } int32_t UnsafeNativeMethods::WindowsCreateString(Il2CppString* sourceString, int32_t length, Il2CppIntPtr* hstring) { NOT_IMPLEMENTED_ICALL(UnsafeNativeMethods::WindowsCreateString); IL2CPP_UNREACHABLE; } int32_t UnsafeNativeMethods::WindowsDeleteString(Il2CppIntPtr hstring) { NOT_IMPLEMENTED_ICALL(UnsafeNativeMethods::WindowsDeleteString); IL2CPP_UNREACHABLE; } Il2CppObject* UnsafeNativeMethods::GetRestrictedErrorInfo() { NOT_IMPLEMENTED_ICALL(UnsafeNativeMethods::GetRestrictedErrorInfo); IL2CPP_UNREACHABLE; } void UnsafeNativeMethods::RoReportUnhandledError(Il2CppObject* error) { NOT_IMPLEMENTED_ICALL(UnsafeNativeMethods::RoReportUnhandledError); IL2CPP_UNREACHABLE; } } // namespace WindowsRuntime } // namespace InteropServices } // namespace Runtime } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Runtime.InteropServices.WindowsRuntime/UnsafeNativeMethods.h ================================================ #pragma once #if NET_4_0 #include "object-internals.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Runtime { namespace InteropServices { namespace WindowsRuntime { class LIBIL2CPP_CODEGEN_API UnsafeNativeMethods { public: static bool RoOriginateLanguageException(int32_t error, Il2CppString* message, Il2CppIntPtr languageException); static Il2CppChar* WindowsGetStringRawBuffer(Il2CppIntPtr hstring, uint32_t* length); static int32_t WindowsCreateString(Il2CppString* sourceString, int32_t length, Il2CppIntPtr* hstring); static int32_t WindowsDeleteString(Il2CppIntPtr hstring); static Il2CppObject* GetRestrictedErrorInfo(); static void RoReportUnhandledError(Il2CppObject* error); }; } // namespace WindowsRuntime } // namespace InteropServices } // namespace Runtime } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Runtime.Remoting/RemotingServices.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Runtime.Remoting/RemotingServices.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Runtime { namespace Remoting { Il2CppReflectionMethod* RemotingServices::GetVirtualMethod(Il2CppReflectionType*, Il2CppReflectionMethod*) { NOT_SUPPORTED_REMOTING(RemotingServices::GetVirtualMethod); return NULL; } Il2CppObject* RemotingServices::InternalExecute(Il2CppReflectionMethod*, Il2CppObject*, Il2CppArray*, Il2CppArray**) { NOT_SUPPORTED_REMOTING(RemotingServices::InternalExecute); return NULL; } bool RemotingServices::IsTransparentProxy(Il2CppObject*) { return false; } } /* namespace Remoting */ } /* namespace Runtime */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Runtime.Remoting/RemotingServices.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppArray; struct Il2CppObject; struct Il2CppReflectionMethod; struct Il2CppReflectionType; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Runtime { namespace Remoting { class LIBIL2CPP_CODEGEN_API RemotingServices { public: static Il2CppReflectionMethod * GetVirtualMethod(Il2CppReflectionType*, Il2CppReflectionMethod*); static Il2CppObject* InternalExecute(Il2CppReflectionMethod*, Il2CppObject*, Il2CppArray*, Il2CppArray**); static bool IsTransparentProxy(Il2CppObject*); }; } /* namespace Remoting */ } /* namespace Runtime */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Runtime.Remoting.Activation/ActivationServices.cpp ================================================ #include "il2cpp-config.h" #include "il2cpp-api.h" #include "icalls/mscorlib/System.Runtime.Remoting.Activation/ActivationServices.h" #include "object-internals.h" #include "class-internals.h" #include "metadata.h" #include "vm/Image.h" #include "vm/Class.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Runtime { namespace Remoting { namespace Activation { void ActivationServices::EnableProxyActivation(Il2CppReflectionType*, bool) { NOT_SUPPORTED_REMOTING(ActivationServices::EnableProxyActivation); } Il2CppObject* ActivationServices::AllocateUninitializedClassInstance(Il2CppReflectionType * type) { Il2CppClass* typeInfo = vm::Class::FromIl2CppType(type->type); if (typeInfo == NULL) return NULL; il2cpp::vm::Class::Init(typeInfo); return il2cpp_object_new(typeInfo); } } /* namespace Activation */ } /* namespace Remoting */ } /* namespace Runtime */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Runtime.Remoting.Activation/ActivationServices.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppObject; struct Il2CppReflectionType; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Runtime { namespace Remoting { namespace Activation { class LIBIL2CPP_CODEGEN_API ActivationServices { public: static void EnableProxyActivation(Il2CppReflectionType*, bool); static Il2CppObject * AllocateUninitializedClassInstance(Il2CppReflectionType*); }; } /* namespace Activation */ } /* namespace Remoting */ } /* namespace Runtime */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Runtime.Remoting.Contexts/Context.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "Context.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Runtime { namespace Remoting { namespace Contexts { void Context::RegisterContext(Il2CppObject* ctx) { NOT_IMPLEMENTED_ICALL(Context::RegisterContext); IL2CPP_UNREACHABLE; } void Context::ReleaseContext(Il2CppObject* ctx) { NOT_IMPLEMENTED_ICALL(Context::ReleaseContext); IL2CPP_UNREACHABLE; } } // namespace Contexts } // namespace Remoting } // namespace Runtime } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Runtime.Remoting.Contexts/Context.h ================================================ #pragma once #if NET_4_0 namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Runtime { namespace Remoting { namespace Contexts { class LIBIL2CPP_CODEGEN_API Context { public: static void RegisterContext(Il2CppObject* ctx); static void ReleaseContext(Il2CppObject* ctx); }; } // namespace Contexts } // namespace Remoting } // namespace Runtime } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Runtime.Remoting.Messaging/AsyncResult.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "object-internals.h" #include "il2cpp-api.h" #include "AsyncResult.h" #include "vm/Runtime.h" #include "vm/WaitHandle.h" #include "vm/ThreadPoolMs.h" #include "os/Event.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Runtime { namespace Remoting { namespace Messaging { Il2CppObject* AsyncResult::Invoke(Il2CppObject* _this) { Il2CppAsyncCall *ac; Il2CppObject *res; Il2CppAsyncResult *ares = (Il2CppAsyncResult*)_this; IL2CPP_ASSERT(ares); IL2CPP_ASSERT(ares->async_delegate); ac = (Il2CppAsyncCall*)ares->object_data; if (!ac) { res = vm::Runtime::DelegateInvoke(ares->async_delegate, (void**)&ares->async_state, NULL); } else { il2cpp::os::EventHandle *wait_event = NULL; ac->msg->exc = NULL; res = il2cpp::vm::ThreadPoolMs::MessageInvoke((Il2CppObject*)ares->async_delegate->target, ac->msg, &ac->msg->exc, &ac->out_args); IL2CPP_OBJECT_SETREF(ac, res, res); il2cpp_monitor_enter((Il2CppObject*)ares); ares->completed = 1; if (ares->handle) wait_event = (il2cpp::os::EventHandle*)il2cpp::vm::WaitHandle::GetPlatformHandle(ares->handle); il2cpp_monitor_exit((Il2CppObject*)ares); if (wait_event != NULL) wait_event->Get().Set(); Il2CppException* completionException = NULL; if (ac->cb_method) vm::Runtime::Invoke(ac->cb_method, ac->cb_target, (void**)&ares, &completionException); if (completionException != NULL) vm::Exception::Raise(completionException); } return res; } } // namespace Messaging } // namespace Remoting } // namespace Runtime } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Runtime.Remoting.Messaging/AsyncResult.h ================================================ #pragma once #if NET_4_0 namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Runtime { namespace Remoting { namespace Messaging { class LIBIL2CPP_CODEGEN_API AsyncResult { public: static Il2CppObject* Invoke(Il2CppObject* _this); }; } // namespace Messaging } // namespace Remoting } // namespace Runtime } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Runtime.Remoting.Messaging/MonoMethodMessage.cpp ================================================ #include "il2cpp-config.h" #include "il2cpp-api.h" #include "class-internals.h" #include "object-internals.h" #include "tabledefs.h" #include "icalls/mscorlib/System.Runtime.Remoting.Messaging/MonoMethodMessage.h" #include "vm/Exception.h" #include "vm/Atomic.h" #include "vm/Array.h" #include "vm/String.h" #include "utils/dynamic_array.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Runtime { namespace Remoting { namespace Messaging { void MonoMethodMessage::InitMessage(Il2CppMethodMessage *this_obj, Il2CppReflectionMethod *method, Il2CppArray *out_args) { #if !NET_4_0 NOT_SUPPORTED_REMOTING(MonoMethodMessage::InitMessage); #else static Il2CppClass *object_array_klass; static Il2CppClass *byte_array_klass; static Il2CppClass *string_array_klass; Il2CppString *name; Il2CppArray *arr; int i, j; unsigned char arg_type; if (!object_array_klass) { Il2CppClass *klass; klass = il2cpp_array_class_get(il2cpp_defaults.byte_class, 1); IL2CPP_ASSERT(klass); byte_array_klass = klass; klass = il2cpp_array_class_get(il2cpp_defaults.string_class, 1); IL2CPP_ASSERT(klass); string_array_klass = klass; klass = il2cpp_array_class_get(il2cpp_defaults.object_class, 1); IL2CPP_ASSERT(klass); il2cpp::vm::Atomic::ExchangePointer(&object_array_klass, klass); } IL2CPP_OBJECT_SETREF(this_obj, method, method); arr = il2cpp_array_new(object_array_klass, method->method->parameters_count); IL2CPP_OBJECT_SETREF(this_obj, args, arr); arr = il2cpp_array_new(byte_array_klass, method->method->parameters_count); IL2CPP_OBJECT_SETREF(this_obj, arg_types, arr); this_obj->async_result = NULL; this_obj->call_type = CallType_Sync; il2cpp::utils::dynamic_array names(method->method->parameters_count); for (int i = 0; i < method->method->parameters_count; ++i) names[i] = method->method->parameters[i].name; arr = il2cpp_array_new(string_array_klass, method->method->parameters_count); IL2CPP_OBJECT_SETREF(this_obj, names, arr); for (i = 0; i < method->method->parameters_count; i++) { name = il2cpp::vm::String::New(names[i]); il2cpp_array_setref(this_obj->names, i, name); } for (i = 0, j = 0; i < method->method->parameters_count; i++) { if (method->method->parameters[i].parameter_type->byref) { if (out_args) { Il2CppObject* arg = (Il2CppObject*)il2cpp_array_get(out_args, void*, j); il2cpp_array_setref(this_obj->args, i, arg); j++; } arg_type = 2; if (!(method->method->parameters[i].parameter_type->attrs & PARAM_ATTRIBUTE_OUT)) arg_type |= 1; } else { arg_type = 1; if (method->method->parameters[i].parameter_type->attrs & PARAM_ATTRIBUTE_OUT) arg_type |= 4; } il2cpp_array_set(this_obj->arg_types, unsigned char, i, arg_type); } #endif } } /* namespace Messaging */ } /* namespace Remoting */ } /* namespace Runtime */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Runtime.Remoting.Messaging/MonoMethodMessage.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppArray; struct Il2CppMethodMessage; struct Il2CppReflectionMethod; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Runtime { namespace Remoting { namespace Messaging { class LIBIL2CPP_CODEGEN_API MonoMethodMessage { public: static void InitMessage(Il2CppMethodMessage*, Il2CppReflectionMethod*, Il2CppArray*); }; } /* namespace Messaging */ } /* namespace Remoting */ } /* namespace Runtime */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Runtime.Remoting.Proxies/RealProxy.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Runtime.Remoting.Proxies/RealProxy.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Runtime { namespace Remoting { namespace Proxies { Il2CppObject* RealProxy::InternalGetTransparentProxy(Il2CppObject*, Il2CppString*) { NOT_SUPPORTED_REMOTING(RealProxy::InternalGetTransparentProxy); return NULL; } Il2CppReflectionType* RealProxy::InternalGetProxyType(Il2CppObject *) { NOT_SUPPORTED_REMOTING(RealProxy::InternalGetProxyType); return NULL; } } /* namespace Proxies */ } /* namespace Remoting */ } /* namespace Runtime */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Runtime.Remoting.Proxies/RealProxy.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppObject; struct Il2CppReflectionType; struct Il2CppString; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Runtime { namespace Remoting { namespace Proxies { class LIBIL2CPP_CODEGEN_API RealProxy { public: static Il2CppObject* InternalGetTransparentProxy(Il2CppObject*, Il2CppString*); static Il2CppReflectionType* InternalGetProxyType(Il2CppObject*); }; } /* namespace Proxies */ } /* namespace Remoting */ } /* namespace Runtime */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Runtime.Versioning/VersioningHelper.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "VersioningHelper.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Runtime { namespace Versioning { int32_t VersioningHelper::GetRuntimeId() { NOT_IMPLEMENTED_ICALL(VersioningHelper::GetRuntimeId); IL2CPP_UNREACHABLE; return 0; } } // namespace Versioning } // namespace Runtime } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Runtime.Versioning/VersioningHelper.h ================================================ #pragma once #if NET_4_0 namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Runtime { namespace Versioning { class LIBIL2CPP_CODEGEN_API VersioningHelper { public: static int32_t GetRuntimeId(); }; } // namespace Versioning } // namespace Runtime } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Security/SecurityFrame.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Security/SecurityFrame.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Security { Il2CppArray * SecurityFrame::_GetSecurityStack(int32_t skip) { NOT_IMPLEMENTED_ICALL(SecurityManager::get_CheckExecutionRights); return 0; } void* /* System.Security.RuntimeSecurityFrame */ SecurityFrame::_GetSecurityFrame(int32_t skip) { NOT_SUPPORTED_IL2CPP(SecurityFrame::_GetSecurityFrame, "This icall is not supported by il2cpp."); return 0; } } /* namespace Security */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Security/SecurityFrame.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppArray; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Security { class LIBIL2CPP_CODEGEN_API SecurityFrame { public: static void* /* System.Security.RuntimeSecurityFrame */ _GetSecurityFrame(int32_t skip); static Il2CppArray * _GetSecurityStack(int32_t skip); }; } /* namespace Security */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Security/SecurityManager.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Security/SecurityManager.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Security { bool SecurityManager::get_CheckExecutionRights() { NOT_IMPLEMENTED_ICALL(SecurityManager::get_CheckExecutionRights); return false; } bool SecurityManager::GetLinkDemandSecurity(mscorlib_System_Reflection_MethodBase * method, mscorlib_System_Security_RuntimeDeclSecurityActions * _____cdecl, mscorlib_System_Security_RuntimeDeclSecurityActions * mdecl) { NOT_IMPLEMENTED_ICALL(SecurityManager::GetLinkDemandSecurity); return false; } bool SecurityManager::get_SecurityEnabled() { return false; } void SecurityManager::set_CheckExecutionRights(bool value) { NOT_SUPPORTED_IL2CPP(SecurityManager::set_CheckExecutionRights, "This icall is not supported by il2cpp."); } void SecurityManager::set_SecurityEnabled(bool value) { NOT_SUPPORTED_IL2CPP(SecurityManager::set_SecurityEnabled, "This icall is not supported by il2cpp."); } } /* namespace Security */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Security/SecurityManager.h ================================================ #pragma once #include "il2cpp-config.h" #include "object-internals.h" struct mscorlib_System_Reflection_MethodBase; struct mscorlib_System_Security_RuntimeDeclSecurityActions; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Security { class LIBIL2CPP_CODEGEN_API SecurityManager { public: static bool get_CheckExecutionRights(); static void set_CheckExecutionRights(bool value); static void set_SecurityEnabled(bool value); static bool GetLinkDemandSecurity(mscorlib_System_Reflection_MethodBase * method, mscorlib_System_Security_RuntimeDeclSecurityActions * _____cdecl, mscorlib_System_Security_RuntimeDeclSecurityActions * mdecl); static bool get_SecurityEnabled(); }; } /* namespace Security */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Security.Cryptography/RNGCryptoServiceProvider.cpp ================================================ #include "il2cpp-config.h" #include "il2cpp-api.h" #include "vm/Array.h" #include "os/Cryptography.h" #include "utils/Memory.h" #include "icalls/mscorlib/System.Security.Cryptography/RNGCryptoServiceProvider.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Security { namespace Cryptography { void RNGCryptoServiceProvider::RngClose(Il2CppIntPtr provider) { os::Cryptography::ReleaseCryptographyProvider(provider.m_value); } Il2CppIntPtr RNGCryptoServiceProvider::RngGetBytes(Il2CppIntPtr provider, Il2CppArray *data) { uint32_t len = il2cpp_array_length(data); unsigned char* buf = il2cpp_array_addr(data, unsigned char, 0); if (!os::Cryptography::FillBufferWithRandomBytes(provider.m_value, len, buf)) { os::Cryptography::ReleaseCryptographyProvider(provider.m_value); provider = RngInitialize(NULL); if (!os::Cryptography::FillBufferWithRandomBytes(provider.m_value, len, buf)) { os::Cryptography::ReleaseCryptographyProvider(provider.m_value); return Il2CppIntPtr::Zero; } } return provider; } Il2CppIntPtr RNGCryptoServiceProvider::RngInitialize(Il2CppArray *seed) { Il2CppIntPtr provider; provider.m_value = os::Cryptography::GetCryptographyProvider(); if ((provider.m_value != 0) && seed) { uint32_t len = il2cpp_array_length(seed); unsigned char *buf = il2cpp_array_addr(seed, unsigned char, 0); unsigned char* data = (unsigned char*)IL2CPP_MALLOC(len); if (data) { memcpy(data, buf, len); os::Cryptography::FillBufferWithRandomBytes(provider.m_value, len, data); memset(data, 0, len); IL2CPP_FREE(data); } } return provider; } bool RNGCryptoServiceProvider::RngOpen() { return os::Cryptography::OpenCryptographyProvider(); } } /* namespace Cryptography */ } /* namespace Security */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Security.Cryptography/RNGCryptoServiceProvider.h ================================================ #pragma once #include "il2cpp-config.h" #include "object-internals.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Security { namespace Cryptography { class LIBIL2CPP_CODEGEN_API RNGCryptoServiceProvider { public: static void RngClose(Il2CppIntPtr handle); static Il2CppIntPtr RngGetBytes(Il2CppIntPtr, Il2CppArray *); static Il2CppIntPtr RngInitialize(Il2CppArray *); static bool RngOpen(); }; } /* namespace Cryptography */ } /* namespace Security */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Security.Policy/Evidence.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Security.Policy/Evidence.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Security { namespace Policy { bool Evidence::IsAuthenticodePresent(Il2CppAssembly* a) { NOT_SUPPORTED_IL2CPP(Evidence::IsAuthenticodePresent, "This icall is not supported by il2cpp."); return false; } } /* namespace Policy */ } /* namespace Security */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Security.Policy/Evidence.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Security { namespace Policy { class LIBIL2CPP_CODEGEN_API Evidence { public: static bool IsAuthenticodePresent(Il2CppAssembly* a); }; } /* namespace Policy */ } /* namespace Security */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Security.Principal/WindowsIdentity.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Security.Principal/WindowsIdentity.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Security { namespace Principal { Il2CppString* WindowsIdentity::GetTokenName(Il2CppIntPtr token) { NOT_IMPLEMENTED_ICALL(WindowsIdentity::GetTokenName); return 0; } Il2CppIntPtr WindowsIdentity::GetCurrentToken() { NOT_IMPLEMENTED_ICALL(WindowsIdentity::GetCurrentToken); return Il2CppIntPtr(); } Il2CppArray* WindowsIdentity::_GetRoles(Il2CppIntPtr token) { NOT_SUPPORTED_IL2CPP(WindowsIdentity::_GetRoles, "This icall is not supported by il2cpp."); return 0; } Il2CppIntPtr WindowsIdentity::GetUserToken(Il2CppString* username) { NOT_SUPPORTED_IL2CPP(WindowsIdentity::GetUserToken, "This icall is not supported by il2cpp."); return Il2CppIntPtr(); } } /* namespace Principal */ } /* namespace Security */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Security.Principal/WindowsIdentity.h ================================================ #pragma once #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppString; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Security { namespace Principal { class LIBIL2CPP_CODEGEN_API WindowsIdentity { public: static Il2CppIntPtr GetUserToken(Il2CppString* username); static Il2CppArray* _GetRoles(Il2CppIntPtr token); static Il2CppString* GetTokenName(Il2CppIntPtr token); static Il2CppIntPtr GetCurrentToken(); }; } /* namespace Principal */ } /* namespace Security */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Security.Principal/WindowsImpersonationContext.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Security.Principal/WindowsImpersonationContext.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Security { namespace Principal { bool WindowsImpersonationContext::CloseToken(Il2CppIntPtr token) { NOT_SUPPORTED_IL2CPP(WindowsImpersonationContext::CloseToken, "This icall is not supported by il2cpp."); return false; } Il2CppIntPtr WindowsImpersonationContext::DuplicateToken(Il2CppIntPtr token) { NOT_SUPPORTED_IL2CPP(WindowsImpersonationContext::DuplicateToken, "This icall is not supported by il2cpp."); return Il2CppIntPtr(); } bool WindowsImpersonationContext::SetCurrentToken(Il2CppIntPtr token) { NOT_SUPPORTED_IL2CPP(WindowsImpersonationContext::SetCurrentToken, "This icall is not supported by il2cpp."); return false; } bool WindowsImpersonationContext::RevertToSelf() { NOT_SUPPORTED_IL2CPP(WindowsImpersonationContext::RevertToSelf, "This icall is not supported by il2cpp."); return false; } } /* namespace Principal */ } /* namespace Security */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Security.Principal/WindowsImpersonationContext.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Security { namespace Principal { class LIBIL2CPP_CODEGEN_API WindowsImpersonationContext { public: static bool RevertToSelf(); static Il2CppIntPtr DuplicateToken(Il2CppIntPtr token); static bool SetCurrentToken(Il2CppIntPtr token); static bool CloseToken(Il2CppIntPtr token); }; } /* namespace Principal */ } /* namespace Security */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Security.Principal/WindowsPrincipal.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Security.Principal/WindowsPrincipal.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Security { namespace Principal { bool WindowsPrincipal::IsMemberOfGroupId(Il2CppIntPtr user, Il2CppIntPtr group) { NOT_SUPPORTED_IL2CPP(WindowsPrincipal::IsMemberOfGroupId, "This icall is not supported by il2cpp."); return false; } bool WindowsPrincipal::IsMemberOfGroupName(Il2CppIntPtr user, Il2CppString* group) { NOT_SUPPORTED_IL2CPP(WindowsPrincipal::IsMemberOfGroupName, "This icall is not supported by il2cpp."); return false; } } /* namespace Principal */ } /* namespace Security */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Security.Principal/WindowsPrincipal.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Security { namespace Principal { class LIBIL2CPP_CODEGEN_API WindowsPrincipal { public: static bool IsMemberOfGroupName(Il2CppIntPtr user, Il2CppString* group); static bool IsMemberOfGroupId(Il2CppIntPtr user, Il2CppIntPtr group); }; } /* namespace Principal */ } /* namespace Security */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Text/Encoding.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Text/Encoding.h" #include #include #include "os/Encoding.h" #include "vm/String.h" #include "utils/StringUtils.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Text { static const char *encodings[] = { (char*)1, "ascii", "us_ascii", "us", "ansi_x3.4_1968", "ansi_x3.4_1986", "cp367", "csascii", "ibm367", "iso_ir_6", "iso646_us", "iso_646.irv:1991", (char*)2, "utf_7", "csunicode11utf7", "unicode_1_1_utf_7", "unicode_2_0_utf_7", "x_unicode_1_1_utf_7", "x_unicode_2_0_utf_7", (char*)3, "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8", "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8", (char*)4, "utf_16", "UTF_16LE", "ucs_2", "unicode", "iso_10646_ucs2", (char*)5, "unicodefffe", "utf_16be", (char*)6, "iso_8859_1", (char*)0 }; Il2CppString* Encoding::InternalCodePage(int32_t *resultCodePage) { const int32_t want_name = *resultCodePage; *resultCodePage = -1; const std::string charSet = os::Encoding::GetCharSet(); std::string codepage(charSet); for (size_t i = 0, length = codepage.length(); i < length; ++i) { char& c = codepage[i]; if (isalpha(c)) c = tolower(c); if (c == '-') c = '_'; } // handle some common aliases const char* p = encodings[0]; int code = 0; for (size_t i = 0; p != 0;) { if ((size_t)p < 7) { code = (int)(size_t)p; p = encodings[++i]; continue; } if (codepage == p) { *resultCodePage = code; break; } p = encodings[++i]; } if (codepage.find("utf_8") != std::string::npos) *resultCodePage |= 0x10000000; if (want_name && *resultCodePage == -1) return il2cpp::vm::String::NewWrapper(charSet.c_str()); else return NULL; } } /* namespace Text */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Text/Encoding.h ================================================ #pragma once #include "il2cpp-config.h" #include struct Il2CppString; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Text { class LIBIL2CPP_CODEGEN_API Encoding { public: static Il2CppString* InternalCodePage(int32_t *codePage); }; } /* namespace Text */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Text/EncodingHelper.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "EncodingHelper.h" #include "Encoding.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Text { Il2CppString* EncodingHelper::InternalCodePage(int32_t* code_page) { return Encoding::InternalCodePage(code_page); } } // namespace Text } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Text/EncodingHelper.h ================================================ #pragma once #if NET_4_0 namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Text { class LIBIL2CPP_CODEGEN_API EncodingHelper { public: static Il2CppString* InternalCodePage(int32_t* code_page); }; } // namespace Text } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Text/Normalization.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "Normalization.h" #include "icalls/mscorlib/Mono.Globalization.Unicode/Normalization.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Text { void Normalization::load_normalization_resource(Il2CppIntPtr* props, Il2CppIntPtr* mappedChars, Il2CppIntPtr* charMapIndex, Il2CppIntPtr* helperIndex, Il2CppIntPtr* mapIdxToComposite, Il2CppIntPtr* combiningClass) { icalls::mscorlib::Mono::Globalization::Unicode::Normalization::load_normalization_resource(props, mappedChars, charMapIndex, helperIndex, mapIdxToComposite, combiningClass); } } // namespace Text } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Text/Normalization.h ================================================ #pragma once #if NET_4_0 #include "object-internals.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Text { class LIBIL2CPP_CODEGEN_API Normalization { public: static void load_normalization_resource(Il2CppIntPtr* props, Il2CppIntPtr* mappedChars, Il2CppIntPtr* charMapIndex, Il2CppIntPtr* helperIndex, Il2CppIntPtr* mapIdxToComposite, Il2CppIntPtr* combiningClass); }; } // namespace Text } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Threading/Interlocked.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Threading/Interlocked.h" #include #include "os/Atomic.h" #include "os/Mutex.h" #include "vm/Exception.h" using namespace il2cpp::os; union LongDoubleUnion { int64_t l_val; double d_val; }; union IntFloatUnion { int32_t i_val; float f_val; }; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Threading { #if !IL2CPP_ENABLE_INTERLOCKED_64_REQUIRED_ALIGNMENT static FastMutex m_Atomic64Mutex; #endif void* Interlocked::CompareExchange_T(void** location, void* value, void* comparand) { return Atomic::CompareExchangePointer(location, value, comparand); } Il2CppIntPtr Interlocked::CompareExchangeIntPtr(Il2CppIntPtr* location, Il2CppIntPtr value, Il2CppIntPtr comparand) { Il2CppIntPtr result; result.m_value = Atomic::CompareExchangePointer(&location->m_value, value.m_value, comparand.m_value); return result; } int32_t Interlocked::CompareExchange(int32_t* location, int32_t value, int32_t comparand) { return Atomic::CompareExchange(location, value, comparand); } int64_t Interlocked::CompareExchange64(int64_t* location, int64_t value, int64_t comparand) { #if IL2CPP_ENABLE_INTERLOCKED_64_REQUIRED_ALIGNMENT return Atomic::CompareExchange64(location, value, comparand); #else FastAutoLock lock(&m_Atomic64Mutex); int64_t orig = *location; if (*location == comparand) *location = value; return orig; #endif } int32_t Interlocked::Add(int32_t* location1, int32_t value) { return Atomic::Add(location1, value); } int64_t Interlocked::Add64(int64_t* location1, int64_t value) { #if IL2CPP_ENABLE_INTERLOCKED_64_REQUIRED_ALIGNMENT return Atomic::Add64(location1, value); #else FastAutoLock lock(&m_Atomic64Mutex); return *location1 += value; #endif } double Interlocked::CompareExchangeDouble(double* location1, double value, double comparand) { LongDoubleUnion val, ret, cmp; cmp.d_val = comparand; val.d_val = value; ret.l_val = (int64_t)Atomic::CompareExchange64((int64_t*)location1, val.l_val, cmp.l_val); return ret.d_val; } float Interlocked::CompareExchangeSingle(float* location1, float value, float comparand) { IntFloatUnion val, ret, cmp; cmp.f_val = comparand; val.f_val = value; ret.i_val = (int32_t)Atomic::CompareExchange((int32_t*)location1, val.i_val, cmp.i_val); return ret.f_val; } int32_t Interlocked::Increment(int32_t* value) { return Atomic::Increment(value); } int64_t Interlocked::Increment64(int64_t* location) { #if IL2CPP_ENABLE_INTERLOCKED_64_REQUIRED_ALIGNMENT return Atomic::Increment64(location); #else FastAutoLock lock(&m_Atomic64Mutex); return ++(*location); #endif } int32_t Interlocked::Decrement(int32_t* location) { return Atomic::Decrement(location); } int64_t Interlocked::Decrement64(int64_t* location) { #if IL2CPP_ENABLE_INTERLOCKED_64_REQUIRED_ALIGNMENT return Atomic::Decrement64(location); #else FastAutoLock lock(&m_Atomic64Mutex); return --(*location); #endif } double Interlocked::ExchangeDouble(double* location1, double value) { LongDoubleUnion val, ret; val.d_val = value; ret.l_val = (int64_t)Atomic::Exchange64((int64_t*)location1, val.l_val); return ret.d_val; } Il2CppIntPtr Interlocked::ExchangeIntPtr(Il2CppIntPtr* location, Il2CppIntPtr value) { Il2CppIntPtr result; result.m_value = Atomic::ExchangePointer(&location->m_value, value.m_value); return result; } int32_t Interlocked::Exchange(int32_t* location1, int32_t value) { return Atomic::Exchange(location1, value); } int64_t Interlocked::Exchange64(int64_t* location1, int64_t value) { #if IL2CPP_ENABLE_INTERLOCKED_64_REQUIRED_ALIGNMENT return Atomic::Exchange64(location1, value); #else FastAutoLock lock(&m_Atomic64Mutex); int64_t orig = *location1; *location1 = value; return orig; #endif } void* Interlocked::ExchangePointer(void** location1, void* value) { return Atomic::ExchangePointer(location1, value); } float Interlocked::ExchangeSingle(float* location1, float value) { IntFloatUnion val, ret; val.f_val = value; ret.i_val = (int32_t)Atomic::Exchange((int32_t*)location1, val.i_val); return ret.f_val; } int64_t Interlocked::Read(int64_t* location) { #if IL2CPP_ENABLE_INTERLOCKED_64_REQUIRED_ALIGNMENT return Atomic::Read64(location); #else FastAutoLock lock(&m_Atomic64Mutex); return *location; #endif } #if NET_4_0 int32_t Interlocked::CompareExchange(int32_t* location1, int32_t value, int32_t comparand, bool* succeeded) { int32_t result = CompareExchange(location1, value, comparand); *succeeded = result == comparand; return result; } #endif } /* namespace Threading */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Threading/Interlocked.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "object-internals.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Threading { class LIBIL2CPP_CODEGEN_API Interlocked { public: static int32_t Add(int32_t* location1, int32_t value); static int64_t Add64(int64_t* location1, int64_t value); static int32_t CompareExchange(int32_t* location, int32_t value, int32_t comparand); static int64_t CompareExchange64(int64_t* location1, int64_t value, int64_t comparand); static double CompareExchangeDouble(double* location1, double value, double comparand); static Il2CppIntPtr CompareExchangeIntPtr(Il2CppIntPtr* location, Il2CppIntPtr value, Il2CppIntPtr comparand); static float CompareExchangeSingle(float* location1, float value, float comparand); static void* CompareExchange_T(void** location, void* value, void* comparand); static int32_t Decrement(int32_t* location); static int64_t Decrement64(int64_t* location); static Il2CppIntPtr ExchangeIntPtr(Il2CppIntPtr* location, Il2CppIntPtr value); static int32_t Exchange(int32_t* location1, int32_t value); static int64_t Exchange64(int64_t* location1, int64_t value); static double ExchangeDouble(double* location1, double value); static void* ExchangePointer(void** location1, void* value); static float ExchangeSingle(float* location1, float value); static int32_t Increment(int32_t* value); static int64_t Increment64(int64_t* location); static int64_t Read(int64_t* location); #if NET_4_0 static int32_t CompareExchange(int32_t* location1, int32_t value, int32_t comparand, bool* succeeded); #endif }; } /* namespace Threading */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Threading/InternalThread.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "InternalThread.h" #include "utils/Memory.h" #include "os/Mutex.h" #include "os/Thread.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Threading { void InternalThread::Thread_free_internal(Il2CppInternalThread* _this, Il2CppIntPtr handle) { delete _this->synch_cs; _this->synch_cs = NULL; IL2CPP_FREE(_this->name); delete static_cast(handle.m_value); handle.m_value = NULL; } } // namespace Threading } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Threading/InternalThread.h ================================================ #pragma once #if NET_4_0 #include "object-internals.h" struct Il2CppInternalThread; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Threading { class LIBIL2CPP_CODEGEN_API InternalThread { public: static void Thread_free_internal(Il2CppInternalThread* _this, Il2CppIntPtr handle); }; } // namespace Threading } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Threading/Monitor.cpp ================================================ #include "il2cpp-config.h" #include "object-internals.h" #include "icalls/mscorlib/System.Threading/Monitor.h" #include "vm/Monitor.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Threading { void Monitor::Enter(Il2CppObject* obj) { IL2CPP_CHECK_ARG_NULL(obj); il2cpp::vm::Monitor::Enter(obj); } void Monitor::Exit(Il2CppObject* obj) { IL2CPP_CHECK_ARG_NULL(obj); il2cpp::vm::Monitor::Exit(obj); } bool Monitor::Monitor_test_synchronised(Il2CppObject* obj) { IL2CPP_CHECK_ARG_NULL(obj); return il2cpp::vm::Monitor::IsAcquired(obj); } void Monitor::Monitor_pulse(Il2CppObject* obj) { IL2CPP_CHECK_ARG_NULL(obj); il2cpp::vm::Monitor::Pulse(obj); } void Monitor::Monitor_pulse_all(Il2CppObject* obj) { IL2CPP_CHECK_ARG_NULL(obj); il2cpp::vm::Monitor::PulseAll(obj); } bool Monitor::Monitor_wait(Il2CppObject* obj, int32_t ms) { IL2CPP_CHECK_ARG_NULL(obj); return il2cpp::vm::Monitor::TryWait(obj, ms); } bool Monitor::Monitor_try_enter(Il2CppObject* obj, int32_t ms) { IL2CPP_CHECK_ARG_NULL(obj); return il2cpp::vm::Monitor::TryEnter(obj, ms); } #if NET_4_0 bool Monitor::Monitor_test_owner(Il2CppObject* obj) { NOT_IMPLEMENTED_ICALL(Monitor::Monitor_test_owner); IL2CPP_UNREACHABLE; } void Monitor::enter_with_atomic_var(Il2CppObject* obj, bool* lockTaken) { IL2CPP_CHECK_ARG_NULL(obj); if (*lockTaken) vm::Exception::Raise(il2cpp::vm::Exception::GetArgumentException("lockTaken", "lockTaken must be false")); il2cpp::vm::Monitor::Enter(obj); *lockTaken = true; } void Monitor::try_enter_with_atomic_var(Il2CppObject* obj, int32_t millisecondsTimeout, bool* lockTaken) { if (*lockTaken) vm::Exception::Raise(il2cpp::vm::Exception::GetArgumentException("lockTaken", "lockTaken must be false")); *lockTaken = Monitor_try_enter(obj, millisecondsTimeout); } #endif } /* namespace Threading */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Threading/Monitor.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppObject; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Threading { class LIBIL2CPP_CODEGEN_API Monitor { public: static void Enter(Il2CppObject *); static void Exit(Il2CppObject *); static void Monitor_pulse(Il2CppObject* obj); static void Monitor_pulse_all(Il2CppObject* obj); static bool Monitor_test_synchronised(Il2CppObject* obj); static bool Monitor_try_enter(Il2CppObject* obj, int32_t ms); static bool Monitor_wait(Il2CppObject* obj, int32_t ms); #if NET_4_0 static bool Monitor_test_owner(Il2CppObject* obj); static void enter_with_atomic_var(Il2CppObject* obj, bool* lockTaken); static void try_enter_with_atomic_var(Il2CppObject* obj, int32_t millisecondsTimeout, bool* lockTaken); #endif }; } /* namespace Threading */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Threading/Mutex.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Threading/Mutex.h" #include "os/Mutex.h" #include "vm/Exception.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Threading { Il2CppIntPtr Mutex::CreateMutex_internal(bool initiallyOwned, Il2CppString* name, bool* created) { *created = true; il2cpp::os::Mutex* mutex = NULL; if (name == NULL) { mutex = new il2cpp::os::Mutex(); } else { NOT_SUPPORTED_IL2CPP(Mutex::CreateMutex_internal, "Named mutexes are not supported"); } if (initiallyOwned) mutex->Lock(); Il2CppIntPtr ret = { new il2cpp::os::MutexHandle(mutex) }; return ret; } bool Mutex::ReleaseMutex_internal(Il2CppIntPtr handle) { il2cpp::os::MutexHandle* mutex = (il2cpp::os::MutexHandle*)handle.m_value; mutex->Get()->Unlock(); return true; } Il2CppIntPtr Mutex::OpenMutex_internal(Il2CppString* name, MutexRights rights, MonoIOError* error) { NOT_IMPLEMENTED_ICALL(Mutex::OpenMutex_internal); return Il2CppIntPtr(); } } /* namespace Threading */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Threading/Mutex.h ================================================ #pragma once #include #include "object-internals.h" #include "il2cpp-config.h" struct Il2CppString; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Threading { struct MonoIOError; typedef int32_t MutexRights; class LIBIL2CPP_CODEGEN_API Mutex { public: static Il2CppIntPtr CreateMutex_internal(bool initiallyOwned, Il2CppString* name, bool* created); static Il2CppIntPtr OpenMutex_internal(Il2CppString* name, MutexRights rights, MonoIOError* error); static bool ReleaseMutex_internal(Il2CppIntPtr handle); }; } /* namespace Threading */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Threading/NativeEventCalls.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Threading/NativeEventCalls.h" #include "os/Event.h" #include "vm/Exception.h" using namespace il2cpp::os; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Threading { bool NativeEventCalls::ResetEvent_internal(Il2CppIntPtr handlePtr) { EventHandle* handle = (EventHandle*)handlePtr.m_value; ErrorCode result = handle->Get().Reset(); return kErrorCodeSuccess == result; } bool NativeEventCalls::SetEvent_internal(Il2CppIntPtr handlePtr) { EventHandle* handle = (EventHandle*)handlePtr.m_value; ErrorCode result = handle->Get().Set(); return kErrorCodeSuccess == result; } #if !NET_4_0 Il2CppIntPtr NativeEventCalls::CreateEvent_internal(bool manualReset, bool signaled, Il2CppString* name, bool* created) { *created = true; il2cpp::os::Event* event = NULL; if (name == NULL) event = new Event(manualReset, signaled); else NOT_SUPPORTED_IL2CPP(NativeEventCalls::CreateEvent_internal, "Named events are not supported."); Il2CppIntPtr ret = { new EventHandle(event) }; return ret; } Il2CppIntPtr NativeEventCalls::OpenEvent_internal(Il2CppString* name, EventWaitHandleRights rights, MonoIOError* error) { NOT_IMPLEMENTED_ICALL(NativeEventCalls::OpenEvent_internal); return Il2CppIntPtr(); } #else Il2CppIntPtr NativeEventCalls::CreateEvent_internal(bool manual, bool initial, Il2CppString* name, int32_t *errorCode) { *errorCode = 0; il2cpp::os::Event* event = NULL; if (name == NULL) event = new Event(manual, initial); else NOT_SUPPORTED_IL2CPP(NativeEventCalls::CreateEvent_internal, "Named events are not supported."); Il2CppIntPtr ret = { new EventHandle(event) }; return ret; } Il2CppIntPtr NativeEventCalls::OpenEvent_internal(Il2CppString* name, EventWaitHandleRights rights, int32_t* errorCode) { NOT_IMPLEMENTED_ICALL(NativeEventCalls::OpenEvent_internal); return Il2CppIntPtr(); } #endif void NativeEventCalls::CloseEvent_internal(Il2CppIntPtr handlePtr) { Handle* handle = (Handle*)handlePtr.m_value; // should we close or just delete //handle->Close (); delete handle; } } /* namespace Threading */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Threading/NativeEventCalls.h ================================================ #pragma once #include #include "object-internals.h" #include "il2cpp-config.h" struct Il2CppString; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Threading { struct MonoIOError; typedef int32_t EventWaitHandleRights; class LIBIL2CPP_CODEGEN_API NativeEventCalls { public: #if !NET_4_0 static Il2CppIntPtr CreateEvent_internal(bool manualReset, bool signaled, Il2CppString* name, bool* created); static Il2CppIntPtr OpenEvent_internal(Il2CppString* name, EventWaitHandleRights rights, MonoIOError* error); #else static Il2CppIntPtr CreateEvent_internal(bool manual, bool initial, Il2CppString* name, int32_t* errorCode); static Il2CppIntPtr OpenEvent_internal(Il2CppString* name, EventWaitHandleRights rights, int32_t* errorCode); #endif static bool ResetEvent_internal(Il2CppIntPtr handlePtr); static bool SetEvent_internal(Il2CppIntPtr handlePtr); static void CloseEvent_internal(Il2CppIntPtr handlePtr); }; } /* namespace Threading */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Threading/Thread.cpp ================================================ #include "il2cpp-config.h" #include #include "icalls/mscorlib/System.Threading/Thread.h" #include "class-internals.h" #include "gc/GarbageCollector.h" #include "os/Atomic.h" #include "os/Thread.h" #include "os/Mutex.h" #include "os/Semaphore.h" #include "utils/StringUtils.h" #include "vm/Array.h" #include "vm/Domain.h" #include "vm/Object.h" #include "vm/Runtime.h" #include "vm/String.h" #include "vm/Thread.h" #include "vm/Exception.h" #include "vm/String.h" #include "vm/StackTrace.h" #include "utils/Memory.h" #include "utils/StringUtils.h" #include "vm/Atomic.h" using namespace il2cpp::vm; using il2cpp::gc::GarbageCollector; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Threading { #define NUM_CACHED_CULTURES 4 #define CULTURES_START_IDX 0 #define UICULTURES_START_IDX NUM_CACHED_CULTURES static Il2CppObject* lookup_cached_culture(Il2CppThread *thisPtr, int32_t start_idx); static void cache_culture(Il2CppThread *thisPtr, Il2CppObject *culture, int start_idx); void Thread::ClrState(Il2CppThread* thisPtr, il2cpp::vm::ThreadState state) { il2cpp::vm::Thread::ClrState(thisPtr, state); } Il2CppThread * Thread::CurrentThread_internal(void) { return il2cpp::vm::Thread::Current(); } int32_t Thread::GetDomainID() { return il2cpp::vm::Domain::GetCurrent()->domain_id; } il2cpp::vm::ThreadState Thread::GetState(Il2CppThread * thisPtr) { il2cpp::os::FastAutoLock lock(thisPtr->GetInternalThread()->synch_cs); return (il2cpp::vm::ThreadState)thisPtr->GetInternalThread()->state; } bool Thread::Join_internal(Il2CppThread * thisPtr, int32_t ms, void* thread) { // Throw ThreadStateException if thread has not been started yet. if (il2cpp::vm::Thread::GetState(thisPtr) & kThreadStateUnstarted) il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetThreadStateException("Thread has not been started.")); // Mark current thread as blocked. Il2CppThread* currentThread = il2cpp::vm::Thread::Current(); SetState(currentThread, kThreadStateWaitSleepJoin); // Join with other thread. il2cpp::os::Thread* osThread = (il2cpp::os::Thread*)thisPtr->GetInternalThread()->handle; IL2CPP_ASSERT(osThread != NULL); il2cpp::os::WaitStatus status = osThread->Join(ms); // Unblock current thread. ClrState(currentThread, kThreadStateWaitSleepJoin); if (status == il2cpp::os::kWaitStatusSuccess) return true; return false; } void Thread::ResetAbort_internal() { il2cpp::vm::Thread::ResetAbort(il2cpp::vm::Thread::Current()); } Il2CppString* Thread::GetName_internal(Il2CppThread* thisPtr) { il2cpp::os::FastAutoLock lock(thisPtr->GetInternalThread()->synch_cs); if (thisPtr->GetInternalThread()->name_len == 0) return NULL; return il2cpp::vm::String::NewUtf16(thisPtr->GetInternalThread()->name, thisPtr->GetInternalThread()->name_len); } void Thread::SetName_internal(Il2CppThread* thisPtr, Il2CppString* name) { vm::Thread::SetName(thisPtr, name); } void Thread::SetState(Il2CppThread* thisPtr, il2cpp::vm::ThreadState state) { il2cpp::os::FastAutoLock lock(thisPtr->GetInternalThread()->synch_cs); il2cpp::vm::Thread::SetState(thisPtr, state); } void Thread::Sleep_internal(int32_t milliseconds) { Il2CppThread* thread = il2cpp::vm::Thread::Current(); SetState(thread, kThreadStateWaitSleepJoin); il2cpp::os::Thread::Sleep(milliseconds, true); ClrState(thread, kThreadStateWaitSleepJoin); } void Thread::Thread_init(Il2CppThread * thisPtr) { il2cpp::vm::Thread::Setup(thisPtr); } struct StartData { Il2CppThread* m_Thread; Il2CppDomain* m_Domain; Il2CppDelegate* m_Delegate; Il2CppObject* m_StartArg; il2cpp::os::Semaphore* m_Semaphore; }; static void ThreadStart(void* arg) { StartData* startData = (StartData*)arg; startData->m_Semaphore->Wait(); { int temp = 0; if (!GarbageCollector::RegisterThread(&temp)) IL2CPP_ASSERT(0 && "GarbageCollector::RegisterThread failed"); il2cpp::vm::StackTrace::InitializeStackTracesForCurrentThread(); il2cpp::vm::Thread::Initialize(startData->m_Thread, startData->m_Domain); il2cpp::vm::Thread::SetState(startData->m_Thread, kThreadStateRunning); try { Il2CppException* exc = NULL; void* args[1] = { startData->m_StartArg }; Runtime::DelegateInvoke(startData->m_Delegate, args, &exc); if (exc) Runtime::UnhandledException(exc); } catch (il2cpp::vm::Thread::NativeThreadAbortException) { // Nothing to do. We've successfully aborted the thread. il2cpp::vm::Thread::SetState(startData->m_Thread, kThreadStateAborted); } il2cpp::vm::Thread::ClrState(startData->m_Thread, kThreadStateRunning); il2cpp::vm::Thread::SetState(startData->m_Thread, kThreadStateStopped); il2cpp::vm::Thread::Uninitialize(startData->m_Thread); il2cpp::vm::StackTrace::CleanupStackTracesForCurrentThread(); } delete startData->m_Semaphore; GarbageCollector::FreeFixed(startData); } Il2CppIntPtr Thread::Thread_internal(Il2CppThread * thisPtr, Il2CppDelegate * start) { IL2CPP_ASSERT(thisPtr->GetInternalThread()->synch_cs != NULL); il2cpp::os::FastAutoLock lock(thisPtr->GetInternalThread()->synch_cs); if (il2cpp::vm::Thread::GetState(thisPtr) & kThreadStateAborted) { Il2CppIntPtr ret = { thisPtr->GetInternalThread()->handle }; return ret; } // use fixed GC memory since we are storing managed object pointers StartData* startData = (StartData*)GarbageCollector::AllocateFixed(sizeof(StartData), NULL); startData->m_Thread = thisPtr; startData->m_Domain = Domain::GetCurrent(); startData->m_Delegate = start; startData->m_StartArg = thisPtr->start_obj; startData->m_Semaphore = new il2cpp::os::Semaphore(0); il2cpp::os::Thread* thread = new il2cpp::os::Thread(); thread->SetStackSize(thisPtr->GetInternalThread()->stack_size); thread->SetExplicitApartment(static_cast(thisPtr->GetInternalThread()->apartment_state)); il2cpp::os::ErrorCode status = thread->Run(&ThreadStart, startData); if (status != il2cpp::os::kErrorCodeSuccess) { delete thread; return Il2CppIntPtr::Zero; } #if NET_4_0 uint32_t existingPriority = il2cpp::vm::Thread::GetPriority(thisPtr); #endif thisPtr->GetInternalThread()->handle = thread; thisPtr->GetInternalThread()->state &= ~kThreadStateUnstarted; thisPtr->GetInternalThread()->tid = thread->Id(); thisPtr->GetInternalThread()->managed_id = il2cpp::vm::Thread::GetNewManagedId(); startData->m_Semaphore->Post(1, NULL); #if NET_4_0 il2cpp::vm::Thread::SetPriority(thisPtr, existingPriority); #endif // this is just checked against 0 in the calling code Il2CppIntPtr ret = { thisPtr->GetInternalThread()->handle }; return ret; } #if !NET_4_0 void Thread::Thread_free_internal(Il2CppThread * thisPtr, Il2CppIntPtr handle) { delete thisPtr->GetInternalThread()->synch_cs; thisPtr->GetInternalThread()->synch_cs = NULL; IL2CPP_FREE(thisPtr->GetInternalThread()->name); delete static_cast(handle.m_value); handle.m_value = NULL; } #endif static void cache_culture(Il2CppThread *thisPtr, Il2CppObject *culture, int start_idx) { int i; Il2CppObject *obj; int free_slot = -1; int same_domain_slot = -1; il2cpp::os::FastAutoLock lock(thisPtr->GetInternalThread()->synch_cs); if (!thisPtr->GetInternalThread()->cached_culture_info) IL2CPP_OBJECT_SETREF(thisPtr->GetInternalThread(), cached_culture_info, il2cpp::vm::Array::NewCached(il2cpp_defaults.object_class, NUM_CACHED_CULTURES * 2)); for (i = start_idx; i < start_idx + NUM_CACHED_CULTURES; ++i) { obj = il2cpp_array_get(thisPtr->GetInternalThread()->cached_culture_info, Il2CppObject*, i); /* Free entry */ if (!obj) { free_slot = i; /* we continue, because there may be a slot used with the same domain */ continue; } /* Replace */ same_domain_slot = i; break; } if (same_domain_slot >= 0) il2cpp_array_setref(thisPtr->GetInternalThread()->cached_culture_info, same_domain_slot, culture); else if (free_slot >= 0) il2cpp_array_setref(thisPtr->GetInternalThread()->cached_culture_info, free_slot, culture); /* we may want to replace an existing entry here, even when no suitable slot is found */ } static Il2CppObject* lookup_cached_culture(Il2CppThread *thisPtr, int32_t start_idx) { Il2CppObject *res; int i; if (thisPtr->GetInternalThread()->cached_culture_info) { for (i = start_idx; i < start_idx + NUM_CACHED_CULTURES; ++i) { res = il2cpp_array_get(thisPtr->GetInternalThread()->cached_culture_info, Il2CppObject*, i); if (res) return res; } } return NULL; } void Thread::FreeLocalSlotValues(int32_t slot, bool use_thread_local) { NOT_IMPLEMENTED_ICALL(Thread::FreeLocalSlotValues); } mscorlib_System_Globalization_CultureInfo* Thread::GetCachedCurrentCulture(Il2CppThread* thisPtr) { return (mscorlib_System_Globalization_CultureInfo*)lookup_cached_culture(thisPtr, CULTURES_START_IDX); } void Thread::SetCachedCurrentCulture(Il2CppThread* thisPtr, Il2CppObject* culture) { cache_culture(thisPtr, culture, CULTURES_START_IDX); } mscorlib_System_Globalization_CultureInfo* Thread::GetCachedCurrentUICulture(Il2CppThread* thisPtr) { return (mscorlib_System_Globalization_CultureInfo*)lookup_cached_culture(thisPtr, UICULTURES_START_IDX); } void Thread::SetCachedCurrentUICulture(Il2CppThread* thisPtr, Il2CppObject* culture) { cache_culture(thisPtr, culture, UICULTURES_START_IDX); } static Il2CppArray* GetSerializedCulture(uint8_t*& data, uint32_t& length) { if (!data) return NULL; Il2CppArray* result = il2cpp::vm::Array::New(il2cpp_defaults.byte_class, length); memcpy(il2cpp_array_addr(result, uint8_t, 0), data, length); return result; } static void SetSerializedCulture(uint8_t*& data, uint32_t& length, Il2CppArray* culture) { if (data != NULL) delete data; int arrayLength = il2cpp::vm::Array::GetByteLength(culture); data = new uint8_t[arrayLength]; length = arrayLength; memcpy(data, il2cpp_array_addr(culture, uint8_t, 0), arrayLength); } #if !NET_4_0 Il2CppArray* Thread::GetSerializedCurrentCulture(Il2CppThread* thisPtr) { il2cpp::os::FastAutoLock lock(thisPtr->synch_cs); return GetSerializedCulture(thisPtr->serialized_culture_info, thisPtr->serialized_culture_info_len); } void Thread::SetSerializedCurrentCulture(Il2CppThread* thisPtr, Il2CppArray* culture) { il2cpp::os::FastAutoLock lock(thisPtr->synch_cs); SetSerializedCulture(thisPtr->serialized_culture_info, thisPtr->serialized_culture_info_len, culture); } Il2CppArray* Thread::GetSerializedCurrentUICulture(Il2CppThread* thisPtr) { il2cpp::os::FastAutoLock lock(thisPtr->synch_cs); return GetSerializedCulture(thisPtr->serialized_ui_culture_info, thisPtr->serialized_ui_culture_info_len); } void Thread::SetSerializedCurrentUICulture(Il2CppThread* thisPtr, Il2CppArray* culture) { il2cpp::os::FastAutoLock lock(thisPtr->synch_cs); SetSerializedCulture(thisPtr->serialized_ui_culture_info, thisPtr->serialized_ui_culture_info_len, culture); } #endif int32_t Thread::GetNewManagedId_internal() { return il2cpp::vm::Thread::GetNewManagedId(); } void Thread::Abort_internal(Il2CppThread* thisPtr, Il2CppObject* stateInfo) { il2cpp::vm::Thread::RequestAbort(thisPtr); } Il2CppObject* Thread::GetAbortExceptionState(void* /* System.Threading.Thread */ self) { NOT_SUPPORTED_IL2CPP(Thread::GetAbortExceptionState, "Thread abortion is currently not implemented on IL2CPP; it is recommended to use safer mechanisms to terminate threads."); return 0; } void Thread::Interrupt_internal(Il2CppThread* thisPtr) { il2cpp::vm::Thread::RequestInterrupt(thisPtr); } void Thread::MemoryBarrier_() { il2cpp::os::Atomic::MemoryBarrier(); } void Thread::Resume_internal(void* /* System.Threading.Thread */ self) { NOT_SUPPORTED_IL2CPP(Thread::Resume_internal, "Thread suspension is obsolete and not supported on IL2CPP."); } void Thread::SpinWait_nop() { } void Thread::Suspend_internal(void* /* System.Threading.Thread */ self) { NOT_SUPPORTED_IL2CPP(Thread::Suspend_internal, "Thread suspension is obsolete and not supported on IL2CPP."); } // Unlike Mono we cannot just do a memory read/write of the correct type and reuse that for the // floating-point types because we are compiling to C++ and have to account for its type conversion // rules. For example, if we read a double as a uint64_t and return it as such, the compiler will // perform a default conversion from uint64_t to double -- whereas what we want is to simply interpret // the memory contents as a double. int8_t Thread::VolatileReadInt8(volatile void* address) { il2cpp::os::Atomic::MemoryBarrier(); return *reinterpret_cast(address); } int16_t Thread::VolatileReadInt16(volatile void* address) { il2cpp::os::Atomic::MemoryBarrier(); return *reinterpret_cast(address); } int32_t Thread::VolatileReadInt32(volatile void* address) { il2cpp::os::Atomic::MemoryBarrier(); return *reinterpret_cast(address); } int64_t Thread::VolatileReadInt64(volatile void* address) { il2cpp::os::Atomic::MemoryBarrier(); return *reinterpret_cast(address); } float Thread::VolatileReadFloat(volatile void* address) { il2cpp::os::Atomic::MemoryBarrier(); return *reinterpret_cast(address); } double Thread::VolatileReadDouble(volatile void* address) { il2cpp::os::Atomic::MemoryBarrier(); return *reinterpret_cast(address); } void* Thread::VolatileReadPtr(volatile void* address) { il2cpp::os::Atomic::MemoryBarrier(); return *reinterpret_cast(address); } Il2CppIntPtr Thread::VolatileReadIntPtr(volatile void* address) { Il2CppIntPtr result; result.m_value = VolatileReadPtr(address); return result; } void Thread::VolatileWriteInt8(volatile void* address, int8_t value) { *reinterpret_cast(address) = value; il2cpp::os::Atomic::MemoryBarrier(); } void Thread::VolatileWriteInt16(volatile void* address, int16_t value) { *reinterpret_cast(address) = value; il2cpp::os::Atomic::MemoryBarrier(); } void Thread::VolatileWriteInt32(volatile void* address, int32_t value) { *reinterpret_cast(address) = value; il2cpp::os::Atomic::MemoryBarrier(); } void Thread::VolatileWriteInt64(volatile void* address, int64_t value) { *reinterpret_cast(address) = value; il2cpp::os::Atomic::MemoryBarrier(); } void Thread::VolatileWriteFloat(volatile void* address, float value) { *reinterpret_cast(address) = value; il2cpp::os::Atomic::MemoryBarrier(); } void Thread::VolatileWriteDouble(volatile void* address, double value) { *reinterpret_cast(address) = value; il2cpp::os::Atomic::MemoryBarrier(); } void Thread::VolatileWritePtr(volatile void* address, void* value) { *reinterpret_cast(address) = value; il2cpp::os::Atomic::MemoryBarrier(); } void Thread::VolatileWriteIntPtr(volatile void* address, Il2CppIntPtr value) { VolatileWritePtr(address, value.m_value); } #if NET_4_0 Il2CppArray* Thread::ByteArrayToCurrentDomain(Il2CppArray* arr) { NOT_IMPLEMENTED_ICALL(Thread::ByteArrayToCurrentDomain); IL2CPP_UNREACHABLE; } Il2CppArray* Thread::ByteArrayToRootDomain(Il2CppArray* arr) { NOT_IMPLEMENTED_ICALL(Thread::ByteArrayToRootDomain); IL2CPP_UNREACHABLE; } bool Thread::YieldInternal() { return vm::Thread::YieldInternal(); } bool Thread::JoinInternal(Il2CppThread* _this, int32_t millisecondsTimeout) { return Join_internal(_this, millisecondsTimeout, NULL); } int32_t Thread::GetPriorityNative(Il2CppThread* _this) { return il2cpp::vm::Thread::GetPriority(_this); } int32_t Thread::SystemMaxStackStize() { NOT_IMPLEMENTED_ICALL(Thread::SystemMaxStackStize); IL2CPP_UNREACHABLE; } Il2CppString* Thread::GetName_internal40(Il2CppInternalThread* thread) { il2cpp::os::FastAutoLock lock(thread->synch_cs); if (thread->name_len == 0) return NULL; return il2cpp::vm::String::NewUtf16(thread->name, thread->name_len); } Il2CppInternalThread* Thread::CurrentInternalThread_internal() { return CurrentThread_internal()->GetInternalThread(); } int32_t Thread::GetState40(Il2CppInternalThread* thread) { il2cpp::os::FastAutoLock lock(thread->synch_cs); return (il2cpp::vm::ThreadState)thread->state; } void Thread::Abort_internal40(Il2CppInternalThread* thread, Il2CppObject* stateInfo) { il2cpp::vm::Thread::RequestAbort(thread); } void Thread::ClrState40(Il2CppInternalThread* thread, il2cpp::vm::ThreadState clr) { il2cpp::vm::Thread::ClrState(thread, clr); } void Thread::ConstructInternalThread(Il2CppThread* _this) { os::Thread* osThread = new os::Thread(); // Create managed object representing the current thread. Il2CppInternalThread* internal = (Il2CppInternalThread*)Object::New(il2cpp_defaults.internal_thread_class); internal->state = kThreadStateUnstarted; internal->handle = osThread; internal->tid = osThread->Id(); internal->synch_cs = new il2cpp::os::FastMutex(); internal->apartment_state = il2cpp::os::kApartmentStateUnknown; internal->managed_id = GetNewManagedId_internal(); vm::Atomic::CompareExchangePointer(&_this->internal_thread, internal, NULL); } void Thread::GetStackTraces(Il2CppArray** threads, Il2CppArray** stack_frames) { NOT_IMPLEMENTED_ICALL(Thread::GetStackTraces); IL2CPP_UNREACHABLE; } void Thread::InterruptInternal(Il2CppThread* _this) { Interrupt_internal(_this); } void Thread::ResetAbortNative(Il2CppObject* _this) { NOT_IMPLEMENTED_ICALL(Thread::ResetAbortNative); IL2CPP_UNREACHABLE; } void Thread::ResumeInternal(Il2CppObject* _this) { NOT_SUPPORTED_IL2CPP(Thread::Resume_internal, "Thread suspension is obsolete and not supported on IL2CPP."); } void Thread::SetName_internal40(Il2CppInternalThread* thread, Il2CppString* name) { il2cpp::os::FastAutoLock lock(thread->synch_cs); // Throw if already set. if (thread->name_len != 0) il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetInvalidOperationException("Thread name can only be set once.")); // Store name. thread->name_len = utils::StringUtils::GetLength(name); thread->name = il2cpp::utils::StringUtils::StringDuplicate(utils::StringUtils::GetChars(name), thread->name_len); // Hand over to OS layer, if thread has been started already. if (thread->handle) { std::string utf8Name = il2cpp::utils::StringUtils::Utf16ToUtf8(thread->name); thread->handle->SetName(utf8Name); } } void Thread::SetPriorityNative(Il2CppThread* _this, int32_t priority) { vm::Thread::SetPriority(_this, priority); } void Thread::SetState40(Il2CppInternalThread* thread, il2cpp::vm::ThreadState state) { vm::Thread::SetState(thread, state); } void Thread::SleepInternal(int32_t millisecondsTimeout) { Sleep_internal(millisecondsTimeout); } void Thread::SuspendInternal(Il2CppObject* _this) { NOT_SUPPORTED_IL2CPP(Thread::SuspendInternal, "Thread suspension is obsolete and not supported on IL2CPP."); } #endif } /* namespace Threading */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Threading/Thread.h ================================================ #pragma once #include #include "object-internals.h" #include "vm/Thread.h" #include "il2cpp-config.h" struct Il2CppString; struct Il2CppThread; struct mscorlib_System_Globalization_CultureInfo; struct Il2CppDelegate; struct mscorlib_System_Threading_Thread; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Threading { class LIBIL2CPP_CODEGEN_API Thread { public: static int32_t GetDomainID(); static Il2CppThread * CurrentThread_internal(); static void ResetAbort_internal(); static void MemoryBarrier_(); static void SpinWait_nop(); static void Abort_internal(Il2CppThread* thisPtr, Il2CppObject* stateInfo); static void ClrState(Il2CppThread* thisPtr, il2cpp::vm::ThreadState clr); static void FreeLocalSlotValues(int32_t slot, bool use_thread_local); static Il2CppObject* GetAbortExceptionState(void* /* System.Threading.Thread */ self); static mscorlib_System_Globalization_CultureInfo * GetCachedCurrentCulture(Il2CppThread* thisPtr); static mscorlib_System_Globalization_CultureInfo* GetCachedCurrentUICulture(Il2CppThread* thisPtr); static Il2CppString* GetName_internal(Il2CppThread* thisPtr); static void SetName_internal(Il2CppThread* thisPtr, Il2CppString* name); static int32_t GetNewManagedId_internal(); #if !NET_4_0 static Il2CppArray * GetSerializedCurrentCulture(Il2CppThread* thisPtr); static Il2CppArray* GetSerializedCurrentUICulture(Il2CppThread* thisPtr); #endif static il2cpp::vm::ThreadState GetState(Il2CppThread * thisPtr); static void Interrupt_internal(Il2CppThread* thisPtr); static bool Join_internal(Il2CppThread * thisPtr, int32_t ms, void* thread); static void Resume_internal(void* /* System.Threading.Thread */ self); static void SetCachedCurrentCulture(Il2CppThread *thisPtr, Il2CppObject* culture); static void SetCachedCurrentUICulture(Il2CppThread* thisPtr, Il2CppObject* culture); #if !NET_4_0 static void SetSerializedCurrentCulture(Il2CppThread* thisPtr, Il2CppArray* culture); static void SetSerializedCurrentUICulture(Il2CppThread* thisPtr, Il2CppArray* culture); #endif static void SetState(Il2CppThread * thisPtr, il2cpp::vm::ThreadState state); static void Sleep_internal(int32_t milliseconds); static void Suspend_internal(void* /* System.Threading.Thread */ self); static void Thread_init(Il2CppThread* thisPtr); static Il2CppIntPtr Thread_internal(Il2CppThread* thisPtr, Il2CppDelegate * start); static int8_t VolatileReadInt8(volatile void* address); static int16_t VolatileReadInt16(volatile void* address); static int32_t VolatileReadInt32(volatile void* address); static int64_t VolatileReadInt64(volatile void* address); static float VolatileReadFloat(volatile void* address); static double VolatileReadDouble(volatile void* address); static void* VolatileReadPtr(volatile void* address); static Il2CppIntPtr VolatileReadIntPtr(volatile void* address); static void VolatileWriteInt8(volatile void* address, int8_t value); static void VolatileWriteInt16(volatile void* address, int16_t value); static void VolatileWriteInt32(volatile void* address, int32_t value); static void VolatileWriteInt64(volatile void* address, int64_t value); static void VolatileWriteFloat(volatile void* address, float value); static void VolatileWriteDouble(volatile void* address, double value); static void VolatileWritePtr(volatile void* address, void* value); static void VolatileWriteIntPtr(volatile void* address, Il2CppIntPtr value); #if !NET_4_0 static void Thread_free_internal(Il2CppThread* thisPtr, Il2CppIntPtr handle); #endif #if NET_4_0 static Il2CppArray* ByteArrayToCurrentDomain(Il2CppArray* arr); static Il2CppArray* ByteArrayToRootDomain(Il2CppArray* arr); static bool YieldInternal(); static bool JoinInternal(Il2CppThread* _this, int32_t millisecondsTimeout); static int32_t GetPriorityNative(Il2CppThread* _this); static int32_t SystemMaxStackStize(); static Il2CppString* GetName_internal40(Il2CppInternalThread* thread); static Il2CppInternalThread* CurrentInternalThread_internal(); static int32_t GetState40(Il2CppInternalThread* thread); static void Abort_internal40(Il2CppInternalThread* thread, Il2CppObject* stateInfo); static void ClrState40(Il2CppInternalThread* thread, il2cpp::vm::ThreadState clr); static void ConstructInternalThread(Il2CppThread* _this); static void GetStackTraces(Il2CppArray** threads, Il2CppArray** stack_frames); static void InterruptInternal(Il2CppThread* _this); static void ResetAbortNative(Il2CppObject* _this); static void ResumeInternal(Il2CppObject* _this); static void SetName_internal40(Il2CppInternalThread* thread, Il2CppString* name); static void SetPriorityNative(Il2CppThread* _this, int32_t priority); static void SetState40(Il2CppInternalThread* thread, vm::ThreadState set); static void SleepInternal(int32_t millisecondsTimeout); static void SuspendInternal(Il2CppObject* _this); #endif }; } /* namespace Threading */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Threading/ThreadPool.cpp ================================================ #include "il2cpp-config.h" #include "icalls/mscorlib/System.Threading/ThreadPool.h" #include "os/Environment.h" #include "vm/Exception.h" #include "vm/ThreadPool.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Threading { void ThreadPool::GetMaxThreads(int32_t* workerThreads, int32_t* completionPortThreads) { vm::ThreadPool::Configuration configuration = vm::ThreadPool::GetConfiguration(); if (workerThreads) *workerThreads = configuration.maxThreads; if (completionPortThreads) *completionPortThreads = configuration.maxAsyncIOThreads; } void ThreadPool::GetMinThreads(int32_t* workerThreads, int32_t* completionPortThreads) { vm::ThreadPool::Configuration configuration = vm::ThreadPool::GetConfiguration(); if (workerThreads) *workerThreads = configuration.minThreads; if (completionPortThreads) *completionPortThreads = configuration.minAsyncIOThreads; } bool ThreadPool::SetMinThreads(int32_t workerThreads, int32_t completionPortThreads) { vm::ThreadPool::Configuration configuration = vm::ThreadPool::GetConfiguration(); int numCoresAvailable = os::Environment::GetProcessorCount(); if (workerThreads < numCoresAvailable || workerThreads > configuration.maxThreads) return false; if (completionPortThreads < numCoresAvailable || completionPortThreads > configuration.maxAsyncIOThreads) return false; configuration.minThreads = workerThreads; configuration.minAsyncIOThreads = completionPortThreads; vm::ThreadPool::SetConfiguration(configuration); return true; } bool ThreadPool::SetMaxThreads(int32_t workerThreads, int32_t completionPortThreads) { vm::ThreadPool::Configuration configuration = vm::ThreadPool::GetConfiguration(); if (workerThreads < configuration.minThreads) return false; if (completionPortThreads < configuration.minAsyncIOThreads) return false; configuration.maxThreads = workerThreads; configuration.maxAsyncIOThreads = completionPortThreads; vm::ThreadPool::SetConfiguration(configuration); return true; } void ThreadPool::GetAvailableThreads(int32_t* workerThreads, int32_t* completionPortThreads) { vm::ThreadPool::Configuration configuration = vm::ThreadPool::GetConfiguration(); if (workerThreads) *workerThreads = configuration.availableThreads; if (completionPortThreads) *completionPortThreads = configuration.availableAsyncIOThreads; } } /* namespace Threading */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Threading/ThreadPool.h ================================================ #pragma once #include #include "object-internals.h" #include "il2cpp-config.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppReflectionType; struct Il2CppReflectionMethod; struct Il2CppReflectionField; struct Il2CppArray; struct Il2CppException; struct Il2CppReflectionModule; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppAppDomain; #if NET_4_0 struct Il2CppNativeOverlapped; #endif namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Threading { class LIBIL2CPP_CODEGEN_API ThreadPool { public: static void GetAvailableThreads(int32_t* workerThreads, int32_t* completionPortThreads); static void GetMinThreads(int32_t* workerThreads, int32_t* completionPortThreads); static bool SetMaxThreads(int32_t workerThreads, int32_t completionPortThreads); static bool SetMinThreads(int32_t workerThreads, int32_t completionPortThreads); static void GetMaxThreads(int32_t* workerThreads, int32_t* completionPortThreads); }; } /* namespace Threading */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Threading/Timer.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "Timer.h" #include "os/Time.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Threading { int64_t Timer::GetTimeMonotonic() { return os::Time::GetTicks100NanosecondsMonotonic(); } } // namespace Threading } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Threading/Timer.h ================================================ #pragma once #if NET_4_0 namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Threading { class LIBIL2CPP_CODEGEN_API Timer { public: static int64_t GetTimeMonotonic(); }; } // namespace Threading } // namespace System } // namespace mscorlib } // namespace icalls } // namespace il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Threading/WaitHandle.cpp ================================================ #include "il2cpp-config.h" #include #include #include "icalls/mscorlib/System.Threading/WaitHandle.h" #include "os/Mutex.h" #include "os/Thread.h" #include "vm/Thread.h" #include "vm/Exception.h" #include "vm/Array.h" #include "vm/WaitHandle.h" namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Threading { std::vector ExtractOsWaitHandles(Il2CppArray* handles) { uint32_t numberOfHandles = vm::Array::GetLength(handles); std::vector osWaitHandles(numberOfHandles); for (uint32_t i = 0; i < numberOfHandles; ++i) { Il2CppObject* handle = il2cpp_array_get(handles, Il2CppObject*, i); Il2CppWaitHandle* waitHandle = (Il2CppWaitHandle*)handle; osWaitHandles[i] = vm::WaitHandle::GetPlatformHandle(waitHandle); } return osWaitHandles; } int32_t WaitHandle::WaitAny_internal(Il2CppArray* handles, int32_t ms, bool exitContext) { std::vector osWaitHandles = ExtractOsWaitHandles(handles); vm::ThreadStateSetter state(vm::kThreadStateWaitSleepJoin); int timeWaitedMs = 0; while (ms == -1 || timeWaitedMs <= ms) { int32_t numberOfOsHandles = (int32_t)osWaitHandles.size(); for (int32_t i = 0; i < numberOfOsHandles; ++i) { if (osWaitHandles[i]->Wait(0)) return i; } os::Thread::Sleep(m_waitIntervalMs, true); timeWaitedMs += m_waitIntervalMs; } return 258; // WAIT_TIMEOUT value } bool WaitHandle::WaitOne_internal(Il2CppObject* unused, Il2CppIntPtr handlePtr, int32_t ms, bool exitContext) { il2cpp::os::Handle* handle = (il2cpp::os::Handle*)handlePtr.m_value; vm::ThreadStateSetter state(vm::kThreadStateWaitSleepJoin); // Check for pending interrupt before we go waiting. il2cpp::vm::Thread::CheckCurrentThreadForInterruptAndThrowIfNecessary(); if (ms == -1) return handle->Wait(); return handle->Wait(ms); } bool WaitHandle::WaitAll_internal(Il2CppArray* handles, int32_t ms, bool exitContext) { std::vector osWaitHandles = ExtractOsWaitHandles(handles); vm::ThreadStateSetter state(vm::kThreadStateWaitSleepJoin); int timeWaitedMs = 0; while (ms == -1 || timeWaitedMs <= ms) { size_t numberOfOsHandles = osWaitHandles.size(); std::vector signaledHandles; for (size_t i = 0; i < numberOfOsHandles; ++i) { if (osWaitHandles[i]->Wait(0)) signaledHandles.push_back(osWaitHandles[i]); } if (signaledHandles.size() == numberOfOsHandles) return true; // All handles have been signaled for (size_t i = 0; i < signaledHandles.size(); ++i) osWaitHandles.erase(std::remove(osWaitHandles.begin(), osWaitHandles.end(), signaledHandles[i]), osWaitHandles.end()); os::Thread::Sleep(m_waitIntervalMs, true); timeWaitedMs += m_waitIntervalMs; } return false; // Timed out waiting for all handles to be signaled } bool WaitHandle::SignalAndWait_Internal(Il2CppIntPtr toSignal, Il2CppIntPtr toWaitOn, int32_t ms, bool exitContext) { os::Handle* toSignalOsHandle = (os::Handle*)toSignal.m_value; toSignalOsHandle->Signal(); return WaitOne_internal(NULL, toWaitOn, ms, exitContext); } #if NET_4_0 int32_t WaitHandle::SignalAndWait_Internal40(Il2CppIntPtr toSignal, Il2CppIntPtr toWaitOn, int32_t ms) { return SignalAndWait_Internal(toSignal, toWaitOn, ms, false) ? 0 : 1; } int32_t WaitHandle::WaitAll_internal40(Il2CppArray* handles, int32_t ms) { return WaitAll_internal(handles, ms, false) ? 0 : 258; } int32_t WaitHandle::WaitAny_internal40(Il2CppArray* handles, int32_t ms) { return WaitAny_internal(handles, ms, false); } int32_t WaitHandle::WaitOne_internal40(Il2CppIntPtr handle, int32_t ms) { return WaitOne_internal(NULL, handle, ms, false) ? 0 : 258; } #endif } /* namespace Threading */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/icalls/mscorlib/System.Threading/WaitHandle.h ================================================ #pragma once #include #include "object-internals.h" #include "il2cpp-config.h" struct Il2CppArray; struct Il2CppObject; namespace il2cpp { namespace icalls { namespace mscorlib { namespace System { namespace Threading { class LIBIL2CPP_CODEGEN_API WaitHandle { public: static bool SignalAndWait_Internal(Il2CppIntPtr toSignal, Il2CppIntPtr toWaitOn, int32_t ms, bool exitContext); static bool WaitAll_internal(Il2CppArray* handles, int32_t ms, bool exitContext); static int32_t WaitAny_internal(Il2CppArray* handles, int32_t ms, bool exitContext); static bool WaitOne_internal(Il2CppObject* unused, Il2CppIntPtr handlePtr, int32_t ms, bool exitContext); #if NET_4_0 static int32_t SignalAndWait_Internal40(Il2CppIntPtr toSignal, Il2CppIntPtr toWaitOn, int32_t ms); static int32_t WaitAll_internal40(Il2CppArray* handles, int32_t ms); static int32_t WaitAny_internal40(Il2CppArray* handles, int32_t ms); static int32_t WaitOne_internal40(Il2CppIntPtr handle, int32_t ms); #endif private: static const int m_waitIntervalMs = 10; }; } /* namespace Threading */ } /* namespace System */ } /* namespace mscorlib */ } /* namespace icalls */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/il2cpp-api-functions.h ================================================ DO_API(void, il2cpp_init, (const char* domain_name)); DO_API(void, il2cpp_init_utf16, (const Il2CppChar * domain_name)); DO_API(void, il2cpp_shutdown, ()); DO_API(void, il2cpp_set_config_dir, (const char *config_path)); DO_API(void, il2cpp_set_data_dir, (const char *data_path)); DO_API(void, il2cpp_set_temp_dir, (const char *temp_path)); DO_API(void, il2cpp_set_commandline_arguments, (int argc, const char* const argv[], const char* basedir)); DO_API(void, il2cpp_set_commandline_arguments_utf16, (int argc, const Il2CppChar * const argv[], const char* basedir)); DO_API(void, il2cpp_set_config_utf16, (const Il2CppChar * executablePath)); DO_API(void, il2cpp_set_config, (const char* executablePath)); DO_API(void, il2cpp_set_memory_callbacks, (Il2CppMemoryCallbacks * callbacks)); DO_API(const Il2CppImage*, il2cpp_get_corlib, ()); DO_API(void, il2cpp_add_internal_call, (const char* name, Il2CppMethodPointer method)); DO_API(Il2CppMethodPointer, il2cpp_resolve_icall, (const char* name)); DO_API(void*, il2cpp_alloc, (size_t size)); DO_API(void, il2cpp_free, (void* ptr)); // array DO_API(Il2CppClass*, il2cpp_array_class_get, (Il2CppClass * element_class, uint32_t rank)); DO_API(uint32_t, il2cpp_array_length, (Il2CppArray * array)); DO_API(uint32_t, il2cpp_array_get_byte_length, (Il2CppArray * array)); DO_API(Il2CppArray*, il2cpp_array_new, (Il2CppClass * elementTypeInfo, il2cpp_array_size_t length)); DO_API(Il2CppArray*, il2cpp_array_new_specific, (Il2CppClass * arrayTypeInfo, il2cpp_array_size_t length)); DO_API(Il2CppArray*, il2cpp_array_new_full, (Il2CppClass * array_class, il2cpp_array_size_t * lengths, il2cpp_array_size_t * lower_bounds)); DO_API(Il2CppClass*, il2cpp_bounded_array_class_get, (Il2CppClass * element_class, uint32_t rank, bool bounded)); DO_API(int, il2cpp_array_element_size, (const Il2CppClass * array_class)); // assembly DO_API(const Il2CppImage*, il2cpp_assembly_get_image, (const Il2CppAssembly * assembly)); // class DO_API(const Il2CppType*, il2cpp_class_enum_basetype, (Il2CppClass * klass)); DO_API(bool, il2cpp_class_is_generic, (const Il2CppClass * klass)); DO_API(bool, il2cpp_class_is_inflated, (const Il2CppClass * klass)); DO_API(bool, il2cpp_class_is_assignable_from, (Il2CppClass * klass, Il2CppClass * oklass)); DO_API(bool, il2cpp_class_is_subclass_of, (Il2CppClass * klass, Il2CppClass * klassc, bool check_interfaces)); DO_API(bool, il2cpp_class_has_parent, (Il2CppClass * klass, Il2CppClass * klassc)); DO_API(Il2CppClass*, il2cpp_class_from_il2cpp_type, (const Il2CppType * type)); DO_API(Il2CppClass*, il2cpp_class_from_name, (const Il2CppImage * image, const char* namespaze, const char *name)); DO_API(Il2CppClass*, il2cpp_class_from_system_type, (Il2CppReflectionType * type)); DO_API(Il2CppClass*, il2cpp_class_get_element_class, (Il2CppClass * klass)); DO_API(const EventInfo*, il2cpp_class_get_events, (Il2CppClass * klass, void* *iter)); DO_API(FieldInfo*, il2cpp_class_get_fields, (Il2CppClass * klass, void* *iter)); DO_API(Il2CppClass*, il2cpp_class_get_nested_types, (Il2CppClass * klass, void* *iter)); DO_API(Il2CppClass*, il2cpp_class_get_interfaces, (Il2CppClass * klass, void* *iter)); DO_API(const PropertyInfo*, il2cpp_class_get_properties, (Il2CppClass * klass, void* *iter)); DO_API(const PropertyInfo*, il2cpp_class_get_property_from_name, (Il2CppClass * klass, const char *name)); DO_API(FieldInfo*, il2cpp_class_get_field_from_name, (Il2CppClass * klass, const char *name)); DO_API(const MethodInfo*, il2cpp_class_get_methods, (Il2CppClass * klass, void* *iter)); DO_API(const MethodInfo*, il2cpp_class_get_method_from_name, (Il2CppClass * klass, const char* name, int argsCount)); DO_API(const char*, il2cpp_class_get_name, (Il2CppClass * klass)); DO_API(const char*, il2cpp_class_get_namespace, (Il2CppClass * klass)); DO_API(Il2CppClass*, il2cpp_class_get_parent, (Il2CppClass * klass)); DO_API(Il2CppClass*, il2cpp_class_get_declaring_type, (Il2CppClass * klass)); DO_API(int32_t, il2cpp_class_instance_size, (Il2CppClass * klass)); DO_API(size_t, il2cpp_class_num_fields, (const Il2CppClass * enumKlass)); DO_API(bool, il2cpp_class_is_valuetype, (const Il2CppClass * klass)); DO_API(int32_t, il2cpp_class_value_size, (Il2CppClass * klass, uint32_t * align)); DO_API(bool, il2cpp_class_is_blittable, (const Il2CppClass * klass)); DO_API(int, il2cpp_class_get_flags, (const Il2CppClass * klass)); DO_API(bool, il2cpp_class_is_abstract, (const Il2CppClass * klass)); DO_API(bool, il2cpp_class_is_interface, (const Il2CppClass * klass)); DO_API(int, il2cpp_class_array_element_size, (const Il2CppClass * klass)); DO_API(Il2CppClass*, il2cpp_class_from_type, (const Il2CppType * type)); DO_API(const Il2CppType*, il2cpp_class_get_type, (Il2CppClass * klass)); DO_API(bool, il2cpp_class_has_attribute, (Il2CppClass * klass, Il2CppClass * attr_class)); DO_API(bool, il2cpp_class_has_references, (Il2CppClass * klass)); DO_API(bool, il2cpp_class_is_enum, (const Il2CppClass * klass)); DO_API(const Il2CppImage*, il2cpp_class_get_image, (Il2CppClass * klass)); DO_API(const char*, il2cpp_class_get_assemblyname, (const Il2CppClass * klass)); // testing only DO_API(size_t, il2cpp_class_get_bitmap_size, (const Il2CppClass * klass)); DO_API(void, il2cpp_class_get_bitmap, (Il2CppClass * klass, size_t * bitmap)); // stats DO_API(bool, il2cpp_stats_dump_to_file, (const char *path)); DO_API(uint64_t, il2cpp_stats_get_value, (Il2CppStat stat)); // domain DO_API(Il2CppDomain*, il2cpp_domain_get, ()); DO_API(const Il2CppAssembly*, il2cpp_domain_assembly_open, (Il2CppDomain * domain, const char* name)); DO_API(const Il2CppAssembly**, il2cpp_domain_get_assemblies, (const Il2CppDomain * domain, size_t * size)); // exception DO_API(void, il2cpp_raise_exception, (Il2CppException*)); DO_API(Il2CppException*, il2cpp_exception_from_name_msg, (const Il2CppImage * image, const char *name_space, const char *name, const char *msg)); DO_API(Il2CppException*, il2cpp_get_exception_argument_null, (const char *arg)); DO_API(void, il2cpp_format_exception, (const Il2CppException * ex, char* message, int message_size)); DO_API(void, il2cpp_format_stack_trace, (const Il2CppException * ex, char* output, int output_size)); DO_API(void, il2cpp_unhandled_exception, (Il2CppException*)); // field DO_API(int, il2cpp_field_get_flags, (FieldInfo * field)); DO_API(const char*, il2cpp_field_get_name, (FieldInfo * field)); DO_API(Il2CppClass*, il2cpp_field_get_parent, (FieldInfo * field)); DO_API(size_t, il2cpp_field_get_offset, (FieldInfo * field)); DO_API(const Il2CppType*, il2cpp_field_get_type, (FieldInfo * field)); DO_API(void, il2cpp_field_get_value, (Il2CppObject * obj, FieldInfo * field, void *value)); DO_API(Il2CppObject*, il2cpp_field_get_value_object, (FieldInfo * field, Il2CppObject * obj)); DO_API(bool, il2cpp_field_has_attribute, (FieldInfo * field, Il2CppClass * attr_class)); DO_API(void, il2cpp_field_set_value, (Il2CppObject * obj, FieldInfo * field, void *value)); DO_API(void, il2cpp_field_static_get_value, (FieldInfo * field, void *value)); DO_API(void, il2cpp_field_static_set_value, (FieldInfo * field, void *value)); DO_API(void, il2cpp_field_set_value_object, (Il2CppObject * instance, FieldInfo * field, Il2CppObject * value)); // gc DO_API(void, il2cpp_gc_collect, (int maxGenerations)); DO_API(int32_t, il2cpp_gc_collect_a_little, ()); DO_API(void, il2cpp_gc_disable, ()); DO_API(void, il2cpp_gc_enable, ()); DO_API(int64_t, il2cpp_gc_get_used_size, ()); DO_API(int64_t, il2cpp_gc_get_heap_size, ()); // gchandle DO_API(uint32_t, il2cpp_gchandle_new, (Il2CppObject * obj, bool pinned)); DO_API(uint32_t, il2cpp_gchandle_new_weakref, (Il2CppObject * obj, bool track_resurrection)); DO_API(Il2CppObject*, il2cpp_gchandle_get_target , (uint32_t gchandle)); DO_API(void, il2cpp_gchandle_free, (uint32_t gchandle)); // liveness DO_API(void*, il2cpp_unity_liveness_calculation_begin, (Il2CppClass * filter, int max_object_count, il2cpp_register_object_callback callback, void* userdata, il2cpp_WorldChangedCallback onWorldStarted, il2cpp_WorldChangedCallback onWorldStopped)); DO_API(void, il2cpp_unity_liveness_calculation_end, (void* state)); DO_API(void, il2cpp_unity_liveness_calculation_from_root, (Il2CppObject * root, void* state)); DO_API(void, il2cpp_unity_liveness_calculation_from_statics, (void* state)); // method DO_API(const Il2CppType*, il2cpp_method_get_return_type, (const MethodInfo * method)); DO_API(Il2CppClass*, il2cpp_method_get_declaring_type, (const MethodInfo * method)); DO_API(const char*, il2cpp_method_get_name, (const MethodInfo * method)); DO_API(Il2CppReflectionMethod*, il2cpp_method_get_object, (const MethodInfo * method, Il2CppClass * refclass)); DO_API(bool, il2cpp_method_is_generic, (const MethodInfo * method)); DO_API(bool, il2cpp_method_is_inflated, (const MethodInfo * method)); DO_API(bool, il2cpp_method_is_instance, (const MethodInfo * method)); DO_API(uint32_t, il2cpp_method_get_param_count, (const MethodInfo * method)); DO_API(const Il2CppType*, il2cpp_method_get_param, (const MethodInfo * method, uint32_t index)); DO_API(Il2CppClass*, il2cpp_method_get_class, (const MethodInfo * method)); DO_API(bool, il2cpp_method_has_attribute, (const MethodInfo * method, Il2CppClass * attr_class)); DO_API(uint32_t, il2cpp_method_get_flags, (const MethodInfo * method, uint32_t * iflags)); DO_API(uint32_t, il2cpp_method_get_token, (const MethodInfo * method)); DO_API(const char*, il2cpp_method_get_param_name, (const MethodInfo * method, uint32_t index)); // profiler #if IL2CPP_ENABLE_PROFILER DO_API(void, il2cpp_profiler_install, (Il2CppProfiler * prof, Il2CppProfileFunc shutdown_callback)); DO_API(void, il2cpp_profiler_set_events, (Il2CppProfileFlags events)); DO_API(void, il2cpp_profiler_install_enter_leave, (Il2CppProfileMethodFunc enter, Il2CppProfileMethodFunc fleave)); DO_API(void, il2cpp_profiler_install_allocation, (Il2CppProfileAllocFunc callback)); DO_API(void, il2cpp_profiler_install_gc, (Il2CppProfileGCFunc callback, Il2CppProfileGCResizeFunc heap_resize_callback)); #endif // property DO_API(uint32_t, il2cpp_property_get_flags, (PropertyInfo * prop)); DO_API(const MethodInfo*, il2cpp_property_get_get_method, (PropertyInfo * prop)); DO_API(const MethodInfo*, il2cpp_property_get_set_method, (PropertyInfo * prop)); DO_API(const char*, il2cpp_property_get_name, (PropertyInfo * prop)); DO_API(Il2CppClass*, il2cpp_property_get_parent, (PropertyInfo * prop)); // object DO_API(Il2CppClass*, il2cpp_object_get_class, (Il2CppObject * obj)); DO_API(uint32_t, il2cpp_object_get_size, (Il2CppObject * obj)); DO_API(const MethodInfo*, il2cpp_object_get_virtual_method, (Il2CppObject * obj, const MethodInfo * method)); DO_API(Il2CppObject*, il2cpp_object_new, (const Il2CppClass * klass)); DO_API(void*, il2cpp_object_unbox, (Il2CppObject * obj)); DO_API(Il2CppObject*, il2cpp_value_box, (Il2CppClass * klass, void* data)); // monitor DO_API(void, il2cpp_monitor_enter, (Il2CppObject * obj)); DO_API(bool, il2cpp_monitor_try_enter, (Il2CppObject * obj, uint32_t timeout)); DO_API(void, il2cpp_monitor_exit, (Il2CppObject * obj)); DO_API(void, il2cpp_monitor_pulse, (Il2CppObject * obj)); DO_API(void, il2cpp_monitor_pulse_all, (Il2CppObject * obj)); DO_API(void, il2cpp_monitor_wait, (Il2CppObject * obj)); DO_API(bool, il2cpp_monitor_try_wait, (Il2CppObject * obj, uint32_t timeout)); // runtime DO_API(Il2CppObject*, il2cpp_runtime_invoke, (const MethodInfo * method, void *obj, void **params, Il2CppException **exc)); DO_API(Il2CppObject*, il2cpp_runtime_invoke_convert_args, (const MethodInfo * method, void *obj, Il2CppObject **params, int paramCount, Il2CppException **exc)); DO_API(void, il2cpp_runtime_class_init, (Il2CppClass * klass)); DO_API(void, il2cpp_runtime_object_init, (Il2CppObject * obj)); DO_API(void, il2cpp_runtime_object_init_exception, (Il2CppObject * obj, Il2CppException** exc)); DO_API(void, il2cpp_runtime_unhandled_exception_policy_set, (Il2CppRuntimeUnhandledExceptionPolicy value)); // string DO_API(int32_t, il2cpp_string_length, (Il2CppString * str)); DO_API(Il2CppChar*, il2cpp_string_chars, (Il2CppString * str)); DO_API(Il2CppString*, il2cpp_string_new, (const char* str)); DO_API(Il2CppString*, il2cpp_string_new_len, (const char* str, uint32_t length)); DO_API(Il2CppString*, il2cpp_string_new_utf16, (const Il2CppChar * text, int32_t len)); DO_API(Il2CppString*, il2cpp_string_new_wrapper, (const char* str)); DO_API(Il2CppString*, il2cpp_string_intern, (Il2CppString * str)); DO_API(Il2CppString*, il2cpp_string_is_interned, (Il2CppString * str)); // thread DO_API(char*, il2cpp_thread_get_name, (Il2CppThread * thread, uint32_t * len)); DO_API(Il2CppThread*, il2cpp_thread_current, ()); DO_API(Il2CppThread*, il2cpp_thread_attach, (Il2CppDomain * domain)); DO_API(void, il2cpp_thread_detach, (Il2CppThread * thread)); DO_API(Il2CppThread**, il2cpp_thread_get_all_attached_threads, (size_t * size)); DO_API(bool, il2cpp_is_vm_thread, (Il2CppThread * thread)); // stacktrace DO_API(void, il2cpp_current_thread_walk_frame_stack, (Il2CppFrameWalkFunc func, void* user_data)); DO_API(void, il2cpp_thread_walk_frame_stack, (Il2CppThread * thread, Il2CppFrameWalkFunc func, void* user_data)); DO_API(bool, il2cpp_current_thread_get_top_frame, (Il2CppStackFrameInfo & frame)); DO_API(bool, il2cpp_thread_get_top_frame, (Il2CppThread * thread, Il2CppStackFrameInfo & frame)); DO_API(bool, il2cpp_current_thread_get_frame_at, (int32_t offset, Il2CppStackFrameInfo & frame)); DO_API(bool, il2cpp_thread_get_frame_at, (Il2CppThread * thread, int32_t offset, Il2CppStackFrameInfo & frame)); DO_API(int32_t, il2cpp_current_thread_get_stack_depth, ()); DO_API(int32_t, il2cpp_thread_get_stack_depth, (Il2CppThread * thread)); // type DO_API(Il2CppObject*, il2cpp_type_get_object, (const Il2CppType * type)); DO_API(int, il2cpp_type_get_type, (const Il2CppType * type)); DO_API(Il2CppClass*, il2cpp_type_get_class_or_element_class, (const Il2CppType * type)); DO_API(char*, il2cpp_type_get_name, (const Il2CppType * type)); // image DO_API(const Il2CppAssembly*, il2cpp_image_get_assembly, (const Il2CppImage * image)); DO_API(const char*, il2cpp_image_get_name, (const Il2CppImage * image)); DO_API(const char*, il2cpp_image_get_filename, (const Il2CppImage * image)); DO_API(const MethodInfo*, il2cpp_image_get_entry_point, (const Il2CppImage * image)); // Memory information DO_API(Il2CppManagedMemorySnapshot*, il2cpp_capture_memory_snapshot, ()); DO_API(void, il2cpp_free_captured_memory_snapshot, (Il2CppManagedMemorySnapshot * snapshot)); DO_API(void, il2cpp_set_find_plugin_callback, (Il2CppSetFindPlugInCallback method)); // Logging DO_API(void, il2cpp_register_log_callback, (Il2CppLogCallback method)); #if IL2CPP_DEBUGGER_ENABLED // debug DO_API(const Il2CppDebugTypeInfo*, il2cpp_debug_get_class_info, (const Il2CppClass * klass)); DO_API(const Il2CppDebugDocument*, il2cpp_debug_class_get_document, (const Il2CppDebugTypeInfo * info)); DO_API(const char*, il2cpp_debug_document_get_filename, (const Il2CppDebugDocument * document)); DO_API(const char*, il2cpp_debug_document_get_directory, (const Il2CppDebugDocument * document)); DO_API(const Il2CppDebugMethodInfo*, il2cpp_debug_get_method_info, (const MethodInfo * method)); DO_API(const Il2CppDebugDocument*, il2cpp_debug_method_get_document, (const Il2CppDebugMethodInfo * info)); DO_API(const int32_t*, il2cpp_debug_method_get_offset_table, (const Il2CppDebugMethodInfo * info)); DO_API(size_t, il2cpp_debug_method_get_code_size, (const Il2CppDebugMethodInfo * info)); DO_API(void, il2cpp_debug_update_frame_il_offset, (int32_t il_offset)); DO_API(const Il2CppDebugLocalsInfo**, il2cpp_debug_method_get_locals_info, (const Il2CppDebugMethodInfo * info)); DO_API(const Il2CppClass*, il2cpp_debug_local_get_type, (const Il2CppDebugLocalsInfo * info)); DO_API(const char*, il2cpp_debug_local_get_name, (const Il2CppDebugLocalsInfo * info)); DO_API(uint32_t, il2cpp_debug_local_get_start_offset, (const Il2CppDebugLocalsInfo * info)); DO_API(uint32_t, il2cpp_debug_local_get_end_offset, (const Il2CppDebugLocalsInfo * info)); DO_API(Il2CppObject*, il2cpp_debug_method_get_param_value, (const Il2CppStackFrameInfo * info, uint32_t position)); DO_API(Il2CppObject*, il2cpp_debug_frame_get_local_value, (const Il2CppStackFrameInfo * info, uint32_t position)); DO_API(void*, il2cpp_debug_method_get_breakpoint_data_at, (const Il2CppDebugMethodInfo * info, int64_t uid, int32_t offset)); DO_API(void, il2cpp_debug_method_set_breakpoint_data_at, (const Il2CppDebugMethodInfo * info, uint64_t location, void *data)); DO_API(void, il2cpp_debug_method_clear_breakpoint_data, (const Il2CppDebugMethodInfo * info)); DO_API(void, il2cpp_debug_method_clear_breakpoint_data_at, (const Il2CppDebugMethodInfo * info, uint64_t location)); #endif ================================================ FILE: unity_decoder/libil2cpp/il2cpp-api-types.h ================================================ #pragma once #include #include struct Il2CppClass; struct Il2CppType; struct EventInfo; struct MethodInfo; struct FieldInfo; struct PropertyInfo; struct Il2CppAssembly; struct Il2CppArray; struct Il2CppDelegate; struct Il2CppDomain; struct Il2CppImage; struct Il2CppException; struct Il2CppProfiler; struct Il2CppObject; struct Il2CppReflectionMethod; struct Il2CppReflectionType; struct Il2CppString; struct Il2CppThread; struct Il2CppAsyncResult; #if IL2CPP_DEBUGGER_ENABLED struct Il2CppDebugDocument; struct Il2CppDebugTypeInfo; struct Il2CppDebugMethodInfo; struct Il2CppDebugLocalsInfo; #endif enum Il2CppProfileFlags { IL2CPP_PROFILE_NONE = 0, IL2CPP_PROFILE_APPDOMAIN_EVENTS = 1 << 0, IL2CPP_PROFILE_ASSEMBLY_EVENTS = 1 << 1, IL2CPP_PROFILE_MODULE_EVENTS = 1 << 2, IL2CPP_PROFILE_CLASS_EVENTS = 1 << 3, IL2CPP_PROFILE_JIT_COMPILATION = 1 << 4, IL2CPP_PROFILE_INLINING = 1 << 5, IL2CPP_PROFILE_EXCEPTIONS = 1 << 6, IL2CPP_PROFILE_ALLOCATIONS = 1 << 7, IL2CPP_PROFILE_GC = 1 << 8, IL2CPP_PROFILE_THREADS = 1 << 9, IL2CPP_PROFILE_REMOTING = 1 << 10, IL2CPP_PROFILE_TRANSITIONS = 1 << 11, IL2CPP_PROFILE_ENTER_LEAVE = 1 << 12, IL2CPP_PROFILE_COVERAGE = 1 << 13, IL2CPP_PROFILE_INS_COVERAGE = 1 << 14, IL2CPP_PROFILE_STATISTICAL = 1 << 15, IL2CPP_PROFILE_METHOD_EVENTS = 1 << 16, IL2CPP_PROFILE_MONITOR_EVENTS = 1 << 17, IL2CPP_PROFILE_IOMAP_EVENTS = 1 << 18, /* this should likely be removed, too */ IL2CPP_PROFILE_GC_MOVES = 1 << 19 }; enum Il2CppGCEvent { IL2CPP_GC_EVENT_START, IL2CPP_GC_EVENT_MARK_START, IL2CPP_GC_EVENT_MARK_END, IL2CPP_GC_EVENT_RECLAIM_START, IL2CPP_GC_EVENT_RECLAIM_END, IL2CPP_GC_EVENT_END, IL2CPP_GC_EVENT_PRE_STOP_WORLD, IL2CPP_GC_EVENT_POST_STOP_WORLD, IL2CPP_GC_EVENT_PRE_START_WORLD, IL2CPP_GC_EVENT_POST_START_WORLD }; enum Il2CppStat { IL2CPP_STAT_NEW_OBJECT_COUNT, IL2CPP_STAT_INITIALIZED_CLASS_COUNT, //IL2CPP_STAT_GENERIC_VTABLE_COUNT, //IL2CPP_STAT_USED_CLASS_COUNT, IL2CPP_STAT_METHOD_COUNT, //IL2CPP_STAT_CLASS_VTABLE_SIZE, IL2CPP_STAT_CLASS_STATIC_DATA_SIZE, IL2CPP_STAT_GENERIC_INSTANCE_COUNT, IL2CPP_STAT_GENERIC_CLASS_COUNT, IL2CPP_STAT_INFLATED_METHOD_COUNT, IL2CPP_STAT_INFLATED_TYPE_COUNT, //IL2CPP_STAT_DELEGATE_CREATIONS, //IL2CPP_STAT_MINOR_GC_COUNT, //IL2CPP_STAT_MAJOR_GC_COUNT, //IL2CPP_STAT_MINOR_GC_TIME_USECS, //IL2CPP_STAT_MAJOR_GC_TIME_USECS }; enum StackFrameType { FRAME_TYPE_MANAGED = 0, FRAME_TYPE_DEBUGGER_INVOKE = 1, FRAME_TYPE_MANAGED_TO_NATIVE = 2, FRAME_TYPE_SENTINEL = 3 }; enum Il2CppRuntimeUnhandledExceptionPolicy { IL2CPP_UNHANDLED_POLICY_LEGACY, IL2CPP_UNHANDLED_POLICY_CURRENT }; struct Il2CppStackFrameInfo { const MethodInfo *method; #if IL2CPP_DEBUGGER_ENABLED int32_t id; StackFrameType type; uint32_t il_offset; void *this_ptr; void **params; uint32_t params_count; void **locals; uint32_t locals_count; #endif }; #if defined(RUNTIME_MONO) #include "mono-api.h" #endif // defined(RUNTIME_MONO) typedef struct { void* (*malloc_func)(size_t size); void* (*aligned_malloc_func)(size_t size, size_t alignment); void (*free_func)(void *ptr); void (*aligned_free_func)(void *ptr); void* (*calloc_func)(size_t nmemb, size_t size); void* (*realloc_func)(void *ptr, size_t size); void* (*aligned_realloc_func)(void *ptr, size_t size, size_t alignment); } Il2CppMemoryCallbacks; #if !__SNC__ // SNC doesn't like the following define: "warning 1576: predefined meaning of __has_feature discarded" #ifndef __has_feature // clang specific __has_feature check #define __has_feature(x) 0 // Compatibility with non-clang compilers. #endif #endif #if _MSC_VER typedef wchar_t Il2CppChar; #elif __has_feature(cxx_unicode_literals) typedef char16_t Il2CppChar; #else typedef uint16_t Il2CppChar; #endif #if _MSC_VER typedef wchar_t Il2CppNativeChar; #define IL2CPP_NATIVE_STRING(str) L##str #else typedef char Il2CppNativeChar; #define IL2CPP_NATIVE_STRING(str) str #endif typedef void (*il2cpp_register_object_callback)(Il2CppObject** arr, int size, void* userdata); typedef void (*il2cpp_WorldChangedCallback)(); typedef void (*Il2CppFrameWalkFunc) (const Il2CppStackFrameInfo *info, void *user_data); typedef void (*Il2CppProfileFunc) (Il2CppProfiler* prof); typedef void (*Il2CppProfileMethodFunc) (Il2CppProfiler* prof, const MethodInfo *method); typedef void (*Il2CppProfileAllocFunc) (Il2CppProfiler* prof, Il2CppObject *obj, Il2CppClass *klass); typedef void (*Il2CppProfileGCFunc) (Il2CppProfiler* prof, Il2CppGCEvent event, int generation); typedef void (*Il2CppProfileGCResizeFunc) (Il2CppProfiler* prof, int64_t new_size); typedef const Il2CppNativeChar* (*Il2CppSetFindPlugInCallback)(const Il2CppNativeChar*); typedef void (*Il2CppLogCallback)(const char*); struct Il2CppManagedMemorySnapshot; typedef void (*Il2CppMethodPointer)(); typedef int32_t il2cpp_array_size_t; ================================================ FILE: unity_decoder/libil2cpp/il2cpp-api.cpp ================================================ #include "il2cpp-api.h" #include "object-internals.h" #include "vm/Array.h" #include "vm/Assembly.h" #include "vm/Class.h" #include "vm/Domain.h" #include "vm/Exception.h" #include "vm/Field.h" #include "vm/Image.h" #include "vm/InternalCalls.h" #include "vm/Liveness.h" #include "vm/MemoryInformation.h" #include "vm/Method.h" #include "vm/Monitor.h" #include "vm/Object.h" #include "vm/Path.h" #include "vm/PlatformInvoke.h" #include "vm/Profiler.h" #include "vm/Property.h" #include "vm/Reflection.h" #include "vm/Runtime.h" #include "vm/StackTrace.h" #include "vm/String.h" #include "vm/Thread.h" #include "vm/ThreadPool.h" #include "vm/Type.h" #include "utils/Exception.h" #include "utils/Logging.h" #include "utils/Memory.h" #include "utils/StringUtils.h" #include "utils/Runtime.h" #include "utils/Environment.h" #if IL2CPP_DEBUGGER_ENABLED #include "il2cpp-debugger.h" #include "vm/Debug.h" #endif #include "gc/GarbageCollector.h" #include "gc/GCHandle.h" #include #include using namespace il2cpp::vm; using il2cpp::utils::Memory; using namespace il2cpp::gc; #if IL2CPP_API_DYNAMIC_NO_DLSYM #include struct SymbolCompare : public std::binary_function { bool operator()(const char* lhs, const char* rhs) const { return strcmp(lhs, rhs) < 0; } }; typedef std::map SymbolTable; static SymbolTable s_SymbolTable; static void RegisterAPIFunction(const char* name, void* symbol) { s_SymbolTable.insert(std::make_pair(name, symbol)); } void il2cpp_api_register_symbols(void) { #define DO_API(r, n, p) RegisterAPIFunction(#n, (void*)n); #include "il2cpp-api-functions.h" #undef DO_API } void* il2cpp_api_lookup_symbol(const char* name) { SymbolTable::iterator it = s_SymbolTable.find(name); if (it != s_SymbolTable.end()) { return it->second; } return NULL; } #endif // IL2CPP_API_DYNAMIC_NO_DLSYM void il2cpp_init(const char* domain_name) { // Use environment's default locale setlocale(LC_ALL, ""); #if IL2CPP_DEBUGGER_ENABLED if (!il2cpp_debugger_agent_is_initialized()) il2cpp_debugger_agent_init(); #endif // NOTE(gab): the runtime_version needs to change once we // will support multiple runtimes. // For now we default to the one used by unity and don't // allow the callers to change it. #if NET_4_0 Runtime::Init(domain_name, "v4.0.30319"); #else Runtime::Init(domain_name, "v2.0.50727"); #endif #if IL2CPP_DEBUGGER_ENABLED il2cpp_debugger_notify_vm_start(); #endif } void il2cpp_init_utf16(const Il2CppChar* domain_name) { return il2cpp_init(il2cpp::utils::StringUtils::Utf16ToUtf8(domain_name).c_str()); } void il2cpp_shutdown() { #if IL2CPP_DEBUGGER_ENABLED il2cpp_debugger_notify_vm_death(); #endif Runtime::Shutdown(); #if IL2CPP_DEBUGGER_ENABLED il2cpp_debugger_agent_dispose(); #endif } void il2cpp_set_config_dir(const char *config_path) { il2cpp::vm::Runtime::SetConfigDir(config_path); } void il2cpp_set_data_dir(const char *data_path) { il2cpp::utils::Runtime::SetDataDir(data_path); } void il2cpp_set_temp_dir(const char *temp_dir) { il2cpp::vm::Path::SetTempPath(temp_dir); } void il2cpp_set_commandline_arguments(int argc, const char* const argv[], const char* basedir) { il2cpp::utils::Environment::SetMainArgs(argv, argc); } void il2cpp_set_commandline_arguments_utf16(int argc, const Il2CppChar* const argv[], const char* basedir) { il2cpp::utils::Environment::SetMainArgs(argv, argc); } void il2cpp_set_config_utf16(const Il2CppChar* executablePath) { il2cpp::vm::Runtime::SetConfigUtf16(executablePath); } void il2cpp_set_config(const char* executablePath) { il2cpp::vm::Runtime::SetConfig(executablePath); } void il2cpp_set_memory_callbacks(Il2CppMemoryCallbacks* callbacks) { Memory::SetMemoryCallbacks(callbacks); } const Il2CppImage* il2cpp_get_corlib() { return Image::GetCorlib(); } void il2cpp_add_internal_call(const char* name, Il2CppMethodPointer method) { return InternalCalls::Add(name, method); } Il2CppMethodPointer il2cpp_resolve_icall(const char* name) { return InternalCalls::Resolve(name); } void* il2cpp_alloc(size_t size) { return IL2CPP_MALLOC(size); } void il2cpp_free(void* ptr) { IL2CPP_FREE(ptr); } // array Il2CppClass *il2cpp_array_class_get(Il2CppClass *element_class, uint32_t rank) { return Class::GetArrayClass(element_class, rank); } uint32_t il2cpp_array_length(Il2CppArray* array) { return Array::GetLength(array); } uint32_t il2cpp_array_get_byte_length(Il2CppArray *array) { return Array::GetByteLength(array); } Il2CppArray* il2cpp_array_new(Il2CppClass *elementTypeInfo, il2cpp_array_size_t length) { return Array::New(elementTypeInfo, length); } Il2CppArray* il2cpp_array_new_specific(Il2CppClass *arrayTypeInfo, il2cpp_array_size_t length) { return Array::NewSpecific(arrayTypeInfo, length); } Il2CppArray* il2cpp_array_new_full(Il2CppClass *array_class, il2cpp_array_size_t *lengths, il2cpp_array_size_t *lower_bounds) { return Array::NewFull(array_class, lengths, lower_bounds); } Il2CppClass* il2cpp_bounded_array_class_get(Il2CppClass *element_class, uint32_t rank, bool bounded) { return Class::GetBoundedArrayClass(element_class, rank, bounded); } int il2cpp_array_element_size(const Il2CppClass* klass) { return Array::GetElementSize(klass); } // assembly const Il2CppImage* il2cpp_assembly_get_image(const Il2CppAssembly *assembly) { return Assembly::GetImage(assembly); } // class const Il2CppType* il2cpp_class_enum_basetype(Il2CppClass *klass) { return Class::GetEnumBaseType(klass); } Il2CppClass* il2cpp_class_from_system_type(Il2CppReflectionType *type) { return Class::FromSystemType(type); } bool il2cpp_class_is_generic(const Il2CppClass *klass) { return Class::IsGeneric(klass); } bool il2cpp_class_is_inflated(const Il2CppClass *klass) { return Class::IsInflated(klass); } bool il2cpp_class_is_assignable_from(Il2CppClass *klass, Il2CppClass *oklass) { return Class::IsAssignableFrom(klass, oklass); } bool il2cpp_class_is_subclass_of(Il2CppClass *klass, Il2CppClass *klassc, bool check_interfaces) { return Class::IsSubclassOf(klass, klassc, check_interfaces); } bool il2cpp_class_has_parent(Il2CppClass *klass, Il2CppClass *klassc) { return Class::HasParent(klass, klassc); } Il2CppClass* il2cpp_class_from_il2cpp_type(const Il2CppType* type) { return Class::FromIl2CppType(type); } Il2CppClass* il2cpp_class_from_name(const Il2CppImage* image, const char* namespaze, const char *name) { return Class::FromName(image, namespaze, name); } Il2CppClass* il2cpp_class_get_element_class(Il2CppClass *klass) { return Class::GetElementClass(klass); } const EventInfo* il2cpp_class_get_events(Il2CppClass *klass, void* *iter) { return Class::GetEvents(klass, iter); } FieldInfo* il2cpp_class_get_fields(Il2CppClass *klass, void* *iter) { return Class::GetFields(klass, iter); } Il2CppClass* il2cpp_class_get_nested_types(Il2CppClass *klass, void* *iter) { return Class::GetNestedTypes(klass, iter); } Il2CppClass* il2cpp_class_get_interfaces(Il2CppClass *klass, void* *iter) { return Class::GetInterfaces(klass, iter); } const PropertyInfo* il2cpp_class_get_properties(Il2CppClass *klass, void* *iter) { return Class::GetProperties(klass, iter); } const PropertyInfo* il2cpp_class_get_property_from_name(Il2CppClass *klass, const char *name) { return Class::GetPropertyFromName(klass, name); } FieldInfo* il2cpp_class_get_field_from_name(Il2CppClass* klass, const char *name) { return Class::GetFieldFromName(klass, name); } const MethodInfo* il2cpp_class_get_methods(Il2CppClass *klass, void* *iter) { return Class::GetMethods(klass, iter); } const MethodInfo* il2cpp_class_get_method_from_name(Il2CppClass *klass, const char* name, int argsCount) { return Class::GetMethodFromName(klass, name, argsCount); } const char* il2cpp_class_get_name(Il2CppClass *klass) { return Class::GetName(klass); } const char* il2cpp_class_get_namespace(Il2CppClass *klass) { return Class::GetNamespace(klass); } Il2CppClass* il2cpp_class_get_parent(Il2CppClass *klass) { return Class::GetParent(klass); } Il2CppClass* il2cpp_class_get_declaring_type(Il2CppClass* klass) { return Class::GetDeclaringType(klass); } int32_t il2cpp_class_instance_size(Il2CppClass *klass) { return Class::GetInstanceSize(klass); } size_t il2cpp_class_num_fields(const Il2CppClass* klass) { return Class::GetNumFields(klass); } bool il2cpp_class_is_valuetype(const Il2CppClass* klass) { return Class::IsValuetype(klass); } bool il2cpp_class_is_blittable(const Il2CppClass* klass) { return Class::IsBlittable(klass); } int32_t il2cpp_class_value_size(Il2CppClass *klass, uint32_t *align) { return Class::GetValueSize(klass, align); } int il2cpp_class_get_flags(const Il2CppClass *klass) { return Class::GetFlags(klass); } bool il2cpp_class_is_abstract(const Il2CppClass *klass) { return Class::IsAbstract(klass); } bool il2cpp_class_is_interface(const Il2CppClass *klass) { return Class::IsInterface(klass); } int il2cpp_class_array_element_size(const Il2CppClass *klass) { return Class::GetArrayElementSize(klass); } Il2CppClass* il2cpp_class_from_type(const Il2CppType *type) { return Class::FromIl2CppType(type); } const Il2CppType* il2cpp_class_get_type(Il2CppClass *klass) { return Class::GetType(klass); } bool il2cpp_class_has_attribute(Il2CppClass *klass, Il2CppClass *attr_class) { return Class::HasAttribute(klass, attr_class); } bool il2cpp_class_has_references(Il2CppClass *klass) { return Class::HasReferences(klass); } bool il2cpp_class_is_enum(const Il2CppClass *klass) { return Class::IsEnum(klass); } const Il2CppImage* il2cpp_class_get_image(Il2CppClass* klass) { return Class::GetImage(klass); } const char *il2cpp_class_get_assemblyname(const Il2CppClass *klass) { return Class::GetAssemblyName(klass); } // testing only size_t il2cpp_class_get_bitmap_size(const Il2CppClass *klass) { return Class::GetBitmapSize(klass); } void il2cpp_class_get_bitmap(Il2CppClass *klass, size_t* bitmap) { size_t dummy = 0; Class::GetBitmap(klass, bitmap, dummy); } // stats extern Il2CppRuntimeStats il2cpp_runtime_stats; bool il2cpp_stats_dump_to_file(const char *path) { std::fstream fs; fs.open(path, std::fstream::out | std::fstream::trunc); fs << "New object count: " << il2cpp_stats_get_value(IL2CPP_STAT_NEW_OBJECT_COUNT) << "\n"; fs << "Method count: " << il2cpp_stats_get_value(IL2CPP_STAT_METHOD_COUNT) << "\n"; fs << "Class static data size: " << il2cpp_stats_get_value(IL2CPP_STAT_CLASS_STATIC_DATA_SIZE) << "\n"; fs << "Inflated method count: " << il2cpp_stats_get_value(IL2CPP_STAT_INFLATED_METHOD_COUNT) << "\n"; fs << "Inflated type count: " << il2cpp_stats_get_value(IL2CPP_STAT_INFLATED_TYPE_COUNT) << "\n"; fs << "Initialized class count: " << il2cpp_stats_get_value(IL2CPP_STAT_INITIALIZED_CLASS_COUNT) << "\n"; fs << "Generic instance count: " << il2cpp_stats_get_value(IL2CPP_STAT_GENERIC_INSTANCE_COUNT) << "\n"; fs << "Generic class count: " << il2cpp_stats_get_value(IL2CPP_STAT_GENERIC_CLASS_COUNT) << "\n"; fs.close(); return true; } uint64_t il2cpp_stats_get_value(Il2CppStat stat) { switch (stat) { case IL2CPP_STAT_NEW_OBJECT_COUNT: return il2cpp_runtime_stats.new_object_count; case IL2CPP_STAT_INITIALIZED_CLASS_COUNT: return il2cpp_runtime_stats.initialized_class_count; /*case IL2CPP_STAT_GENERIC_VTABLE_COUNT: return il2cpp_runtime_stats.generic_vtable_count; case IL2CPP_STAT_USED_CLASS_COUNT: return il2cpp_runtime_stats.used_class_count;*/ case IL2CPP_STAT_METHOD_COUNT: return il2cpp_runtime_stats.method_count; /*case IL2CPP_STAT_CLASS_VTABLE_SIZE: return il2cpp_runtime_stats.class_vtable_size;*/ case IL2CPP_STAT_CLASS_STATIC_DATA_SIZE: return il2cpp_runtime_stats.class_static_data_size; case IL2CPP_STAT_GENERIC_INSTANCE_COUNT: return il2cpp_runtime_stats.generic_instance_count; case IL2CPP_STAT_GENERIC_CLASS_COUNT: return il2cpp_runtime_stats.generic_class_count; case IL2CPP_STAT_INFLATED_METHOD_COUNT: return il2cpp_runtime_stats.inflated_method_count; case IL2CPP_STAT_INFLATED_TYPE_COUNT: return il2cpp_runtime_stats.inflated_type_count; /*case IL2CPP_STAT_DELEGATE_CREATIONS: return il2cpp_runtime_stats.delegate_creations; case IL2CPP_STAT_MINOR_GC_COUNT: return il2cpp_runtime_stats.minor_gc_count; case IL2CPP_STAT_MAJOR_GC_COUNT: return il2cpp_runtime_stats.major_gc_count; case IL2CPP_STAT_MINOR_GC_TIME_USECS: return il2cpp_runtime_stats.minor_gc_time_usecs; case IL2CPP_STAT_MAJOR_GC_TIME_USECS: return il2cpp_runtime_stats.major_gc_time_usecs;*/ } return 0; } // domain Il2CppDomain* il2cpp_domain_get() { return Domain::GetCurrent(); } const Il2CppAssembly* il2cpp_domain_assembly_open(Il2CppDomain *domain, const char *name) { return Assembly::Load(name); } const Il2CppAssembly** il2cpp_domain_get_assemblies(const Il2CppDomain* domain, size_t* size) { il2cpp::vm::AssemblyVector* assemblies = Assembly::GetAllAssemblies(); *size = assemblies->size(); return &(*assemblies)[0]; } // exception void il2cpp_raise_exception(Il2CppException* exc) { Exception::Raise(exc); } Il2CppException* il2cpp_exception_from_name_msg(const Il2CppImage* image, const char *name_space, const char *name, const char *msg) { return Exception::FromNameMsg(image, name_space, name, msg); } Il2CppException* il2cpp_get_exception_argument_null(const char *arg) { return Exception::GetArgumentNullException(arg); } void il2cpp_format_exception(const Il2CppException* ex, char* message, int message_size) { strncpy(message, il2cpp::utils::Exception::FormatException(ex).c_str(), message_size); } void il2cpp_format_stack_trace(const Il2CppException* ex, char* output, int output_size) { strncpy(output, il2cpp::utils::Exception::FormatStackTrace(ex).c_str(), output_size); } void il2cpp_unhandled_exception(Il2CppException* exc) { Runtime::UnhandledException(exc); } // field const char* il2cpp_field_get_name(FieldInfo *field) { return Field::GetName(field); } int il2cpp_field_get_flags(FieldInfo *field) { return Field::GetFlags(field); } Il2CppClass* il2cpp_field_get_parent(FieldInfo *field) { return Field::GetParent(field); } size_t il2cpp_field_get_offset(FieldInfo *field) { return Field::GetOffset(field); } const Il2CppType* il2cpp_field_get_type(FieldInfo *field) { return Field::GetType(field); } void il2cpp_field_get_value(Il2CppObject *obj, FieldInfo *field, void *value) { return Field::GetValue(obj, field, value); } Il2CppObject* il2cpp_field_get_value_object(FieldInfo *field, Il2CppObject *obj) { return Field::GetValueObject(field, obj); } bool il2cpp_field_has_attribute(FieldInfo *field, Il2CppClass *attr_class) { return Field::HasAttribute(field, attr_class); } void il2cpp_field_set_value(Il2CppObject *obj, FieldInfo *field, void *value) { Field::SetValue(obj, field, value); } void il2cpp_field_set_value_object(Il2CppObject* objectInstance, FieldInfo* field, Il2CppObject* value) { Field::SetInstanceFieldValueObject(objectInstance, field, value); } void il2cpp_field_static_get_value(FieldInfo *field, void *value) { Field::StaticGetValue(field, value); } void il2cpp_field_static_set_value(FieldInfo *field, void *value) { Field::StaticSetValue(field, value); } // gc void il2cpp_gc_collect(int maxGenerations) { GarbageCollector::Collect(maxGenerations); } int32_t il2cpp_gc_collect_a_little() { return GarbageCollector::CollectALittle(); } void il2cpp_gc_enable() { GarbageCollector::Enable(); } void il2cpp_gc_disable() { GarbageCollector::Disable(); } int64_t il2cpp_gc_get_used_size() { return GarbageCollector::GetUsedHeapSize(); } int64_t il2cpp_gc_get_heap_size() { return GarbageCollector::GetAllocatedHeapSize(); } // gchandle uint32_t il2cpp_gchandle_new(Il2CppObject *obj, bool pinned) { return GCHandle::New(obj, pinned); } uint32_t il2cpp_gchandle_new_weakref(Il2CppObject *obj, bool track_resurrection) { return GCHandle::NewWeakref(obj, track_resurrection); } Il2CppObject* il2cpp_gchandle_get_target(uint32_t gchandle) { return GCHandle::GetTarget(gchandle); } void il2cpp_gchandle_free(uint32_t gchandle) { GCHandle::Free(gchandle); } // liveness void* il2cpp_unity_liveness_calculation_begin(Il2CppClass* filter, int max_object_count, il2cpp_register_object_callback callback, void* userdata, il2cpp_WorldChangedCallback onWorldStarted, il2cpp_WorldChangedCallback onWorldStopped) { return Liveness::Begin(filter, max_object_count, callback, userdata, onWorldStarted, onWorldStopped); } void il2cpp_unity_liveness_calculation_end(void* state) { Liveness::End(state); } void il2cpp_unity_liveness_calculation_from_root(Il2CppObject* root, void* state) { Liveness::FromRoot(root, state); } void il2cpp_unity_liveness_calculation_from_statics(void* state) { Liveness::FromStatics(state); } // method const Il2CppType* il2cpp_method_get_return_type(const MethodInfo* method) { return Method::GetReturnType(method); } Il2CppReflectionMethod* il2cpp_method_get_object(const MethodInfo *method, Il2CppClass *refclass) { return Reflection::GetMethodObject(method, refclass); } const char* il2cpp_method_get_name(const MethodInfo *method) { return Method::GetName(method); } bool il2cpp_method_is_generic(const MethodInfo *method) { return Method::IsGeneric(method); } bool il2cpp_method_is_inflated(const MethodInfo *method) { return Method::IsInflated(method); } bool il2cpp_method_is_instance(const MethodInfo *method) { return Method::IsInstance(method); } uint32_t il2cpp_method_get_param_count(const MethodInfo *method) { return Method::GetParamCount(method); } const Il2CppType* il2cpp_method_get_param(const MethodInfo *method, uint32_t index) { return Method::GetParam(method, index); } Il2CppClass* il2cpp_method_get_class(const MethodInfo *method) { return Method::GetClass(method); } bool il2cpp_method_has_attribute(const MethodInfo *method, Il2CppClass *attr_class) { return Method::HasAttribute(method, attr_class); } Il2CppClass* il2cpp_method_get_declaring_type(const MethodInfo* method) { return Method::GetDeclaringType(method); } uint32_t il2cpp_method_get_flags(const MethodInfo *method, uint32_t *iflags) { if (iflags != 0) *iflags = Method::GetImplementationFlags(method); return Method::GetFlags(method); } uint32_t il2cpp_method_get_token(const MethodInfo *method) { return Method::GetToken(method); } const char *il2cpp_method_get_param_name(const MethodInfo *method, uint32_t index) { return Method::GetParamName(method, index); } // profiler #if IL2CPP_ENABLE_PROFILER void il2cpp_profiler_install(Il2CppProfiler *prof, Il2CppProfileFunc shutdown_callback) { Profiler::Install(prof, shutdown_callback); } void il2cpp_profiler_set_events(Il2CppProfileFlags events) { Profiler::SetEvents(events); } void il2cpp_profiler_install_enter_leave(Il2CppProfileMethodFunc enter, Il2CppProfileMethodFunc fleave) { Profiler::InstallEnterLeave(enter, fleave); } void il2cpp_profiler_install_allocation(Il2CppProfileAllocFunc callback) { Profiler::InstallAllocation(callback); } void il2cpp_profiler_install_gc(Il2CppProfileGCFunc callback, Il2CppProfileGCResizeFunc heap_resize_callback) { Profiler::InstallGC(callback, heap_resize_callback); } #endif // property const char* il2cpp_property_get_name(PropertyInfo *prop) { return Property::GetName(prop); } const MethodInfo* il2cpp_property_get_get_method(PropertyInfo *prop) { return Property::GetGetMethod(prop); } const MethodInfo* il2cpp_property_get_set_method(PropertyInfo *prop) { return Property::GetSetMethod(prop); } Il2CppClass* il2cpp_property_get_parent(PropertyInfo *prop) { return Property::GetParent(prop); } uint32_t il2cpp_property_get_flags(PropertyInfo *prop) { return Property::GetFlags(prop); } // object Il2CppClass* il2cpp_object_get_class(Il2CppObject* obj) { return Object::GetClass(obj); } uint32_t il2cpp_object_get_size(Il2CppObject* obj) { return Object::GetSize(obj); } const MethodInfo* il2cpp_object_get_virtual_method(Il2CppObject *obj, const MethodInfo *method) { return Object::GetVirtualMethod(obj, method); } Il2CppObject* il2cpp_object_new(const Il2CppClass *klass) { try { return Object::New(const_cast(klass)); } catch (const Il2CppExceptionWrapper&) { // If a static constructor throws, that exception will occur here. // We don't want that to escape across the embedding API. return NULL; } } void* il2cpp_object_unbox(Il2CppObject* obj) { return Object::Unbox(obj); } Il2CppObject* il2cpp_value_box(Il2CppClass *klass, void* data) { return Object::Box(klass, data); } // monitor void il2cpp_monitor_enter(Il2CppObject* obj) { Monitor::Enter(obj); } bool il2cpp_monitor_try_enter(Il2CppObject* obj, uint32_t timeout) { return Monitor::TryEnter(obj, timeout); } void il2cpp_monitor_exit(Il2CppObject* obj) { Monitor::Exit(obj); } void il2cpp_monitor_pulse(Il2CppObject* obj) { Monitor::Pulse(obj); } void il2cpp_monitor_pulse_all(Il2CppObject* obj) { Monitor::PulseAll(obj); } void il2cpp_monitor_wait(Il2CppObject* obj) { Monitor::Wait(obj); } bool il2cpp_monitor_try_wait(Il2CppObject* obj, uint32_t timeout) { return Monitor::TryWait(obj, timeout); } // runtime Il2CppObject* il2cpp_runtime_invoke_convert_args(const MethodInfo *method, void *obj, Il2CppObject **params, int paramCount, Il2CppException **exc) { // Our embedding API has historically taken pointers to unboxed value types, rather than Il2CppObjects. // However, with the introduction of adjustor thunks, our invokees expect us to pass them Il2CppObject*, or at least something that // ressembles boxed value type. Since it's not going to access any of the Il2CppObject* fields, // it's fine to just subtract sizeof(Il2CppObject) from obj pointer if (method->declaring_type->valuetype) obj = static_cast(obj) - 1; return Runtime::InvokeConvertArgs(method, obj, params, paramCount, exc); } Il2CppObject* il2cpp_runtime_invoke(const MethodInfo *method, void *obj, void **params, Il2CppException **exc) { // Our embedding API has historically taken pointers to unboxed value types, rather than Il2CppObjects. // However, with the introduction of adjustor thunks, our invokees expect us to pass them Il2CppObject*, or at least something that // ressembles boxed value type. Since it's not going to access any of the Il2CppObject* fields, // it's fine to just subtract sizeof(Il2CppObject) from obj pointer if (method->declaring_type->valuetype) obj = static_cast(obj) - 1; return Runtime::Invoke(method, obj, params, exc); } void il2cpp_runtime_class_init(Il2CppClass* klass) { return Runtime::ClassInit(klass); } void il2cpp_runtime_object_init(Il2CppObject *obj) { Runtime::ObjectInit(obj); } void il2cpp_runtime_object_init_exception(Il2CppObject *obj, Il2CppException **exc) { Runtime::ObjectInitException(obj, exc); } void il2cpp_runtime_unhandled_exception_policy_set(Il2CppRuntimeUnhandledExceptionPolicy value) { Runtime::SetUnhandledExceptionPolicy(value); } // string int32_t il2cpp_string_length(Il2CppString* str) { return il2cpp::utils::StringUtils::GetLength(str); } Il2CppChar* il2cpp_string_chars(Il2CppString* str) { return il2cpp::utils::StringUtils::GetChars(str); } // Same as il2cpp_string_new_wrapper, because other normally takes a domain Il2CppString* il2cpp_string_new(const char* str) { return String::New(str); } Il2CppString* il2cpp_string_new_wrapper(const char* str) { return String::NewWrapper(str); } Il2CppString* il2cpp_string_new_utf16(const Il2CppChar *text, int32_t len) { return String::NewUtf16(text, len); } Il2CppString* il2cpp_string_new_len(const char* str, uint32_t length) { return String::NewLen(str, length); } Il2CppString* il2cpp_string_intern(Il2CppString* str) { return String::Intern(str); } Il2CppString* il2cpp_string_is_interned(Il2CppString* str) { return String::IsInterned(str); } // thread char *il2cpp_thread_get_name(Il2CppThread *thread, uint32_t *len) { return Thread::GetName(len); } Il2CppThread *il2cpp_thread_current() { return Thread::Current(); } Il2CppThread *il2cpp_thread_attach(Il2CppDomain *domain) { return Thread::Attach(domain); } void il2cpp_thread_detach(Il2CppThread *thread) { Thread::Detach(thread); } Il2CppThread **il2cpp_thread_get_all_attached_threads(size_t *size) { return Thread::GetAllAttachedThreads(*size); } bool il2cpp_is_vm_thread(Il2CppThread *thread) { return Thread::IsVmThread(thread); } // stacktrace void il2cpp_current_thread_walk_frame_stack(Il2CppFrameWalkFunc func, void* user_data) { StackTrace::WalkFrameStack(func, user_data); } void il2cpp_thread_walk_frame_stack(Il2CppThread *thread, Il2CppFrameWalkFunc func, void *user_data) { return StackTrace::WalkThreadFrameStack(thread, func, user_data); } bool il2cpp_current_thread_get_top_frame(Il2CppStackFrameInfo& frame) { return StackTrace::GetTopStackFrame(frame); } bool il2cpp_thread_get_top_frame(Il2CppThread* thread, Il2CppStackFrameInfo& frame) { return StackTrace::GetThreadTopStackFrame(thread, frame); } bool il2cpp_current_thread_get_frame_at(int32_t offset, Il2CppStackFrameInfo& frame) { return StackTrace::GetStackFrameAt(offset, frame); } bool il2cpp_thread_get_frame_at(Il2CppThread* thread, int32_t offset, Il2CppStackFrameInfo& frame) { return StackTrace::GetThreadStackFrameAt(thread, offset, frame); } int32_t il2cpp_current_thread_get_stack_depth() { return static_cast(StackTrace::GetStackDepth()); } int32_t il2cpp_thread_get_stack_depth(Il2CppThread *thread) { return StackTrace::GetThreadStackDepth(thread); } // type Il2CppObject* il2cpp_type_get_object(const Il2CppType *type) { return (Il2CppObject*)Reflection::GetTypeObject(type); } int il2cpp_type_get_type(const Il2CppType *type) { return Type::GetType(type); } Il2CppClass* il2cpp_type_get_class_or_element_class(const Il2CppType *type) { return Type::GetClassOrElementClass(type); } char* il2cpp_type_get_name(const Il2CppType *type) { std::string name = Type::GetName(type, IL2CPP_TYPE_NAME_FORMAT_IL); char* buffer = static_cast(il2cpp_alloc(name.length() + 1)); memcpy(buffer, name.c_str(), name.length() + 1); return buffer; } // image const Il2CppAssembly* il2cpp_image_get_assembly(const Il2CppImage *image) { return Image::GetAssembly(image); } const char* il2cpp_image_get_name(const Il2CppImage *image) { return Image::GetName(image); } const char* il2cpp_image_get_filename(const Il2CppImage *image) { return Image::GetFileName(image); } const MethodInfo* il2cpp_image_get_entry_point(const Il2CppImage *image) { return Image::GetEntryPoint(image); } Il2CppManagedMemorySnapshot* il2cpp_capture_memory_snapshot() { return MemoryInformation::CaptureManagedMemorySnapshot(); } void il2cpp_free_captured_memory_snapshot(Il2CppManagedMemorySnapshot* snapshot) { MemoryInformation::FreeCapturedManagedMemorySnapshot(snapshot); } void il2cpp_set_find_plugin_callback(Il2CppSetFindPlugInCallback method) { il2cpp::vm::PlatformInvoke::SetFindPluginCallback(method); } // Logging void il2cpp_register_log_callback(Il2CppLogCallback method) { il2cpp::utils::Logging::SetLogCallback(method); } #if IL2CPP_DEBUGGER_ENABLED // debug const Il2CppDebugTypeInfo* il2cpp_debug_get_class_info(const Il2CppClass *klass) { return Class::GetDebugInfo(klass); } const Il2CppDebugDocument* il2cpp_debug_class_get_document(const Il2CppDebugTypeInfo* info) { return Debug::GetDocument(info); } const char* il2cpp_debug_document_get_filename(const Il2CppDebugDocument* document) { return Debug::DocumentGetFilename(document); } const char* il2cpp_debug_document_get_directory(const Il2CppDebugDocument* document) { return Debug::DocumentGetDirectory(document); } const Il2CppDebugMethodInfo* il2cpp_debug_get_method_info(const MethodInfo *method) { return Method::GetDebugInfo(method); } const Il2CppDebugDocument* il2cpp_debug_method_get_document(const Il2CppDebugMethodInfo* info) { return Debug::GetDocument(info); } const int32_t* il2cpp_debug_method_get_offset_table(const Il2CppDebugMethodInfo* info) { return Debug::GetOffsetTable(info); } size_t il2cpp_debug_method_get_code_size(const Il2CppDebugMethodInfo* info) { return Debug::GetCodeSize(info); } void il2cpp_debug_update_frame_il_offset(int32_t il_offset) { Debug::UpdateFrameIlOffset(il_offset); } const Il2CppDebugLocalsInfo **il2cpp_debug_method_get_locals_info(const Il2CppDebugMethodInfo* info) { return Debug::GetLocalsInfo(info); } const Il2CppClass *il2cpp_debug_local_get_type(const Il2CppDebugLocalsInfo *info) { return Debug::GetType(info); } const char *il2cpp_debug_local_get_name(const Il2CppDebugLocalsInfo *info) { return Debug::GetName(info); } uint32_t il2cpp_debug_local_get_start_offset(const Il2CppDebugLocalsInfo *info) { return Debug::GetStartOffset(info); } uint32_t il2cpp_debug_local_get_end_offset(const Il2CppDebugLocalsInfo *info) { return Debug::GetEndOffset(info); } Il2CppObject *il2cpp_debug_method_get_param_value(const Il2CppStackFrameInfo *info, uint32_t position) { return Debug::GetParamValue(info, position); } Il2CppObject *il2cpp_debug_frame_get_local_value(const Il2CppStackFrameInfo *info, uint32_t position) { return Debug::GetLocalValue(info, position); } void *il2cpp_debug_method_get_breakpoint_data_at(const Il2CppDebugMethodInfo* info, int64_t uid, int32_t offset) { return Debug::GetBreakpointDataAt(info, uid, offset); } void il2cpp_debug_method_set_breakpoint_data_at(const Il2CppDebugMethodInfo* info, uint64_t location, void *data) { Debug::SetBreakpointDataAt(info, location, data); } void il2cpp_debug_method_clear_breakpoint_data(const Il2CppDebugMethodInfo* info) { Debug::ClearBreakpointData(info); } void il2cpp_debug_method_clear_breakpoint_data_at(const Il2CppDebugMethodInfo* info, uint64_t location) { Debug::ClearBreakpointDataAt(info, location); } #endif ================================================ FILE: unity_decoder/libil2cpp/il2cpp-api.h ================================================ #pragma once #include #include "il2cpp-config.h" #if IL2CPP_API_DYNAMIC_NO_DLSYM extern "C" { IL2CPP_EXPORT void il2cpp_api_register_symbols(void); IL2CPP_EXPORT void* il2cpp_api_lookup_symbol(const char* name); } #endif extern "C" { #define DO_API(r, n, p) IL2CPP_EXPORT r n p; #include "il2cpp-api-functions.h" #undef DO_API } ================================================ FILE: unity_decoder/libil2cpp/il2cpp-config.h ================================================ #pragma once #include #include #include #include #include #include /* first setup platform defines*/ #if defined(SN_TARGET_PSP2) #define IL2CPP_TARGET_PSP2 1 #define _UNICODE 1 #define UNICODE 1 #include "il2cpp-config-psp2.h" #elif defined(SN_TARGET_ORBIS) #define IL2CPP_TARGET_PS4 1 #define _UNICODE 1 #define UNICODE 1 #elif defined(_MSC_VER) #define IL2CPP_TARGET_WINDOWS 1 #if defined(_XBOX_ONE) #define IL2CPP_TARGET_XBOXONE 1 #elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) #define IL2CPP_TARGET_WINRT 1 #else #define IL2CPP_TARGET_WINDOWS_DESKTOP 1 #endif #define _UNICODE 1 #define UNICODE 1 #define STRICT 1 #elif defined(__APPLE__) #define IL2CPP_TARGET_DARWIN 1 #include "TargetConditionals.h" #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR || TARGET_TVOS_SIMULATOR #define IL2CPP_TARGET_IOS 1 #endif #elif defined(__ANDROID__) #define IL2CPP_TARGET_ANDROID 1 #elif defined(EMSCRIPTEN) #define IL2CPP_TARGET_JAVASCRIPT 1 #elif defined(TIZEN) #define IL2CPP_TARGET_TIZEN 1 #elif defined(__linux__) #define IL2CPP_TARGET_LINUX 1 #elif defined(NN_PLATFORM_CTR) #define IL2CPP_TARGET_N3DS 1 #elif defined(NN_BUILD_TARGET_PLATFORM_NX) #define IL2CPP_TARGET_SWITCH 1 #else #error please define your target platform #endif #ifndef IL2CPP_TARGET_WINDOWS #define IL2CPP_TARGET_WINDOWS 0 #endif #ifndef IL2CPP_TARGET_WINDOWS_DESKTOP #define IL2CPP_TARGET_WINDOWS_DESKTOP 0 #endif #ifndef IL2CPP_TARGET_WINRT #define IL2CPP_TARGET_WINRT 0 #endif #ifndef IL2CPP_TARGET_XBOXONE #define IL2CPP_TARGET_XBOXONE 0 #endif #ifndef IL2CPP_TARGET_DARWIN #define IL2CPP_TARGET_DARWIN 0 #endif #ifndef IL2CPP_TARGET_IOS #define IL2CPP_TARGET_IOS 0 #endif #ifndef IL2CPP_TARGET_ANDROID #define IL2CPP_TARGET_ANDROID 0 #endif #ifndef IL2CPP_TARGET_JAVASCRIPT #define IL2CPP_TARGET_JAVASCRIPT 0 #endif #ifndef IL2CPP_TARGET_TIZEN #define IL2CPP_TARGET_TIZEN 0 #endif #ifndef IL2CPP_TARGET_LINUX #define IL2CPP_TARGET_LINUX 0 #endif #ifndef IL2CPP_TARGET_N3DS #define IL2CPP_TARGET_N3DS 0 #endif #ifndef IL2CPP_TARGET_PS4 #define IL2CPP_TARGET_PS4 0 #endif #ifndef IL2CPP_TARGET_PSP2 #define IL2CPP_TARGET_PSP2 0 #endif #ifndef IL2CPP_TARGET_SWITCH #define IL2CPP_TARGET_SWITCH 0 #endif #define IL2CPP_TARGET_POSIX (IL2CPP_TARGET_DARWIN || IL2CPP_TARGET_JAVASCRIPT || IL2CPP_TARGET_LINUX || IL2CPP_TARGET_ANDROID || IL2CPP_TARGET_PS4 || IL2CPP_TARGET_PSP2 || IL2CPP_TARGET_TIZEN) #define IL2CPP_COMPILER_MSVC (IL2CPP_TARGET_WINDOWS || IL2CPP_TARGET_XBOXONE) #ifndef IL2CPP_EXCEPTION_DISABLED #define IL2CPP_EXCEPTION_DISABLED 0 #endif // If the platform loads il2cpp as a dynamic library but does not have dlsym (or equivalent) then // define IL2CPP_API_DYNAMIC_NO_DLSYM = 1 to add support for api function registration and symbol // lookup APIs, see il2cpp-api.cpp #ifndef IL2CPP_API_DYNAMIC_NO_DLSYM #define IL2CPP_API_DYNAMIC_NO_DLSYM 0 #endif #ifdef _MSC_VER # include # define IL2CPP_EXPORT __declspec(dllexport) # define IL2CPP_IMPORT __declspec(dllimport) #elif IL2CPP_TARGET_PSP2 || IL2CPP_TARGET_PS4 # define IL2CPP_EXPORT __declspec(dllexport) # define IL2CPP_IMPORT __declspec(dllimport) #else # define IL2CPP_EXPORT __attribute__ ((visibility ("default"))) # define IL2CPP_IMPORT #endif #ifdef LIBIL2CPP_EXPORT_CODEGEN_API # define LIBIL2CPP_CODEGEN_API IL2CPP_EXPORT #elif LIBIL2CPP_IMPORT_CODEGEN_API # define LIBIL2CPP_CODEGEN_API IL2CPP_IMPORT #else # define LIBIL2CPP_CODEGEN_API #endif #if IL2CPP_TARGET_WINDOWS || IL2CPP_TARGET_XBOXONE || IL2CPP_TARGET_WINRT #include #define IL2CPP_ASSERT(expr) \ _ASSERTE(expr) #else #define IL2CPP_ASSERT(expr) \ assert(expr) #endif #if defined(__ARMCC_VERSION) #include #include #include #define INTPTR_MAX 2147483647 #endif #if IL2CPP_TARGET_DARWIN #define IL2CPP_METHOD_ATTR // the following gives more accurate managed stack traces, but may cause linker errors on ARMv7 builds // #define IL2CPP_METHOD_ATTR __attribute__((section ("__TEXT,__managed,regular,pure_instructions"))) #else #define IL2CPP_METHOD_ATTR #endif #if defined(_MSC_VER) #if defined(_M_X64) #define IL2CPP_SIZEOF_VOID_P 8 #elif defined(_M_IX86) || defined(_M_ARM) #define IL2CPP_SIZEOF_VOID_P 4 #else #error invalid windows architecture #endif #elif defined(__GNUC__) || defined(__SNC__) #if defined(__x86_64__) #define IL2CPP_SIZEOF_VOID_P 8 #elif defined(__i386__) #define IL2CPP_SIZEOF_VOID_P 4 #elif defined(EMSCRIPTEN) #define IL2CPP_SIZEOF_VOID_P 4 #elif defined(__arm__) #define IL2CPP_SIZEOF_VOID_P 4 #elif defined(__arm64__) #define IL2CPP_SIZEOF_VOID_P 8 #else #error invalid windows architecture #endif #else #error please define your target architecture size #endif #if defined(_MSC_VER) #define IL2CPP_CXX_ABI_MSVC 1 #else #define IL2CPP_CXX_ABI_MSVC 0 #endif #if IL2CPP_COMPILER_MSVC #define STDCALL __stdcall #define CDECL __cdecl #else #define STDCALL #define CDECL #endif #if IL2CPP_COMPILER_MSVC || defined(__ARMCC_VERSION) #define NORETURN __declspec(noreturn) #else #define NORETURN #endif #if IL2CPP_TARGET_IOS || IL2CPP_TARGET_ANDROID || IL2CPP_TARGET_DARWIN #define REAL_NORETURN __attribute__ ((noreturn)) #else #define REAL_NORETURN NORETURN #endif #if IL2CPP_COMPILER_MSVC || defined(__ARMCC_VERSION) #define IL2CPP_NO_INLINE __declspec(noinline) #else #define IL2CPP_NO_INLINE __attribute__ ((noinline)) #endif #if IL2CPP_COMPILER_MSVC #define NOVTABLE __declspec(novtable) #else #define NOVTABLE #endif #define IL2CPP_ENABLE_MONO_BUG_EMULATION 1 // We currently use ALIGN_TYPE just for types decorated with IL2CPPStructAlignment, as it's needed for WebGL to properly align UnityEngine.Color. // On MSVC, it causes build issues on x86 since you cannot pass aligned type by value as an argument to a function: // error C2719: 'value': formal parameter with requested alignment of 16 won't be aligned // Since this isn't actually needed for Windows, and it's not a standard .NET feature but just IL2CPP extension, let's just turn it off on Windows #if defined(__GNUC__) || defined(__SNC__) || defined(__clang__) #define ALIGN_OF(T) __alignof__(T) #define ALIGN_TYPE(val) __attribute__((aligned(val))) #define ALIGN_FIELD(val) ALIGN_TYPE(val) #define FORCE_INLINE inline __attribute__ ((always_inline)) #elif defined(_MSC_VER) #define ALIGN_OF(T) __alignof(T) #define ALIGN_TYPE(val) #define ALIGN_FIELD(val) __declspec(align(val)) #define FORCE_INLINE __forceinline #else #define ALIGN_TYPE(size) #define ALIGN_FIELD(size) #define FORCE_INLINE inline #endif #define IL2CPP_PAGE_SIZE 4096 /* Trigger assert if 'ptr' is not aligned to 'alignment'. */ #define ASSERT_ALIGNMENT(ptr, alignment) \ IL2CPP_ASSERT((((ptrdiff_t) ptr) & (alignment - 1)) == 0 && "Unaligned pointer!") // 64-bit types are aligned to 8 bytes on 64-bit platforms and always on Windows #define IL2CPP_ENABLE_INTERLOCKED_64_REQUIRED_ALIGNMENT ((IL2CPP_SIZEOF_VOID_P == 8) || (IL2CPP_TARGET_WINDOWS)) /* Debugging */ #ifndef IL2CPP_DEBUG #define IL2CPP_DEBUG 0 #endif #ifndef IL2CPP_DEVELOPMENT #define IL2CPP_DEVELOPMENT 0 #endif /* Threading */ #define IL2CPP_SUPPORT_THREADS !IL2CPP_TARGET_JAVASCRIPT #define IL2CPP_USE_STD_THREAD 0 #define IL2CPP_THREADS_STD IL2CPP_USE_STD_THREAD #define IL2CPP_THREADS_PTHREAD (!IL2CPP_THREADS_STD && IL2CPP_TARGET_POSIX) #define IL2CPP_THREADS_WIN32 (!IL2CPP_THREADS_STD && IL2CPP_TARGET_WINDOWS) #define IL2CPP_THREADS_N3DS (!IL2CPP_THREADS_STD && IL2CPP_TARGET_N3DS) #define IL2CPP_THREADS_PS4 (!IL2CPP_THREADS_STD && IL2CPP_TARGET_PS4) #define IL2CPP_THREADS_PSP2 (!IL2CPP_THREADS_STD && IL2CPP_TARGET_PSP2) #define IL2CPP_THREADS_SWITCH (!IL2CPP_THREADS_STD && IL2CPP_TARGET_SWITCH) #define IL2CPP_THREADS_ALL_ACCESS (!IL2CPP_THREADS_STD && IL2CPP_TARGET_XBOXONE) #if (IL2CPP_SUPPORT_THREADS && (!IL2CPP_THREADS_STD && !IL2CPP_THREADS_PTHREAD && !IL2CPP_THREADS_WIN32 && !IL2CPP_THREADS_XBOXONE && !IL2CPP_THREADS_N3DS && !IL2CPP_THREADS_PS4 && !IL2CPP_THREADS_PSP2 && !IL2CPP_THREADS_SWITCH)) #error "No thread implementation defined" #endif /* Platform support to cleanup attached threads even when native threads are not exited cleanly */ #define IL2CPP_HAS_NATIVE_THREAD_CLEANUP (IL2CPP_THREADS_PTHREAD) #define IL2CPP_THREAD_IMPL_HAS_COM_APARTMENTS IL2CPP_TARGET_WINDOWS #if !defined(IL2CPP_ENABLE_PLATFORM_THREAD_STACKSIZE) && IL2CPP_TARGET_IOS #define IL2CPP_ENABLE_PLATFORM_THREAD_STACKSIZE 1 #endif #define IL2CPP_ENABLE_STACKTRACES 1 /* Platforms which use OS specific implementation to extract stracktrace */ #if !defined(IL2CPP_ENABLE_NATIVE_STACKTRACES) #define IL2CPP_ENABLE_NATIVE_STACKTRACES (IL2CPP_TARGET_WINDOWS || IL2CPP_TARGET_LINUX || IL2CPP_TARGET_DARWIN || IL2CPP_TARGET_IOS || IL2CPP_TARGET_TIZEN || IL2CPP_TARGET_ANDROID) #endif /* Platforms which use stacktrace sentries */ #define IL2CPP_ENABLE_STACKTRACE_SENTRIES (IL2CPP_TARGET_JAVASCRIPT || IL2CPP_TARGET_N3DS || IL2CPP_TARGET_SWITCH) #if (IL2CPP_ENABLE_STACKTRACES && !IL2CPP_ENABLE_NATIVE_STACKTRACES && !IL2CPP_ENABLE_STACKTRACE_SENTRIES) #error "If stacktraces are supported, then either native stack traces must be supported, or usage of stacktrace sentries must be enabled!" #endif #if (IL2CPP_ENABLE_NATIVE_STACKTRACES + IL2CPP_ENABLE_STACKTRACE_SENTRIES) > 1 #error "Only one type of stacktraces are allowed" #endif #define IL2CPP_CAN_USE_MULTIPLE_SYMBOL_MAPS IL2CPP_TARGET_IOS /* Profiler */ #ifndef IL2CPP_ENABLE_PROFILER #define IL2CPP_ENABLE_PROFILER 1 #endif /* GC defines*/ #define IL2CPP_GC_BOEHM 1 #define IL2CPP_GC_NULL !IL2CPP_GC_BOEHM #define IL2CPP_ENABLE_DEFERRED_GC IL2CPP_TARGET_JAVASCRIPT /* we always need to NULL pointer free memory with our current allocators */ #define NEED_TO_ZERO_PTRFREE 1 #define IL2CPP_HAS_GC_DESCRIPTORS 1 #if defined(_MSC_VER) #define IL2CPP_ZERO_LEN_ARRAY 0 #else #define IL2CPP_ZERO_LEN_ARRAY 0 #endif #define IL2CPP_HAS_CXX_CONSTEXPR (__has_feature (cxx_constexpr)) /* clang specific __has_builtin check */ #ifndef __has_builtin #define __has_builtin(x) 0 // Compatibility with non-clang compilers. #endif #if _MSC_VER #define IL2CPP_UNREACHABLE __assume(0) #elif __has_builtin(__builtin_unreachable) #define IL2CPP_UNREACHABLE __builtin_unreachable() #else #define IL2CPP_UNREACHABLE #endif typedef uint32_t Il2CppMethodSlot; /* Debug macros */ #define STRINGIZE(L) #L #define MAKE_STRING(M, L) M(L) #define $Line MAKE_STRING( STRINGIZE, __LINE__ ) #define FIXME __FILE__ "(" $Line ") : FIXME: " #define ICALLMESSAGE(name) __FILE__ "(" $Line ") : FIXME: Missing internal call implementation: " name #define RUNTIMEMESSAGE(name) __FILE__ "(" $Line ") : FIXME: Missing runtime implementation: " name #define NOTSUPPORTEDICALLMESSAGE(target, name, reason) __FILE__ "(" $Line ") : Unsupported internal call for " target ":" name " - " reason // Keeping this for future usage if needed. //#if defined(_MSC_VER) // #define PRAGMA_MESSAGE(value) __pragma(message(value)) //#else // #define PRAGMA_MESSAGE(value) _Pragma(STRINGIZE(value)) //#endif #define PRAGMA_MESSAGE(value) #if !defined(EMSCRIPTEN) #define NOT_IMPLEMENTED_ICALL(func) \ PRAGMA_MESSAGE(ICALLMESSAGE(#func)) \ IL2CPP_ASSERT(0 && #func) #define NOT_IMPLEMENTED_ICALL_NO_ASSERT(func, reason) \ PRAGMA_MESSAGE(ICALLMESSAGE(#func)) #define NOT_IMPLEMENTED(func) \ PRAGMA_MESSAGE(RUNTIMEMESSAGE(#func)) \ IL2CPP_ASSERT(0 && #func) #define NOT_IMPLEMENTED_NO_ASSERT(func, reason) \ PRAGMA_MESSAGE(RUNTIMEMESSAGE(#func)) #else // emscripten's assert will throw an exception in js. // For now, we don't want that, so just printf and move on. #define NOT_IMPLEMENTED_ICALL(func) \ PRAGMA_MESSAGE(message(ICALLMESSAGE(#func))) \ printf("Not implemented icall: %s\n", #func); #define NOT_IMPLEMENTED_ICALL_NO_ASSERT(func, reason) \ PRAGMA_MESSAGE(message(ICALLMESSAGE(#func))) #define NOT_IMPLEMENTED(func) \ PRAGMA_MESSAGE(message(RUNTIMEMESSAGE(#func))) \ printf("Not implemented: %s\n", #func); #define NOT_IMPLEMENTED_NO_ASSERT(func, reason) \ PRAGMA_MESSAGE(message(RUNTIMEMESSAGE(#func))) #endif #define NOT_SUPPORTED_IL2CPP(func, reason) \ il2cpp::vm::Exception::Raise (il2cpp::vm::Exception::GetNotSupportedException ( NOTSUPPORTEDICALLMESSAGE ("IL2CPP", #func, #reason) )) #define NOT_SUPPORTED_SRE(func) \ il2cpp::vm::Exception::Raise (il2cpp::vm::Exception::GetNotSupportedException ( NOTSUPPORTEDICALLMESSAGE ("IL2CPP", #func, "System.Reflection.Emit is not supported.") )) #define NOT_SUPPORTED_REMOTING(func) \ il2cpp::vm::Exception::Raise (il2cpp::vm::Exception::GetNotSupportedException ( NOTSUPPORTEDICALLMESSAGE ("IL2CPP", #func, "System.Runtime.Remoting is not supported.") )) #if IL2CPP_TARGET_JAVASCRIPT #define NOT_SUPPORTED_WEBGL(func, reason) \ il2cpp::vm::Exception::Raise (il2cpp::vm::Exception::GetNotSupportedException ( NOTSUPPORTEDICALLMESSAGE ("WebGL", #func, #reason) )) #else #define NOT_SUPPORTED_WEBGL(func, reason) #endif #if IL2CPP_COMPILER_MSVC #define IL2CPP_DIR_SEPARATOR '\\' /* backslash */ #else #define IL2CPP_DIR_SEPARATOR '/' /* forward slash */ #endif #ifndef IL2CPP_DEBUGGER_ENABLED #define IL2CPP_DEBUGGER_ENABLED 0 #endif #ifndef IL2CPP_DEBUGGER_LOG #define IL2CPP_DEBUGGER_LOG 0 #endif #ifndef IL2CPP_DISABLE_FULL_MESSAGES #define IL2CPP_DISABLE_FULL_MESSAGES 1 #endif #if IL2CPP_COMPILER_MSVC #define IL2CPP_USE_GENERIC_SOCKET_IMPL 0 #else #define IL2CPP_USE_GENERIC_SOCKET_IMPL (!IL2CPP_TARGET_POSIX || IL2CPP_TARGET_JAVASCRIPT) && (!IL2CPP_TARGET_SWITCH) #endif /* set by platforms that require special handling of SIGPIPE signalling during socket sends */ #ifndef IL2CPP_USE_SEND_NOSIGNAL #define IL2CPP_USE_SEND_NOSIGNAL 0 #endif #define IL2CPP_USE_GENERIC_ENVIRONMENT (!IL2CPP_TARGET_WINDOWS && !IL2CPP_TARGET_POSIX) #define IL2CPP_USE_GENERIC_COM (!IL2CPP_TARGET_WINDOWS) #define IL2CPP_USE_GENERIC_COM_SAFEARRAYS (!IL2CPP_TARGET_WINDOWS || IL2CPP_TARGET_XBOXONE) #define IL2CPP_USE_GENERIC_WINDOWSRUNTIME (!IL2CPP_TARGET_WINDOWS || RUNTIME_MONO || RUNTIME_NONE) #ifndef IL2CPP_USE_GENERIC_MEMORY_MAPPED_FILE #define IL2CPP_USE_GENERIC_MEMORY_MAPPED_FILE (IL2CPP_TARGET_XBOXONE || (!IL2CPP_TARGET_WINDOWS && !IL2CPP_TARGET_POSIX)) #endif #define IL2CPP_SIZEOF_STRUCT_WITH_NO_INSTANCE_FIELDS 1 #define IL2CPP_VALIDATE_FIELD_LAYOUT 0 #if IL2CPP_COMPILER_MSVC // Use stub "return false" implementation where it's not implemented #define IL2CPP_ISDEBUGGERPRESENT_IMPLEMENTED 1 #else #define IL2CPP_ISDEBUGGERPRESENT_IMPLEMENTED 0 #endif #ifndef IL2CPP_USE_POSIX_COND_TIMEDWAIT_REL #define IL2CPP_USE_POSIX_COND_TIMEDWAIT_REL ( IL2CPP_TARGET_DARWIN || IL2CPP_TARGET_ANDROID || IL2CPP_TARGET_PSP2 ) #endif template struct Il2CppStaticAssertHelper; template<> struct Il2CppStaticAssertHelper { }; #define Assert(x) do { (void)(x); IL2CPP_ASSERT(x); } while (false) #define Il2CppStaticAssert(...) do { Il2CppStaticAssertHelper<(__VA_ARGS__)>(); } while (false) const int32_t kIl2CppInt32Min = INT32_MIN; const int32_t kIl2CppInt32Max = INT32_MAX; const uint32_t kIl2CppUInt32Max = UINT32_MAX; const int64_t kIl2CppInt64Min = INT64_MIN; const int64_t kIl2CppInt64Max = INT64_MAX; const uint64_t kIl2CppUInt64Max = UINT64_MAX; #if IL2CPP_SIZEOF_VOID_P == 8 const intptr_t kIl2CppIntPtrMin = kIl2CppInt64Min; const intptr_t kIl2CppIntPtrMax = kIl2CppInt64Max; const uintptr_t kIl2CppUIntPtrMax = kIl2CppUInt64Max; #else const intptr_t kIl2CppIntPtrMin = kIl2CppInt32Min; const intptr_t kIl2CppIntPtrMax = kIl2CppInt32Max; const uintptr_t kIl2CppUIntPtrMax = kIl2CppUInt32Max; #endif const int ipv6AddressSize = 16; #define IL2CPP_SUPPORT_IPV6 !IL2CPP_TARGET_PS4 && !IL2CPP_TARGET_SWITCH // Android: "There is no support for locales in the C library" https://code.google.com/p/android/issues/detail?id=57313 // PS4/PS2: strtol_d doesn't exist #define IL2CPP_SUPPORT_LOCALE_INDEPENDENT_PARSING (!IL2CPP_TARGET_ANDROID && !IL2CPP_TARGET_PS4 && !IL2CPP_TARGET_PSP2) #define NO_UNUSED_WARNING(expr) (void)(expr) typedef int32_t il2cpp_hresult_t; // Sorted numerically! #define IL2CPP_S_OK ((il2cpp_hresult_t)0) #define IL2CPP_E_BOUNDS ((il2cpp_hresult_t)0x8000000B) #define IL2CPP_E_CHANGED_STATE ((il2cpp_hresult_t)0x8000000C) #define IL2CPP_E_ILLEGAL_METHOD_CALL ((il2cpp_hresult_t)0x8000000E) #define IL2CPP_RO_E_CLOSED ((il2cpp_hresult_t)0x80000013) #define IL2CPP_E_NOTIMPL ((il2cpp_hresult_t)0x80004001) #define IL2CPP_E_NOINTERFACE ((il2cpp_hresult_t)0x80004002) #define IL2CPP_E_POINTER ((il2cpp_hresult_t)0x80004003) #define IL2CPP_E_ABORT ((il2cpp_hresult_t)0x80004004) #define IL2CPP_E_FAIL ((il2cpp_hresult_t)0x80004005) #define IL2CPP_E_UNEXPECTED ((il2cpp_hresult_t)0x8000FFFF) #define IL2CPP_RPC_E_DISCONNECTED ((il2cpp_hresult_t)0x80010108) #define IL2CPP_RPC_E_WRONG_THREAD ((il2cpp_hresult_t)0x8001010E) #define IL2CPP_DISP_E_PARAMNOTFOUND ((il2cpp_hresult_t)0x80020004) #define IL2CPP_REGDB_E_CLASSNOTREG ((il2cpp_hresult_t)0x80040154) #define IL2CPP_E_ACCESS_DENIED ((il2cpp_hresult_t)0x80070005) #define IL2CPP_E_OUTOFMEMORY ((il2cpp_hresult_t)0x8007000E) #define IL2CPP_E_INVALIDARG ((il2cpp_hresult_t)0x80070057) #define IL2CPP_COR_E_EXCEPTION ((il2cpp_hresult_t)0x80131500) #define IL2CPP_COR_E_INVALIDOPERATION ((il2cpp_hresult_t)0x80131509) #define IL2CPP_COR_E_PLATFORMNOTSUPPORTED ((il2cpp_hresult_t)0x80131539) #define IL2CPP_COR_E_OPERATIONCANCELED ((il2cpp_hresult_t)0x8013153B) #define IL2CPP_COR_E_OBJECTDISPOSED ((il2cpp_hresult_t)0x80131622) #define IL2CPP_HR_SUCCEEDED(hr) (((il2cpp_hresult_t)(hr)) >= 0) #define IL2CPP_HR_FAILED(hr) (((il2cpp_hresult_t)(hr)) < 0) #include "il2cpp-api-types.h" #define IL2CPP_LITTLE_ENDIAN 1 #define IL2CPP_BIG_ENDIAN 2 #define IL2CPP_BYTE_ORDER IL2CPP_LITTLE_ENDIAN #if (defined(_MSC_VER) && _MSC_VER > 1600) || (__has_feature(cxx_override_control)) #define IL2CPP_OVERRIDE override #define IL2CPP_FINAL final #else #define IL2CPP_OVERRIDE #define IL2CPP_FINAL #endif #if (__has_feature(cxx_deleted_functions) || (defined(_MSC_VER) && _MSC_VER >= 1800)) #define IL2CPP_HAS_DELETED_FUNCTIONS 1 #else #define IL2CPP_HAS_DELETED_FUNCTIONS 0 #endif #if IL2CPP_TARGET_WINDOWS const Il2CppChar kIl2CppNewLine[] = { '\r', '\n', '\0' }; #else const Il2CppChar kIl2CppNewLine[] = { '\n', '\0' }; #endif #if IL2CPP_TARGET_ANDROID && defined(__i386__) // On Android with x86, function pointers are not aligned, so we // need to use all of the bits when comparing them. Hence we mask // nothing. #define IL2CPP_POINTER_SPARE_BITS 0 #else // On ARMv7 with Thumb instructions the lowest bit is always set. // With Thumb2 the second-to-lowest bit is also set. Mask both of // them off so that we can do a comparison properly based on the data // from the linker map file. On other architectures this operation should // not matter, as we assume these two bits are always zero because the pointer // will be aligned. #define IL2CPP_POINTER_SPARE_BITS 3 #endif #define MAXIMUM_NESTED_GENERICS_EXCEPTION_MESSAGE "IL2CPP encountered a managed type which it cannot convert ahead-of-time. The type uses generic or array types which are nested beyond the maximum depth which can be converted." #if IL2CPP_COMPILER_MSVC #define IL2CPP_ATTRIBUTE_WEAK #else #define IL2CPP_ATTRIBUTE_WEAK __attribute__((weak)) #endif ================================================ FILE: unity_decoder/libil2cpp/il2cpp-debugger.cpp ================================================ #if IL2CPP_DEBUGGER_ENABLED #include "il2cpp-debugger.h" #include "debugger/agent.h" #include "debugger/command-line-parser.h" using namespace il2cpp; bool il2cpp_debugger_parse_command_line(int argc, char* argv[], char** host, int32_t* port, bool* print_help) { debugger::CommandLineOptions options; bool properArgumentsProvided = debugger::CommandLineParser::Parse(argc, argv, &options); *print_help = options.print_help; if (properArgumentsProvided) { *host = options.host; *port = options.port; } return properArgumentsProvided; } void il2cpp_debugger_print_usage() { debugger::CommandLineParser::PrintUsage(std::cout); } void il2cpp_debugger_agent_init() { debugger::Agent::instance().Initialize( debugger::AgentConfig::Default); } void il2cpp_debugger_agent_init(const char *host, int32_t port) { debugger::AgentConfig config; config.server = true; config.host = host; config.port = port; debugger::Agent::instance().Initialize(config); } bool il2cpp_debugger_agent_is_initialized() { return debugger::Agent::instance().IsInitialized(); } void il2cpp_debugger_agent_dispose() { debugger::Agent::instance().Dispose(); } void il2cpp_debugger_notify_vm_start() { debugger::Agent::instance().NotifyVmStart(); } void il2cpp_debugger_notify_vm_death() { debugger::Agent::instance().NotifyVmDeath(); } void il2cpp_debugger_notify_user_break() { debugger::Agent::instance().NotifyUserBreak(); } void il2cpp_debugger_notify_appdomain_create(Il2CppDomain *domain) { debugger::Agent::instance().NotifyAppDomainCreate(domain); } void il2cpp_debugger_notify_assembly_load(const Il2CppAssembly *assembly) { debugger::Agent::instance().NotifyAssemblyLoad(assembly); } void il2cpp_debugger_sequence_point_hit(int64_t uid, int32_t offset) { // TODO: this is time critical, it might make sense to inline it directly? debugger::Agent::instance().SequencePointHit(uid, offset); } void il2cpp_debugger_notify_type_load(Il2CppClass *type) { debugger::Agent::instance().NotifyTypeLoad(type); } void il2cpp_debugger_method_entry(const Il2CppStackFrameInfo &info) { debugger::Agent::instance().OnMethodEntry(info); } void il2cpp_debugger_method_exit(const Il2CppStackFrameInfo &info) { debugger::Agent::instance().OnMethodExit(info); } void il2cpp_debugger_notify_thread_attach(Il2CppThread *thread) { debugger::Agent::instance().OnThreadAttach(thread); } void il2cpp_debugger_notify_thread_detach(Il2CppThread *thread) { debugger::Agent::instance().OnThreadDetach(thread); } #endif ================================================ FILE: unity_decoder/libil2cpp/il2cpp-debugger.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppClass; struct MethodInfo; struct Il2CppThread; struct Il2CppDomain; struct Il2CppAssembly; struct Il2CppStackFrameInfo; #if IL2CPP_DEBUGGER_ENABLED void il2cpp_debugger_agent_init(); void il2cpp_debugger_agent_init(const char *host, int32_t port); void il2cpp_debugger_agent_dispose(); bool il2cpp_debugger_agent_is_initialized(); bool il2cpp_debugger_parse_command_line(int argc, char* argv[], char** host, int32_t* port, bool* print_help); void il2cpp_debugger_print_usage(); void il2cpp_debugger_notify_vm_start(); void il2cpp_debugger_notify_vm_death(); void il2cpp_debugger_notify_user_break(); void il2cpp_debugger_notify_appdomain_create(Il2CppDomain *domain); void il2cpp_debugger_notify_assembly_load(const Il2CppAssembly *assembly); void il2cpp_debugger_sequence_point_hit(int64_t uid, int32_t offset); void il2cpp_debugger_notify_thread_attach(Il2CppThread *thread); void il2cpp_debugger_notify_thread_detach(Il2CppThread *thread); void il2cpp_debugger_notify_type_load(Il2CppClass *type); void il2cpp_debugger_method_entry(const Il2CppStackFrameInfo &info); void il2cpp_debugger_method_exit(const Il2CppStackFrameInfo &info); #endif ================================================ FILE: unity_decoder/libil2cpp/il2cpp-metadata.h ================================================ #pragma once #include "il2cpp-config.h" #include // This file contains the structures specifying how we store converted metadata. // These structures have 3 constraints: // 1. These structures will be stored in an external file, and as such must not contain any pointers. // All references to other metadata should occur via an index into a corresponding table. // 2. These structures are assumed to be const. Either const structures in the binary or mapped as // readonly memory from an external file. Do not add any 'calculated' fields which will be written to at runtime. // 3. These structures should be optimized for size. Other structures are used at runtime which can // be larger to store cached information typedef int32_t TypeIndex; typedef int32_t TypeDefinitionIndex; typedef int32_t FieldIndex; typedef int32_t DefaultValueIndex; typedef int32_t DefaultValueDataIndex; typedef int32_t CustomAttributeIndex; typedef int32_t ParameterIndex; typedef int32_t MethodIndex; typedef int32_t GenericMethodIndex; typedef int32_t PropertyIndex; typedef int32_t EventIndex; typedef int32_t GenericContainerIndex; typedef int32_t GenericParameterIndex; typedef int16_t GenericParameterConstraintIndex; typedef int32_t NestedTypeIndex; typedef int32_t InterfacesIndex; typedef int32_t VTableIndex; typedef int32_t InterfaceOffsetIndex; typedef int32_t RGCTXIndex; typedef int32_t StringIndex; typedef int32_t StringLiteralIndex; typedef int32_t GenericInstIndex; typedef int32_t ImageIndex; typedef int32_t AssemblyIndex; typedef int32_t InteropDataIndex; const TypeIndex kTypeIndexInvalid = -1; const TypeDefinitionIndex kTypeDefinitionIndexInvalid = -1; const DefaultValueDataIndex kDefaultValueIndexNull = -1; const EventIndex kEventIndexInvalid = -1; const FieldIndex kFieldIndexInvalid = -1; const MethodIndex kMethodIndexInvalid = -1; const PropertyIndex kPropertyIndexInvalid = -1; const GenericContainerIndex kGenericContainerIndexInvalid = -1; const GenericParameterIndex kGenericParameterIndexInvalid = -1; const RGCTXIndex kRGCTXIndexInvalid = -1; const StringLiteralIndex kStringLiteralIndexInvalid = -1; const InteropDataIndex kInteropDataIndexInvalid = -1; // Encoded index (1 bit) // MethodDef - 0 // MethodSpec - 1 // We use the top 3 bits to indicate what table to index into // Type Binary Hex // Il2CppClass 001 0x20000000 // Il2CppType 010 0x40000000 // MethodInfo 011 0x60000000 // FieldInfo 100 0x80000000 // StringLiteral 101 0xA0000000 // MethodRef 110 0xC0000000 typedef uint32_t EncodedMethodIndex; enum Il2CppMetadataUsage { kIl2CppMetadataUsageInvalid, kIl2CppMetadataUsageTypeInfo, kIl2CppMetadataUsageIl2CppType, kIl2CppMetadataUsageMethodDef, kIl2CppMetadataUsageFieldInfo, kIl2CppMetadataUsageStringLiteral, kIl2CppMetadataUsageMethodRef, }; static inline Il2CppMetadataUsage GetEncodedIndexType(EncodedMethodIndex index) { return (Il2CppMetadataUsage)((index & 0xE0000000) >> 29); } static inline uint32_t GetDecodedMethodIndex(EncodedMethodIndex index) { return index & 0x1FFFFFFFU; } struct Il2CppImage; struct Il2CppType; struct Il2CppTypeDefinitionMetadata; union Il2CppRGCTXDefinitionData { int32_t rgctxDataDummy; MethodIndex methodIndex; TypeIndex typeIndex; }; enum Il2CppRGCTXDataType { IL2CPP_RGCTX_DATA_INVALID, IL2CPP_RGCTX_DATA_TYPE, IL2CPP_RGCTX_DATA_CLASS, IL2CPP_RGCTX_DATA_METHOD, IL2CPP_RGCTX_DATA_ARRAY, }; struct Il2CppRGCTXDefinition { Il2CppRGCTXDataType type; Il2CppRGCTXDefinitionData data; }; struct Il2CppInterfaceOffsetPair { TypeIndex interfaceTypeIndex; int32_t offset; }; struct Il2CppTypeDefinition { StringIndex nameIndex; StringIndex namespaceIndex; CustomAttributeIndex customAttributeIndex; TypeIndex byvalTypeIndex; TypeIndex byrefTypeIndex; TypeIndex declaringTypeIndex; TypeIndex parentIndex; TypeIndex elementTypeIndex; // we can probably remove this one. Only used for enums RGCTXIndex rgctxStartIndex; int32_t rgctxCount; GenericContainerIndex genericContainerIndex; uint32_t flags; FieldIndex fieldStart; MethodIndex methodStart; EventIndex eventStart; PropertyIndex propertyStart; NestedTypeIndex nestedTypesStart; InterfacesIndex interfacesStart; VTableIndex vtableStart; InterfacesIndex interfaceOffsetsStart; uint16_t method_count; uint16_t property_count; uint16_t field_count; uint16_t event_count; uint16_t nested_type_count; uint16_t vtable_count; uint16_t interfaces_count; uint16_t interface_offsets_count; // bitfield to portably encode boolean values as single bits // 01 - valuetype; // 02 - enumtype; // 03 - has_finalize; // 04 - has_cctor; // 05 - is_blittable; // 06 - is_import_or_windows_runtime; // 07-10 - One of nine possible PackingSize values (0, 1, 2, 4, 8, 16, 32, 64, or 128) uint32_t bitfield; uint32_t token; }; struct Il2CppFieldDefinition { StringIndex nameIndex; TypeIndex typeIndex; CustomAttributeIndex customAttributeIndex; uint32_t token; }; struct Il2CppFieldDefaultValue { FieldIndex fieldIndex; TypeIndex typeIndex; DefaultValueDataIndex dataIndex; }; struct Il2CppFieldMarshaledSize { FieldIndex fieldIndex; TypeIndex typeIndex; int32_t size; }; struct Il2CppFieldRef { TypeIndex typeIndex; FieldIndex fieldIndex; // local offset into type fields }; struct Il2CppParameterDefinition { StringIndex nameIndex; uint32_t token; CustomAttributeIndex customAttributeIndex; TypeIndex typeIndex; }; struct Il2CppParameterDefaultValue { ParameterIndex parameterIndex; TypeIndex typeIndex; DefaultValueDataIndex dataIndex; }; struct Il2CppMethodDefinition { StringIndex nameIndex; TypeDefinitionIndex declaringType; TypeIndex returnType; ParameterIndex parameterStart; CustomAttributeIndex customAttributeIndex; GenericContainerIndex genericContainerIndex; MethodIndex methodIndex; MethodIndex invokerIndex; MethodIndex reversePInvokeWrapperIndex; RGCTXIndex rgctxStartIndex; int32_t rgctxCount; uint32_t token; uint16_t flags; uint16_t iflags; uint16_t slot; uint16_t parameterCount; }; struct Il2CppEventDefinition { StringIndex nameIndex; TypeIndex typeIndex; MethodIndex add; MethodIndex remove; MethodIndex raise; CustomAttributeIndex customAttributeIndex; uint32_t token; }; struct Il2CppPropertyDefinition { StringIndex nameIndex; MethodIndex get; MethodIndex set; uint32_t attrs; CustomAttributeIndex customAttributeIndex; uint32_t token; }; struct Il2CppMethodSpec { MethodIndex methodDefinitionIndex; GenericInstIndex classIndexIndex; GenericInstIndex methodIndexIndex; }; struct Il2CppStringLiteral { uint32_t length; StringLiteralIndex dataIndex; }; struct Il2CppGenericMethodIndices { MethodIndex methodIndex; MethodIndex invokerIndex; }; struct Il2CppGenericMethodFunctionsDefinitions { GenericMethodIndex genericMethodIndex; Il2CppGenericMethodIndices indices; }; const int kPublicKeyByteLength = 8; struct Il2CppAssemblyName { StringIndex nameIndex; StringIndex cultureIndex; StringIndex hashValueIndex; StringIndex publicKeyIndex; uint32_t hash_alg; int32_t hash_len; uint32_t flags; int32_t major; int32_t minor; int32_t build; int32_t revision; uint8_t publicKeyToken[kPublicKeyByteLength]; }; struct Il2CppImageDefinition { StringIndex nameIndex; AssemblyIndex assemblyIndex; TypeDefinitionIndex typeStart; uint32_t typeCount; TypeDefinitionIndex exportedTypeStart; uint32_t exportedTypeCount; MethodIndex entryPointIndex; uint32_t token; }; struct Il2CppAssembly { ImageIndex imageIndex; CustomAttributeIndex customAttributeIndex; int32_t referencedAssemblyStart; int32_t referencedAssemblyCount; Il2CppAssemblyName aname; }; struct Il2CppMetadataUsageList { uint32_t start; uint32_t count; }; struct Il2CppMetadataUsagePair { uint32_t destinationIndex; uint32_t encodedSourceIndex; }; struct Il2CppCustomAttributeTypeRange { int32_t start; int32_t count; }; struct Il2CppRange { int32_t start; int32_t length; }; struct Il2CppWindowsRuntimeTypeNamePair { StringIndex nameIndex; TypeIndex typeIndex; }; #pragma pack(push, p1,4) struct Il2CppGlobalMetadataHeader { int32_t sanity; int32_t version; int32_t stringLiteralOffset; // string data for managed code int32_t stringLiteralCount; int32_t stringLiteralDataOffset; int32_t stringLiteralDataCount; int32_t stringOffset; // string data for metadata int32_t stringCount; int32_t eventsOffset; // Il2CppEventDefinition int32_t eventsCount; int32_t propertiesOffset; // Il2CppPropertyDefinition int32_t propertiesCount; int32_t methodsOffset; // Il2CppMethodDefinition int32_t methodsCount; int32_t parameterDefaultValuesOffset; // Il2CppParameterDefaultValue int32_t parameterDefaultValuesCount; int32_t fieldDefaultValuesOffset; // Il2CppFieldDefaultValue int32_t fieldDefaultValuesCount; int32_t fieldAndParameterDefaultValueDataOffset; // uint8_t int32_t fieldAndParameterDefaultValueDataCount; int32_t fieldMarshaledSizesOffset; // Il2CppFieldMarshaledSize int32_t fieldMarshaledSizesCount; int32_t parametersOffset; // Il2CppParameterDefinition int32_t parametersCount; int32_t fieldsOffset; // Il2CppFieldDefinition int32_t fieldsCount; int32_t genericParametersOffset; // Il2CppGenericParameter int32_t genericParametersCount; int32_t genericParameterConstraintsOffset; // TypeIndex int32_t genericParameterConstraintsCount; int32_t genericContainersOffset; // Il2CppGenericContainer int32_t genericContainersCount; int32_t nestedTypesOffset; // TypeDefinitionIndex int32_t nestedTypesCount; int32_t interfacesOffset; // TypeIndex int32_t interfacesCount; int32_t vtableMethodsOffset; // EncodedMethodIndex int32_t vtableMethodsCount; int32_t interfaceOffsetsOffset; // Il2CppInterfaceOffsetPair int32_t interfaceOffsetsCount; int32_t typeDefinitionsOffset; // Il2CppTypeDefinition int32_t typeDefinitionsCount; int32_t rgctxEntriesOffset; // Il2CppRGCTXDefinition int32_t rgctxEntriesCount; int32_t imagesOffset; // Il2CppImageDefinition int32_t imagesCount; int32_t assembliesOffset; // Il2CppAssemblyDefinition int32_t assembliesCount; int32_t metadataUsageListsOffset; // Il2CppMetadataUsageList int32_t metadataUsageListsCount; int32_t metadataUsagePairsOffset; // Il2CppMetadataUsagePair int32_t metadataUsagePairsCount; int32_t fieldRefsOffset; // Il2CppFieldRef int32_t fieldRefsCount; int32_t referencedAssembliesOffset; // int32_t int32_t referencedAssembliesCount; int32_t attributesInfoOffset; // Il2CppCustomAttributeTypeRange int32_t attributesInfoCount; int32_t attributeTypesOffset; // TypeIndex int32_t attributeTypesCount; int32_t unresolvedVirtualCallParameterTypesOffset; // TypeIndex int32_t unresolvedVirtualCallParameterTypesCount; int32_t unresolvedVirtualCallParameterRangesOffset; // Il2CppRange int32_t unresolvedVirtualCallParameterRangesCount; int32_t windowsRuntimeTypeNamesOffset; // Il2CppWindowsRuntimeTypeNamePair int32_t windowsRuntimeTypeNamesSize; int32_t exportedTypeDefinitionsOffset; // TypeDefinitionIndex int32_t exportedTypeDefinitionsCount; }; #pragma pack(pop, p1) #if RUNTIME_MONO #pragma pack(push, p1,4) struct Il2CppGlobalMonoMetadataHeader { int32_t sanity; int32_t version; int32_t stringOffset; // string data for metadata int32_t stringCount; int32_t methodInfoMappingOffset; // hash -> MonoMethodInfo mapping int32_t methodInfoMappingCount; int32_t genericMethodInfoMappingOffset; // hash -> generic MonoMethodInfo mapping int32_t genericMethodInfoMappingCount; int32_t rgctxIndicesOffset; // runtime generic context indices int32_t rgctxIndicesCount; int32_t rgctxInfoOffset; // runtime generic context info int32_t rgctxInfoCount; int32_t monoStringOffset; // mono strings int32_t monoStringCount; int32_t methodMetadataOffset; // method metadata int32_t methodMetadataCount; int32_t genericArgumentIndicesOffset; // generic argument indices int32_t genericArgumentIndicesCount; int32_t typeTableOffset; // type table int32_t typeTableCount; int32_t fieldTableOffset; // field table int32_t fieldTableCount; int32_t methodIndexTableOffset; // method index table int32_t methodIndexTableCount; int32_t genericMethodIndexTableOffset; // generic method index table int32_t genericMethodIndexTableCount; int32_t metaDataUsageListsTableOffset; // meta data usage lists table int32_t metaDataUsageListsTableCount; int32_t metaDataUsagePairsTableOffset; // meta data usage pairs table int32_t metaDataUsagePairsTableCount; int32_t assemblyNameTableOffset; // assembly names int32_t assemblyNameTableCount; }; #pragma pack(pop, p1) #endif ================================================ FILE: unity_decoder/libil2cpp/il2cpp-string-types.h ================================================ #pragma once #include "il2cpp-config.h" #include typedef std::basic_string UTF16String; typedef std::basic_string Il2CppNativeString; ================================================ FILE: unity_decoder/libil2cpp/il2cpp-vm-support.h ================================================ #pragma once #include "il2cpp-config.h" // This file is a compile-time abstraction for VM support needed by code in the os and utils namespaces that is used by both the // libil2cpp and the libmono runtimes. Code in those namespaces should never depend up on the vm namespace directly. #if defined(RUNTIME_MONO) #include "mono-api.h" #include "il2cpp-mono-support.h" #include #define IL2CPP_VM_RAISE_EXCEPTION(exception) mono_raise_exception(exception) #define IL2CPP_VM_RAISE_COM_EXCEPTION(hresult, defaultToCOMException) assert(false && "COM exceptions are not implemented yet.") #define IL2CPP_VM_RAISE_IF_FAILED(hresult, defaultToCOMException) assert(false && "COM exceptions are not implemented yet.") #define IL2CPP_VM_STRING_EMPTY() mono_string_empty(mono_domain_get()) #define IL2CPP_VM_STRING_NEW_UTF16(value, length) mono_string_new_utf16(mono_domain_get(), value, length) #define IL2CPP_VM_STRING_NEW_LEN(value, length) mono_string_new_len(mono_domain_get(), value, length); #define IL2CPP_VM_NOT_SUPPORTED(func, reason) mono_raise_exception(mono_get_exception_not_supported(NOTSUPPORTEDICALLMESSAGE ("IL2CPP", #func, #reason))) #define IL2CPP_VM_METHOD_METADATA_FROM_INDEX(isGeneric, methodIndex) isGeneric ? GenericMethodFromIndex(methodIndex) : MethodFromIndex(methodIndex) #define IL2CPP_VM_SHUTDOWN() do { if (mono_runtime_try_shutdown()) mono_runtime_quit(); } while(0) #define IL2CPP_VM_GET_CREATE_CCW_EXCEPTION(ex) NULL typedef MonoString VmString; typedef MonoMethod VmMethod; #elif RUNTIME_NONE // OS layer compiled with no runtime #define IL2CPP_VM_RAISE_EXCEPTION(exception) IL2CPP_ASSERT(0 && "This is not implemented wihout a VM runtime backend.") #define IL2CPP_VM_RAISE_COM_EXCEPTION(hresult, defaultToCOMException) IL2CPP_ASSERT(0 && "This is not implemented wihout a VM runtime backend.") #define IL2CPP_VM_RAISE_IF_FAILED(hresult, defaultToCOMException) IL2CPP_ASSERT(0 && "This is not implemented wihout a VM runtime backend.") #define IL2CPP_VM_STRING_EMPTY() NULL #define IL2CPP_VM_STRING_NEW_UTF16(value, length) NULL #define IL2CPP_VM_STRING_NEW_LEN(value, length) NULL #define IL2CPP_VM_NOT_SUPPORTED(func, reason) IL2CPP_ASSERT(0 && "This is not implemented wihout a VM runtime backend.") #define IL2CPP_VM_METHOD_METADATA_FROM_INDEX(isGeneric, methodIndex) IL2CPP_ASSERT(0 && "This is not implemented wihout a VM runtime backend.") #define IL2CPP_VM_SHUTDOWN() IL2CPP_ASSERT(0 && "This is not implemented wihout a VM runtime backend.") #define IL2CPP_VM_GET_CREATE_CCW_EXCEPTION(ex) NULL #else // Assume the libil2cpp runtime #include "vm/Exception.h" #include "vm/MetadataCache.h" #include "vm/StackTrace.h" #include "vm/String.h" #define IL2CPP_VM_RAISE_EXCEPTION(exception) il2cpp::vm::Exception::Raise(exception) #define IL2CPP_VM_RAISE_COM_EXCEPTION(hresult, defaultToCOMException) il2cpp::vm::Exception::Raise(hresult, defaultToCOMException) #define IL2CPP_VM_RAISE_IF_FAILED(hresult, defaultToCOMException) il2cpp::vm::Exception::RaiseIfFailed(hresult, defaultToCOMException) #define IL2CPP_VM_STRING_EMPTY() il2cpp::vm::String::Empty() #define IL2CPP_VM_STRING_NEW_UTF16(value, length) il2cpp::vm::String::NewUtf16(value, length) #define IL2CPP_VM_STRING_NEW_LEN(value, length) il2cpp::vm::String::NewLen(value, length) #define IL2CPP_VM_NOT_SUPPORTED(func, reason) NOT_SUPPORTED_IL2CPP(func, reason) #define IL2CPP_VM_METHOD_METADATA_FROM_INDEX(isGeneric, methodIndex) il2cpp::vm::MetadataCache::GetMethodInfoFromMethodDefinitionIndex (methodIndex) #define IL2CPP_VM_SHUTDOWN() il2cpp_shutdown() #define IL2CPP_VM_GET_CREATE_CCW_EXCEPTION(ex) vm::CCW::GetOrCreate(reinterpret_cast(ex), Il2CppIUnknown::IID) typedef Il2CppString VmString; typedef MethodInfo VmMethod; #endif ================================================ FILE: unity_decoder/libil2cpp/libil2cpp.def ================================================ LIBRARY libil2cpp.dll EXPORTS il2cpp_init il2cpp_shutdown il2cpp_set_config_dir il2cpp_set_data_dir il2cpp_set_temp_dir il2cpp_set_commandline_arguments il2cpp_set_memory_callbacks il2cpp_get_corlib il2cpp_add_internal_call il2cpp_resolve_icall il2cpp_alloc il2cpp_free il2cpp_array_class_get il2cpp_array_length il2cpp_array_get_byte_length il2cpp_array_new il2cpp_array_new_specific il2cpp_array_new_full il2cpp_bounded_array_class_get il2cpp_array_element_size il2cpp_assembly_get_image il2cpp_class_enum_basetype il2cpp_class_is_generic il2cpp_class_is_assignable_from il2cpp_class_is_subclass_of il2cpp_class_from_il2cpp_type il2cpp_class_from_name il2cpp_class_from_system_type il2cpp_class_get_declaring_type il2cpp_class_get_element_class il2cpp_class_get_fields il2cpp_class_get_nested_types il2cpp_class_get_field_from_name il2cpp_class_get_interfaces il2cpp_class_get_methods il2cpp_class_get_method_from_name il2cpp_class_get_name il2cpp_class_get_namespace il2cpp_class_get_parent il2cpp_class_get_properties il2cpp_class_get_property_from_name il2cpp_class_instance_size il2cpp_class_num_fields il2cpp_class_is_valuetype il2cpp_class_is_blittable il2cpp_class_value_size il2cpp_class_get_flags il2cpp_class_is_abstract il2cpp_class_is_interface il2cpp_class_array_element_size il2cpp_class_from_type il2cpp_class_get_type il2cpp_class_has_attribute il2cpp_class_has_references il2cpp_class_is_enum il2cpp_class_get_image il2cpp_class_get_assemblyname il2cpp_domain_get il2cpp_domain_assembly_open il2cpp_raise_exception il2cpp_exception_from_name_msg il2cpp_get_exception_argument_null il2cpp_field_get_flags il2cpp_field_get_name il2cpp_field_get_parent il2cpp_field_get_offset il2cpp_field_get_type il2cpp_field_get_value il2cpp_field_get_value_object il2cpp_field_has_attribute il2cpp_field_set_value il2cpp_field_static_get_value il2cpp_field_static_set_value il2cpp_field_set_value_object il2cpp_gc_collect il2cpp_gc_collect_a_little il2cpp_gc_disable il2cpp_gc_enable il2cpp_gc_get_used_size il2cpp_gc_get_heap_size il2cpp_gchandle_new il2cpp_gchandle_new_weakref il2cpp_gchandle_get_target il2cpp_gchandle_free il2cpp_unity_liveness_calculation_begin il2cpp_unity_liveness_calculation_end il2cpp_unity_liveness_calculation_from_root il2cpp_unity_liveness_calculation_from_statics il2cpp_method_get_return_type il2cpp_method_get_name il2cpp_method_get_object il2cpp_method_is_instance il2cpp_method_get_param_count il2cpp_method_get_param il2cpp_method_get_class il2cpp_method_has_attribute il2cpp_profiler_install il2cpp_profiler_set_events il2cpp_profiler_install_enter_leave il2cpp_profiler_install_allocation il2cpp_profiler_install_gc il2cpp_property_get_flags il2cpp_property_get_get_method il2cpp_property_get_set_method il2cpp_property_get_name il2cpp_property_get_parent il2cpp_object_get_class il2cpp_object_get_size il2cpp_object_get_virtual_method il2cpp_object_new il2cpp_object_unbox il2cpp_value_box il2cpp_runtime_invoke il2cpp_runtime_invoke_convert_args il2cpp_runtime_class_init il2cpp_runtime_object_init il2cpp_runtime_object_init_exception il2cpp_runtime_unhandled_exception_policy_set il2cpp_string_length il2cpp_string_chars il2cpp_string_new il2cpp_string_new_len il2cpp_string_new_utf16 il2cpp_string_new_wrapper il2cpp_thread_current il2cpp_thread_attach il2cpp_thread_detach il2cpp_type_get_object il2cpp_type_get_type il2cpp_type_get_class_or_element_class il2cpp_type_get_name ____visualizerHelpersPreventLinkerStripping @65535 NONAME DATA ================================================ FILE: unity_decoder/libil2cpp/libil2cpp.icalls ================================================ // Mono.Globalization.Unicode.Normalization Mono.Globalization.Unicode.Normalization::load_normalization_resource(System.IntPtr&,System.IntPtr&,System.IntPtr&,System.IntPtr&,System.IntPtr&,System.IntPtr&) mscorlib::Mono::Globalization::Unicode::Normalization::load_normalization_resource // Mono.Interop.ComInteropProxy Mono.Interop.ComInteropProxy::AddProxy(System.IntPtr,Mono.Interop.ComInteropProxy) mscorlib::Mono::Interop::ComInteropProxy::AddProxy Mono.Interop.ComInteropProxy::FindProxy(System.IntPtr) mscorlib::Mono::Interop::ComInteropProxy::FindProxy // Mono.Runtime Mono.Runtime::GetDisplayName() mscorlib::Mono::Runtime::GetDisplayName Mono.Runtime::mono_runtime_install_handlers() mscorlib::Mono::Runtime::mono_runtime_install_handlers Mono.Runtime::GetNativeStackTrace(System.Exception) mscorlib::Mono::Runtime::GetNativeStackTrace // Mono.Security.Cryptography.KeyPairPersistence Mono.Security.Cryptography.KeyPairPersistence::_CanSecure(System.String) mscorlib::Mono::Security::Cryptography::KeyPairPersistence::_CanSecure Mono.Security.Cryptography.KeyPairPersistence::_IsMachineProtected(System.String) mscorlib::Mono::Security::Cryptography::KeyPairPersistence::_IsMachineProtected Mono.Security.Cryptography.KeyPairPersistence::_IsUserProtected(System.String) mscorlib::Mono::Security::Cryptography::KeyPairPersistence::_IsUserProtected Mono.Security.Cryptography.KeyPairPersistence::_ProtectMachine(System.String) mscorlib::Mono::Security::Cryptography::KeyPairPersistence::_ProtectMachine Mono.Security.Cryptography.KeyPairPersistence::_ProtectUser(System.String) mscorlib::Mono::Security::Cryptography::KeyPairPersistence::_ProtectUser // System.__ComObject System.__ComObject::CreateRCW(System.Type) mscorlib::System::__ComObject::CreateRCW System.__ComObject::GetInterfaceInternal(System.Type,System.Boolean) mscorlib::System::__ComObject::GetInterfaceInternal System.__ComObject::ReleaseInterfaces() mscorlib::System::__ComObject::ReleaseInterfaces // System.Activator System.Activator::CreateInstanceInternal(System.Type) mscorlib::System::Activator::CreateInstanceInternal // System.AppDomain System.AppDomain::createDomain(System.String,System.AppDomainSetup) mscorlib::System::AppDomain::createDomain System.AppDomain::ExecuteAssembly(System.Reflection.Assembly,System.String[]) mscorlib::System::AppDomain::ExecuteAssembly System.AppDomain::GetAssemblies(System.Boolean) mscorlib::System::AppDomain::GetAssemblies System.AppDomain::getCurDomain() mscorlib::System::AppDomain::getCurDomain System.AppDomain::GetData(System.String) mscorlib::System::AppDomain::GetData System.AppDomain::getFriendlyName() mscorlib::System::AppDomain::getFriendlyName System.AppDomain::getRootDomain() mscorlib::System::AppDomain::getRootDomain System.AppDomain::getSetup() mscorlib::System::AppDomain::getSetup System.AppDomain::InternalGetContext() mscorlib::System::AppDomain::InternalGetContext System.AppDomain::InternalGetDefaultContext() mscorlib::System::AppDomain::InternalGetDefaultContext System.AppDomain::InternalGetProcessGuid(System.String) mscorlib::System::AppDomain::InternalGetProcessGuid System.AppDomain::InternalIsFinalizingForUnload(System.Int32) mscorlib::System::AppDomain::InternalIsFinalizingForUnload System.AppDomain::InternalPopDomainRef() mscorlib::System::AppDomain::InternalPopDomainRef System.AppDomain::InternalPushDomainRef(System.AppDomain) mscorlib::System::AppDomain::InternalPushDomainRef System.AppDomain::InternalPushDomainRefByID(System.Int32) mscorlib::System::AppDomain::InternalPushDomainRefByID System.AppDomain::InternalSetContext(System.Runtime.Remoting.Contexts.Context) mscorlib::System::AppDomain::InternalSetContext System.AppDomain::InternalSetDomain(System.AppDomain) mscorlib::System::AppDomain::InternalSetDomain System.AppDomain::InternalSetDomainByID(System.Int32) mscorlib::System::AppDomain::InternalSetDomainByID System.AppDomain::InternalUnload(System.Int32) mscorlib::System::AppDomain::InternalUnload System.AppDomain::LoadAssembly(System.String,System.Security.Policy.Evidence,System.Boolean) mscorlib::System::AppDomain::LoadAssembly System.AppDomain::LoadAssemblyRaw(System.Byte[],System.Byte[],System.Security.Policy.Evidence,System.Boolean) mscorlib::System::AppDomain::LoadAssemblyRaw System.AppDomain::SetData(System.String,System.Object) mscorlib::System::AppDomain::SetData System.AppDomain::DoUnhandledException(System.Exception) mscorlib::System::AppDomain::DoUnhandledException // System.ArgIterator System.ArgIterator::IntGetNextArg() mscorlib::System::ArgIterator::IntGetNextArg_mscorlib_System_TypedReference System.ArgIterator::IntGetNextArg(System.IntPtr) mscorlib::System::ArgIterator::IntGetNextArg_mscorlib_System_TypedReference_mscorlib_System_IntPtr System.ArgIterator::IntGetNextArgType() mscorlib::System::ArgIterator::IntGetNextArgType System.ArgIterator::Setup(System.IntPtr,System.IntPtr) mscorlib::System::ArgIterator::Setup // System.Array System.Array::ClearInternal(System.Array,System.Int32,System.Int32) mscorlib::System::Array::ClearInternal System.Array::Clone() mscorlib::System::Array::Clone System.Array::CreateInstanceImpl(System.Type,System.Int32[],System.Int32[]) mscorlib::System::Array::CreateInstanceImpl System.Array::FastCopy(System.Array,System.Int32,System.Array,System.Int32,System.Int32) mscorlib::System::Array::FastCopy System.Array::GetLength(System.Int32) mscorlib::System::Array::GetLength System.Array::GetLowerBound(System.Int32) mscorlib::System::Array::GetLowerBound System.Array::GetRank() mscorlib::System::Array::GetRank System.Array::GetValue(System.Int32[]) mscorlib::System::Array::GetValue System.Array::GetValueImpl(System.Int32) mscorlib::System::Array::GetValueImpl System.Array::SetValue(System.Object,System.Int32[]) mscorlib::System::Array::SetValue System.Array::SetValueImpl(System.Object,System.Int32) mscorlib::System::Array::SetValueImpl // System.Buffer System.Buffer::BlockCopyInternal(System.Array,System.Int32,System.Array,System.Int32,System.Int32) mscorlib::System::Buffer::BlockCopyInternal System.Buffer::ByteLengthInternal(System.Array) mscorlib::System::Buffer::ByteLengthInternal System.Buffer::GetByteInternal(System.Array,System.Int32) mscorlib::System::Buffer::GetByteInternal System.Buffer::SetByteInternal(System.Array,System.Int32,System.Int32) mscorlib::System::Buffer::SetByteInternal System.Buffer::_GetByte(System.Array,System.Int32) mscorlib::System::Buffer::_GetByte System.Buffer::InternalBlockCopy(System.Array,System.Int32,System.Array,System.Int32,System.Int32) mscorlib::System::Buffer::InternalBlockCopy System.Buffer::_ByteLength(System.Array) mscorlib::System::Buffer::_ByteLength System.Buffer::_SetByte(System.Array,System.Int32,System.Byte) mscorlib::System::Buffer::_SetByte // System.Char System.Char::GetDataTablePointers(System.Byte*&,System.Byte*&,System.Double*&,System.UInt16*&,System.UInt16*&,System.UInt16*&,System.UInt16*&) mscorlib::System::Char::GetDataTablePointers // System.Configuration.DefaultConfig System.Configuration.DefaultConfig::get_bundled_machine_config() System::System::Configuration::DefaultConfig::get_bundled_machine_config System.Configuration.DefaultConfig::get_machine_config_path() System::System::Configuration::DefaultConfig::get_machine_config_path // System.Configuration.InternalConfigurationHost System.Configuration.InternalConfigurationHost::get_bundled_machine_config() System::System::Configuration::InternalConfigurationHost::get_bundled_machine_config System.Configuration.InternalConfigurationHost::get_bundled_app_config() System::Configuration::System::Configuration::InternalConfigurationHost::get_bundled_app_config // System.ConsoleDriver System.ConsoleDriver::InternalKeyAvailable(System.Int32) mscorlib::System::ConsoleDriver::InternalKeyAvailable System.ConsoleDriver::Isatty(System.IntPtr) mscorlib::System::ConsoleDriver::Isatty System.ConsoleDriver::SetBreak(System.Boolean) mscorlib::System::ConsoleDriver::SetBreak System.ConsoleDriver::SetEcho(System.Boolean) mscorlib::System::ConsoleDriver::SetEcho System.ConsoleDriver::TtySetup(System.String,System.String,System.Byte[]&,System.Int32*&) mscorlib::System::ConsoleDriver::TtySetup // System.Convert System.Convert::InternalFromBase64CharArray(System.Char[],System.Int32,System.Int32) mscorlib::System::Convert::InternalFromBase64CharArray System.Convert::InternalFromBase64String(System.String,System.Boolean) mscorlib::System::Convert::InternalFromBase64String // System.CurrentSystemTimeZone System.CurrentSystemTimeZone::GetTimeZoneData(System.Int32,System.Int64[]&,System.String[]&) mscorlib::System::CurrentSystemTimeZone::GetTimeZoneData // System.ComponentModel.Win32Exception System.ComponentModel.Win32Exception::W32ErrorMessage(System.Int32) System::System::ComponentModel::Win32Exception::W32ErrorMessage // System.DateTime System.DateTime::GetNow() mscorlib::System::DateTime::GetNow System.DateTime::GetTimeMonotonic() mscorlib::System::DateTime::GetTimeMonotonic System.DateTime::GetSystemTimeAsFileTime() mscorlib::System::DateTime::GetSystemTimeAsFileTime // System.Decimal System.Decimal::decimal2double(System.Decimal&) mscorlib::System::Decimal::decimal2double System.Decimal::decimal2Int64(System.Decimal&,System.Int64&) mscorlib::System::Decimal::decimal2Int64 System.Decimal::decimal2string(System.Decimal&,System.Int32,System.Int32,System.Char[],System.Int32,System.Int32&,System.Int32&) mscorlib::System::Decimal::decimal2string System.Decimal::decimal2UInt64(System.Decimal&,System.UInt64&) mscorlib::System::Decimal::decimal2UInt64 System.Decimal::decimalCompare(System.Decimal&,System.Decimal&) mscorlib::System::Decimal::decimalCompare System.Decimal::decimalDiv(System.Decimal&,System.Decimal&,System.Decimal&) mscorlib::System::Decimal::decimalDiv System.Decimal::decimalFloorAndTrunc(System.Decimal&,System.Int32) mscorlib::System::Decimal::decimalFloorAndTrunc System.Decimal::decimalIncr(System.Decimal&,System.Decimal&) mscorlib::System::Decimal::decimalIncr System.Decimal::decimalIntDiv(System.Decimal&,System.Decimal&,System.Decimal&) mscorlib::System::Decimal::decimalIntDiv System.Decimal::decimalMult(System.Decimal&,System.Decimal&) mscorlib::System::Decimal::decimalMult System.Decimal::decimalSetExponent(System.Decimal&,System.Int32) mscorlib::System::Decimal::decimalSetExponent System.Decimal::string2decimal(System.Decimal&,System.String,System.UInt32,System.Int32) mscorlib::System::Decimal::string2decimal System.Decimal::ToDouble(System.Decimal) mscorlib::System::Decimal::ToDouble System.Decimal::FCallCompare(System.Decimal&,System.Decimal&) mscorlib::System::Decimal::FCallCompare System.Decimal::FCallToInt32(System.Decimal) mscorlib::System::Decimal::FCallToInt32 System.Decimal::GetHashCode() mscorlib::System::Decimal::GetHashCode System.Decimal::ToSingle(System.Decimal) mscorlib::System::Decimal::ToSingle System.Decimal::.ctor(System.Double) mscorlib::System::Decimal::ConstructorDouble System.Decimal::.ctor(System.Single) mscorlib::System::Decimal::ConstructorFloat System.Decimal::FCallAddSub(System.Decimal&,System.Decimal&,System.Byte) mscorlib::System::Decimal::FCallAddSub System.Decimal::FCallDivide(System.Decimal&,System.Decimal&) mscorlib::System::Decimal::FCallDivide System.Decimal::FCallFloor(System.Decimal&) mscorlib::System::Decimal::FCallFloor System.Decimal::FCallMultiply(System.Decimal&,System.Decimal&) mscorlib::System::Decimal::FCallMultiply System.Decimal::FCallRound(System.Decimal&,System.Int32) mscorlib::System::Decimal::FCallRound System.Decimal::FCallTruncate(System.Decimal&) mscorlib::System::Decimal::FCallTruncate // System.Delegate System.Delegate::CreateDelegate_internal(System.Type,System.Object,System.Reflection.MethodInfo,System.Boolean) mscorlib::System::Delegate::CreateDelegate_internal System.Delegate::SetMulticastInvoke() mscorlib::System::Delegate::SetMulticastInvoke System.Delegate::AllocDelegateLike_internal(System.Delegate) mscorlib::System::Delegate::AllocDelegateLike_internal System.Delegate::GetVirtualMethod_internal() mscorlib::System::Delegate::GetVirtualMethod_internal // System.Diagnostics.Debugger System.Diagnostics.Debugger::IsAttached_internal() mscorlib::System::Diagnostics::Debugger::IsAttached_internal System.Diagnostics.Debugger::IsLogging() mscorlib::System::Diagnostics::Debugger::IsLogging System.Diagnostics.Debugger::Log(System.Int32,System.String,System.String) mscorlib::System::Diagnostics::Debugger::Log // System.Diagnostics.DefaultTraceListener System.Diagnostics.DefaultTraceListener::WriteWindowsDebugString(System.String) System::System::Diagnostics::DefaultTraceListener::WriteWindowsDebugString // System.Diagnostics.FileVersionInfo System.Diagnostics.FileVersionInfo::GetVersionInfo_internal(System.String) System::System::Diagnostics::FileVersionInfo::GetVersionInfo_internal // System.Diagnostics.PerformanceCounter System.Diagnostics.PerformanceCounter::FreeData(System.IntPtr) System::System::Diagnostics::PerformanceCounter::FreeData System.Diagnostics.PerformanceCounter::GetImpl(System.String,System.String,System.String,System.String,System.Diagnostics.PerformanceCounterType&,System.Boolean&) System::System::Diagnostics::PerformanceCounter::GetImpl System.Diagnostics.PerformanceCounter::GetSample(System.IntPtr,System.Boolean,System.Diagnostics.CounterSample&) System::System::Diagnostics::PerformanceCounter::GetSample System.Diagnostics.PerformanceCounter::UpdateValue(System.IntPtr,System.Boolean,System.Int64) System::System::Diagnostics::PerformanceCounter::UpdateValue // System.Diagnostics.PerformanceCounterCategory System.Diagnostics.PerformanceCounterCategory::CategoryDelete(System.String) System::System::Diagnostics::PerformanceCounterCategory::CategoryDelete System.Diagnostics.PerformanceCounterCategory::CategoryHelpInternal(System.String,System.String) System::System::Diagnostics::PerformanceCounterCategory::CategoryHelpInternal System.Diagnostics.PerformanceCounterCategory::CounterCategoryExists(System.String,System.String,System.String) System::System::Diagnostics::PerformanceCounterCategory::CounterCategoryExists System.Diagnostics.PerformanceCounterCategory::Create(System.String,System.String,System.Diagnostics.PerformanceCounterCategoryType,System.Diagnostics.CounterCreationData[]) System::System::Diagnostics::PerformanceCounterCategory::Create System.Diagnostics.PerformanceCounterCategory::GetCategoryNames(System.String) System::System::Diagnostics::PerformanceCounterCategory::GetCategoryNames System.Diagnostics.PerformanceCounterCategory::GetCounterNames(System.String,System.String) System::System::Diagnostics::PerformanceCounterCategory::GetCounterNames System.Diagnostics.PerformanceCounterCategory::GetInstanceNames(System.String,System.String) System::System::Diagnostics::PerformanceCounterCategory::GetInstanceNames System.Diagnostics.PerformanceCounterCategory::InstanceExistsInternal(System.String,System.String,System.String) System::System::Diagnostics::PerformanceCounterCategory::InstanceExistsInternal // System.Diagnostics.Process System.Diagnostics.Process::CreateProcess_internal(System.Diagnostics.ProcessStartInfo,System.IntPtr,System.IntPtr,System.IntPtr,System.Diagnostics.Process/ProcInfo&) System::System::Diagnostics::Process::CreateProcess_internal System.Diagnostics.Process::ExitCode_internal(System.IntPtr) System::System::Diagnostics::Process::ExitCode_internal System.Diagnostics.Process::ExitTime_internal(System.IntPtr) System::System::Diagnostics::Process::ExitTime_internal System.Diagnostics.Process::GetModules_internal(System.IntPtr) System::System::Diagnostics::Process::GetModules_internal System.Diagnostics.Process::GetPid_internal() System::System::Diagnostics::Process::GetPid_internal System.Diagnostics.Process::GetPriorityClass(System.IntPtr,System.Int32&) System::System::Diagnostics::Process::GetPriorityClass System.Diagnostics.Process::GetProcess_internal(System.Int32) System::System::Diagnostics::Process::GetProcess_internal System.Diagnostics.Process::GetProcessData(System.Int32,System.Int32,System.Int32&) System::System::Diagnostics::Process::GetProcessData System.Diagnostics.Process::GetProcesses_internal() System::System::Diagnostics::Process::GetProcesses_internal System.Diagnostics.Process::GetWorkingSet_internal(System.IntPtr,System.Int32&,System.Int32&) System::System::Diagnostics::Process::GetWorkingSet_internal System.Diagnostics.Process::Kill_internal(System.IntPtr,System.Int32) System::System::Diagnostics::Process::Kill_internal System.Diagnostics.Process::Process_free_internal(System.IntPtr) System::System::Diagnostics::Process::Process_free_internal System.Diagnostics.Process::ProcessName_internal(System.IntPtr) System::System::Diagnostics::Process::ProcessName_internal System.Diagnostics.Process::SetPriorityClass(System.IntPtr,System.Int32,System.Int32&) System::System::Diagnostics::Process::SetPriorityClass System.Diagnostics.Process::SetWorkingSet_internal(System.IntPtr,System.Int32,System.Int32,System.Boolean) System::System::Diagnostics::Process::SetWorkingSet_internal System.Diagnostics.Process::ShellExecuteEx_internal(System.Diagnostics.ProcessStartInfo,System.Diagnostics.Process/ProcInfo&) System::System::Diagnostics::Process::ShellExecuteEx_internal System.Diagnostics.Process::StartTime_internal(System.IntPtr) System::System::Diagnostics::Process::StartTime_internal System.Diagnostics.Process::Times(System.IntPtr,System.Int32) System::System::Diagnostics::Process::Times System.Diagnostics.Process::WaitForExit_internal(System.IntPtr,System.Int32) System::System::Diagnostics::Process::WaitForExit_internal System.Diagnostics.Process::WaitForInputIdle_internal(System.IntPtr,System.Int32) System::System::Diagnostics::Process::WaitForInputIdle_internal // System.Diagnostics.StackFrame System.Diagnostics.StackFrame::get_frame_info(System.Int32,System.Boolean,System.Reflection.MethodBase&,System.Int32&,System.Int32&,System.String&,System.Int32&,System.Int32&) mscorlib::System::Diagnostics::StackFrame::get_frame_info // System.Diagnostics.StackTrace System.Diagnostics.StackTrace::get_trace(System.Exception,System.Int32,System.Boolean) mscorlib::System::Diagnostics::StackTrace::get_trace // System.Diagnostics.Stopwatch System.Diagnostics.Stopwatch::GetTimestamp() System::System::Diagnostics::Stopwatch::GetTimestamp // System.Double System.Double::ParseImpl(System.Byte*,System.Double&) mscorlib::System::Double::ParseImpl // System.Enum System.Enum::compare_value_to(System.Object) mscorlib::System::Enum::compare_value_to System.Enum::get_hashcode() mscorlib::System::Enum::get_hashcode System.Enum::get_underlying_type(System.Type) mscorlib::System::Enum::get_underlying_type System.Enum::get_value() mscorlib::System::Enum::get_value System.Enum::ToObject(System.Type,System.Object) mscorlib::System::Enum::ToObject System.Enum::GetEnumValuesAndNames(System.RuntimeType,System.UInt64[]&,System.String[]&) mscorlib::System::Enum::GetEnumValuesAndNames System.Enum::InternalHasFlag(System.Enum) mscorlib::System::Enum::InternalHasFlag System.Enum::InternalCompareTo(System.Object,System.Object) mscorlib::System::Enum::InternalCompareTo System.Enum::InternalBoxEnum(System.RuntimeType,System.Int64) mscorlib::System::Enum::InternalBoxEnum System.Enum::InternalGetUnderlyingType(System.RuntimeType) mscorlib::System::Enum::InternalGetUnderlyingType // System.Environment System.Environment::Exit(System.Int32) mscorlib::System::Environment::Exit System.Environment::get_EmbeddingHostName() mscorlib::System::Environment::get_EmbeddingHostName System.Environment::get_ExitCode() mscorlib::System::Environment::get_ExitCode System.Environment::get_HasShutdownStarted() mscorlib::System::Environment::get_HasShutdownStarted System.Environment::get_MachineName() mscorlib::System::Environment::get_MachineName System.Environment::get_NewLine() mscorlib::System::Environment::get_NewLine System.Environment::get_Platform() mscorlib::System::Environment::get_Platform System.Environment::get_ProcessorCount() mscorlib::System::Environment::get_ProcessorCount System.Environment::get_SocketSecurityEnabled() mscorlib::System::Environment::get_SocketSecurityEnabled System.Environment::get_TickCount() mscorlib::System::Environment::get_TickCount System.Environment::get_UserName() mscorlib::System::Environment::get_UserName System.Environment::GetCommandLineArgs() mscorlib::System::Environment::GetCommandLineArgs System.Environment::GetEnvironmentVariableNames() mscorlib::System::Environment::GetEnvironmentVariableNames System.Environment::GetLogicalDrivesInternal() mscorlib::System::Environment::GetLogicalDrivesInternal System.Environment::GetMachineConfigPath() mscorlib::System::Environment::GetMachineConfigPath System.Environment::GetOSVersionString() mscorlib::System::Environment::GetOSVersionString System.Environment::GetWindowsFolderPath(System.Int32) mscorlib::System::Environment::GetWindowsFolderPath System.Environment::internalBroadcastSettingChange() mscorlib::System::Environment::internalBroadcastSettingChange System.Environment::internalGetEnvironmentVariable(System.String) mscorlib::System::Environment::internalGetEnvironmentVariable System.Environment::internalGetEnvironmentVariable_native(System.IntPtr) mscorlib::System::Environment::internalGetEnvironmentVariable_native System.Environment::internalGetGacPath() mscorlib::System::Environment::internalGetGacPath System.Environment::internalGetHome() mscorlib::System::Environment::internalGetHome System.Environment::InternalSetEnvironmentVariable(System.String,System.String) mscorlib::System::Environment::InternalSetEnvironmentVariable System.Environment::set_ExitCode(System.Int32) mscorlib::System::Environment::set_ExitCode System.Environment::GetIs64BitOperatingSystem() mscorlib::System::Environment::GetIs64BitOperatingSystem System.Environment::GetPageSize() mscorlib::System::Environment::GetPageSize System.Environment::GetNewLine() mscorlib::System::Environment::GetNewLine System.Environment::get_bundled_machine_config() mscorlib::System::Environment::get_bundled_machine_config // System.GC System.GC::CollectionCount(System.Int32) mscorlib::System::GC::CollectionCount System.GC::get_MaxGeneration() mscorlib::System::GC::get_MaxGeneration System.GC::GetGeneration(System.Object) mscorlib::System::GC::GetGeneration System.GC::GetTotalMemory(System.Boolean) mscorlib::System::GC::GetTotalMemory System.GC::InternalCollect(System.Int32) mscorlib::System::GC::InternalCollect System.GC::KeepAlive(System.Object) mscorlib::System::GC::KeepAlive System.GC::RecordPressure(System.Int64) mscorlib::System::GC::RecordPressure System.GC::ReRegisterForFinalize(System.Object) mscorlib::System::GC::ReRegisterForFinalize System.GC::SuppressFinalize(System.Object) mscorlib::System::GC::SuppressFinalize System.GC::WaitForPendingFinalizers() mscorlib::System::GC::WaitForPendingFinalizers System.GC::get_ephemeron_tombstone() mscorlib::System::GC::get_ephemeron_tombstone System.GC::register_ephemeron_array(System.Runtime.CompilerServices.Ephemeron[]) mscorlib::System::GC::register_ephemeron_array System.GC::GetCollectionCount(System.Int32) mscorlib::System::GC::GetCollectionCount System.GC::GetMaxGeneration() mscorlib::System::GC::GetMaxGeneration System.GC::_ReRegisterForFinalize(System.Object) mscorlib::System::GC::_ReRegisterForFinalize System.GC::_SuppressFinalize(System.Object) mscorlib::System::GC::_SuppressFinalize // System.Globalization.CompareInfo System.Globalization.CompareInfo::assign_sortkey(System.Object,System.String,System.Globalization.CompareOptions) mscorlib::System::Globalization::CompareInfo::assign_sortkey System.Globalization.CompareInfo::construct_compareinfo(System.String) mscorlib::System::Globalization::CompareInfo::construct_compareinfo System.Globalization.CompareInfo::free_internal_collator() mscorlib::System::Globalization::CompareInfo::free_internal_collator System.Globalization.CompareInfo::internal_compare(System.String,System.Int32,System.Int32,System.String,System.Int32,System.Int32,System.Globalization.CompareOptions) mscorlib::System::Globalization::CompareInfo::internal_compare System.Globalization.CompareInfo::internal_index(System.String,System.Int32,System.Int32,System.Char,System.Globalization.CompareOptions,System.Boolean) mscorlib::System::Globalization::CompareInfo::internal_index System.Globalization.CompareInfo::internal_index(System.String,System.Int32,System.Int32,System.String,System.Globalization.CompareOptions,System.Boolean) mscorlib::System::Globalization::CompareInfo::internal_index // System.Globalization.CultureInfo System.Globalization.CultureInfo::construct_datetime_format() mscorlib::System::Globalization::CultureInfo::construct_datetime_format System.Globalization.CultureInfo::construct_internal_locale_from_current_locale(System.Globalization.CultureInfo) mscorlib::System::Globalization::CultureInfo::construct_internal_locale_from_current_locale System.Globalization.CultureInfo::construct_internal_locale_from_lcid(System.Int32) mscorlib::System::Globalization::CultureInfo::construct_internal_locale_from_lcid System.Globalization.CultureInfo::construct_internal_locale_from_name(System.String) mscorlib::System::Globalization::CultureInfo::construct_internal_locale_from_name System.Globalization.CultureInfo::construct_internal_locale_from_specific_name(System.Globalization.CultureInfo,System.String) mscorlib::System::Globalization::CultureInfo::construct_internal_locale_from_specific_name System.Globalization.CultureInfo::construct_number_format() mscorlib::System::Globalization::CultureInfo::construct_number_format System.Globalization.CultureInfo::internal_get_cultures(System.Boolean,System.Boolean,System.Boolean) mscorlib::System::Globalization::CultureInfo::internal_get_cultures System.Globalization.CultureInfo::internal_is_lcid_neutral(System.Int32,System.Boolean&) mscorlib::System::Globalization::CultureInfo::internal_is_lcid_neutral System.Globalization.CultureInfo::get_current_locale_name() mscorlib::System::Globalization::CultureInfo::get_current_locale_name // System.Globalization.RegionInfo System.Globalization.RegionInfo::construct_internal_region_from_name(System.String) mscorlib::System::Globalization::RegionInfo::construct_internal_region_from_name // System.IO.DriveInfo System.IO.DriveInfo::GetDiskFreeSpaceInternal(System.String,System.UInt64&,System.UInt64&,System.UInt64&,System.IO.MonoIOError&) mscorlib::System::IO::DriveInfo::GetDiskFreeSpaceInternal System.IO.DriveInfo::GetDriveTypeInternal(System.String) mscorlib::System::IO::DriveInfo::GetDriveTypeInternal System.IO.DriveInfo::GetDriveFormat(System.String) mscorlib::System::IO::DriveInfo::GetDriveFormat // System.IO.FAMWatcher System.IO.FAMWatcher::InternalFAMNextEvent(System.IO.FAMConnection&,System.String&,System.Int32&,System.Int32&) System::System::IO::FAMWatcher::InternalFAMNextEvent // System.IO.FileSystemWatcher System.IO.FileSystemWatcher::InternalSupportsFSW() System::System::IO::FileSystemWatcher::InternalSupportsFSW // System.IO.InotifyWatcher System.IO.InotifyWatcher::AddWatch(System.IntPtr,System.String,System.IO.InotifyMask) System::System::IO::InotifyWatcher::AddWatch System.IO.InotifyWatcher::GetInotifyInstance() System::System::IO::InotifyWatcher::GetInotifyInstance System.IO.InotifyWatcher::RemoveWatch(System.IntPtr,System.Int32) System::System::IO::InotifyWatcher::RemoveWatch // System.IO.MonoIO System.IO.MonoIO::Close(System.IntPtr,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::Close System.IO.MonoIO::CopyFile(System.String,System.String,System.Boolean,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::CopyFile System.IO.MonoIO::CreateDirectory(System.String,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::CreateDirectory System.IO.MonoIO::CreatePipe(System.IntPtr&,System.IntPtr&) mscorlib::System::IO::MonoIO::CreatePipe System.IO.MonoIO::DeleteFile(System.String,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::DeleteFile System.IO.MonoIO::DuplicateHandle(System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr&,System.Int32,System.Int32,System.Int32) mscorlib::System::IO::MonoIO::DuplicateHandle System.IO.MonoIO::Flush(System.IntPtr,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::Flush System.IO.MonoIO::get_AltDirectorySeparatorChar() mscorlib::System::IO::MonoIO::get_AltDirectorySeparatorChar System.IO.MonoIO::get_ConsoleError() mscorlib::System::IO::MonoIO::get_ConsoleError System.IO.MonoIO::get_ConsoleInput() mscorlib::System::IO::MonoIO::get_ConsoleInput System.IO.MonoIO::get_ConsoleOutput() mscorlib::System::IO::MonoIO::get_ConsoleOutput System.IO.MonoIO::get_DirectorySeparatorChar() mscorlib::System::IO::MonoIO::get_DirectorySeparatorChar System.IO.MonoIO::get_PathSeparator() mscorlib::System::IO::MonoIO::get_PathSeparator System.IO.MonoIO::get_VolumeSeparatorChar() mscorlib::System::IO::MonoIO::get_VolumeSeparatorChar System.IO.MonoIO::GetCurrentDirectory(System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::GetCurrentDirectory System.IO.MonoIO::GetFileAttributes(System.String,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::GetFileAttributes System.IO.MonoIO::GetFileStat(System.String,System.IO.MonoIOStat&,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::GetFileStat System.IO.MonoIO::GetFileSystemEntries(System.String,System.String,System.Int32,System.Int32,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::GetFileSystemEntries System.IO.MonoIO::GetFileType(System.IntPtr,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::GetFileType System.IO.MonoIO::GetLength(System.IntPtr,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::GetLength System.IO.MonoIO::GetTempPath(System.String&) mscorlib::System::IO::MonoIO::GetTempPath System.IO.MonoIO::Lock(System.IntPtr,System.Int64,System.Int64,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::Lock System.IO.MonoIO::MoveFile(System.String,System.String,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::MoveFile System.IO.MonoIO::Open(System.String,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare,System.IO.FileOptions,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::Open System.IO.MonoIO::Read(System.IntPtr,System.Byte[],System.Int32,System.Int32,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::Read System.IO.MonoIO::RemoveDirectory(System.String,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::RemoveDirectory System.IO.MonoIO::ReplaceFile(System.String,System.String,System.String,System.Boolean,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::ReplaceFile System.IO.MonoIO::Seek(System.IntPtr,System.Int64,System.IO.SeekOrigin,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::Seek System.IO.MonoIO::SetCurrentDirectory(System.String,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::SetCurrentDirectory System.IO.MonoIO::SetFileAttributes(System.String,System.IO.FileAttributes,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::SetFileAttributes System.IO.MonoIO::SetFileTime(System.IntPtr,System.Int64,System.Int64,System.Int64,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::SetFileTime System.IO.MonoIO::SetLength(System.IntPtr,System.Int64,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::SetLength System.IO.MonoIO::Unlock(System.IntPtr,System.Int64,System.Int64,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::Unlock System.IO.MonoIO::Write(System.IntPtr,System.Byte[],System.Int32,System.Int32,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::Write System.IO.MonoIO::CreatePipe(System.IntPtr&,System.IntPtr&,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::CreatePipe40 System.IO.MonoIO::DuplicateHandle(System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr&,System.Int32,System.Int32,System.Int32,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::DuplicateHandle40 System.IO.MonoIO::FindClose(System.IntPtr) mscorlib::System::IO::MonoIO::FindClose System.IO.MonoIO::FindFirst(System.String,System.String,System.IO.FileAttributes&,System.IO.MonoIOError&,System.IntPtr&) mscorlib::System::IO::MonoIO::FindFirst System.IO.MonoIO::FindNext(System.IntPtr,System.IO.FileAttributes&,System.IO.MonoIOError&) mscorlib::System::IO::MonoIO::FindNext System.IO.MonoIO::DumpHandles() mscorlib::System::IO::MonoIO::DumpHandles System.IO.MonoIO::RemapPath(System.String,System.String&) mscorlib::System::IO::MonoIO::RemapPath // System.IO.Path System.IO.Path::get_temp_path() mscorlib::System::IO::Path::get_temp_path // System.Math System.Math::Acos(System.Double) mscorlib::System::Math::Acos System.Math::Asin(System.Double) mscorlib::System::Math::Asin System.Math::Atan(System.Double) mscorlib::System::Math::Atan System.Math::Atan2(System.Double,System.Double) mscorlib::System::Math::Atan2 System.Math::Cos(System.Double) mscorlib::System::Math::Cos System.Math::Cosh(System.Double) mscorlib::System::Math::Cosh System.Math::Exp(System.Double) mscorlib::System::Math::Exp System.Math::Floor(System.Double) mscorlib::System::Math::Floor System.Math::Log(System.Double) mscorlib::System::Math::Log System.Math::Log10(System.Double) mscorlib::System::Math::Log10 System.Math::Pow(System.Double,System.Double) mscorlib::System::Math::Pow System.Math::Round(System.Double) mscorlib::System::Math::Round System.Math::Round2(System.Double,System.Int32,System.Boolean) mscorlib::System::Math::Round2 System.Math::Sin(System.Double) mscorlib::System::Math::Sin System.Math::Sinh(System.Double) mscorlib::System::Math::Sinh System.Math::Sqrt(System.Double) mscorlib::System::Math::Sqrt System.Math::Tan(System.Double) mscorlib::System::Math::Tan System.Math::Tanh(System.Double) mscorlib::System::Math::Tanh System.Math::Abs(System.Double) mscorlib::System::Math::Abs System.Math::Ceiling(System.Double) mscorlib::System::Math::Ceiling System.Math::SplitFractionDouble(System.Double*) mscorlib::System::Math::SplitFractionDouble System.Math::Abs(System.Single) mscorlib::System::Math::Abs // System.MonoCustomAttrs System.MonoCustomAttrs::GetCustomAttributesDataInternal(System.Reflection.ICustomAttributeProvider) mscorlib::System::MonoCustomAttrs::GetCustomAttributesDataInternal System.MonoCustomAttrs::GetCustomAttributesInternal(System.Reflection.ICustomAttributeProvider,System.Type,System.Boolean) mscorlib::System::MonoCustomAttrs::GetCustomAttributesInternal System.MonoCustomAttrs::IsDefinedInternal(System.Reflection.ICustomAttributeProvider,System.Type) mscorlib::System::MonoCustomAttrs::IsDefinedInternal // System.MonoEnumInfo System.MonoEnumInfo::get_enum_info(System.Type,System.MonoEnumInfo&) mscorlib::System::MonoEnumInfo::get_enum_info // System.MonoType System.MonoType::get_Assembly() mscorlib::System::MonoType::get_Assembly System.MonoType::get_attributes(System.Type) mscorlib::System::MonoType::get_attributes System.MonoType::get_BaseType() mscorlib::System::MonoType::get_BaseType System.MonoType::get_DeclaringMethod() mscorlib::System::MonoType::get_DeclaringMethod System.MonoType::get_DeclaringType() mscorlib::System::MonoType::get_DeclaringType System.MonoType::get_IsGenericParameter() mscorlib::System::MonoType::get_IsGenericParameter System.MonoType::get_Module() mscorlib::System::MonoType::get_Module System.MonoType::get_Name() mscorlib::System::MonoType::get_Name System.MonoType::get_Namespace() mscorlib::System::MonoType::get_Namespace System.MonoType::GetArrayRank() mscorlib::System::MonoType::GetArrayRank System.MonoType::GetConstructors_internal(System.Reflection.BindingFlags,System.Type) mscorlib::System::MonoType::GetConstructors_internal System.MonoType::GetCorrespondingInflatedConstructor(System.Reflection.ConstructorInfo) mscorlib::System::MonoType::GetCorrespondingInflatedMethod System.MonoType::GetCorrespondingInflatedMethod(System.Reflection.MethodInfo) mscorlib::System::MonoType::GetCorrespondingInflatedMethod System.MonoType::GetElementType() mscorlib::System::MonoType::GetElementType System.MonoType::GetEvents_internal(System.Reflection.BindingFlags,System.Type) mscorlib::System::MonoType::GetEvents_internal System.MonoType::GetField(System.String,System.Reflection.BindingFlags) mscorlib::System::MonoType::GetField System.MonoType::GetFields_internal(System.Reflection.BindingFlags,System.Type) mscorlib::System::MonoType::GetFields_internal System.MonoType::getFullName(System.Boolean,System.Boolean) mscorlib::System::MonoType::getFullName System.MonoType::GetGenericArguments() mscorlib::System::MonoType::GetGenericArguments System.MonoType::GetInterfaces() mscorlib::System::MonoType::GetInterfaces System.MonoType::GetMethodsByName(System.String,System.Reflection.BindingFlags,System.Boolean,System.Type) mscorlib::System::MonoType::GetMethodsByName System.MonoType::GetNestedType(System.String,System.Reflection.BindingFlags) mscorlib::System::MonoType::GetNestedType System.MonoType::GetNestedTypes(System.Reflection.BindingFlags) mscorlib::System::MonoType::GetNestedTypes System.MonoType::GetPropertiesByName(System.String,System.Reflection.BindingFlags,System.Boolean,System.Type) mscorlib::System::MonoType::GetPropertiesByName System.MonoType::InternalGetEvent(System.String,System.Reflection.BindingFlags) mscorlib::System::MonoType::InternalGetEvent System.MonoType::IsByRefImpl() mscorlib::System::MonoType::IsByRefImpl System.MonoType::IsCOMObjectImpl() mscorlib::System::MonoType::IsCOMObjectImpl System.MonoType::IsPointerImpl() mscorlib::System::MonoType::IsPointerImpl System.MonoType::IsPrimitiveImpl() mscorlib::System::MonoType::IsPrimitiveImpl System.MonoType::type_from_obj(System.MonoType,System.Object) mscorlib::System::MonoType::type_from_obj // System.NumberFormatter System.NumberFormatter::GetFormatterTables(System.UInt64*&,System.Int32*&,System.Char*&,System.Char*&,System.Int64*&,System.Int32*&) mscorlib::System::NumberFormatter::GetFormatterTables // System.Net System.Net.Dns::GetHostByAddr_internal(System.String,System.String&,System.String[]&,System.String[]&) System::System::Net::Dns::GetHostByAddr System.Net.Dns::GetHostByName_internal(System.String,System.String&,System.String[]&,System.String[]&) System::System::Net::Dns::GetHostByName System.Net.Dns::GetHostName_internal(System.String&) System::System::Net::Dns::GetHostName // System.Net.Sockets System.Net.Sockets.Socket::Accept_internal(System.IntPtr,System.Int32&,System.Boolean) System::System::Net::Sockets::Socket::Accept System.Net.Sockets.Socket::Available_internal(System.IntPtr,System.Int32&) System::System::Net::Sockets::Socket::Available System.Net.Sockets.Socket::Bind_internal(System.IntPtr,System.Net.SocketAddress,System.Int32&) System::System::Net::Sockets::Socket::Bind System.Net.Sockets.Socket::Blocking_internal(System.IntPtr,System.Boolean,System.Int32&) System::System::Net::Sockets::Socket::Blocking System.Net.Sockets.Socket::Close_internal(System.IntPtr,System.Int32&) System::System::Net::Sockets::Socket::Close System.Net.Sockets.Socket::Connect_internal_real(System.IntPtr,System.Net.SocketAddress,System.Int32&) System::System::Net::Sockets::Socket::Connect System.Net.Sockets.Socket::Disconnect_internal(System.IntPtr,System.Boolean,System.Int32&) System::System::Net::Sockets::Socket::Disconnect System.Net.Sockets.Socket::GetSocketOption_arr_internal(System.IntPtr,System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,System.Byte[]&,System.Int32&) System::System::Net::Sockets::Socket::GetSocketOptionArray System.Net.Sockets.Socket::GetSocketOption_obj_internal(System.IntPtr,System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,System.Object&,System.Int32&) System::System::Net::Sockets::Socket::GetSocketOptionObj System.Net.Sockets.Socket::Listen_internal(System.IntPtr,System.Int32,System.Int32&) System::System::Net::Sockets::Socket::Listen System.Net.Sockets.Socket::LocalEndPoint_internal(System.IntPtr,System.Int32&) System::System::Net::Sockets::Socket::LocalEndPoint System.Net.Sockets.Socket::Poll_internal(System.IntPtr,System.Net.Sockets.SelectMode,System.Int32,System.Int32&) System::System::Net::Sockets::Socket::Poll System.Net.Sockets.Socket::Receive_internal(System.IntPtr,System.Net.Sockets.Socket/WSABUF[],System.Net.Sockets.SocketFlags,System.Int32&) System::System::Net::Sockets::Socket::ReceiveArray System.Net.Sockets.Socket::Receive_internal(System.IntPtr,System.Byte[],System.Int32,System.Int32,System.Net.Sockets.SocketFlags,System.Int32&) System::System::Net::Sockets::Socket::Receive System.Net.Sockets.Socket::RecvFrom_internal(System.IntPtr,System.Byte[],System.Int32,System.Int32,System.Net.Sockets.SocketFlags,System.Net.SocketAddress&,System.Int32&) System::System::Net::Sockets::Socket::RecvFrom System.Net.Sockets.Socket::RemoteEndPoint_internal(System.IntPtr,System.Int32&) System::System::Net::Sockets::Socket::RemoteEndPoint System.Net.Sockets.Socket::Select_internal(System.Net.Sockets.Socket[]&,System.Int32,System.Int32&) System::System::Net::Sockets::Socket::Select System.Net.Sockets.Socket::SendFile(System.IntPtr,System.String,System.Byte[],System.Byte[],System.Net.Sockets.TransmitFileOptions) System::System::Net::Sockets::Socket::SendFile System.Net.Sockets.Socket::SendTo_internal_real(System.IntPtr,System.Byte[],System.Int32,System.Int32,System.Net.Sockets.SocketFlags,System.Net.SocketAddress,System.Int32&) System::System::Net::Sockets::Socket::SendTo System.Net.Sockets.Socket::Send_internal(System.IntPtr,System.Net.Sockets.Socket/WSABUF[],System.Net.Sockets.SocketFlags,System.Int32&) System::System::Net::Sockets::Socket::SendArray System.Net.Sockets.Socket::Send_internal(System.IntPtr,System.Byte[],System.Int32,System.Int32,System.Net.Sockets.SocketFlags,System.Int32&) System::System::Net::Sockets::Socket::Send System.Net.Sockets.Socket::SetSocketOption_internal(System.IntPtr,System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,System.Object,System.Byte[],System.Int32,System.Int32&) System::System::Net::Sockets::Socket::SetSocketOption System.Net.Sockets.Socket::Shutdown_internal(System.IntPtr,System.Net.Sockets.SocketShutdown,System.Int32&) System::System::Net::Sockets::Socket::Shutdown System.Net.Sockets.Socket::Socket_internal(System.Net.Sockets.AddressFamily,System.Net.Sockets.SocketType,System.Net.Sockets.ProtocolType,System.Int32&) System::System::Net::Sockets::Socket::Socket_internal System.Net.Sockets.Socket::WSAIoctl(System.IntPtr,System.Int32,System.Byte[],System.Byte[],System.Int32&) System::System::Net::Sockets::Socket::WSAIoctl System.Net.Sockets.SocketException::WSAGetLastError_internal System::System::Net::Sockets::SocketException::WSAGetLastError // System.Object System.Object::GetType() mscorlib::System::Object::GetType System.Object::InternalGetHashCode(System.Object) mscorlib::System::Object::InternalGetHashCode System.Object::MemberwiseClone() mscorlib::System::Object::MemberwiseClone System.Object::obj_address() mscorlib::System::Object::obj_address // System.Reflection.Assembly System.Reflection.Assembly::FillName(System.Reflection.Assembly,System.Reflection.AssemblyName) mscorlib::System::Reflection::Assembly::FillName System.Reflection.Assembly::get_code_base(System.Boolean) mscorlib::System::Reflection::Assembly::get_code_base System.Reflection.Assembly::get_EntryPoint() mscorlib::System::Reflection::Assembly::get_EntryPoint System.Reflection.Assembly::get_fullname() mscorlib::System::Reflection::Assembly::get_fullname System.Reflection.Assembly::get_global_assembly_cache() mscorlib::System::Reflection::Assembly::get_global_assembly_cache System.Reflection.Assembly::get_location() mscorlib::System::Reflection::Assembly::get_location System.Reflection.Assembly::get_ReflectionOnly() mscorlib::System::Reflection::Assembly::get_ReflectionOnly System.Reflection.Assembly::GetCallingAssembly() mscorlib::System::Reflection::Assembly::GetCallingAssembly System.Reflection.Assembly::GetEntryAssembly() mscorlib::System::Reflection::Assembly::GetEntryAssembly System.Reflection.Assembly::GetExecutingAssembly() mscorlib::System::Reflection::Assembly::GetExecutingAssembly System.Reflection.Assembly::GetFilesInternal(System.String,System.Boolean) mscorlib::System::Reflection::Assembly::GetFilesInternal System.Reflection.Assembly::GetManifestModuleInternal() mscorlib::System::Reflection::Assembly::GetManifestModuleInternal System.Reflection.Assembly::GetManifestResourceInfoInternal(System.String,System.Reflection.ManifestResourceInfo) mscorlib::System::Reflection::Assembly::GetManifestResourceInfoInternal System.Reflection.Assembly::GetManifestResourceInternal(System.String,System.Int32&,System.Reflection.Module&) mscorlib::System::Reflection::Assembly::GetManifestResourceInternal System.Reflection.Assembly::GetManifestResourceNames() mscorlib::System::Reflection::Assembly::GetManifestResourceNames System.Reflection.Assembly::GetModulesInternal() mscorlib::System::Reflection::Assembly::GetModulesInternal System.Reflection.Assembly::GetNamespaces() mscorlib::System::Reflection::Assembly::GetNamespaces System.Reflection.Assembly::GetReferencedAssemblies() mscorlib::System::Reflection::Assembly::GetReferencedAssemblies System.Reflection.Assembly::GetTypes(System.Boolean) mscorlib::System::Reflection::Assembly::GetTypes System.Reflection.Assembly::InternalGetAssemblyName(System.String,System.Reflection.AssemblyName) mscorlib::System::Reflection::Assembly::InternalGetAssemblyName System.Reflection.Assembly::InternalGetType(System.Reflection.Module,System.String,System.Boolean,System.Boolean) mscorlib::System::Reflection::Assembly::InternalGetType System.Reflection.Assembly::InternalImageRuntimeVersion() mscorlib::System::Reflection::Assembly::InternalImageRuntimeVersion System.Reflection.Assembly::load_with_partial_name(System.String,System.Security.Policy.Evidence) mscorlib::System::Reflection::Assembly::load_with_partial_name System.Reflection.Assembly::LoadFrom(System.String,System.Boolean) mscorlib::System::Reflection::Assembly::LoadFrom System.Reflection.Assembly::LoadPermissions(System.Reflection.Assembly,System.IntPtr&,System.Int32&,System.IntPtr&,System.Int32&,System.IntPtr&,System.Int32&) mscorlib::System::Reflection::Assembly::LoadPermissions System.Reflection.Assembly::MonoDebugger_GetMethodToken(System.Reflection.MethodBase) mscorlib::System::Reflection::Assembly::MonoDebugger_GetMethodToken System.Reflection.Assembly::GetReferencedAssemblies(System.Reflection.Assembly) mscorlib::System::Reflection::Assembly::GetReferencedAssemblies System.Reflection.Assembly::GetAotId() mscorlib::System::Reflection::Assembly::GetAotId // System.Reflection.AssemblyName System.Reflection.AssemblyName::ParseName(System.Reflection.AssemblyName,System.String) mscorlib::System::Reflection::AssemblyName::ParseName System.Reflection.AssemblyName::get_public_token(System.Byte*,System.Byte*,System.Int32) mscorlib::System::Reflection::AssemblyName::get_public_token System.Reflection.AssemblyName::GetNativeName(System.IntPtr) mscorlib::System::Reflection::AssemblyName::GetNativeName System.Reflection.AssemblyName::ParseAssemblyName(System.IntPtr,Mono.MonoAssemblyName&,System.Boolean&,System.Boolean&) mscorlib::System::Reflection::AssemblyName::ParseAssemblyName // System.Reflection.Emit.AssemblyBuilder System.Reflection.Emit.AssemblyBuilder::basic_init(System.Reflection.Emit.AssemblyBuilder) mscorlib::System::Reflection::Emit::AssemblyBuilder::basic_init System.Reflection.Emit.AssemblyBuilder::InternalAddModule(System.String) mscorlib::System::Reflection::Emit::AssemblyBuilder::InternalAddModule // System.Reflection.Emit.CustomAttributeBuilder System.Reflection.Emit.CustomAttributeBuilder::GetBlob(System.Reflection.Assembly,System.Reflection.ConstructorInfo,System.Object[],System.Reflection.PropertyInfo[],System.Object[],System.Reflection.FieldInfo[],System.Object[]) mscorlib::System::Reflection::Emit::CustomAttributeBuilder::GetBlob // System.Reflection.Emit.DerivedType System.Reflection.Emit.DerivedType::create_unmanaged_type(System.Type) mscorlib::System::Reflection::Emit::DerivedType::create_unmanaged_type // System.Reflection.Emit.DynamicMethod System.Reflection.Emit.DynamicMethod::create_dynamic_method(System.Reflection.Emit.DynamicMethod) mscorlib::System::Reflection::Emit::DynamicMethod::create_dynamic_method System.Reflection.Emit.DynamicMethod::destroy_dynamic_method(System.Reflection.Emit.DynamicMethod) mscorlib::System::Reflection::Emit::DynamicMethod::destroy_dynamic_method // System.Reflection.Emit.EnumBuilder System.Reflection.Emit.EnumBuilder::setup_enum_type(System.Type) mscorlib::System::Reflection::Emit::EnumBuilder::setup_enum_type // System.Reflection.Emit.GenericTypeParameterBuilder System.Reflection.Emit.GenericTypeParameterBuilder::initialize() mscorlib::System::Reflection::Emit::GenericTypeParameterBuilder::initialize // System.Reflection.Emit.MethodBuilder System.Reflection.Emit.MethodBuilder::MakeGenericMethod(System.Type[]) mscorlib::System::Reflection::Emit::MethodBuilder::MakeGenericMethod // System.Reflection.Emit.ModuleBuilder System.Reflection.Emit.ModuleBuilder::basic_init(System.Reflection.Emit.ModuleBuilder) mscorlib::System::Reflection::Emit::ModuleBuilder::basic_init System.Reflection.Emit.ModuleBuilder::build_metadata(System.Reflection.Emit.ModuleBuilder) mscorlib::System::Reflection::Emit::ModuleBuilder::build_metadata System.Reflection.Emit.ModuleBuilder::create_modified_type(System.Reflection.Emit.TypeBuilder,System.String) mscorlib::System::Reflection::Emit::ModuleBuilder::create_modified_type System.Reflection.Emit.ModuleBuilder::getMethodToken(System.Reflection.Emit.ModuleBuilder,System.Reflection.MethodInfo,System.Type[]) mscorlib::System::Reflection::Emit::ModuleBuilder::getMethodToken System.Reflection.Emit.ModuleBuilder::getToken(System.Reflection.Emit.ModuleBuilder,System.Object) mscorlib::System::Reflection::Emit::ModuleBuilder::getToken System.Reflection.Emit.ModuleBuilder::getUSIndex(System.Reflection.Emit.ModuleBuilder,System.String) mscorlib::System::Reflection::Emit::ModuleBuilder::getUSIndex System.Reflection.Emit.ModuleBuilder::RegisterToken(System.Object,System.Int32) mscorlib::System::Reflection::Emit::ModuleBuilder::RegisterToken System.Reflection.Emit.ModuleBuilder::set_wrappers_type(System.Reflection.Emit.ModuleBuilder,System.Type) mscorlib::System::Reflection::Emit::ModuleBuilder::set_wrappers_type System.Reflection.Emit.ModuleBuilder::WriteToFile(System.IntPtr) mscorlib::System::Reflection::Emit::ModuleBuilder::WriteToFile System.Reflection.Emit.ModuleBuilder::getMethodToken(System.Reflection.Emit.ModuleBuilder,System.Reflection.MethodBase,System.Type[]) mscorlib::System::Reflection::Emit::ModuleBuilder::getMethodToken40 System.Reflection.Emit.ModuleBuilder::getToken(System.Reflection.Emit.ModuleBuilder,System.Object,System.Boolean) mscorlib::System::Reflection::Emit::ModuleBuilder::getToken40 System.Reflection.Emit.ModuleBuilder::GetRegisteredToken(System.Int32) mscorlib::System::Reflection::Emit::ModuleBuilder::GetRegisteredToken // System.Reflection.Emit.SignatureHelper System.Reflection.Emit.SignatureHelper::get_signature_field() mscorlib::System::Reflection::Emit::SignatureHelper::get_signature_field System.Reflection.Emit.SignatureHelper::get_signature_local() mscorlib::System::Reflection::Emit::SignatureHelper::get_signature_local // System.Reflection.Emit.TypeBuilder System.Reflection.Emit.TypeBuilder::create_generic_class() mscorlib::System::Reflection::Emit::TypeBuilder::create_generic_class System.Reflection.Emit.TypeBuilder::create_internal_class(System.Reflection.Emit.TypeBuilder) mscorlib::System::Reflection::Emit::TypeBuilder::create_internal_class System.Reflection.Emit.TypeBuilder::create_runtime_class(System.Reflection.Emit.TypeBuilder) mscorlib::System::Reflection::Emit::TypeBuilder::create_runtime_class System.Reflection.Emit.TypeBuilder::get_event_info(System.Reflection.Emit.EventBuilder) mscorlib::System::Reflection::Emit::TypeBuilder::get_event_info System.Reflection.Emit.TypeBuilder::get_IsGenericParameter() mscorlib::System::Reflection::Emit::TypeBuilder::get_IsGenericParameter System.Reflection.Emit.TypeBuilder::setup_generic_class() mscorlib::System::Reflection::Emit::TypeBuilder::setup_generic_class System.Reflection.Emit.TypeBuilder::setup_internal_class(System.Reflection.Emit.TypeBuilder) mscorlib::System::Reflection::Emit::TypeBuilder::setup_internal_class System.Reflection.Emit.TypeBuilder::create_runtime_class(System.Reflection.Emit.TypeBuilder) mscorlib::System::Reflection::Emit::TypeBuilder::create_runtime_class // System.Reflection.FieldInfo System.Reflection.FieldInfo::GetTypeModifiers(System.Boolean) mscorlib::System::Reflection::FieldInfo::GetTypeModifiers System.Reflection.FieldInfo::GetUnmanagedMarshal() mscorlib::System::Reflection::FieldInfo::GetUnmanagedMarshal System.Reflection.FieldInfo::internal_from_handle_type(System.IntPtr,System.IntPtr) mscorlib::System::Reflection::FieldInfo::internal_from_handle_type System.Reflection.FieldInfo::get_marshal_info() mscorlib::System::Reflection::FieldInfo::get_marshal_info // System.Reflection.MemberInfo System.Reflection.MemberInfo::get_MetadataToken() mscorlib::System::Reflection::MemberInfo::get_MetadataToken // System.Reflection.MethodBase System.Reflection.MethodBase::GetCurrentMethod() mscorlib::System::Reflection::MethodBase::GetCurrentMethod System.Reflection.MethodBase::GetMethodBodyInternal(System.IntPtr) mscorlib::System::Reflection::MethodBase::GetMethodBodyInternal System.Reflection.MethodBase::GetMethodFromHandleInternalType(System.IntPtr,System.IntPtr) mscorlib::System::Reflection::MethodBase::GetMethodFromHandleInternalType System.Reflection.MethodBase::GetMethodFromHandleInternalType_native(System.IntPtr,System.IntPtr,System.Boolean) mscorlib::System::Reflection::MethodBase::GetMethodFromHandleInternalType_native // System.Reflection.Module System.Reflection.Module::get_MetadataToken() mscorlib::System::Reflection::Module::get_MetadataToken System.Reflection.Module::GetGlobalType() mscorlib::System::Reflection::Module::GetGlobalType System.Reflection.Module::GetGuidInternal() mscorlib::System::Reflection::Module::GetGuidInternal System.Reflection.Module::GetHINSTANCE() mscorlib::System::Reflection::Module::GetHINSTANCE System.Reflection.Module::GetMDStreamVersion(System.IntPtr) mscorlib::System::Reflection::Module::GetMDStreamVersion System.Reflection.Module::GetPEKind(System.IntPtr,System.Reflection.PortableExecutableKinds&,System.Reflection.ImageFileMachine&) mscorlib::System::Reflection::Module::GetPEKind System.Reflection.Module::InternalGetTypes() mscorlib::System::Reflection::Module::InternalGetTypes System.Reflection.Module::ResolveFieldToken(System.IntPtr,System.Int32,System.IntPtr[],System.IntPtr[],System.Reflection.ResolveTokenError&) mscorlib::System::Reflection::Module::ResolveFieldToken System.Reflection.Module::ResolveMemberToken(System.IntPtr,System.Int32,System.IntPtr[],System.IntPtr[],System.Reflection.ResolveTokenError&) mscorlib::System::Reflection::Module::ResolveMemberToken System.Reflection.Module::ResolveMethodToken(System.IntPtr,System.Int32,System.IntPtr[],System.IntPtr[],System.Reflection.ResolveTokenError&) mscorlib::System::Reflection::Module::ResolveMethodToken System.Reflection.Module::ResolveSignature(System.IntPtr,System.Int32,System.Reflection.ResolveTokenError&) mscorlib::System::Reflection::Module::ResolveSignature System.Reflection.Module::ResolveStringToken(System.IntPtr,System.Int32,System.Reflection.ResolveTokenError&) mscorlib::System::Reflection::Module::ResolveStringToken System.Reflection.Module::ResolveTypeToken(System.IntPtr,System.Int32,System.IntPtr[],System.IntPtr[],System.Reflection.ResolveTokenError&) mscorlib::System::Reflection::Module::ResolveTypeToken System.Reflection.Module::get_MetadataToken(System.Reflection.Module) mscorlib::System::Reflection::Module::get_MetadataToken // System.Reflection.MonoCMethod System.Reflection.MonoCMethod::InternalInvoke(System.Object,System.Object[],System.Exception&) mscorlib::System::Reflection::MonoMethod::InternalInvoke System.Reflection.MonoCMethod::get_core_clr_security_level() mscorlib::System::Reflection::MonoCMethod::get_core_clr_security_level // System.Reflection.MonoEventInfo System.Reflection.MonoEventInfo::get_event_info(System.Reflection.MonoEvent,System.Reflection.MonoEventInfo&) mscorlib::System::Reflection::MonoEventInfo::get_event_info // System.Reflection.MonoField System.Reflection.MonoField::GetFieldOffset() mscorlib::System::Reflection::MonoField::GetFieldOffset System.Reflection.MonoField::GetParentType(System.Boolean) mscorlib::System::Reflection::MonoField::GetParentType System.Reflection.MonoField::GetRawConstantValue() mscorlib::System::Reflection::MonoField::GetRawConstantValue System.Reflection.MonoField::GetValueInternal(System.Object) mscorlib::System::Reflection::MonoField::GetValueInternal System.Reflection.MonoField::SetValueInternal(System.Reflection.FieldInfo,System.Object,System.Object) mscorlib::System::Reflection::MonoField::SetValueInternal System.Reflection.MonoField::get_core_clr_security_level() mscorlib::System::Reflection::MonoField::get_core_clr_security_level System.Reflection.MonoField::ResolveType() mscorlib::System::Reflection::MonoField::ResolveType // System.Reflection.MonoGenericClass System.Reflection.MonoGenericClass::initialize(System.Reflection.MethodInfo[],System.Reflection.ConstructorInfo[],System.Reflection.FieldInfo[],System.Reflection.PropertyInfo[],System.Reflection.EventInfo[]) mscorlib::System::Reflection::MonoGenericClass::initialize System.Reflection.MonoGenericClass::initialize(System.Reflection.FieldInfo[]) mscorlib::System::Reflection::MonoGenericClass::initialize40 System.Reflection.MonoGenericClass::register_with_runtime(System.Type) mscorlib::System::Reflection::MonoGenericClass::register_with_runtime // System.Reflection.MonoGenericCMethod System.Reflection.MonoGenericCMethod::get_ReflectedType() mscorlib::System::Reflection::MonoGenericCMethod::get_ReflectedType // System.Reflection.MonoGenericMethod System.Reflection.MonoGenericMethod::get_ReflectedType() mscorlib::System::Reflection::MonoGenericMethod::get_ReflectedType // System.Reflection.MonoMethod System.Reflection.MonoMethod::get_base_definition(System.Reflection.MonoMethod) mscorlib::System::Reflection::MonoMethod::get_base_definition System.Reflection.MonoMethod::get_IsGenericMethod() mscorlib::System::Reflection::MonoMethod::get_IsGenericMethod System.Reflection.MonoMethod::get_IsGenericMethodDefinition() mscorlib::System::Reflection::MonoMethod::get_IsGenericMethodDefinition System.Reflection.MonoMethod::get_name(System.Reflection.MethodBase) mscorlib::System::Reflection::MonoMethod::get_name System.Reflection.MonoMethod::GetDllImportAttribute(System.IntPtr) mscorlib::System::Reflection::MonoMethod::GetDllImportAttribute System.Reflection.MonoMethod::GetGenericArguments() mscorlib::System::Reflection::MonoMethod::GetGenericArguments System.Reflection.MonoMethod::GetGenericMethodDefinition_impl() mscorlib::System::Reflection::MonoMethod::GetGenericMethodDefinition_impl System.Reflection.MonoMethod::InternalInvoke(System.Object,System.Object[],System.Exception&) mscorlib::System::Reflection::MonoMethod::InternalInvoke System.Reflection.MonoMethod::MakeGenericMethod_impl(System.Type[]) mscorlib::System::Reflection::MonoMethod::MakeGenericMethod_impl System.Reflection.MonoMethod::get_core_clr_security_level() mscorlib::System::Reflection::MonoMethod::get_core_clr_security_level System.Reflection.MonoMethod::get_base_method(System.Reflection.MonoMethod,System.Boolean) mscorlib::System::Reflection::MonoMethod::get_base_method System.Reflection.MonoMethod::GetPInvoke(System.Reflection.PInvokeAttributes&,System.String&,System.String&) mscorlib::System::Reflection::MonoMethod::GetPInvoke // System.Reflection.MonoMethodInfo System.Reflection.MonoMethodInfo::get_method_info(System.IntPtr,System.Reflection.MonoMethodInfo&) mscorlib::System::Reflection::MonoMethodInfo::get_method_info System.Reflection.MonoMethodInfo::get_parameter_info(System.IntPtr,System.Reflection.MemberInfo) mscorlib::System::Reflection::MonoMethodInfo::get_parameter_info System.Reflection.MonoMethodInfo::get_retval_marshal(System.IntPtr) mscorlib::System::Reflection::MonoMethodInfo::get_retval_marshal System.Reflection.MonoMethodInfo::get_method_attributes(System.IntPtr) mscorlib::System::Reflection::MonoMethodInfo::get_method_attributes System.Reflection.MonoMethodInfo::get_retval_marshal(System.IntPtr) mscorlib::System::Reflection::MonoMethodInfo::get_retval_marshal // System.Reflection.MonoPropertyInfo System.Reflection.MonoPropertyInfo::get_property_info(System.Reflection.MonoProperty,System.Reflection.MonoPropertyInfo&,System.Reflection.PInfo) mscorlib::System::Reflection::MonoPropertyInfo::get_property_info System.Reflection.MonoPropertyInfo::GetTypeModifiers(System.Reflection.MonoProperty,System.Boolean) mscorlib::System::Reflection::MonoPropertyInfo::GetTypeModifiers System.Reflection.MonoPropertyInfo::get_default_value(System.Reflection.MonoProperty) mscorlib::System::Reflection::MonoPropertyInfo::get_default_value // System.Reflection.ParameterInfo System.Reflection.ParameterInfo::GetMetadataToken() mscorlib::System::Reflection::ParameterInfo::GetMetadataToken System.Reflection.ParameterInfo::GetTypeModifiers(System.Boolean) mscorlib::System::Reflection::ParameterInfo::GetTypeModifiers // System.Runtime.CompilerServices.RuntimeHelpers System.Runtime.CompilerServices.RuntimeHelpers::get_OffsetToStringData() mscorlib::System::Runtime::CompilerServices::RuntimeHelpers::get_OffsetToStringData System.Runtime.CompilerServices.RuntimeHelpers::GetObjectValue(System.Object) mscorlib::System::Runtime::CompilerServices::RuntimeHelpers::GetObjectValue System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(System.Array,System.IntPtr) mscorlib::System::Runtime::CompilerServices::RuntimeHelpers::InitializeArray System.Runtime.CompilerServices.RuntimeHelpers::RunClassConstructor(System.IntPtr) mscorlib::System::Runtime::CompilerServices::RuntimeHelpers::RunClassConstructor System.Runtime.CompilerServices.RuntimeHelpers::RunModuleConstructor(System.IntPtr) mscorlib::System::Runtime::CompilerServices::RuntimeHelpers::RunModuleConstructor System.Runtime.CompilerServices.RuntimeHelpers::SufficientExecutionStack() mscorlib::System::Runtime::CompilerServices::RuntimeHelpers::SufficientExecutionStack // System.Runtime.InteropServices.GCHandle System.Runtime.InteropServices.GCHandle::CheckCurrentDomain(System.Int32) mscorlib::System::Runtime::InteropServices::GCHandle::CheckCurrentDomain System.Runtime.InteropServices.GCHandle::FreeHandle(System.Int32) mscorlib::System::Runtime::InteropServices::GCHandle::FreeHandle System.Runtime.InteropServices.GCHandle::GetAddrOfPinnedObject(System.Int32) mscorlib::System::Runtime::InteropServices::GCHandle::GetAddrOfPinnedObject System.Runtime.InteropServices.GCHandle::GetTarget(System.Int32) mscorlib::System::Runtime::InteropServices::GCHandle::GetTarget System.Runtime.InteropServices.GCHandle::GetTargetHandle(System.Object,System.Int32,System.Runtime.InteropServices.GCHandleType) mscorlib::System::Runtime::InteropServices::GCHandle::GetTargetHandle // System.Runtime.InteropServices.Marshal System.Runtime.InteropServices.Marshal::AddRefInternal(System.IntPtr) mscorlib::System::Runtime::InteropServices::Marshal::AddRefInternal System.Runtime.InteropServices.Marshal::AllocCoTaskMem(System.Int32) mscorlib::System::Runtime::InteropServices::Marshal::AllocCoTaskMem System.Runtime.InteropServices.Marshal::AllocHGlobal(System.IntPtr) mscorlib::System::Runtime::InteropServices::Marshal::AllocHGlobal System.Runtime.InteropServices.Marshal::copy_from_unmanaged(System.IntPtr,System.Int32,System.Array,System.Int32) mscorlib::System::Runtime::InteropServices::Marshal::copy_from_unmanaged System.Runtime.InteropServices.Marshal::copy_to_unmanaged(System.Array,System.Int32,System.IntPtr,System.Int32) mscorlib::System::Runtime::InteropServices::Marshal::copy_to_unmanaged System.Runtime.InteropServices.Marshal::DestroyStructure(System.IntPtr,System.Type) mscorlib::System::Runtime::InteropServices::Marshal::DestroyStructure System.Runtime.InteropServices.Marshal::FreeBSTR(System.IntPtr) mscorlib::System::Runtime::InteropServices::Marshal::FreeBSTR System.Runtime.InteropServices.Marshal::FreeCoTaskMem(System.IntPtr) mscorlib::System::Runtime::InteropServices::Marshal::FreeCoTaskMem System.Runtime.InteropServices.Marshal::FreeHGlobal(System.IntPtr) mscorlib::System::Runtime::InteropServices::Marshal::FreeHGlobal System.Runtime.InteropServices.Marshal::GetCCW(System.Object,System.Type) mscorlib::System::Runtime::InteropServices::Marshal::GetCCW System.Runtime.InteropServices.Marshal::GetComSlotForMethodInfoInternal(System.Reflection.MemberInfo) mscorlib::System::Runtime::InteropServices::Marshal::GetComSlotForMethodInfoInternal System.Runtime.InteropServices.Marshal::GetDelegateForFunctionPointerInternal(System.IntPtr,System.Type) mscorlib::System::Runtime::InteropServices::Marshal::GetDelegateForFunctionPointerInternal System.Runtime.InteropServices.Marshal::GetFunctionPointerForDelegateInternal(System.Delegate) mscorlib::System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegateInternal System.Runtime.InteropServices.Marshal::GetIDispatchForObjectInternal(System.Object) mscorlib::System::Runtime::InteropServices::Marshal::GetIDispatchForObjectInternal System.Runtime.InteropServices.Marshal::GetIUnknownForObjectInternal(System.Object) mscorlib::System::Runtime::InteropServices::Marshal::GetIUnknownForObjectInternal System.Runtime.InteropServices.Marshal::GetLastWin32Error() mscorlib::System::Runtime::InteropServices::Marshal::GetLastWin32Error System.Runtime.InteropServices.Marshal::GetObjectForCCW(System.IntPtr) mscorlib::System::Runtime::InteropServices::Marshal::GetObjectForCCW System.Runtime.InteropServices.Marshal::IsComObject(System.Object) mscorlib::System::Runtime::InteropServices::Marshal::IsComObject System.Runtime.InteropServices.Marshal::OffsetOf(System.Type,System.String) mscorlib::System::Runtime::InteropServices::Marshal::OffsetOf System.Runtime.InteropServices.Marshal::Prelink(System.Reflection.MethodInfo) mscorlib::System::Runtime::InteropServices::Marshal::Prelink System.Runtime.InteropServices.Marshal::PrelinkAll(System.Type) mscorlib::System::Runtime::InteropServices::Marshal::PrelinkAll System.Runtime.InteropServices.Marshal::PtrToStringAnsi(System.IntPtr) mscorlib::System::Runtime::InteropServices::Marshal::PtrToStringAnsi_mscorlib_System_String_mscorlib_System_IntPtr System.Runtime.InteropServices.Marshal::PtrToStringAnsi(System.IntPtr,System.Int32) mscorlib::System::Runtime::InteropServices::Marshal::PtrToStringAnsi_mscorlib_System_String_mscorlib_System_IntPtr_mscorlib_System_Int32 System.Runtime.InteropServices.Marshal::PtrToStringBSTR(System.IntPtr) mscorlib::System::Runtime::InteropServices::Marshal::PtrToStringBSTR System.Runtime.InteropServices.Marshal::PtrToStringUni(System.IntPtr) mscorlib::System::Runtime::InteropServices::Marshal::PtrToStringUni_mscorlib_System_String_mscorlib_System_IntPtr System.Runtime.InteropServices.Marshal::PtrToStringUni(System.IntPtr,System.Int32) mscorlib::System::Runtime::InteropServices::Marshal::PtrToStringUni_mscorlib_System_String_mscorlib_System_IntPtr_mscorlib_System_Int32 System.Runtime.InteropServices.Marshal::PtrToStructure(System.IntPtr,System.Object) mscorlib::System::Runtime::InteropServices::Marshal::PtrToStructureObject System.Runtime.InteropServices.Marshal::PtrToStructure(System.IntPtr,System.Type) mscorlib::System::Runtime::InteropServices::Marshal::PtrToStructure System.Runtime.InteropServices.Marshal::QueryInterfaceInternal(System.IntPtr,System.Guid&,System.IntPtr&) mscorlib::System::Runtime::InteropServices::Marshal::QueryInterfaceInternal System.Runtime.InteropServices.Marshal::ReadByte(System.IntPtr,System.Int32) mscorlib::System::Runtime::InteropServices::Marshal::ReadByte System.Runtime.InteropServices.Marshal::ReadInt16(System.IntPtr,System.Int32) mscorlib::System::Runtime::InteropServices::Marshal::ReadInt16 System.Runtime.InteropServices.Marshal::ReadInt32(System.IntPtr,System.Int32) mscorlib::System::Runtime::InteropServices::Marshal::ReadInt32 System.Runtime.InteropServices.Marshal::ReadInt64(System.IntPtr,System.Int32) mscorlib::System::Runtime::InteropServices::Marshal::ReadInt64 System.Runtime.InteropServices.Marshal::ReadIntPtr(System.IntPtr,System.Int32) mscorlib::System::Runtime::InteropServices::Marshal::ReadIntPtr System.Runtime.InteropServices.Marshal::ReAllocCoTaskMem(System.IntPtr,System.Int32) mscorlib::System::Runtime::InteropServices::Marshal::ReAllocCoTaskMem System.Runtime.InteropServices.Marshal::ReAllocHGlobal(System.IntPtr,System.IntPtr) mscorlib::System::Runtime::InteropServices::Marshal::ReAllocHGlobal System.Runtime.InteropServices.Marshal::ReleaseComObjectInternal(System.Object) mscorlib::System::Runtime::InteropServices::Marshal::ReleaseComObjectInternal System.Runtime.InteropServices.Marshal::ReleaseInternal(System.IntPtr) mscorlib::System::Runtime::InteropServices::Marshal::ReleaseInternal System.Runtime.InteropServices.Marshal::SizeOf(System.Type) mscorlib::System::Runtime::InteropServices::Marshal::SizeOf System.Runtime.InteropServices.Marshal::StringToBSTR(System.String) mscorlib::System::Runtime::InteropServices::Marshal::StringToBSTR System.Runtime.InteropServices.Marshal::StringToHGlobalAnsi(System.String) mscorlib::System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi System.Runtime.InteropServices.Marshal::StringToHGlobalUni(System.String) mscorlib::System::Runtime::InteropServices::Marshal::StringToHGlobalUni System.Runtime.InteropServices.Marshal::StructureToPtr(System.Object,System.IntPtr,System.Boolean) mscorlib::System::Runtime::InteropServices::Marshal::StructureToPtr System.Runtime.InteropServices.Marshal::UnsafeAddrOfPinnedArrayElement(System.Array,System.Int32) mscorlib::System::Runtime::InteropServices::Marshal::UnsafeAddrOfPinnedArrayElement System.Runtime.InteropServices.Marshal::WriteByte(System.IntPtr,System.Int32,System.Byte) mscorlib::System::Runtime::InteropServices::Marshal::WriteByte System.Runtime.InteropServices.Marshal::WriteInt16(System.IntPtr,System.Int32,System.Char) mscorlib::System::Runtime::InteropServices::Marshal::WriteInt16 System.Runtime.InteropServices.Marshal::WriteInt16(System.IntPtr,System.Int32,System.Int16) mscorlib::System::Runtime::InteropServices::Marshal::WriteInt16 System.Runtime.InteropServices.Marshal::WriteInt32(System.IntPtr,System.Int32,System.Int32) mscorlib::System::Runtime::InteropServices::Marshal::WriteInt32 System.Runtime.InteropServices.Marshal::WriteInt64(System.IntPtr,System.Int32,System.Int64) mscorlib::System::Runtime::InteropServices::Marshal::WriteInt64 System.Runtime.InteropServices.Marshal::WriteIntPtr(System.IntPtr,System.Int32,System.IntPtr) mscorlib::System::Runtime::InteropServices::Marshal::WriteIntPtr System.Runtime.InteropServices.Marshal::BufferToBSTR(System.Array,System.Int32) mscorlib::System::Runtime::InteropServices::Marshal::BufferToBSTR System.Runtime.InteropServices.Marshal::GetHRForException_WinRT(System.Exception) mscorlib::System::Runtime::InteropServices::Marshal::GetHRForException_WinRT System.Runtime.InteropServices.Marshal::GetRawIUnknownForComObjectNoAddRef(System.Object) mscorlib::System::Runtime::InteropServices::Marshal::GetRawIUnknownForComObjectNoAddRef System.Runtime.InteropServices.Marshal::GetNativeActivationFactory(System.Type) mscorlib::System::Runtime::InteropServices::Marshal::GetNativeActivationFactory // System.Runtime.Remoting.Activation.ActivationServices System.Runtime.Remoting.Activation.ActivationServices::AllocateUninitializedClassInstance(System.Type) mscorlib::System::Runtime::Remoting::Activation::ActivationServices::AllocateUninitializedClassInstance System.Runtime.Remoting.Activation.ActivationServices::EnableProxyActivation(System.Type,System.Boolean) mscorlib::System::Runtime::Remoting::Activation::ActivationServices::EnableProxyActivation // System.Runtime.Remoting.Messaging.MonoMethodMessage System.Runtime.Remoting.Messaging.MonoMethodMessage::InitMessage(System.Reflection.MonoMethod,System.Object[]) mscorlib::System::Runtime::Remoting::Messaging::MonoMethodMessage::InitMessage // System.Runtime.Remoting.Proxies.RealProxy System.Runtime.Remoting.Proxies.RealProxy::InternalGetProxyType(System.Object) mscorlib::System::Runtime::Remoting::Proxies::RealProxy::InternalGetProxyType System.Runtime.Remoting.Proxies.RealProxy::InternalGetTransparentProxy(System.String) mscorlib::System::Runtime::Remoting::Proxies::RealProxy::InternalGetTransparentProxy // System.Runtime.Remoting.RemotingServices System.Runtime.Remoting.RemotingServices::GetVirtualMethod(System.Type,System.Reflection.MethodBase) mscorlib::System::Runtime::Remoting::RemotingServices::GetVirtualMethod System.Runtime.Remoting.RemotingServices::InternalExecute(System.Reflection.MethodBase,System.Object,System.Object[],System.Object[]&) mscorlib::System::Runtime::Remoting::RemotingServices::InternalExecute System.Runtime.Remoting.RemotingServices::IsTransparentProxy(System.Object) mscorlib::System::Runtime::Remoting::RemotingServices::IsTransparentProxy // System.RuntimeMethodHandle System.RuntimeMethodHandle::GetFunctionPointer(System.IntPtr) mscorlib::System::RuntimeMethodHandle::GetFunctionPointer // System.Security.Cryptography.RNGCryptoServiceProvider System.Security.Cryptography.RNGCryptoServiceProvider::RngClose(System.IntPtr) mscorlib::System::Security::Cryptography::RNGCryptoServiceProvider::RngClose System.Security.Cryptography.RNGCryptoServiceProvider::RngGetBytes(System.IntPtr,System.Byte[]) mscorlib::System::Security::Cryptography::RNGCryptoServiceProvider::RngGetBytes System.Security.Cryptography.RNGCryptoServiceProvider::RngInitialize(System.Byte[]) mscorlib::System::Security::Cryptography::RNGCryptoServiceProvider::RngInitialize System.Security.Cryptography.RNGCryptoServiceProvider::RngOpen() mscorlib::System::Security::Cryptography::RNGCryptoServiceProvider::RngOpen // System.Security.Policy.Evidence System.Security.Policy.Evidence::IsAuthenticodePresent(System.Reflection.Assembly) mscorlib::System::Security::Policy::Evidence::IsAuthenticodePresent // System.Security.Principal.WindowsIdentity System.Security.Principal.WindowsIdentity::_GetRoles(System.IntPtr) mscorlib::System::Security::Principal::WindowsIdentity::_GetRoles System.Security.Principal.WindowsIdentity::GetCurrentToken() mscorlib::System::Security::Principal::WindowsIdentity::GetCurrentToken System.Security.Principal.WindowsIdentity::GetTokenName(System.IntPtr) mscorlib::System::Security::Principal::WindowsIdentity::GetTokenName System.Security.Principal.WindowsIdentity::GetUserToken(System.String) mscorlib::System::Security::Principal::WindowsIdentity::GetUserToken // System.Security.Principal.WindowsImpersonationContext System.Security.Principal.WindowsImpersonationContext::CloseToken(System.IntPtr) mscorlib::System::Security::Principal::WindowsImpersonationContext::CloseToken System.Security.Principal.WindowsImpersonationContext::DuplicateToken(System.IntPtr) mscorlib::System::Security::Principal::WindowsImpersonationContext::DuplicateToken System.Security.Principal.WindowsImpersonationContext::RevertToSelf() mscorlib::System::Security::Principal::WindowsImpersonationContext::RevertToSelf System.Security.Principal.WindowsImpersonationContext::SetCurrentToken(System.IntPtr) mscorlib::System::Security::Principal::WindowsImpersonationContext::SetCurrentToken // System.Security.Principal.WindowsPrincipal System.Security.Principal.WindowsPrincipal::IsMemberOfGroupId(System.IntPtr,System.IntPtr) mscorlib::System::Security::Principal::WindowsPrincipal::IsMemberOfGroupId System.Security.Principal.WindowsPrincipal::IsMemberOfGroupName(System.IntPtr,System.String) mscorlib::System::Security::Principal::WindowsPrincipal::IsMemberOfGroupName // System.Security.SecurityFrame System.Security.SecurityFrame::_GetSecurityFrame(System.Int32) mscorlib::System::Security::SecurityFrame::_GetSecurityFrame System.Security.SecurityFrame::_GetSecurityStack(System.Int32) mscorlib::System::Security::SecurityFrame::_GetSecurityStack // System.Security.SecurityManager System.Security.SecurityManager::get_CheckExecutionRights() mscorlib::System::Security::SecurityManager::get_CheckExecutionRights System.Security.SecurityManager::get_SecurityEnabled() mscorlib::System::Security::SecurityManager::get_SecurityEnabled System.Security.SecurityManager::GetLinkDemandSecurity(System.Reflection.MethodBase,System.Security.RuntimeDeclSecurityActions*,System.Security.RuntimeDeclSecurityActions*) mscorlib::System::Security::SecurityManager::GetLinkDemandSecurity System.Security.SecurityManager::set_CheckExecutionRights(System.Boolean) mscorlib::System::Security::SecurityManager::set_CheckExecutionRights System.Security.SecurityManager::set_SecurityEnabled(System.Boolean) mscorlib::System::Security::SecurityManager::set_SecurityEnabled // System.String::.ctor(System.Char*) mscorlib::System::String::RedirectToCreateString System.String::.ctor(System.Char*,System.Int32,System.Int32) mscorlib::System::String::RedirectToCreateString System.String::.ctor(System.Char,System.Int32) mscorlib::System::String::RedirectToCreateString System.String::.ctor(System.Char[]) mscorlib::System::String::RedirectToCreateString System.String::.ctor(System.Char[],System.Int32,System.Int32) mscorlib::System::String::RedirectToCreateString System.String::.ctor(System.SByte*) mscorlib::System::String::RedirectToCreateString System.String::.ctor(System.SByte*,System.Int32,System.Int32) mscorlib::System::String::RedirectToCreateString System.String::.ctor(System.SByte*,System.Int32,System.Int32,System.Text.Encoding) mscorlib::System::String::RedirectToCreateString // System.String System.String::InternalAllocateStr(System.Int32) mscorlib::System::String::InternalAllocateStr System.String::InternalIntern(System.String) mscorlib::System::String::InternalIntern System.String::InternalIsInterned(System.String) mscorlib::System::String::InternalIsInterned System.String::InternalSplit(System.Char[],System.Int32,System.Int32) mscorlib::System::String::InternalSplit System.String::FastAllocateString(System.Int32) mscorlib::System::String::FastAllocateString // System.Text.Encoding System.Text.Encoding::InternalCodePage(System.Int32&) mscorlib::System::Text::Encoding::InternalCodePage // System.Threading.Interlocked System.Threading.Interlocked::Add(System.Int32&,System.Int32) mscorlib::System::Threading::Interlocked::Add System.Threading.Interlocked::Add(System.Int64&,System.Int64) mscorlib::System::Threading::Interlocked::Add64 System.Threading.Interlocked::CompareExchange(System.Double&,System.Double,System.Double) mscorlib::System::Threading::Interlocked::CompareExchangeDouble System.Threading.Interlocked::CompareExchange(System.Int32&,System.Int32,System.Int32) mscorlib::System::Threading::Interlocked::CompareExchange System.Threading.Interlocked::CompareExchange(System.Int64&,System.Int64,System.Int64) mscorlib::System::Threading::Interlocked::CompareExchange64 System.Threading.Interlocked::CompareExchange(System.IntPtr&,System.IntPtr,System.IntPtr) mscorlib::System::Threading::Interlocked::CompareExchangeIntPtr System.Threading.Interlocked::CompareExchange(System.Object&,System.Object,System.Object) mscorlib::System::Threading::Interlocked::CompareExchange_T System.Threading.Interlocked::CompareExchange(System.Single&,System.Single,System.Single) mscorlib::System::Threading::Interlocked::CompareExchangeSingle System.Threading.Interlocked::CompareExchange(T&,T,T) mscorlib::System::Threading::Interlocked::CompareExchange_T System.Threading.Interlocked::Decrement(System.Int32&) mscorlib::System::Threading::Interlocked::Decrement System.Threading.Interlocked::Decrement(System.Int64&) mscorlib::System::Threading::Interlocked::Decrement64 System.Threading.Interlocked::Exchange(T&,T,T) mscorlib::System::Threading::Interlocked::ExchangePointer System.Threading.Interlocked::Exchange(System.Double&,System.Double) mscorlib::System::Threading::Interlocked::ExchangeDouble System.Threading.Interlocked::Exchange(System.Int32&,System.Int32) mscorlib::System::Threading::Interlocked::Exchange System.Threading.Interlocked::Exchange(System.Int64&,System.Int64) mscorlib::System::Threading::Interlocked::Exchange64 System.Threading.Interlocked::Exchange(System.IntPtr&,System.IntPtr) mscorlib::System::Threading::Interlocked::ExchangeIntPtr System.Threading.Interlocked::Exchange(System.Object&,System.Object) mscorlib::System::Threading::Interlocked::ExchangePointer System.Threading.Interlocked::Exchange(System.Single&,System.Single) mscorlib::System::Threading::Interlocked::ExchangeSingle System.Threading.Interlocked::Increment(System.Int32&) mscorlib::System::Threading::Interlocked::Increment System.Threading.Interlocked::Increment(System.Int64&) mscorlib::System::Threading::Interlocked::Increment64 System.Threading.Interlocked::Read(System.Int64&) mscorlib::System::Threading::Interlocked::Read System.Threading.Interlocked::CompareExchange(System.Int32&,System.Int32,System.Int32,System.Boolean&) mscorlib::System::Threading::Interlocked::CompareExchange // System.Threading.Monitor System.Threading.Monitor::Enter(System.Object) mscorlib::System::Threading::Monitor::Enter System.Threading.Monitor::Exit(System.Object) mscorlib::System::Threading::Monitor::Exit System.Threading.Monitor::Monitor_pulse(System.Object) mscorlib::System::Threading::Monitor::Monitor_pulse System.Threading.Monitor::Monitor_pulse_all(System.Object) mscorlib::System::Threading::Monitor::Monitor_pulse_all System.Threading.Monitor::Monitor_test_synchronised(System.Object) mscorlib::System::Threading::Monitor::Monitor_test_synchronised System.Threading.Monitor::Monitor_try_enter(System.Object,System.Int32) mscorlib::System::Threading::Monitor::Monitor_try_enter System.Threading.Monitor::Monitor_wait(System.Object,System.Int32) mscorlib::System::Threading::Monitor::Monitor_wait System.Threading.Monitor::Monitor_test_owner(System.Object) mscorlib::System::Threading::Monitor::Monitor_test_owner System.Threading.Monitor::enter_with_atomic_var(System.Object,System.Boolean&) mscorlib::System::Threading::Monitor::enter_with_atomic_var System.Threading.Monitor::try_enter_with_atomic_var(System.Object,System.Int32,System.Boolean&) mscorlib::System::Threading::Monitor::try_enter_with_atomic_var // System.Threading.Mutex System.Threading.Mutex::CreateMutex_internal(System.Boolean,System.String,System.Boolean&) mscorlib::System::Threading::Mutex::CreateMutex_internal System.Threading.Mutex::OpenMutex_internal(System.String,System.Security.AccessControl.MutexRights,System.IO.MonoIOError&) mscorlib::System::Threading::Mutex::OpenMutex_internal System.Threading.Mutex::ReleaseMutex_internal(System.IntPtr) mscorlib::System::Threading::Mutex::ReleaseMutex_internal // System.Threading.NativeEventCalls System.Threading.NativeEventCalls::CloseEvent_internal(System.IntPtr) mscorlib::System::Threading::NativeEventCalls::CloseEvent_internal System.Threading.NativeEventCalls::CreateEvent_internal(System.Boolean,System.Boolean,System.String,System.Boolean&) mscorlib::System::Threading::NativeEventCalls::CreateEvent_internal System.Threading.NativeEventCalls::CreateEvent_internal(System.Boolean,System.Boolean,System.String,System.Int32&) mscorlib::System::Threading::NativeEventCalls::CreateEvent_internal System.Threading.NativeEventCalls::OpenEvent_internal(System.String,System.Security.AccessControl.EventWaitHandleRights,System.IO.MonoIOError&) mscorlib::System::Threading::NativeEventCalls::OpenEvent_internal System.Threading.NativeEventCalls::OpenEvent_internal(System.String,System.Security.AccessControl.EventWaitHandleRights,System.Int32&) mscorlib::System::Threading::NativeEventCalls::OpenEvent_internal System.Threading.NativeEventCalls::ResetEvent_internal(System.IntPtr) mscorlib::System::Threading::NativeEventCalls::ResetEvent_internal System.Threading.NativeEventCalls::SetEvent_internal(System.IntPtr) mscorlib::System::Threading::NativeEventCalls::SetEvent_internal // System.Threading.Semaphore System.Threading.Semaphore::CreateSemaphore_internal(System.Int32,System.Int32,System.String,System.Boolean&) System::System::Threading::Semaphore::CreateSemaphore_internal System.Threading.Semaphore::OpenSemaphore_internal(System.String,System.Security.AccessControl.SemaphoreRights,System.IO.MonoIOError&) System::System::Threading::Semaphore::OpenSemaphore_internal System.Threading.Semaphore::ReleaseSemaphore_internal(System.IntPtr,System.Int32,System.Boolean&) System::System::Threading::Semaphore::ReleaseSemaphore_internal System.Threading.Semaphore::CreateSemaphore_internal(System.Int32,System.Int32,System.String,System.Int32&) System::System::Threading::Semaphore::CreateSemaphore_internal40 System.Threading.Semaphore::ReleaseSemaphore_internal(System.IntPtr,System.Int32,System.Int32&) System::System::Threading::Semaphore::ReleaseSemaphore_internal40 // System.Threading.Thread System.Threading.Thread::Abort_internal(System.Object) mscorlib::System::Threading::Thread::Abort_internal System.Threading.Thread::ClrState(System.Threading.ThreadState) mscorlib::System::Threading::Thread::ClrState System.Threading.Thread::CurrentThread_internal() mscorlib::System::Threading::Thread::CurrentThread_internal System.Threading.Thread::FreeLocalSlotValues(System.Int32,System.Boolean) mscorlib::System::Threading::Thread::FreeLocalSlotValues System.Threading.Thread::GetAbortExceptionState() mscorlib::System::Threading::Thread::GetAbortExceptionState System.Threading.Thread::GetCachedCurrentCulture() mscorlib::System::Threading::Thread::GetCachedCurrentCulture System.Threading.Thread::GetCachedCurrentUICulture() mscorlib::System::Threading::Thread::GetCachedCurrentUICulture System.Threading.Thread::GetDomainID() mscorlib::System::Threading::Thread::GetDomainID System.Threading.Thread::GetName_internal() mscorlib::System::Threading::Thread::GetName_internal System.Threading.Thread::GetNewManagedId_internal() mscorlib::System::Threading::Thread::GetNewManagedId_internal System.Threading.Thread::GetSerializedCurrentCulture() mscorlib::System::Threading::Thread::GetSerializedCurrentCulture System.Threading.Thread::GetSerializedCurrentUICulture() mscorlib::System::Threading::Thread::GetSerializedCurrentUICulture System.Threading.Thread::GetState() mscorlib::System::Threading::Thread::GetState System.Threading.Thread::Interrupt_internal() mscorlib::System::Threading::Thread::Interrupt_internal System.Threading.Thread::Join_internal(System.Int32,System.IntPtr) mscorlib::System::Threading::Thread::Join_internal System.Threading.Thread::MemoryBarrier() mscorlib::System::Threading::Thread::MemoryBarrier_ System.Threading.Thread::ResetAbort_internal() mscorlib::System::Threading::Thread::ResetAbort_internal System.Threading.Thread::Resume_internal() mscorlib::System::Threading::Thread::Resume_internal System.Threading.Thread::SetCachedCurrentCulture(System.Globalization.CultureInfo) mscorlib::System::Threading::Thread::SetCachedCurrentCulture System.Threading.Thread::SetCachedCurrentUICulture(System.Globalization.CultureInfo) mscorlib::System::Threading::Thread::SetCachedCurrentUICulture System.Threading.Thread::SetName_internal(System.String) mscorlib::System::Threading::Thread::SetName_internal System.Threading.Thread::SetSerializedCurrentCulture(System.Byte[]) mscorlib::System::Threading::Thread::SetSerializedCurrentCulture System.Threading.Thread::SetSerializedCurrentUICulture(System.Byte[]) mscorlib::System::Threading::Thread::SetSerializedCurrentUICulture System.Threading.Thread::SetState(System.Threading.ThreadState) mscorlib::System::Threading::Thread::SetState System.Threading.Thread::Sleep_internal(System.Int32) mscorlib::System::Threading::Thread::Sleep_internal System.Threading.Thread::SpinWait_nop() mscorlib::System::Threading::Thread::SpinWait_nop System.Threading.Thread::Suspend_internal() mscorlib::System::Threading::Thread::Suspend_internal System.Threading.Thread::Thread_free_internal(System.IntPtr) mscorlib::System::Threading::Thread::Thread_free_internal System.Threading.Thread::Thread_init() mscorlib::System::Threading::Thread::Thread_init System.Threading.Thread::Thread_internal(System.MulticastDelegate) mscorlib::System::Threading::Thread::Thread_internal System.Threading.Thread::VolatileRead(System.Byte&) mscorlib::System::Threading::Thread::VolatileReadInt8 System.Threading.Thread::VolatileRead(System.Double&) mscorlib::System::Threading::Thread::VolatileReadDouble System.Threading.Thread::VolatileRead(System.Int16&) mscorlib::System::Threading::Thread::VolatileReadInt16 System.Threading.Thread::VolatileRead(System.Int32&) mscorlib::System::Threading::Thread::VolatileReadInt32 System.Threading.Thread::VolatileRead(System.Int64&) mscorlib::System::Threading::Thread::VolatileReadInt64 System.Threading.Thread::VolatileRead(System.IntPtr&) mscorlib::System::Threading::Thread::VolatileReadIntPtr System.Threading.Thread::VolatileRead(System.Object&) mscorlib::System::Threading::Thread::VolatileReadPtr System.Threading.Thread::VolatileRead(System.SByte&) mscorlib::System::Threading::Thread::VolatileReadInt8 System.Threading.Thread::VolatileRead(System.Single&) mscorlib::System::Threading::Thread::VolatileReadFloat System.Threading.Thread::VolatileRead(System.UInt16&) mscorlib::System::Threading::Thread::VolatileReadInt16 System.Threading.Thread::VolatileRead(System.UInt32&) mscorlib::System::Threading::Thread::VolatileReadInt32 System.Threading.Thread::VolatileRead(System.UInt64&) mscorlib::System::Threading::Thread::VolatileReadInt64 System.Threading.Thread::VolatileRead(System.UIntPtr&) mscorlib::System::Threading::Thread::VolatileReadIntPtr System.Threading.Thread::VolatileWrite(System.Byte&,System.Byte) mscorlib::System::Threading::Thread::VolatileWriteInt8 System.Threading.Thread::VolatileWrite(System.Double&,System.Double) mscorlib::System::Threading::Thread::VolatileWriteDouble System.Threading.Thread::VolatileWrite(System.Int16&,System.Int16) mscorlib::System::Threading::Thread::VolatileWriteInt16 System.Threading.Thread::VolatileWrite(System.Int32&,System.Int32) mscorlib::System::Threading::Thread::VolatileWriteInt32 System.Threading.Thread::VolatileWrite(System.Int64&,System.Int64) mscorlib::System::Threading::Thread::VolatileWriteInt64 System.Threading.Thread::VolatileWrite(System.IntPtr&,System.IntPtr) mscorlib::System::Threading::Thread::VolatileWriteIntPtr System.Threading.Thread::VolatileWrite(System.Object&,System.Object) mscorlib::System::Threading::Thread::VolatileWritePtr System.Threading.Thread::VolatileWrite(System.SByte&,System.SByte) mscorlib::System::Threading::Thread::VolatileWriteInt8 System.Threading.Thread::VolatileWrite(System.Single&,System.Single) mscorlib::System::Threading::Thread::VolatileWriteFloat System.Threading.Thread::VolatileWrite(System.UInt16&,System.UInt16) mscorlib::System::Threading::Thread::VolatileWriteInt16 System.Threading.Thread::VolatileWrite(System.UInt32&,System.UInt32) mscorlib::System::Threading::Thread::VolatileWriteInt32 System.Threading.Thread::VolatileWrite(System.UInt64&,System.UInt64) mscorlib::System::Threading::Thread::VolatileWriteInt64 System.Threading.Thread::VolatileWrite(System.UIntPtr&,System.UIntPtr) mscorlib::System::Threading::Thread::VolatileWriteIntPtr System.Threading.Thread::ByteArrayToCurrentDomain(System.Byte[]) mscorlib::System::Threading::Thread::ByteArrayToCurrentDomain System.Threading.Thread::ByteArrayToRootDomain(System.Byte[]) mscorlib::System::Threading::Thread::ByteArrayToRootDomain System.Threading.Thread::YieldInternal() mscorlib::System::Threading::Thread::YieldInternal System.Threading.Thread::JoinInternal(System.Int32) mscorlib::System::Threading::Thread::JoinInternal System.Threading.Thread::GetPriorityNative() mscorlib::System::Threading::Thread::GetPriorityNative System.Threading.Thread::SystemMaxStackStize() mscorlib::System::Threading::Thread::SystemMaxStackStize System.Threading.Thread::GetName_internal(System.Threading.InternalThread) mscorlib::System::Threading::Thread::GetName_internal40 System.Threading.Thread::CurrentInternalThread_internal() mscorlib::System::Threading::Thread::CurrentInternalThread_internal System.Threading.Thread::GetState(System.Threading.InternalThread) mscorlib::System::Threading::Thread::GetState40 System.Threading.Thread::Abort_internal(System.Threading.InternalThread,System.Object) mscorlib::System::Threading::Thread::Abort_internal40 System.Threading.Thread::ClrState(System.Threading.InternalThread,System.Threading.ThreadState) mscorlib::System::Threading::Thread::ClrState40 System.Threading.Thread::ConstructInternalThread() mscorlib::System::Threading::Thread::ConstructInternalThread System.Threading.Thread::GetStackTraces(System.Threading.Thread[]&,System.Object[]&) mscorlib::System::Threading::Thread::GetStackTraces System.Threading.Thread::InterruptInternal() mscorlib::System::Threading::Thread::InterruptInternal System.Threading.Thread::ResetAbortNative() mscorlib::System::Threading::Thread::ResetAbortNative System.Threading.Thread::ResumeInternal() mscorlib::System::Threading::Thread::ResumeInternal System.Threading.Thread::SetName_internal(System.Threading.InternalThread,System.String) mscorlib::System::Threading::Thread::SetName_internal40 System.Threading.Thread::SetPriorityNative(System.Int32) mscorlib::System::Threading::Thread::SetPriorityNative System.Threading.Thread::SetState(System.Threading.InternalThread,System.Threading.ThreadState) mscorlib::System::Threading::Thread::SetState40 System.Threading.Thread::SleepInternal(System.Int32) mscorlib::System::Threading::Thread::SleepInternal System.Threading.Thread::SuspendInternal() mscorlib::System::Threading::Thread::SuspendInternal // System.Threading.ThreadPool System.Threading.ThreadPool::GetAvailableThreads(System.Int32&,System.Int32&) mscorlib::System::Threading::ThreadPool::GetAvailableThreads System.Threading.ThreadPool::GetMaxThreads(System.Int32&,System.Int32&) mscorlib::System::Threading::ThreadPool::GetMaxThreads System.Threading.ThreadPool::GetMinThreads(System.Int32&,System.Int32&) mscorlib::System::Threading::ThreadPool::GetMinThreads System.Threading.ThreadPool::SetMaxThreads(System.Int32,System.Int32) mscorlib::System::Threading::ThreadPool::SetMaxThreads System.Threading.ThreadPool::SetMinThreads(System.Int32,System.Int32) mscorlib::System::Threading::ThreadPool::SetMinThreads System.Threading.ThreadPool::BindIOCompletionCallbackNative(System.IntPtr) ves_icall_System_Threading_ThreadPool_BindIOCompletionCallbackNative System.Threading.ThreadPool::IsThreadPoolHosted() ves_icall_System_Threading_ThreadPool_IsThreadPoolHosted System.Threading.ThreadPool::NotifyWorkItemComplete() ves_icall_System_Threading_ThreadPool_NotifyWorkItemComplete System.Threading.ThreadPool::PostQueuedCompletionStatus(System.Threading.NativeOverlapped*) ves_icall_System_Threading_ThreadPool_PostQueuedCompletionStatus System.Threading.ThreadPool::RequestWorkerThread() ves_icall_System_Threading_ThreadPool_RequestWorkerThread System.Threading.ThreadPool::SetMaxThreadsNative(System.Int32,System.Int32) ves_icall_System_Threading_ThreadPool_SetMaxThreadsNative System.Threading.ThreadPool::SetMinThreadsNative(System.Int32,System.Int32) ves_icall_System_Threading_ThreadPool_SetMinThreadsNative System.Threading.ThreadPool::GetAvailableThreadsNative(System.Int32&,System.Int32&) ves_icall_System_Threading_ThreadPool_GetAvailableThreadsNative System.Threading.ThreadPool::GetMaxThreadsNative(System.Int32&,System.Int32&) ves_icall_System_Threading_ThreadPool_GetMaxThreadsNative System.Threading.ThreadPool::GetMinThreadsNative(System.Int32&,System.Int32&) ves_icall_System_Threading_ThreadPool_GetMinThreadsNative System.Threading.ThreadPool::InitializeVMTp(System.Boolean&) ves_icall_System_Threading_ThreadPool_InitializeVMTp System.Threading.ThreadPool::NotifyWorkItemProgressNative() ves_icall_System_Threading_ThreadPool_NotifyWorkItemProgressNative System.Threading.ThreadPool::ReportThreadStatus(System.Boolean) ves_icall_System_Threading_ThreadPool_ReportThreadStatus // System.Threading.WaitHandle System.Threading.WaitHandle::SignalAndWait_Internal(System.IntPtr,System.IntPtr,System.Int32,System.Boolean) mscorlib::System::Threading::WaitHandle::SignalAndWait_Internal System.Threading.WaitHandle::WaitAll_internal(System.Threading.WaitHandle[],System.Int32,System.Boolean) mscorlib::System::Threading::WaitHandle::WaitAll_internal System.Threading.WaitHandle::WaitAny_internal(System.Threading.WaitHandle[],System.Int32,System.Boolean) mscorlib::System::Threading::WaitHandle::WaitAny_internal System.Threading.WaitHandle::WaitOne_internal(System.IntPtr,System.Int32,System.Boolean) mscorlib::System::Threading::WaitHandle::WaitOne_internal System.Threading.WaitHandle::SignalAndWait_Internal(System.IntPtr,System.IntPtr,System.Int32) mscorlib::System::Threading::WaitHandle::SignalAndWait_Internal40 System.Threading.WaitHandle::WaitAll_internal(System.Threading.WaitHandle[],System.Int32) mscorlib::System::Threading::WaitHandle::WaitAll_internal40 System.Threading.WaitHandle::WaitAny_internal(System.Threading.WaitHandle[],System.Int32) mscorlib::System::Threading::WaitHandle::WaitAny_internal40 System.Threading.WaitHandle::WaitOne_internal(System.IntPtr,System.Int32) mscorlib::System::Threading::WaitHandle::WaitOne_internal40 // System.Type System.Type::EqualsInternal(System.Type) mscorlib::System::Type::EqualsInternal System.Type::get_IsGenericType() mscorlib::System::Type::get_IsGenericType System.Type::get_IsGenericTypeDefinition() mscorlib::System::Type::get_IsGenericTypeDefinition System.Type::GetGenericParameterAttributes() mscorlib::System::Type::GetGenericParameterAttributes System.Type::GetGenericParameterConstraints_impl() mscorlib::System::Type::GetGenericParameterConstraints_impl System.Type::GetGenericParameterPosition() mscorlib::System::Type::GetGenericParameterPosition System.Type::GetGenericTypeDefinition_impl() mscorlib::System::Type::GetGenericTypeDefinition_impl System.Type::GetInterfaceMapData(System.Type,System.Type,System.Reflection.MethodInfo[]&,System.Reflection.MethodInfo[]&) mscorlib::System::Type::GetInterfaceMapData System.Type::GetPacking(System.Int32&,System.Int32&) mscorlib::System::Type::GetPacking System.Type::GetTypeCodeInternal(System.Type) mscorlib::System::Type::GetTypeCodeInternal System.Type::internal_from_handle(System.IntPtr) mscorlib::System::Type::internal_from_handle System.Type::internal_from_name(System.String,System.Boolean,System.Boolean) mscorlib::System::Type::internal_from_name System.Type::IsArrayImpl(System.Type) mscorlib::System::Type::IsArrayImpl System.Type::IsInstanceOfType(System.Object) mscorlib::System::Type::IsInstanceOfType System.Type::make_array_type(System.Int32) mscorlib::System::Type::make_array_type System.Type::make_byref_type() mscorlib::System::Type::make_byref_type System.Type::MakeGenericType(System.Type,System.Type[]) mscorlib::System::Type::MakeGenericType System.Type::MakePointerType() mscorlib::System::Type::MakePointerType System.Type::type_is_assignable_from(System.Type,System.Type) mscorlib::System::Type::type_is_assignable_from System.Type::type_is_subtype_of(System.Type,System.Type,System.Boolean) mscorlib::System::Type::type_is_subtype_of // System.TypedReference System.TypedReference::ToObject(System.TypedReference) mscorlib::System::TypedReference::ToObject System.TypedReference::InternalToObject(System.Void*) mscorlib::System::TypedReference::InternalToObject System.TypedReference::MakeTypedReferenceInternal(System.Object,System.Reflection.FieldInfo[]) mscorlib::System::TypedReference::MakeTypedReferenceInternal // System.ValueType System.ValueType::InternalEquals(System.Object,System.Object,System.Object[]&) mscorlib::System::ValueType::InternalEquals System.ValueType::InternalGetHashCode(System.Object,System.Object[]&) mscorlib::System::ValueType::InternalGetHashCode // System.CLRConfig System.CLRConfig::CheckThrowUnobservedTaskExceptions() mscorlib::System::CLRConfig::CheckThrowUnobservedTaskExceptions // System.Exception System.Exception::nIsTransient(System.Int32) mscorlib::System::Exception::nIsTransient System.Exception::GetMethodFromStackTrace(System.Object) mscorlib::System::Exception::GetMethodFromStackTrace // System.Number System.Number::NumberBufferToDecimal(System.Byte*,System.Decimal&) mscorlib::System::Number::NumberBufferToDecimal System.Number::NumberBufferToDouble(System.Byte*,System.Double&) mscorlib::System::Number::NumberBufferToDouble // System.RuntimeType System.RuntimeType::IsTypeExportedToWindowsRuntime(System.RuntimeType) mscorlib::System::RuntimeType::IsTypeExportedToWindowsRuntime System.RuntimeType::IsWindowsRuntimeObjectType(System.RuntimeType) mscorlib::System::RuntimeType::IsWindowsRuntimeObjectType System.RuntimeType::get_core_clr_security_level() mscorlib::System::RuntimeType::get_core_clr_security_level System.RuntimeType::GetGenericParameterPosition() mscorlib::System::RuntimeType::GetGenericParameterPosition System.RuntimeType::CreateInstanceInternal(System.Type) mscorlib::System::RuntimeType::CreateInstanceInternal System.RuntimeType::GetGenericParameterAttributes() mscorlib::System::RuntimeType::GetGenericParameterAttributes System.RuntimeType::get_DeclaringMethod() mscorlib::System::RuntimeType::get_DeclaringMethod System.RuntimeType::GetConstructors_internal(System.Reflection.BindingFlags,System.Type) mscorlib::System::RuntimeType::GetConstructors_internal System.RuntimeType::GetEvents_internal(System.String,System.Reflection.BindingFlags,System.Type) mscorlib::System::RuntimeType::GetEvents_internal System.RuntimeType::GetFields_internal(System.String,System.Reflection.BindingFlags,System.Type) mscorlib::System::RuntimeType::GetFields_internal System.RuntimeType::GetMethodsByName(System.String,System.Reflection.BindingFlags,System.Boolean,System.Type) mscorlib::System::RuntimeType::GetMethodsByName System.RuntimeType::GetPropertiesByName(System.String,System.Reflection.BindingFlags,System.Boolean,System.Type) mscorlib::System::RuntimeType::GetPropertiesByName System.RuntimeType::GetNestedTypes_internal(System.String,System.Reflection.BindingFlags) mscorlib::System::RuntimeType::GetNestedTypes_internal System.RuntimeType::get_Name() mscorlib::System::RuntimeType::get_Name System.RuntimeType::get_Namespace() mscorlib::System::RuntimeType::get_Namespace System.RuntimeType::getFullName(System.Boolean,System.Boolean) mscorlib::System::RuntimeType::getFullName System.RuntimeType::get_DeclaringType() mscorlib::System::RuntimeType::get_DeclaringType System.RuntimeType::make_array_type(System.Int32) mscorlib::System::RuntimeType::make_array_type System.RuntimeType::make_byref_type() mscorlib::System::RuntimeType::make_byref_type System.RuntimeType::MakeGenericType(System.Type,System.Type[]) mscorlib::System::RuntimeType::MakeGenericType System.RuntimeType::MakePointerType(System.Type) mscorlib::System::RuntimeType::MakePointerType System.RuntimeType::GetGenericArgumentsInternal(System.Boolean) mscorlib::System::RuntimeType::GetGenericArgumentsInternal System.RuntimeType::GetGenericParameterConstraints_impl() mscorlib::System::RuntimeType::GetGenericParameterConstraints_impl System.RuntimeType::GetInterfaces() mscorlib::System::RuntimeType::GetInterfaces System.RuntimeType::GetTypeCodeImplInternal(System.Type) mscorlib::System::RuntimeType::GetTypeCodeImplInternal System.RuntimeType::GetInterfaceMapData(System.Type,System.Type,System.Reflection.MethodInfo[]&,System.Reflection.MethodInfo[]&) mscorlib::System::RuntimeType::GetInterfaceMapData System.RuntimeType::GetPacking(System.Int32&,System.Int32&) mscorlib::System::RuntimeType::GetPacking System.RuntimeType::GetConstructors_native(System.Reflection.BindingFlags) mscorlib::System::RuntimeType::GetConstructors_native System.RuntimeType::GetEvents_native(System.IntPtr,System.Reflection.BindingFlags) mscorlib::System::RuntimeType::GetEvents_native System.RuntimeType::GetFields_native(System.IntPtr,System.Reflection.BindingFlags) mscorlib::System::RuntimeType::GetFields_native System.RuntimeType::GetMethodsByName_native(System.IntPtr,System.Reflection.BindingFlags,System.Boolean) mscorlib::System::RuntimeType::GetMethodsByName_native System.RuntimeType::GetNestedTypes_native(System.IntPtr,System.Reflection.BindingFlags) mscorlib::System::RuntimeType::GetNestedTypes_native System.RuntimeType::GetPropertiesByName_native(System.IntPtr,System.Reflection.BindingFlags,System.Boolean) mscorlib::System::RuntimeType::GetPropertiesByName_native // System.RuntimeTypeHandle System.RuntimeTypeHandle::HasInstantiation(System.RuntimeType) mscorlib::System::RuntimeTypeHandle::HasInstantiation System.RuntimeTypeHandle::IsArray(System.RuntimeType) mscorlib::System::RuntimeTypeHandle::IsArray System.RuntimeTypeHandle::IsByRef(System.RuntimeType) mscorlib::System::RuntimeTypeHandle::IsByRef System.RuntimeTypeHandle::IsComObject(System.RuntimeType) mscorlib::System::RuntimeTypeHandle::IsComObject System.RuntimeTypeHandle::IsGenericTypeDefinition(System.RuntimeType) mscorlib::System::RuntimeTypeHandle::IsGenericTypeDefinition System.RuntimeTypeHandle::IsGenericVariable(System.RuntimeType) mscorlib::System::RuntimeTypeHandle::IsGenericVariable System.RuntimeTypeHandle::IsInstanceOfType(System.RuntimeType,System.Object) mscorlib::System::RuntimeTypeHandle::IsInstanceOfType System.RuntimeTypeHandle::IsPointer(System.RuntimeType) mscorlib::System::RuntimeTypeHandle::IsPointer System.RuntimeTypeHandle::IsPrimitive(System.RuntimeType) mscorlib::System::RuntimeTypeHandle::IsPrimitive System.RuntimeTypeHandle::type_is_assignable_from(System.Type,System.Type) mscorlib::System::RuntimeTypeHandle::type_is_assignable_from System.RuntimeTypeHandle::GetArrayRank(System.RuntimeType) mscorlib::System::RuntimeTypeHandle::GetArrayRank System.RuntimeTypeHandle::GetMetadataToken(System.RuntimeType) mscorlib::System::RuntimeTypeHandle::GetMetadataToken System.RuntimeTypeHandle::GetAssembly(System.RuntimeType) mscorlib::System::RuntimeTypeHandle::GetAssembly System.RuntimeTypeHandle::GetModule(System.RuntimeType) mscorlib::System::RuntimeTypeHandle::GetModule System.RuntimeTypeHandle::GetAttributes(System.RuntimeType) mscorlib::System::RuntimeTypeHandle::GetAttributes System.RuntimeTypeHandle::GetBaseType(System.RuntimeType) mscorlib::System::RuntimeTypeHandle::GetBaseType System.RuntimeTypeHandle::GetElementType(System.RuntimeType) mscorlib::System::RuntimeTypeHandle::GetElementType System.RuntimeTypeHandle::GetGenericTypeDefinition_impl(System.RuntimeType) mscorlib::System::RuntimeTypeHandle::GetGenericTypeDefinition_impl System.RuntimeTypeHandle::GetGenericParameterInfo(System.RuntimeType) mscorlib::System::RuntimeTypeHandle::GetGenericParameterInfo // System.TimeSpan System.TimeSpan::LegacyFormatMode() mscorlib::System::TimeSpan::LegacyFormatMode // System.MissingMemberException System.MissingMemberException::FormatSignature(System.Byte[]) mscorlib::System::MissingMemberException::FormatSignature // System.IOSelector System.IOSelector::Add(System.IntPtr,System.IOSelectorJob) ves_icall_System_IOSelector_Add System.IOSelector::Remove(System.IntPtr) ves_icall_System_IOSelector_Remove // System.RuntimeFieldHandle System.RuntimeFieldHandle::SetValueDirect(System.Reflection.RtFieldInfo,System.RuntimeType,System.Void*,System.Object,System.RuntimeType) mscorlib::System::RuntimeFieldHandle::SetValueDirect System.RuntimeFieldHandle::SetValueInternal(System.Reflection.FieldInfo,System.Object,System.Object) mscorlib::System::RuntimeFieldHandle::SetValueInternal // System.Threading.Volatile System.Threading.Volatile::Read(System.Byte&) mscorlib::System::Threading::Volatile::Read System.Threading.Volatile::Read(System.Boolean&) mscorlib::System::Threading::Volatile::Read System.Threading.Volatile::Read(System.Double&) mscorlib::System::Threading::Volatile::Read System.Threading.Volatile::Read(System.Int16&) mscorlib::System::Threading::Volatile::Read System.Threading.Volatile::Read(System.Int32&) mscorlib::System::Threading::Volatile::Read System.Threading.Volatile::Read(System.Int64&) mscorlib::System::Threading::Volatile::Read System.Threading.Volatile::Read(System.IntPtr&) mscorlib::System::Threading::Volatile::Read System.Threading.Volatile::Read(System.SByte&) mscorlib::System::Threading::Volatile::Read System.Threading.Volatile::Read(System.Single&) mscorlib::System::Threading::Volatile::Read System.Threading.Volatile::Read(System.UInt16&) mscorlib::System::Threading::Volatile::Read System.Threading.Volatile::Read(System.UInt32&) mscorlib::System::Threading::Volatile::Read System.Threading.Volatile::Read(System.UInt64&) mscorlib::System::Threading::Volatile::Read System.Threading.Volatile::Read(System.UIntPtr&) mscorlib::System::Threading::Volatile::Read // System.Threading.Timer System.Threading.Timer::GetTimeMonotonic() mscorlib::System::Threading::Timer::GetTimeMonotonic // System.Threading.InternalThread System.Threading.InternalThread::Thread_free_internal(System.IntPtr) mscorlib::System::Threading::InternalThread::Thread_free_internal // System.Diagnostics.Assert System.Diagnostics.Assert::ShowDefaultAssertDialog(System.String,System.String,System.String,System.String) mscorlib::System::Diagnostics::Assert::ShowDefaultAssertDialog // System.Globalization.CalendarData System.Globalization.CalendarData::fill_calendar_data(System.String,System.Int32) mscorlib::System::Globalization::CalendarData::fill_calendar_data // System.Globalization.CultureData System.Globalization.CultureData::fill_culture_data(System.Int32) mscorlib::System::Globalization::CultureData::fill_culture_data System.Globalization.CultureData::fill_number_data(System.Globalization.NumberFormatInfo,System.Int32) mscorlib::System::Globalization::CultureData::fill_number_data // System.IO.KqueueMonitor System.IO.KqueueMonitor::kevent_notimeout(System.Int32&,System.IntPtr,System.Int32,System.IntPtr,System.Int32) System::System::IO::KqueueMonitor::kevent_notimeout // System.Reflection.Emit.SymbolType System.Reflection.Emit.SymbolType::create_unmanaged_type(System.Type) mscorlib::System::Reflection::Emit::SymbolType::create_unmanaged_type // System.Reflection.RtFieldInfo System.Reflection.RtFieldInfo::UnsafeGetValue(System.Object) mscorlib::System::Reflection::RtFieldInfo::UnsafeGetValue // System.Reflection.CustomAttributeData System.Reflection.CustomAttributeData::ResolveArgumentsInternal(System.Reflection.ConstructorInfo,System.Reflection.Assembly,System.IntPtr,System.UInt32,System.Object[]&,System.Object[]&) mscorlib::System::Reflection::CustomAttributeData::ResolveArgumentsInternal // System.Runtime.Versioning.VersioningHelper System.Runtime.Versioning.VersioningHelper::GetRuntimeId() mscorlib::System::Runtime::Versioning::VersioningHelper::GetRuntimeId // System.Runtime.Remoting.Messaging.AsyncResult System.Runtime.Remoting.Messaging.AsyncResult::Invoke() mscorlib::System::Runtime::Remoting::Messaging::AsyncResult::Invoke // System.Text.EncodingHelper System.Text.EncodingHelper::InternalCodePage(System.Int32&) mscorlib::System::Text::EncodingHelper::InternalCodePage // System.Text.Normalization System.Text.Normalization::load_normalization_resource(System.IntPtr&,System.IntPtr&,System.IntPtr&,System.IntPtr&,System.IntPtr&,System.IntPtr&) mscorlib::System::Text::Normalization::load_normalization_resource // System.Runtime.Remoting.Contexts.Context System.Runtime.Remoting.Contexts.Context::RegisterContext(System.Runtime.Remoting.Contexts.Context) mscorlib::System::Runtime::Remoting::Contexts::Context::RegisterContext System.Runtime.Remoting.Contexts.Context::ReleaseContext(System.Runtime.Remoting.Contexts.Context) mscorlib::System::Runtime::Remoting::Contexts::Context::ReleaseContext // Microsoft.Win32.NativeMethods Microsoft.Win32.NativeMethods::CloseProcess(System.IntPtr) System::Microsoft::Win32::NativeMethods::CloseProcess Microsoft.Win32.NativeMethods::GetExitCodeProcess(System.IntPtr,System.Int32&) System::Microsoft::Win32::NativeMethods::GetExitCodeProcess Microsoft.Win32.NativeMethods::GetProcessTimes(System.IntPtr,System.Int64&,System.Int64&,System.Int64&,System.Int64&) System::Microsoft::Win32::NativeMethods::GetProcessTimes Microsoft.Win32.NativeMethods::GetProcessWorkingSetSize(System.IntPtr,System.IntPtr&,System.IntPtr&) System::Microsoft::Win32::NativeMethods::GetProcessWorkingSetSize Microsoft.Win32.NativeMethods::SetPriorityClass(System.IntPtr,System.Int32) System::Microsoft::Win32::NativeMethods::SetPriorityClass Microsoft.Win32.NativeMethods::SetProcessWorkingSetSize(System.IntPtr,System.IntPtr,System.IntPtr) System::Microsoft::Win32::NativeMethods::SetProcessWorkingSetSize Microsoft.Win32.NativeMethods::TerminateProcess(System.IntPtr,System.Int32) System::Microsoft::Win32::NativeMethods::TerminateProcess Microsoft.Win32.NativeMethods::GetPriorityClass(System.IntPtr) System::Microsoft::Win32::NativeMethods::GetPriorityClass Microsoft.Win32.NativeMethods::WaitForInputIdle(System.IntPtr,System.Int32) System::Microsoft::Win32::NativeMethods::WaitForInputIdle Microsoft.Win32.NativeMethods::GetCurrentProcess() System::Microsoft::Win32::NativeMethods::GetCurrentProcess Microsoft.Win32.NativeMethods::GetCurrentProcessId() System::Microsoft::Win32::NativeMethods::GetCurrentProcessId // System.Net.NetworkInformation.MacOsIPInterfaceProperties System.Net.NetworkInformation.MacOsIPInterfaceProperties::ParseRouteInfo_internal(System.String,System.String[]&) System::System::Net::NetworkInformation::MacOsIPInterfaceProperties::ParseRouteInfo_internal // System.Net.Sockets.Socket System.Net.Sockets.Socket::SendFile_internal(System.IntPtr,System.String,System.Byte[],System.Byte[],System.Net.Sockets.TransmitFileOptions) System::System::Net::Sockets::Socket::SendFile_internal System.Net.Sockets.Socket::SupportsPortReuse(System.Net.Sockets.ProtocolType) System::System::Net::Sockets::Socket::SupportsPortReuse System.Net.Sockets.Socket::IOControl_internal(System.IntPtr,System.Int32,System.Byte[],System.Byte[],System.Int32&) System::System::Net::Sockets::Socket::IOControl_internal System.Net.Sockets.Socket::ReceiveFrom_internal(System.IntPtr,System.Byte[],System.Int32,System.Int32,System.Net.Sockets.SocketFlags,System.Net.SocketAddress&,System.Int32&) System::System::Net::Sockets::Socket::ReceiveFrom_internal System.Net.Sockets.Socket::SendTo_internal(System.IntPtr,System.Byte[],System.Int32,System.Int32,System.Net.Sockets.SocketFlags,System.Net.SocketAddress,System.Int32&) System::System::Net::Sockets::Socket::SendTo_internal System.Net.Sockets.Socket::LocalEndPoint_internal(System.IntPtr,System.Int32,System.Int32&) System::System::Net::Sockets::Socket::LocalEndPoint_internal System.Net.Sockets.Socket::RemoteEndPoint_internal(System.IntPtr,System.Int32,System.Int32&) System::System::Net::Sockets::Socket::RemoteEndPoint_internal System.Net.Sockets.Socket::cancel_blocking_socket_operation(System.Threading.Thread) System::System::Net::Sockets::Socket::cancel_blocking_socket_operation System.Net.Sockets.Socket::Connect_internal(System.IntPtr,System.Net.SocketAddress,System.Int32&) System::System::Net::Sockets::Socket::Connect_internal // System.IO.MemoryMappedFiles.MemoryMapImpl System.IO.MemoryMappedFiles.MemoryMapImpl::Unmap(System.IntPtr) System::Core::System::IO::MemoryMappedFiles::MemoryMapImpl::Unmap System.IO.MemoryMappedFiles.MemoryMapImpl::MapInternal(System.IntPtr,System.Int64,System.Int64&,System.IO.MemoryMappedFiles.MemoryMappedFileAccess,System.IntPtr&,System.IntPtr&) System::Core::System::IO::MemoryMappedFiles::MemoryMapImpl::MapInternal System.IO.MemoryMappedFiles.MemoryMapImpl::OpenFileInternal(System.String,System.IO.FileMode,System.String,System.Int64&,System.IO.MemoryMappedFiles.MemoryMappedFileAccess,System.IO.MemoryMappedFiles.MemoryMappedFileOptions,System.Int32&) System::Core::System::IO::MemoryMappedFiles::MemoryMapImpl::OpenFileInternal System.IO.MemoryMappedFiles.MemoryMapImpl::OpenHandleInternal(System.IntPtr,System.String,System.Int64&,System.IO.MemoryMappedFiles.MemoryMappedFileAccess,System.IO.MemoryMappedFiles.MemoryMappedFileOptions,System.Int32&) System::Core::System::IO::MemoryMappedFiles::MemoryMapImpl::OpenHandleInternal System.IO.MemoryMappedFiles.MemoryMapImpl::CloseMapping(System.IntPtr) System::Core::System::IO::MemoryMappedFiles::MemoryMapImpl::CloseMapping System.IO.MemoryMappedFiles.MemoryMapImpl::ConfigureHandleInheritability(System.IntPtr,System.IO.HandleInheritability) System::Core::System::IO::MemoryMappedFiles::MemoryMapImpl::ConfigureHandleInheritability System.IO.MemoryMappedFiles.MemoryMapImpl::Flush(System.IntPtr) System::Core::System::IO::MemoryMappedFiles::MemoryMapImpl::Flush // Mono.RuntimeClassHandle Mono.RuntimeClassHandle::GetTypeFromClass(Mono.RuntimeStructs/MonoClass*) mscorlib::Mono::RuntimeClassHandle::GetTypeFromClass // Mono.SafeStringMarshal Mono.SafeStringMarshal::StringToUtf8(System.String) mscorlib::Mono::SafeStringMarshal::StringToUtf8 Mono.SafeStringMarshal::GFree(System.IntPtr) mscorlib::Mono::SafeStringMarshal::GFree // System.Reflection.EventInfo System.Reflection.EventInfo::internal_from_handle_type(System.IntPtr,System.IntPtr) mscorlib::System::Reflection::EventInfo::internal_from_handle_type // System.Reflection.PropertyInfo System.Reflection.PropertyInfo::internal_from_handle_type(System.IntPtr,System.IntPtr) mscorlib::System::Reflection::PropertyInfo::internal_from_handle_type // Mono.RuntimeGPtrArrayHandle Mono.RuntimeGPtrArrayHandle::GPtrArrayFree(Mono.RuntimeStructs/GPtrArray*) mscorlib::Mono::RuntimeGPtrArrayHandle::GPtrArrayFree // Mono.RuntimeMarshal Mono.RuntimeMarshal::FreeAssemblyName(Mono.MonoAssemblyName&) mscorlib::Mono::RuntimeMarshal::FreeAssemblyName // System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods::RoOriginateLanguageException(System.Int32,System.String,System.IntPtr) mscorlib::System::Runtime::InteropServices::WindowsRuntime::UnsafeNativeMethods::RoOriginateLanguageException System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods::WindowsGetStringRawBuffer(System.IntPtr,System.UInt32*) mscorlib::System::Runtime::InteropServices::WindowsRuntime::UnsafeNativeMethods::WindowsGetStringRawBuffer System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods::WindowsCreateString(System.String,System.Int32,System.IntPtr*) mscorlib::System::Runtime::InteropServices::WindowsRuntime::UnsafeNativeMethods::WindowsCreateString System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods::WindowsDeleteString(System.IntPtr) mscorlib::System::Runtime::InteropServices::WindowsRuntime::UnsafeNativeMethods::WindowsDeleteString System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods::GetRestrictedErrorInfo() mscorlib::System::Runtime::InteropServices::WindowsRuntime::UnsafeNativeMethods::GetRestrictedErrorInfo System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods::RoReportUnhandledError(System.Runtime.InteropServices.WindowsRuntime.IRestrictedErrorInfo) mscorlib::System::Runtime::InteropServices::WindowsRuntime::UnsafeNativeMethods::RoReportUnhandledError // System.TimeZoneInfo System.TimeZoneInfo::UseRegistryForTimeZoneInformation() mscorlib::System::TimeZoneInfo::UseRegistryForTimeZoneInformation // Mono.Net.Security.MonoTlsProviderFactory Mono.Net.Security.MonoTlsProviderFactory::IsBtlsSupported() System::Mono::Net::Security::MonoTlsProviderFactory::IsBtlsSupported // System.SizedReference System.SizedReference::GetApproximateSizeOfSizedRef(System.IntPtr) mscorlib::System::SizedReference::GetApproximateSizeOfSizedRef System.SizedReference::CreateSizedRef(System.Object) mscorlib::System::SizedReference::CreateSizedRef System.SizedReference::GetTargetOfSizedRef(System.IntPtr) mscorlib::System::SizedReference::GetTargetOfSizedRef System.SizedReference::FreeSizedRef(System.IntPtr) mscorlib::System::SizedReference::FreeSizedRef // System.Net.NetworkInformation.LinuxNetworkInterface System.Net.NetworkInformation.LinuxNetworkInterface::GetInterfaceAddresses(System.IntPtr&) System::System::Net::NetworkInformation::LinuxNetworkInterface::GetInterfaceAddresses System.Net.NetworkInformation.LinuxNetworkInterface::FreeInterfaceAddresses(System.IntPtr) System::System::Net::NetworkInformation::LinuxNetworkInterface::FreeInterfaceAddresses System.Net.NetworkInformation.LinuxNetworkInterface::InitializeInterfaceAddresses() System::System::Net::NetworkInformation::LinuxNetworkInterface::InitializeInterfaceAddresses ================================================ FILE: unity_decoder/libil2cpp/libil2cpp.vcxproj ================================================  Debug45 ARM Debug45 Win32 Debug45 x64 Debug_Tests ARM Debug_Tests Win32 Debug_Tests x64 Debug ARM Debug Win32 Debug x64 Release45 ARM Release45 Win32 Release45 x64 Release ARM Release Win32 Release x64 WinRT-UWP-Debug45 ARM WinRT-UWP-Debug45 Win32 WinRT-UWP-Debug45 x64 WinRT-UWP-Debug ARM WinRT-UWP-Debug Win32 WinRT-UWP-Debug x64 WinRT-UWP-Release45 ARM WinRT-UWP-Release45 Win32 WinRT-UWP-Release45 x64 WinRT-UWP-Release ARM WinRT-UWP-Release Win32 WinRT-UWP-Release x64 {848E3796-AAAC-4726-9B51-94FBFEB667B3} Win32Proj libil2cpp 10.0.10240.0 UAP StaticLibrary true Unicode StaticLibrary true Unicode StaticLibrary true Unicode StaticLibrary true Unicode StaticLibrary true Unicode v140 true StaticLibrary true Unicode v140 true StaticLibrary true Unicode v140 true StaticLibrary true Unicode v140 true StaticLibrary true Unicode StaticLibrary true Unicode StaticLibrary true Unicode v140 true StaticLibrary true Unicode v140 true StaticLibrary true Unicode StaticLibrary true Unicode StaticLibrary true Unicode StaticLibrary false true Unicode StaticLibrary false true Unicode StaticLibrary false true Unicode StaticLibrary false true Unicode StaticLibrary false true Unicode v140 true StaticLibrary false true Unicode v140 true StaticLibrary false true Unicode v140 true StaticLibrary false true Unicode v140 true StaticLibrary false true Unicode StaticLibrary false true Unicode StaticLibrary false true Unicode v140 true StaticLibrary false true Unicode v140 true $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\ build\$(Configuration)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ Level3 Disabled WIN32;_DEBUG;_LIB;IL2CPP_DEBUGGER_ENABLED=1;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreadedDebug $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) false true false Windows true ws2_32.lib;%(AdditionalDependencies) Level3 Disabled WIN32;_DEBUG;_LIB;IL2CPP_DEBUGGER_ENABLED=1;NET_4_0=1;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreadedDebug $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) false true false Windows true ws2_32.lib;%(AdditionalDependencies) Level3 Disabled WIN32;_DEBUG;_LIB;IL2CPP_DEBUGGER_ENABLED=1;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreadedDebug $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) false true false Windows true ws2_32.lib;%(AdditionalDependencies) Level3 Disabled WIN32;_DEBUG;_LIB;IL2CPP_DEBUGGER_ENABLED=1;NET_4_0=1;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreadedDebug $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) false true false Windows true ws2_32.lib;%(AdditionalDependencies) Level3 Disabled WIN32;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;_DEBUG;_LIB;IL2CPP_DEBUGGER_ENABLED=0;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreadedDebugDLL $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) false true false Windows true ws2_32.lib;%(AdditionalDependencies) Level3 Disabled WIN32;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;_DEBUG;_LIB;IL2CPP_DEBUGGER_ENABLED=0;NET_4_0=1;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreadedDebugDLL $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) false true false Windows true ws2_32.lib;%(AdditionalDependencies) Level3 Disabled WIN32;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;_DEBUG;_LIB;IL2CPP_DEBUGGER_ENABLED=0;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreadedDebugDLL $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) false true false Windows true ws2_32.lib;%(AdditionalDependencies) Level3 Disabled WIN32;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;_DEBUG;_LIB;IL2CPP_DEBUGGER_ENABLED=0;NET_4_0=1;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreadedDebugDLL $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) false true false Windows true ws2_32.lib;%(AdditionalDependencies) Level3 Disabled WIN32;_DEBUG;_LIB;IL2CPP_DEBUGGER_ENABLED=1;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreadedDebug $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) false true false Windows true ws2_32.lib;%(AdditionalDependencies) Level3 Disabled WIN32;_DEBUG;_LIB;IL2CPP_DEBUGGER_ENABLED=1;NET_4_0=1;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreadedDebug $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) false true false Windows true ws2_32.lib;%(AdditionalDependencies) Level3 Disabled WIN32;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;_DEBUG;_LIB;IL2CPP_DEBUGGER_ENABLED=0;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreadedDebugDLL $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) false true false Windows true ws2_32.lib;%(AdditionalDependencies) Level3 Disabled WIN32;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;_DEBUG;_LIB;IL2CPP_DEBUGGER_ENABLED=0;NET_4_0=1;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreadedDebugDLL $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) false true false Windows true ws2_32.lib;%(AdditionalDependencies) Level3 Disabled WIN32;_DEBUG;_LIB;IL2CPP_DEBUGGER_ENABLED=1;IL2CPP_DEBUGGER_LOG=1;IL2CPP_UNIT_TESTS_ENABLED=1;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreadedDebug $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) false true false Windows true ws2_32.lib;%(AdditionalDependencies) Level3 Disabled WIN32;_DEBUG;_LIB;IL2CPP_DEBUGGER_ENABLED=1;IL2CPP_DEBUGGER_LOG=1;IL2CPP_UNIT_TESTS_ENABLED=1;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreadedDebug $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) false true false Windows true ws2_32.lib;%(AdditionalDependencies) Level3 Disabled WIN32;_DEBUG;_LIB;IL2CPP_DEBUGGER_ENABLED=1;IL2CPP_DEBUGGER_LOG=1;IL2CPP_UNIT_TESTS_ENABLED=1;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreadedDebug $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) false true false Windows true ws2_32.lib;%(AdditionalDependencies) Level3 MaxSpeed true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreaded $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) true Windows true true true Level3 MaxSpeed true true WIN32;NDEBUG;_LIB;NET_4_0=1;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreaded $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) true Windows true true true Level3 MaxSpeed true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreaded $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) true Windows true true true Level3 MaxSpeed true true WIN32;NDEBUG;_LIB;NET_4_0=1;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreaded $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) true Windows true true true Level3 MaxSpeed true true WIN32;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;NDEBUG;_LIB;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreadedDLL $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) true Windows true true true Level3 MaxSpeed true true WIN32;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;NDEBUG;_LIB;NET_4_0=1;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreadedDLL $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) true Windows true true true Level3 MaxSpeed true true WIN32;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;NDEBUG;_LIB;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreadedDLL $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) true Windows true true true Level3 MaxSpeed true true WIN32;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;NDEBUG;_LIB;NET_4_0=1;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreadedDLL $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) true Windows true true true Level3 MaxSpeed true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreaded $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) true Windows true true true Level3 MaxSpeed true true WIN32;NDEBUG;_LIB;NET_4_0=1;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreaded $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) true Windows true true true Level3 MaxSpeed true true WIN32;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;NDEBUG;_LIB;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreadedDLL $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) true Windows true true true Level3 MaxSpeed true true WIN32;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;NDEBUG;_LIB;NET_4_0=1;%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS .\..\external\boehmgc\include;.\;..\libmono MultiThreadedDLL $(IntDir)%(RelativeDir) /we4002 %(AdditionalOptions) true Windows true true true ================================================ FILE: unity_decoder/libil2cpp/libil2cpp.vcxproj.filters ================================================  vm vm vm vm vm vm vm vm vm vm vm utils utils utils vm gc gc gc vm vm vm vm vm vm debugger debugger debugger debugger debugger debugger\protocol debugger\protocol debugger\protocol debugger\protocol\commands debugger\protocol\commands debugger\protocol\commands debugger\protocol\commands debugger\protocol\commands debugger\handlers debugger\handlers os\Win32 os\Posix os os\Posix os\Win32 os os\Win32 os\Posix os os\Win32 os\Posix os os\Win32 os\Posix os\Std os os\Win32 os\Posix debugger\handlers debugger\handlers debugger\handlers debugger\handlers debugger\handlers debugger\handlers debugger\handlers debugger\handlers debugger\handlers debugger\handlers debugger\handlers debugger\handlers debugger\protocol\commands debugger\protocol\commands debugger\protocol\commands debugger\protocol\commands vm debugger\protocol\commands debugger\protocol\commands debugger\protocol\commands debugger\protocol\commands debugger\protocol\commands icalls\System\System.Diagnostics debugger os\Posix os\Win32 os\Posix os\Win32 os\Posix os\Win32 icalls\mscorlib\Mono icalls\mscorlib\System.Threading icalls\mscorlib\System.Threading icalls\mscorlib\System.Threading icalls\mscorlib\System.Threading icalls\mscorlib\System.Threading icalls\mscorlib\System.Threading icalls\mscorlib\System.Threading icalls\mscorlib\System.Text icalls\mscorlib\System.Security.Principal icalls\mscorlib\System.Security.Principal icalls\mscorlib\System.Security.Principal icalls\mscorlib\System.Security.Policy os\Win32 os\Win32 os\Win32 os\Posix os\Posix os\Posix os\Posix os\Win32 os\Posix vm icalls\System\System.Net.Sockets icalls\System\System.Net.Sockets icalls\System\System.ComponentModel icalls\System\System.Diagnostics icalls\System\System.Diagnostics icalls\System\System.Diagnostics icalls\System\System.IO icalls\System\System.IO icalls\System\System.IO icalls\System\System.Net icalls\mscorlib\System icalls\System\System.Configuration icalls\System\System.Diagnostics icalls\System\System.Diagnostics os\Posix os os\Win32 os\Generic os\Posix os os os gc debugger debugger debugger os\Win32 os\Posix os\Generic os\Win32 os\Posix os\Win32 os\Posix vm os\Posix os\Win32 os\Win32 externals external\zlib external\zlib external\zlib external\zlib external\zlib external\zlib external\zlib external\zlib external\zlib external\zlib external\zlib external\zlib os\Posix os\Win32 os\Win32 icalls\System\System.Configuration vm vm vm vm metadata metadata metadata metadata metadata metadata metadata metadata vm metadata vm metadata metadata metadata metadata metadata metadata os\Win32 os vm utils vm os\Win32 os\OSX os\Posix os\Generic os\Posix os\Win32 utils vm vm vm os\WinRT os\WinRT os\WinRT os\WinRT os\Generic os\Win32 os\WinRT vm utils vm vm vm vm vm os\Generic os\Win32 os\Win32 vm vm vm gc icalls\System\System.Diagnostics vm os\Win32 os\Generic icalls\mscorlib\System.Diagnostics icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System.Globalization icalls\mscorlib\System.Globalization icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection.Emit icalls\mscorlib\System.Runtime.Remoting.Contexts icalls\mscorlib\System.Runtime.Remoting.Messaging icalls\mscorlib\System.Runtime.Versioning icalls\mscorlib\System.Text icalls\mscorlib\System.Text icalls\mscorlib\System.Threading icalls\mscorlib\System.Threading icalls\System.Configuration\System.Configuration icalls\System.Core\System.IO.MemoryMappedFiles icalls\System\System.Net.NetworkInformation icalls\System\System icalls\System\System.IO vm icalls\System\Microsoft.Win32 os\Win32 os\Posix os\OSX metadata metadata utils os\Posix os\WinRT os\WinRT os\WinRT os os\Win32 os\Posix vm os\Win32 os\Posix utils os\Win32 icalls\mscorlib\Mono icalls\mscorlib\Mono icalls\mscorlib\Mono icalls\mscorlib\Mono icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection vm utils icalls\System\System.Net.NetworkInformation external\xamarin-android vm os\Android utils utils os\c-api os\c-api os\c-api os\c-api os\c-api os\c-api os\c-api vm-utils vm-utils vm-utils vm-utils utils utils icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System.Security.Cryptography icalls\mscorlib\System.Security.Cryptography icalls\mscorlib\System.Security icalls\mscorlib\System.Security icalls\mscorlib\System.Runtime.Remoting.Proxies icalls\mscorlib\System.Runtime.Remoting.Activation icalls\mscorlib\System.Runtime.Remoting.Messaging icalls\mscorlib\System.Runtime.Remoting icalls\mscorlib\System.Runtime.InteropServices icalls\mscorlib\System.Runtime.InteropServices icalls\mscorlib\System.Runtime.CompilerServices icalls\mscorlib\System.Reflection.Emit icalls\mscorlib\System.Reflection.Emit icalls\mscorlib\System.Reflection.Emit icalls\mscorlib\System.Reflection.Emit icalls\mscorlib\System.Reflection.Emit icalls\mscorlib\System.Reflection.Emit icalls\mscorlib\System.Reflection.Emit icalls\mscorlib\System.Reflection.Emit icalls\mscorlib\System.Reflection.Emit icalls\mscorlib\System.Reflection.Emit icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.IO icalls\mscorlib\System.IO icalls\mscorlib\System.IO icalls\mscorlib\System.Diagnostics icalls\mscorlib\System.Diagnostics icalls\mscorlib\System.Diagnostics icalls\mscorlib\System.Globalization icalls\mscorlib\System.Globalization icalls\mscorlib\System.Globalization icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\Mono.Globalization.Unicode icalls\mscorlib\Mono.Interop icalls\mscorlib\Mono.Security.Cryptography icalls\System\System.Threading vm os\Win32 os os vm icalls\System\System.Net.Sockets icalls\System\System.Net.Sockets icalls\System\System.ComponentModel icalls\System\System.Diagnostics icalls\System\System.Diagnostics icalls\System\System.Diagnostics icalls\System\System.IO icalls\System\System.IO icalls\System\System.IO icalls\System\System.Net icalls\System\System.Threading icalls\mscorlib\System icalls\System\System.Configuration icalls\System\System.Diagnostics icalls\System\System.Diagnostics os utils\utf8-cpp utils\utf8-cpp os\Generic os\Posix os\Posix os os os gc os vm icalls\System\System.Threading os os os vm os externals external\zlib external\zlib external\zlib external\zlib external\zlib external\zlib external\zlib external\zlib external\zlib external\zlib os\Posix os\Posix os\Win32 utils os\Win32 icalls\System\System.Configuration vm vm vm vm metadata metadata metadata metadata metadata metadata metadata metadata utils vm metadata metadata metadata metadata metadata metadata metadata vm utils metadata os utils vm vm utils vm utils os os utils vm vm vm os\WinRT os os vm utils utils vm vm vm vm vm os os\Generic os os os vm vm vm vm vm vm gc gc icalls\mscorlib\System.Diagnostics icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System.Globalization icalls\mscorlib\System.Globalization icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection.Emit icalls\mscorlib\System.Runtime.Remoting.Contexts icalls\mscorlib\System.Runtime.Remoting.Messaging icalls\mscorlib\System.Runtime.Versioning icalls\mscorlib\System.Text icalls\mscorlib\System.Text icalls\mscorlib\System.Threading icalls\mscorlib\System.Threading icalls\System.Configuration\System.Configuration icalls\System.Core\System.IO.MemoryMappedFiles icalls\System\System.Net.NetworkInformation icalls\System\System icalls\System\System.IO vm icalls\System\Microsoft.Win32 os metadata metadata external\google\sparsehash external\google\sparsehash external\google\sparsehash external\google\sparsehash utils utils utils utils os\WinRT os\WinRT os os\Win32 os\Posix vm codegen os gc icalls\mscorlib\Mono icalls\mscorlib\Mono icalls\mscorlib\Mono icalls\mscorlib\Mono icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection vm utils icalls\System\System.Net.NetworkInformation external\xamarin-android external\xamarin-android external\xamarin-android vm codegen codegen utils utils os\c-api os\c-api os\c-api os\c-api os\c-api os\c-api os\c-api vm-utils vm-utils vm-utils vm-utils utils vm vm vm vm vm vm vm vm vm vm vm utils os utils utils utils utils vm gc gc gc codegen os os vm vm vm os os vm vm vm debugger debugger debugger debugger debugger debugger debugger debugger\protocol debugger\protocol debugger\protocol debugger\protocol debugger\protocol\commands debugger\protocol\commands debugger\protocol\commands debugger\protocol\commands debugger\protocol\commands debugger\protocol\commands debugger\protocol\commands debugger\protocol\commands debugger\protocol\commands debugger\protocol\commands debugger\protocol\commands os os os os utils os\Posix os\Win32 os\Win32 os\Posix os\Win32 os\Win32 os\Posix os os\Win32 os\Posix os os\Std os os\Win32 os\Posix os os\Win32 debugger\protocol\commands debugger\protocol\commands debugger\protocol\commands vm debugger debugger\protocol icalls\System\System.Diagnostics os debugger os debugger debugger debugger vm icalls\mscorlib\Mono icalls\mscorlib\System.Threading icalls\mscorlib\System.Threading icalls\mscorlib\System.Threading icalls\mscorlib\System.Threading icalls\mscorlib\System.Threading icalls\mscorlib\System.Threading icalls\mscorlib\System.Threading icalls\mscorlib\System.Text icalls\mscorlib\System.Security.Principal icalls\mscorlib\System.Security.Principal icalls\mscorlib\System.Security.Principal icalls\mscorlib\System.Security.Policy icalls\mscorlib\System.Security.Cryptography icalls\mscorlib\System.Security icalls\mscorlib\System.Security icalls\mscorlib\System.Runtime.Remoting.Proxies icalls\mscorlib\System.Runtime.Remoting.Activation icalls\mscorlib\System.Runtime.Remoting.Messaging icalls\mscorlib\System.Runtime.Remoting icalls\mscorlib\System.Runtime.InteropServices icalls\mscorlib\System.Runtime.InteropServices icalls\mscorlib\System.Runtime.CompilerServices icalls\mscorlib\System.Reflection.Emit icalls\mscorlib\System.Reflection.Emit icalls\mscorlib\System.Reflection.Emit icalls\mscorlib\System.Reflection.Emit icalls\mscorlib\System.Reflection.Emit icalls\mscorlib\System.Reflection.Emit icalls\mscorlib\System.Reflection.Emit icalls\mscorlib\System.Reflection.Emit icalls\mscorlib\System.Reflection.Emit icalls\mscorlib\System.Reflection.Emit icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.Reflection icalls\mscorlib\System.IO icalls\mscorlib\System.IO icalls\mscorlib\System.IO icalls\mscorlib\System.Diagnostics icalls\mscorlib\System.Diagnostics icalls\mscorlib\System.Diagnostics icalls\mscorlib\System.Globalization icalls\mscorlib\System.Globalization icalls\mscorlib\System.Globalization icalls\mscorlib\System.Globalization icalls\mscorlib\System.Globalization icalls\mscorlib\System.Globalization icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\System icalls\mscorlib\Mono.Globalization.Unicode icalls\mscorlib\Mono.Interop icalls\mscorlib\Mono.Security.Cryptography {d0a67431-31ec-4bbe-8701-8100f710d5f8} {12a6451d-ca5e-4230-8d8b-1b3bb35f4e4c} {738658e0-940e-4050-b41b-99d6437759fb} {b78baafa-5991-4293-8270-d25a884e64ba} {0dd1f5b7-c97b-4294-bc4a-8de28eb89d78} {0430ba0d-4c62-44b9-a5ce-3e64da2e486b} {51dd375a-cf90-496c-9c94-4674d2f48f42} {8ef1b810-0910-4457-823a-ca2929779288} {e40bc88f-140f-4d9f-aa3e-293e4d36e194} {7046bf2b-3ca4-4335-8814-97f903cc02d9} {180a504a-294c-44bb-ae0f-ad14ee9fd527} {8517adbc-a129-4978-a4ef-6aed73addc95} {439ba954-2c07-40ef-b1af-c09d66d3e1ad} {1f949457-47de-4a6b-85a8-43298921ce96} {e79916cc-3664-46d9-9281-a18428719ef3} {d7c6200b-3dd3-4800-8989-cdfb8e963722} {8fcde566-0958-4c94-aef9-64c8b5bda310} {413cf900-a6d8-4c43-9a83-842a4be111f5} {c0c54006-b8f5-4471-85ab-56ae7f5e8677} {ca5df3f1-bbd2-44a6-9b29-ad881606d8a1} {02da9909-10a6-4e6b-9b74-df93cc70eeca} {34bbb29c-1734-4c3a-8b51-7c6dc40736db} {2063ebbb-cef5-45d1-8214-b9a063698429} {027d0b2f-01ca-40ff-b405-8b832403c735} {a4e50a2b-8cc0-4b94-8ce4-61f0f0bda60a} {aea99ed3-49d2-479a-a165-8a9df63c1eae} {fee96542-a7ef-456a-a3d5-54d524c39258} {89a08caa-c0c1-440d-b1f9-e9285efbb85c} {9c670285-c3d2-486a-8589-95e815a581b6} {d0df3daa-3047-43fb-9090-cf76f5b7f8dc} {14a9903f-d61e-4137-95b0-b78c6a553584} {ed74ed87-9f24-480e-a867-910c55f592c4} {40dfb16f-7299-4125-b03c-47b1a8fe8406} {def4e741-6f7a-4655-89f0-2df2c2c80cff} {fd7f312d-f13b-47dc-92c8-355a4a138276} {999fdd8e-3a26-4a18-945d-335d829efb05} {1575433e-5ea0-42da-8e34-ef74066fb9ae} {a4f6cf11-3f99-418b-a476-5aef272b8302} {b94d665a-d61a-462c-954c-b41a750610e7} {d510bb08-b41d-4fd5-925e-1097f01fa1cb} {f2f9fff2-0dd8-4aa7-92e0-9b2d7c3ee84a} {015bf5e3-9cbe-44e0-aedb-cb62ab085f32} {e04a3b73-3d05-478c-9265-0a21bc3b9cf1} {f42dada5-8f7e-4824-8f35-5d674fde0260} {e8baedf4-38c9-407c-9565-ee80d8e6b6b3} {68af634a-880a-476d-be5e-8a3bbddcf9c1} {6ed1563b-2499-4017-903a-8e8a58ac9d9d} {86a616f5-da91-46be-ad81-de62af32f3fe} {05a3316c-38cc-475e-8c5f-e88f6b064dc7} {6d114f22-0edb-4a93-a4b7-d96ca88f1535} {7c83bd52-b497-4e70-b977-0d000b1578de} {6976f933-477a-486f-bbd5-2cf9bb1c964c} {0430df54-ee7b-4738-bea9-75626c882575} {1cb9ee6f-bcb5-4532-85fb-a0d143f92f97} {63befc8d-e21a-4298-833c-7fee92721959} {2caaeb5d-64a8-4a7a-b7d6-f3a34f6518ac} {275c89c7-b7c2-44f1-9ef9-8a1ee72d4be5} {a0b052a6-7577-438c-b228-ec9aa944aa34} {95cd4b03-aecf-40eb-bc1e-fbce3595ca45} {2917f620-4eeb-4519-8c89-b41c2acc1f0c} {9d8ad3a4-09bc-495c-b303-141f8391e497} {c5851c1d-3fab-4248-a54a-05bbd5690c37} {31d18c78-b7d7-4ffd-ac5b-afc9849ed2b2} {cb9dfdd5-8359-4a4b-a94c-d6bcb85032e2} {b4723b4d-6f82-47d4-a565-c63585dc3646} {1f2821fc-c40c-40c8-ad24-200ee6b123fd} {4862e90c-23f0-4fcf-a14b-787c976f6083} {9b67d9fa-cf50-45a7-93fc-b2e25ac4e73a} {af05b2ca-3dde-4659-8af7-c9655f11d420} {282f089e-e7a0-494c-8a4b-f56ca071fb01} vm ================================================ FILE: unity_decoder/libil2cpp/metadata/ArrayMetadata.cpp ================================================ #include "il2cpp-config.h" #include "os/Mutex.h" #include "vm/Class.h" #include "vm/GenericClass.h" #include "vm/Image.h" #include "vm/MetadataLock.h" #include "vm/Type.h" #include "metadata/ArrayMetadata.h" #include "metadata/GenericMetadata.h" #include "metadata/GenericMethod.h" #include "metadata/Il2CppGenericClassHash.h" #include "metadata/Il2CppGenericClassCompare.h" #include "metadata/Il2CppGenericInstCompare.h" #include "metadata/Il2CppGenericInstHash.h" #include "metadata/Il2CppTypeCompare.h" #include "metadata/Il2CppTypeHash.h" #include "vm/MetadataAlloc.h" #include "vm/MetadataCache.h" #include "vm/Runtime.h" #include "utils/Memory.h" #include "utils/Il2CppHashMap.h" #include "utils/StringUtils.h" #include "class-internals.h" #include "tabledefs.h" #include #include #include using namespace il2cpp::vm; using il2cpp::os::FastAutoLock; using il2cpp::utils::StringUtils; using il2cpp::vm::MetadataCache; using il2cpp::vm::MetadataCalloc; using il2cpp::vm::MetadataMalloc; using std::vector; using std::pair; #if NET_4_0 const size_t kImplicitArrayInterfaceCount = 5; #else const size_t kImplicitArrayInterfaceCount = 3; #endif namespace il2cpp { namespace metadata { static const char* GetArrayName(const char* elementClassName, uint32_t rank, bool bounded) { std::string name; name += elementClassName; name += "["; for (uint32_t i = 1; i < rank; i++) name += ","; if (bounded) name += "*"; name += "]"; return StringUtils::StringDuplicate(name.c_str()); } static MethodInfo* ConstructArrayMethod(Il2CppClass* declaringType, const char* name, const Il2CppType* returnType, uint8_t parameterCount, const Il2CppType** parameterTypes) { MethodInfo* method = (MethodInfo*)MetadataCalloc(1, sizeof(MethodInfo)); method->declaring_type = declaringType; method->flags = METHOD_ATTRIBUTE_PUBLIC; method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL; method->name = name; method->slot = -1; method->return_type = returnType; method->parameters_count = parameterCount; ParameterInfo* parameters = (ParameterInfo*)MetadataCalloc(parameterCount, sizeof(ParameterInfo)); for (uint8_t i = 0; i < parameterCount; i++) { parameters[i].position = i; parameters[i].parameter_type = parameterTypes[i]; parameters[i].name = NULL; } method->parameters = parameters; if (!strcmp(".ctor", name)) { method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME; } else { method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME; } ++il2cpp_runtime_stats.method_count; return method; } struct GenericArrayMethod { std::string name; const MethodInfo* method; const MethodInfo* interfaceMethodDefinition; }; typedef vector GenericArrayMethods; static GenericArrayMethods s_GenericArrayMethods; static size_t GetArrayGenericMethodsCount(); static void PopulateArrayGenericMethods(Il2CppClass* klass, uint16_t offset, const GenericArrayMethods& genericArrayMethods); static void CollectImplicitArrayInterfaces(Il2CppClass* elementClass, ::std::vector& interfaces); static void SetupArrayMethods(Il2CppClass* arrayClass) { size_t methodIndex = 0; uint8_t rank = arrayClass->rank; ::std::vector interfaces; CollectImplicitArrayInterfaces(arrayClass, interfaces); size_t methodCount = 3 + (rank > 1 ? 2 : 1) + interfaces.size() * GetArrayGenericMethodsCount(); IL2CPP_ASSERT(methodCount <= std::numeric_limits::max()); arrayClass->method_count = static_cast(methodCount); arrayClass->methods = (const MethodInfo**)MetadataCalloc(methodCount, sizeof(MethodInfo*)); const Il2CppType** parameters = (const Il2CppType**)alloca(rank * sizeof(Il2CppType*)); for (uint8_t i = 0; i < rank; i++) parameters[i] = il2cpp_defaults.int32_class->byval_arg; arrayClass->methods[methodIndex++] = ConstructArrayMethod(arrayClass, ".ctor", il2cpp_defaults.void_class->byval_arg, rank, parameters); if (rank > 1) { parameters = (const Il2CppType**)alloca(2 * rank * sizeof(Il2CppType*)); for (uint8_t i = 0; i < 2 * rank; i++) parameters[i] = il2cpp_defaults.int32_class->byval_arg; arrayClass->methods[methodIndex++] = ConstructArrayMethod(arrayClass, ".ctor", il2cpp_defaults.void_class->byval_arg, 2 * rank, parameters); } parameters = (const Il2CppType**)alloca((rank + 1) * sizeof(Il2CppType*)); for (uint8_t i = 0; i < rank; i++) parameters[i] = il2cpp_defaults.int32_class->byval_arg; parameters[rank] = arrayClass->element_class->byval_arg; arrayClass->methods[methodIndex++] = ConstructArrayMethod(arrayClass, "Set", il2cpp_defaults.void_class->byval_arg, rank + 1, parameters); parameters = (const Il2CppType**)alloca(rank * sizeof(Il2CppType*)); for (uint8_t i = 0; i < rank; i++) parameters[i] = il2cpp_defaults.int32_class->byval_arg; arrayClass->methods[methodIndex++] = ConstructArrayMethod(arrayClass, "Address", arrayClass->element_class->this_arg, rank, parameters); parameters = (const Il2CppType**)alloca(rank * sizeof(Il2CppType*)); for (uint8_t i = 0; i < rank; i++) parameters[i] = il2cpp_defaults.int32_class->byval_arg; arrayClass->methods[methodIndex++] = ConstructArrayMethod(arrayClass, "Get", arrayClass->element_class->byval_arg, rank, parameters); IL2CPP_ASSERT(methodIndex <= std::numeric_limits::max()); PopulateArrayGenericMethods(arrayClass, static_cast(methodIndex), s_GenericArrayMethods); } static void CollectImplicitArrayInterfacesFromElementClass(Il2CppClass* elementClass, ::std::vector& interfaces) { while (elementClass != NULL) { interfaces.push_back(elementClass); if (!elementClass->valuetype && elementClass != il2cpp_defaults.value_type_class && elementClass != il2cpp_defaults.enum_class) { void* iter = NULL; while (Il2CppClass* itf = Class::GetInterfaces(elementClass, &iter)) interfaces.push_back(itf); } if (elementClass->rank == 1) { ::std::vector elementInterfaces; CollectImplicitArrayInterfacesFromElementClass(elementClass->element_class, elementInterfaces); for (::std::vector::iterator iter = elementInterfaces.begin(); iter != elementInterfaces.end(); ++iter) { Il2CppTypeVector genericArguments; genericArguments.push_back((*iter)->byval_arg); interfaces.push_back(Class::GetInflatedGenericInstanceClass(il2cpp_defaults.generic_ilist_class, genericArguments)); interfaces.push_back(Class::GetInflatedGenericInstanceClass(il2cpp_defaults.generic_icollection_class, genericArguments)); interfaces.push_back(Class::GetInflatedGenericInstanceClass(il2cpp_defaults.generic_ienumerable_class, genericArguments)); #if NET_4_0 interfaces.push_back(Class::GetInflatedGenericInstanceClass(il2cpp_defaults.generic_ireadonlylist_class, genericArguments)); interfaces.push_back(Class::GetInflatedGenericInstanceClass(il2cpp_defaults.generic_ireadonlycollection_class, genericArguments)); #endif } } elementClass = Class::GetParent(elementClass); if (elementClass != NULL && (elementClass->valuetype || elementClass == il2cpp_defaults.value_type_class || elementClass == il2cpp_defaults.enum_class)) break; } } static void CollectImplicitArrayInterfaces(Il2CppClass* arrayClass, ::std::vector& interfaces) { if (arrayClass->byval_arg->type != IL2CPP_TYPE_SZARRAY) return; CollectImplicitArrayInterfacesFromElementClass(arrayClass->element_class, interfaces); } // note assuming list is ordered as IList, ICollection, IEnumerable static void CollectGenericArrayMethods(GenericArrayMethods& genericArrayMethods) { const size_t kNumGenericArrayMethods = 13; genericArrayMethods.reserve(kNumGenericArrayMethods); void* iter = NULL; while (const MethodInfo* method = Class::GetMethods(il2cpp_defaults.array_class, &iter)) { if (strncmp(method->name, "InternalArray__", 15)) continue; std::string name; std::string methodName; Il2CppClass* implementingInterface = NULL; if (!strncmp(method->name, "InternalArray__ICollection_", 27)) { implementingInterface = il2cpp_defaults.generic_icollection_class; methodName = method->name + 27; name = StringUtils::Printf("System.Collections.Generic.ICollection`1.%s", method->name + 27); } else if (!strncmp(method->name, "InternalArray__IEnumerable_", 27)) { implementingInterface = il2cpp_defaults.generic_ienumerable_class; methodName = method->name + 27; name = StringUtils::Printf("System.Collections.Generic.IEnumerable`1.%s", method->name + 27); } #if NET_4_0 else if (!strncmp(method->name, "InternalArray__IReadOnlyList_", 29)) { implementingInterface = il2cpp_defaults.generic_ireadonlylist_class; methodName = method->name + 29; name = StringUtils::Printf("System.Collections.Generic.IReadOnlyList`1.%s", method->name + 29); } else if (!strncmp(method->name, "InternalArray__IReadOnlyCollection_", 35)) { implementingInterface = il2cpp_defaults.generic_ireadonlycollection_class; methodName = method->name + 35; name = StringUtils::Printf("System.Collections.Generic.IReadOnlyCollection`1.%s", method->name + 35); } #endif else { implementingInterface = il2cpp_defaults.generic_ilist_class; methodName = method->name + 15; name = StringUtils::Printf("System.Collections.Generic.IList`1.%s", method->name + 15); } const MethodInfo* matchingInterfacesMethod = NULL; for (int methodIndex = 0; methodIndex < implementingInterface->method_count; methodIndex++) { const MethodInfo* interfaceMethod = implementingInterface->methods[methodIndex]; if (methodName == interfaceMethod->name) matchingInterfacesMethod = interfaceMethod; } if (matchingInterfacesMethod != NULL) { GenericArrayMethod generiArrayMethod = { name, method, matchingInterfacesMethod }; genericArrayMethods.push_back(generiArrayMethod); } } } static size_t GetArrayGenericMethodsCount() { if (s_GenericArrayMethods.size() == 0) CollectGenericArrayMethods(s_GenericArrayMethods); return s_GenericArrayMethods.size(); } static MethodInfo* ConstructGenericArrayMethod(const GenericArrayMethod& genericArrayMethod, Il2CppClass* klass, Il2CppGenericContext* context) { MethodInfo* inflatedMethod = (MethodInfo*)MetadataCalloc(1, sizeof(MethodInfo)); inflatedMethod->name = StringUtils::StringDuplicate(genericArrayMethod.name.c_str()); inflatedMethod->declaring_type = klass; const MethodInfo* methodToCopyDataFrom = genericArrayMethod.method; if (genericArrayMethod.method->is_generic) { const Il2CppGenericMethod* genericMethod = MetadataCache::GetGenericMethod(genericArrayMethod.method, context->class_inst, context->method_inst); methodToCopyDataFrom = GenericMethod::GetMethod(genericMethod); inflatedMethod->is_inflated = true; inflatedMethod->genericMethod = genericMethod; inflatedMethod->rgctx_data = methodToCopyDataFrom->rgctx_data; } inflatedMethod->slot = methodToCopyDataFrom->slot; inflatedMethod->parameters_count = methodToCopyDataFrom->parameters_count; inflatedMethod->parameters = methodToCopyDataFrom->parameters; inflatedMethod->return_type = methodToCopyDataFrom->return_type; inflatedMethod->methodPointer = methodToCopyDataFrom->methodPointer; inflatedMethod->invoker_method = methodToCopyDataFrom->invoker_method; return inflatedMethod; } static void PopulateArrayGenericMethods(Il2CppClass* klass, uint16_t offset, const GenericArrayMethods& genericArrayMethods) { for (int i = 0; i < klass->interface_offsets_count; i++) { Il2CppClass* interfaceType = klass->interfaceOffsets[i].interfaceType; if (!interfaceType->generic_class) continue; Il2CppClass* interfaceDefinition = GenericClass::GetTypeDefinition(interfaceType->generic_class); Il2CppGenericContext context = { 0 }; Il2CppTypeVector types; types.push_back(interfaceType->generic_class->context.class_inst->type_argv[0]); context.method_inst = MetadataCache::GetGenericInst(types); for (GenericArrayMethods::const_iterator iter = genericArrayMethods.begin(); iter != genericArrayMethods.end(); ++iter) { if (iter->interfaceMethodDefinition->declaring_type != interfaceDefinition) continue; MethodInfo* arrayMethod = ConstructGenericArrayMethod(*iter, klass, &context); klass->methods[offset++] = arrayMethod; size_t vtableIndex = klass->interfaceOffsets[i].offset + iter->interfaceMethodDefinition->slot; klass->vtable[vtableIndex].method = arrayMethod; klass->vtable[vtableIndex].methodPtr = arrayMethod->methodPointer; } } } static void SetupArrayVTableAndInterfaceOffsets(Il2CppClass* klass) { Il2CppClass* arrayClass = Class::GetParent(klass); size_t arrayInterfacesCount = arrayClass->interface_offsets_count; ::std::vector interfaces; if (klass->byval_arg->type == IL2CPP_TYPE_SZARRAY) { CollectImplicitArrayInterfaces(klass, interfaces); } Il2CppRuntimeInterfaceOffsetPair* newInterfaceOffsets = (Il2CppRuntimeInterfaceOffsetPair*)MetadataMalloc((arrayInterfacesCount + kImplicitArrayInterfaceCount * interfaces.size()) * sizeof(Il2CppRuntimeInterfaceOffsetPair)); memcpy(newInterfaceOffsets, arrayClass->interfaceOffsets, (arrayInterfacesCount) * sizeof(Il2CppRuntimeInterfaceOffsetPair)); int32_t arrayVTableSlot = arrayClass->vtable_count; size_t slots = arrayVTableSlot + interfaces.size() * (il2cpp_defaults.generic_ilist_class->method_count + il2cpp_defaults.generic_icollection_class->method_count + il2cpp_defaults.generic_ienumerable_class->method_count); #if NET_4_0 slots += interfaces.size() * (il2cpp_defaults.generic_ireadonlylist_class->method_count + il2cpp_defaults.generic_ireadonlycollection_class->method_count); #endif memcpy(klass->vtable, arrayClass->vtable, arrayVTableSlot * sizeof(VirtualInvokeData)); size_t index = arrayInterfacesCount; int32_t vtableSlot = arrayVTableSlot; for (::std::vector::iterator iter = interfaces.begin(); iter != interfaces.end(); iter++, index += kImplicitArrayInterfaceCount) { Il2CppTypeVector genericArguments; genericArguments.push_back((*iter)->byval_arg); newInterfaceOffsets[index].interfaceType = Class::GetInflatedGenericInstanceClass(il2cpp_defaults.generic_ilist_class, genericArguments); newInterfaceOffsets[index].offset = vtableSlot; vtableSlot += newInterfaceOffsets[index].interfaceType->method_count; newInterfaceOffsets[index + 1].interfaceType = Class::GetInflatedGenericInstanceClass(il2cpp_defaults.generic_icollection_class, genericArguments); newInterfaceOffsets[index + 1].offset = vtableSlot; vtableSlot += newInterfaceOffsets[index + 1].interfaceType->method_count; newInterfaceOffsets[index + 2].interfaceType = Class::GetInflatedGenericInstanceClass(il2cpp_defaults.generic_ienumerable_class, genericArguments); newInterfaceOffsets[index + 2].offset = vtableSlot; vtableSlot += newInterfaceOffsets[index + 2].interfaceType->method_count; #if NET_4_0 newInterfaceOffsets[index + 3].interfaceType = Class::GetInflatedGenericInstanceClass(il2cpp_defaults.generic_ireadonlylist_class, genericArguments); newInterfaceOffsets[index + 3].offset = vtableSlot; vtableSlot += newInterfaceOffsets[index + 3].interfaceType->method_count; newInterfaceOffsets[index + 4].interfaceType = Class::GetInflatedGenericInstanceClass(il2cpp_defaults.generic_ireadonlycollection_class, genericArguments); newInterfaceOffsets[index + 4].offset = vtableSlot; vtableSlot += newInterfaceOffsets[index + 4].interfaceType->method_count; #endif } size_t interfaceOffsetsCount = arrayInterfacesCount + kImplicitArrayInterfaceCount * interfaces.size(); IL2CPP_ASSERT(interfaceOffsetsCount <= std::numeric_limits::max()); klass->interface_offsets_count = static_cast(interfaceOffsetsCount); klass->interfaceOffsets = newInterfaceOffsets; } void SetupCastClass(Il2CppClass *arrayType) { Il2CppClass *elementType = arrayType->element_class; if (elementType->enumtype) arrayType->castClass = elementType->element_class; else arrayType->castClass = elementType; if (arrayType->castClass == il2cpp_defaults.sbyte_class) arrayType->castClass = il2cpp_defaults.byte_class; else if (arrayType->castClass == il2cpp_defaults.uint16_class) arrayType->castClass = il2cpp_defaults.int16_class; else if (arrayType->castClass == il2cpp_defaults.uint32_class) arrayType->castClass = il2cpp_defaults.int32_class; else if (arrayType->castClass == il2cpp_defaults.uint64_class) arrayType->castClass = il2cpp_defaults.int64_class; #if IL2CPP_SIZEOF_VOID_P == 8 else if (arrayType->castClass == il2cpp_defaults.int_class || arrayType->castClass == il2cpp_defaults.uint_class) arrayType->castClass = il2cpp_defaults.int64_class; #else else if (arrayType->castClass == il2cpp_defaults.int_class || arrayType->castClass == il2cpp_defaults.uint_class) arrayType->castClass = il2cpp_defaults.int32_class; #endif arrayType->has_references = Type::IsReference(elementType->byval_arg) || elementType->has_references; } void ArrayMetadata::SetupArrayInterfaces(Il2CppClass* klass, const FastAutoLock& lock) { if (klass->byval_arg->type == IL2CPP_TYPE_SZARRAY) { Il2CppTypeVector genericArguments; genericArguments.push_back(klass->element_class->byval_arg); IL2CPP_ASSERT(klass->interfaces_count == kImplicitArrayInterfaceCount); klass->implementedInterfaces = (Il2CppClass**)MetadataMalloc(klass->interfaces_count * sizeof(Il2CppClass*)); klass->implementedInterfaces[0] = Class::GetInflatedGenericInstanceClass(il2cpp_defaults.generic_ilist_class, genericArguments); IL2CPP_ASSERT(klass->implementedInterfaces[0]); klass->implementedInterfaces[1] = Class::GetInflatedGenericInstanceClass(il2cpp_defaults.generic_icollection_class, genericArguments); IL2CPP_ASSERT(klass->implementedInterfaces[1]); klass->implementedInterfaces[2] = Class::GetInflatedGenericInstanceClass(il2cpp_defaults.generic_ienumerable_class, genericArguments); IL2CPP_ASSERT(klass->implementedInterfaces[2]); #if NET_4_0 klass->implementedInterfaces[3] = Class::GetInflatedGenericInstanceClass(il2cpp_defaults.generic_ireadonlylist_class, genericArguments); IL2CPP_ASSERT(klass->implementedInterfaces[3]); klass->implementedInterfaces[4] = Class::GetInflatedGenericInstanceClass(il2cpp_defaults.generic_ireadonlycollection_class, genericArguments); IL2CPP_ASSERT(klass->implementedInterfaces[4]); #endif } } void ArrayMetadata::SetupArrayVTable(Il2CppClass* klass, const FastAutoLock& lock) { // we assume we are being called as part of Class::Init and that the element class has already been initialized IL2CPP_ASSERT(klass->element_class->initialized); SetupCastClass(klass); SetupArrayVTableAndInterfaceOffsets(klass); SetupArrayMethods(klass); } struct SZArrayClassHash { size_t operator()(const Il2CppClass* arrayClass) const { return Il2CppTypeHash::Hash(arrayClass->byval_arg); } }; struct SZArrayClassCompare { bool operator()(const Il2CppClass* arrayClass1, const Il2CppClass* arrayClass2) const { return Il2CppTypeEqualityComparer::AreEqual(arrayClass1->byval_arg, arrayClass2->byval_arg); } }; struct ArrayClassHash { size_t operator()(const std::pair& arrayClass) const { return Il2CppTypeHash::Hash(arrayClass.first->byval_arg) * arrayClass.second; } }; struct ArrayClassCompare { bool operator()(const std::pair& arrayClass1, const std::pair& arrayClass2) const { return Il2CppTypeEqualityComparer::AreEqual(arrayClass1.first->byval_arg, arrayClass2.first->byval_arg) && arrayClass1.second == arrayClass2.second; } }; typedef Il2CppHashMap SZArrayClassMap; typedef Il2CppHashMap, Il2CppClass*, ArrayClassHash, ArrayClassCompare> ArrayClassMap; SZArrayClassMap s_SZArrayClassMap; ArrayClassMap s_ArrayClassMap; Il2CppClass* ArrayMetadata::GetBoundedArrayClass(Il2CppClass* elementClass, uint32_t rank, bool bounded) { FastAutoLock lock(&il2cpp::vm::g_MetadataLock); NOT_IMPLEMENTED_NO_ASSERT(ArrayMetadata::GetBoundedArrayClass, "Use more granular lock for looking up arrays, but then handle race between lookup, construction, and caching"); IL2CPP_ASSERT(rank <= 255); if (rank > 1) bounded = false; if (rank > 1 || bounded) { ArrayClassMap::const_iterator iter = s_ArrayClassMap.find(std::make_pair(elementClass, rank)); if (iter != s_ArrayClassMap.end()) return iter->second; } else { SZArrayClassMap::const_iterator iter = s_SZArrayClassMap.find(elementClass); if (iter != s_SZArrayClassMap.end()) return iter->second; } Il2CppClass* arrayClass = il2cpp_defaults.array_class; Class::Init(arrayClass); //count number of virtual call slots for array class ::std::vector interfaces; if (rank <= 1 && !bounded) CollectImplicitArrayInterfacesFromElementClass(elementClass, interfaces); size_t slots = arrayClass->vtable_count + interfaces.size() * (il2cpp_defaults.generic_ilist_class->method_count + il2cpp_defaults.generic_icollection_class->method_count + il2cpp_defaults.generic_ienumerable_class->method_count); #if NET_4_0 slots += interfaces.size() * (il2cpp_defaults.generic_ireadonlylist_class->method_count + il2cpp_defaults.generic_ireadonlycollection_class->method_count); #endif Il2CppClass* klass = (Il2CppClass*)MetadataCalloc(1, sizeof(Il2CppClass) + (slots * sizeof(VirtualInvokeData))); klass->image = elementClass->image; // can share the const char* since it's immutable klass->namespaze = elementClass->namespaze; klass->name = GetArrayName(elementClass->name, rank, bounded); klass->parent = il2cpp_defaults.array_class; klass->flags = TYPE_ATTRIBUTE_AUTO_LAYOUT | TYPE_ATTRIBUTE_ANSI_CLASS | TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_PUBLIC | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_SERIALIZABLE; klass->rank = rank; klass->instance_size = Class::GetInstanceSize(arrayClass); klass->vtable_count = static_cast(slots); // need this before we access the size or has_references Class::SetupFields(elementClass); klass->element_size = Class::GetArrayElementSize(elementClass); klass->native_size = klass->thread_static_fields_offset = -1; klass->has_references = Type::IsReference(elementClass->byval_arg) || elementClass->has_references; klass->element_class = elementClass; Il2CppType* thisArg = (Il2CppType*)MetadataCalloc(1, sizeof(Il2CppType)); Il2CppType* byValArg = (Il2CppType*)MetadataCalloc(1, sizeof(Il2CppType)); if (rank > 1 || bounded) { Il2CppArrayType *at = (Il2CppArrayType*)MetadataCalloc(1, sizeof(Il2CppArrayType)); byValArg->type = IL2CPP_TYPE_ARRAY; byValArg->data.array = at; at->etype = elementClass->byval_arg; at->rank = rank; } else { byValArg->type = IL2CPP_TYPE_SZARRAY; byValArg->data.type = elementClass->byval_arg; } memcpy(thisArg, byValArg, sizeof(Il2CppType)); thisArg->byref = 1; klass->this_arg = thisArg; klass->byval_arg = byValArg; if (rank > 1 || bounded) { klass->interfaces_count = 0; } else { klass->interfaces_count = kImplicitArrayInterfaceCount; } klass->interopData = MetadataCache::GetInteropDataForType(klass->byval_arg); if (rank > 1 || bounded) s_ArrayClassMap.insert(std::make_pair(ArrayClassMap::key_type(std::make_pair(klass->element_class, klass->rank)), klass)); else s_SZArrayClassMap.insert(std::make_pair(klass->element_class, klass)); return klass; } void ArrayMetadata::WalkSZArrays(ArrayTypeWalkCallback callback, void* context) { FastAutoLock lock(&il2cpp::vm::g_MetadataLock); for (SZArrayClassMap::iterator it = s_SZArrayClassMap.begin(); it != s_SZArrayClassMap.end(); it++) { callback(it->second, context); } } void ArrayMetadata::WalkArrays(ArrayTypeWalkCallback callback, void* context) { FastAutoLock lock(&il2cpp::vm::g_MetadataLock); for (ArrayClassMap::iterator it = s_ArrayClassMap.begin(); it != s_ArrayClassMap.end(); it++) { callback(it->second, context); } } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/ArrayMetadata.h ================================================ #pragma once #include #include "os/Mutex.h" struct Il2CppClass; namespace il2cpp { namespace metadata { class ArrayMetadata { public: static Il2CppClass* GetBoundedArrayClass(Il2CppClass* elementClass, uint32_t rank, bool bounded); typedef void(*ArrayTypeWalkCallback)(Il2CppClass* type, void* context); static void WalkSZArrays(ArrayTypeWalkCallback callback, void* context); static void WalkArrays(ArrayTypeWalkCallback callback, void* context); // called as part of Class::Init with lock held static void SetupArrayInterfaces(Il2CppClass* klass, const il2cpp::os::FastAutoLock& lock); static void SetupArrayVTable(Il2CppClass* klass, const il2cpp::os::FastAutoLock& lock); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/FieldLayout.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "vm/Class.h" #include "vm/GenericClass.h" #include "vm/Type.h" #include "metadata/FieldLayout.h" #include using il2cpp::vm::Class; using il2cpp::vm::GenericClass; using il2cpp::vm::Type; namespace il2cpp { namespace metadata { typedef void* voidptr_t; #define IL2CPP_ALIGN_STRUCT(type) struct type ## AlignStruct {uint8_t pad; type t; }; IL2CPP_ALIGN_STRUCT(voidptr_t) IL2CPP_ALIGN_STRUCT(int8_t) IL2CPP_ALIGN_STRUCT(int16_t) IL2CPP_ALIGN_STRUCT(int32_t) IL2CPP_ALIGN_STRUCT(int64_t) IL2CPP_ALIGN_STRUCT(intptr_t) IL2CPP_ALIGN_STRUCT(float) IL2CPP_ALIGN_STRUCT(double) #define IL2CPP_ALIGN_OF(type) ((size_t)offsetof(type ## AlignStruct, t)) SizeAndAlignment FieldLayout::GetTypeSizeAndAlignment(const Il2CppType* type) { SizeAndAlignment sa = { 0 }; if (type->byref) { sa.size = sizeof(voidptr_t); sa.alignment = IL2CPP_ALIGN_OF(voidptr_t); return sa; } switch (type->type) { case IL2CPP_TYPE_I1: case IL2CPP_TYPE_U1: case IL2CPP_TYPE_BOOLEAN: sa.size = sizeof(int8_t); sa.alignment = IL2CPP_ALIGN_OF(int8_t); return sa; case IL2CPP_TYPE_I2: case IL2CPP_TYPE_U2: case IL2CPP_TYPE_CHAR: sa.size = sizeof(int16_t); sa.alignment = IL2CPP_ALIGN_OF(int16_t); return sa; case IL2CPP_TYPE_I4: case IL2CPP_TYPE_U4: sa.size = sizeof(int32_t); sa.alignment = IL2CPP_ALIGN_OF(int32_t); return sa; case IL2CPP_TYPE_I8: case IL2CPP_TYPE_U8: sa.size = sizeof(int64_t); sa.alignment = IL2CPP_ALIGN_OF(int64_t); return sa; case IL2CPP_TYPE_I: case IL2CPP_TYPE_U: // TODO should we use pointer or size_t here? sa.size = sizeof(intptr_t); sa.alignment = IL2CPP_ALIGN_OF(intptr_t); return sa; case IL2CPP_TYPE_R4: sa.size = sizeof(float); sa.alignment = IL2CPP_ALIGN_OF(float); return sa; case IL2CPP_TYPE_R8: sa.size = sizeof(double); sa.alignment = IL2CPP_ALIGN_OF(double); return sa; case IL2CPP_TYPE_PTR: case IL2CPP_TYPE_FNPTR: case IL2CPP_TYPE_STRING: case IL2CPP_TYPE_SZARRAY: case IL2CPP_TYPE_ARRAY: case IL2CPP_TYPE_CLASS: case IL2CPP_TYPE_OBJECT: case IL2CPP_TYPE_VAR: case IL2CPP_TYPE_MVAR: sa.size = sizeof(voidptr_t); sa.alignment = IL2CPP_ALIGN_OF(voidptr_t); return sa; case IL2CPP_TYPE_VALUETYPE: if (Type::IsEnum(type)) { return GetTypeSizeAndAlignment(Class::GetEnumBaseType(Type::GetClass(type))); } else { uint32_t alignment; sa.size = Class::GetValueSize(Type::GetClass(type), &alignment); sa.alignment = alignment; return sa; } case IL2CPP_TYPE_GENERICINST: { Il2CppGenericClass* gclass = type->data.generic_class; Il2CppClass* container_class = GenericClass::GetTypeDefinition(gclass); if (container_class != NULL && container_class->valuetype) { if (container_class->enumtype) { return GetTypeSizeAndAlignment(Class::GetEnumBaseType(container_class)); } else { uint32_t alignment; sa.size = Class::GetValueSize(Class::FromIl2CppType(type), &alignment); sa.alignment = alignment; return sa; } } else { sa.size = sizeof(voidptr_t); sa.alignment = IL2CPP_ALIGN_OF(voidptr_t); return sa; } } default: IL2CPP_ASSERT(0); break; } return sa; } static size_t AlignTo(size_t size, size_t alignment) { if (size & (alignment - 1)) { size += alignment - 1; size &= ~(alignment - 1); } return size; } void FieldLayout::LayoutFields(size_t parentSize, size_t actualParentSize, size_t parentAlignment, const metadata::Il2CppTypeVector& fieldTypes, FieldLayoutData& data) { data.classSize = parentSize; data.actualClassSize = actualParentSize; IL2CPP_ASSERT(parentAlignment <= std::numeric_limits::max()); data.minimumAlignment = static_cast(parentAlignment); for (Il2CppTypeVector::const_iterator iter = fieldTypes.begin(); iter != fieldTypes.end(); ++iter) { SizeAndAlignment sa = GetTypeSizeAndAlignment(*iter); size_t offset = data.actualClassSize; offset += sa.alignment - 1; offset &= ~(sa.alignment - 1); data.FieldOffsets.push_back(offset); data.actualClassSize = offset + sa.size; data.minimumAlignment = std::max(data.minimumAlignment, (uint8_t)sa.alignment); } data.classSize = AlignTo(data.actualClassSize, data.minimumAlignment); // C++ ABI difference between MS and Clang #if IL2CPP_CXX_ABI_MSVC data.actualClassSize = data.classSize; #endif } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/FieldLayout.h ================================================ #pragma once #include #include #include "metadata/Il2CppTypeVector.h" namespace il2cpp { namespace metadata { struct SizeAndAlignment { size_t size; uint8_t alignment; }; class FieldLayout { public: struct FieldLayoutData { std::vector FieldOffsets; size_t classSize; size_t actualClassSize; uint8_t minimumAlignment; }; static void LayoutFields(size_t parentSize, size_t actualParentSize, size_t parentAlignment, const Il2CppTypeVector& fieldTypes, FieldLayoutData& data); static SizeAndAlignment GetTypeSizeAndAlignment(const Il2CppType* type); }; } /* namespace metadata */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/GenericMetadata.cpp ================================================ #include "il2cpp-config.h" #include "os/Mutex.h" #include "vm/Class.h" #include "vm/GenericClass.h" #include "vm/Image.h" #include "vm/Type.h" #include "metadata/GenericMetadata.h" #include "metadata/GenericMethod.h" #include "metadata/Il2CppGenericClassHash.h" #include "metadata/Il2CppGenericClassCompare.h" #include "metadata/Il2CppGenericInstCompare.h" #include "metadata/Il2CppGenericInstHash.h" #include "metadata/Il2CppTypeCompare.h" #include "metadata/Il2CppTypeHash.h" #include "utils/Memory.h" #include "utils/Il2CppHashMap.h" #include "utils/Il2CppHashSet.h" #include "utils/StringUtils.h" #include "vm/MetadataAlloc.h" #include "vm/MetadataCache.h" #include "class-internals.h" #include "tabledefs.h" #include #include using namespace il2cpp::vm; using il2cpp::metadata::GenericMethod; using il2cpp::os::FastAutoLock; using il2cpp::os::FastMutex; using il2cpp::utils::StringUtils; using std::vector; using std::pair; namespace il2cpp { namespace metadata { ParameterInfo* GenericMetadata::InflateParameters(const ParameterInfo* parameters, uint8_t parameterCount, const Il2CppGenericContext* context, bool inflateMethodVars) { ParameterInfo* inflatedParameters = (ParameterInfo*)MetadataCalloc(parameterCount, sizeof(ParameterInfo)); for (uint8_t j = 0; j < parameterCount; j++) { const ParameterInfo* param = parameters + j; ParameterInfo* param2 = inflatedParameters + j; param2->name = param->name; param2->position = param->position; param2->parameter_type = InflateIfNeeded(param->parameter_type, context, inflateMethodVars); param2->token = param->token; } return inflatedParameters; } const Il2CppType* GenericMetadata::InflateIfNeeded(const Il2CppType* type, const Il2CppGenericContext* context, bool inflateMethodVars) { switch (type->type) { case IL2CPP_TYPE_VAR: { Il2CppType* inflatedType = (Il2CppType*)MetadataMalloc(sizeof(Il2CppType)); const Il2CppGenericParameter* gp = Type::GetGenericParameter(type); IL2CPP_ASSERT(context->class_inst); IL2CPP_ASSERT(gp->num < context->class_inst->type_argc); memcpy(inflatedType, context->class_inst->type_argv[gp->num], sizeof(Il2CppType)); inflatedType->byref = type->byref; inflatedType->attrs = type->attrs; ++il2cpp_runtime_stats.inflated_type_count; return inflatedType; } case IL2CPP_TYPE_MVAR: { if (context->method_inst) { Il2CppType* inflatedType = (Il2CppType*)MetadataMalloc(sizeof(Il2CppType)); const Il2CppGenericParameter* gp = Type::GetGenericParameter(type); IL2CPP_ASSERT(gp->num < context->method_inst->type_argc); memcpy(inflatedType, context->method_inst->type_argv[gp->num], sizeof(Il2CppType)); inflatedType->byref = type->byref; inflatedType->attrs = type->attrs; ++il2cpp_runtime_stats.inflated_type_count; return inflatedType; } return type; } case IL2CPP_TYPE_ARRAY: { Il2CppType* inflatedType = (Il2CppType*)MetadataMalloc(sizeof(Il2CppType)); memcpy(inflatedType, type, sizeof(Il2CppType)); Il2CppArrayType* arrayType = (Il2CppArrayType*)MetadataMalloc(sizeof(Il2CppArrayType)); memcpy(arrayType, type->data.array, sizeof(Il2CppArrayType)); arrayType->etype = InflateIfNeeded(type->data.array->etype, context, inflateMethodVars); inflatedType->data.array = arrayType; ++il2cpp_runtime_stats.inflated_type_count; return inflatedType; } case IL2CPP_TYPE_SZARRAY: { Il2CppType* arrayType = (Il2CppType*)MetadataMalloc(sizeof(Il2CppType)); memcpy(arrayType, type, sizeof(Il2CppType)); arrayType->data.type = InflateIfNeeded(type->data.type, context, inflateMethodVars); ++il2cpp_runtime_stats.inflated_type_count; return arrayType; } case IL2CPP_TYPE_GENERICINST: { Il2CppType* genericType = (Il2CppType*)MetadataMalloc(sizeof(Il2CppType)); memcpy(genericType, type, sizeof(Il2CppType)); const Il2CppGenericInst* inst = type->data.generic_class->context.class_inst; Il2CppTypeVector types; for (uint32_t i = 0; i < inst->type_argc; i++) types.push_back(InflateIfNeeded(inst->type_argv[i], context, inflateMethodVars)); const Il2CppGenericInst* inflatedInst = MetadataCache::GetGenericInst(types); genericType->data.generic_class = GenericMetadata::GetGenericClass(GenericClass::GetTypeDefinition(type->data.generic_class), inflatedInst); ++il2cpp_runtime_stats.inflated_type_count; return genericType; } default: return type; } } static os::FastMutex s_GenericClassMutex; typedef Il2CppHashSet Il2CppGenericClassSet; static Il2CppGenericClassSet s_GenericClassSet; Il2CppGenericClass* GenericMetadata::GetGenericClass(Il2CppClass* containerClass, const Il2CppGenericInst* inst) { return GetGenericClass(MetadataCache::GetIndexForTypeDefinition(containerClass), inst); } Il2CppGenericClass* GenericMetadata::GetGenericClass(TypeDefinitionIndex elementClassIndex, const Il2CppGenericInst* inst) { // temporary inst to lookup a permanent one that may already exist Il2CppGenericClass genericClass = { 0 }; genericClass.typeDefinitionIndex = elementClassIndex; genericClass.context.class_inst = inst; FastAutoLock lock(&s_GenericClassMutex); Il2CppGenericClassSet::const_iterator iter = s_GenericClassSet.find(&genericClass); if (iter != s_GenericClassSet.end()) return *iter; Il2CppGenericClass* newClass = MetadataAllocGenericClass(); newClass->typeDefinitionIndex = elementClassIndex; newClass->context.class_inst = inst; s_GenericClassSet.insert(newClass); ++il2cpp_runtime_stats.generic_class_count; return newClass; } const MethodInfo* GenericMetadata::Inflate(const MethodInfo* methodDefinition, Il2CppClass* declaringClass, const Il2CppGenericContext* context) { const Il2CppGenericMethod* gmethod = MetadataCache::GetGenericMethod(methodDefinition, context->class_inst, context->method_inst); return GenericMethod::GetMethod(gmethod); } static void RecursiveGenericDepthFor(const Il2CppGenericInst* inst, int& depth) { if (inst == NULL) return; int maximumDepth = depth; for (size_t i = 0; i < inst->type_argc; i++) { if (inst->type_argv[i]->type == IL2CPP_TYPE_GENERICINST) { maximumDepth++; int classInstDepth = 0; RecursiveGenericDepthFor(inst->type_argv[i]->data.generic_class->context.class_inst, classInstDepth); int methodInstDepth = 0; RecursiveGenericDepthFor(inst->type_argv[i]->data.generic_class->context.method_inst, methodInstDepth); maximumDepth += std::max(classInstDepth, methodInstDepth); } } depth = maximumDepth; } static int RecursiveGenericDepthFor(const Il2CppGenericInst* inst) { int depth = 0; RecursiveGenericDepthFor(inst, depth); return depth; } const Il2CppGenericMethod* GenericMetadata::Inflate(const Il2CppGenericMethod* genericMethod, const Il2CppGenericContext* context) { const Il2CppGenericInst* classInst = genericMethod->context.class_inst; const Il2CppGenericInst* methodInst = genericMethod->context.method_inst; if (classInst) { Il2CppTypeVector classTypes; for (size_t i = 0; i < classInst->type_argc; i++) classTypes.push_back(GenericMetadata::InflateIfNeeded(classInst->type_argv[i], context, true)); classInst = MetadataCache::GetGenericInst(classTypes); } if (methodInst) { Il2CppTypeVector methodTypes; for (size_t i = 0; i < methodInst->type_argc; i++) methodTypes.push_back(GenericMetadata::InflateIfNeeded(methodInst->type_argv[i], context, true)); methodInst = MetadataCache::GetGenericInst(methodTypes); } // We have cases where we could infinitely recurse, inflating generics at runtime. This will lead to a stack overflow. // As we do for code generation, let's cut this off at an arbitrary level. If something tries to execute code at this // level, a crash will happen. We'll assume that this code won't actually be executed though. if (RecursiveGenericDepthFor(classInst) > MaximumRuntimeGenericDepth || RecursiveGenericDepthFor(methodInst) > MaximumRuntimeGenericDepth) return NULL; return MetadataCache::GetGenericMethod(genericMethod->methodDefinition, classInst, methodInst); } Il2CppRGCTXData* GenericMetadata::InflateRGCTX(RGCTXIndex rgctxStartIndex, int16_t rgctxCount, const Il2CppGenericContext* context) { if (rgctxStartIndex == kRGCTXIndexInvalid) return NULL; Il2CppRGCTXData* dataValues = (Il2CppRGCTXData*)MetadataCalloc(rgctxCount, sizeof(Il2CppRGCTXData)); for (RGCTXIndex rgctxIndex = 0; rgctxIndex < rgctxCount; rgctxIndex++) { const Il2CppRGCTXDefinition* definitionData = MetadataCache::GetRGCTXDefinitionFromIndex(rgctxStartIndex + rgctxIndex); switch (definitionData->type) { case IL2CPP_RGCTX_DATA_TYPE: dataValues[rgctxIndex].type = GenericMetadata::InflateIfNeeded(MetadataCache::GetIl2CppTypeFromIndex(definitionData->data.typeIndex), context, true); break; case IL2CPP_RGCTX_DATA_CLASS: dataValues[rgctxIndex].klass = Class::FromIl2CppType(GenericMetadata::InflateIfNeeded(MetadataCache::GetIl2CppTypeFromIndex(definitionData->data.typeIndex), context, true)); break; case IL2CPP_RGCTX_DATA_METHOD: dataValues[rgctxIndex].method = GenericMethod::GetMethod(Inflate(MetadataCache::GetGenericMethodFromIndex(definitionData->data.methodIndex), context)); break; default: IL2CPP_ASSERT(0); } } return dataValues; } // temporary while we generate generics void GenericMetadata::RegisterGenericClass(Il2CppGenericClass *gclass) { // don't lock, this should only be called from startup and temporarily s_GenericClassSet.insert(gclass); } void GenericMetadata::WalkAllGenericClasses(GenericClassWalkCallback callback, void* context) { FastAutoLock lock(&s_GenericClassMutex); for (Il2CppGenericClassSet::iterator it = s_GenericClassSet.begin(); it != s_GenericClassSet.end(); it++) { if ((*it).key->cached_class != NULL) callback((*it).key->cached_class, context); } } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/GenericMetadata.h ================================================ #pragma once #include #include "il2cpp-metadata.h" #include "metadata/Il2CppTypeVector.h" struct Il2CppGenericClass; struct Il2CppGenericContext; struct Il2CppGenericInst; struct Il2CppGenericMethod; union Il2CppRGCTXData; struct Il2CppRGCTXDefinition; struct Il2CppType; struct MethodInfo; struct ParameterInfo; struct Il2CppClass; namespace il2cpp { namespace metadata { class GenericMetadata { public: static ParameterInfo* InflateParameters(const ParameterInfo* parameters, uint8_t parameterCount, const Il2CppGenericContext* context, bool inflateMethodVars); static Il2CppGenericClass* GetGenericClass(Il2CppClass* elementClass, const Il2CppGenericInst* inst); static Il2CppGenericClass* GetGenericClass(TypeDefinitionIndex elementClassIndex, const Il2CppGenericInst* inst); static const MethodInfo* Inflate(const MethodInfo* methodDefinition, Il2CppClass* declaringClass, const Il2CppGenericContext* context); static const Il2CppGenericMethod* Inflate(const Il2CppGenericMethod* genericMethod, const Il2CppGenericContext* context); static Il2CppRGCTXData* InflateRGCTX(RGCTXIndex rgctxEntryIndex, int16_t rgctxEntryCount, const Il2CppGenericContext* context); // temporary while we generate generics static void RegisterGenericClass(Il2CppGenericClass *gclass); static const Il2CppType* InflateIfNeeded(const Il2CppType* type, const Il2CppGenericContext* context, bool inflateMethodVars); typedef void(*GenericClassWalkCallback)(Il2CppClass* type, void* context); static void WalkAllGenericClasses(GenericClassWalkCallback callback, void* context); static const int MaximumRuntimeGenericDepth = 8; }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/GenericMethod.cpp ================================================ #include "il2cpp-config.h" #include "metadata/GenericMetadata.h" #include "metadata/GenericMethod.h" #include "metadata/GenericSharing.h" #include "metadata/Il2CppGenericMethodCompare.h" #include "metadata/Il2CppGenericMethodHash.h" #include "os/Mutex.h" #include "utils/Memory.h" #include "vm/Class.h" #include "vm/GenericClass.h" #include "vm/MetadataAlloc.h" #include "vm/MetadataCache.h" #include "vm/MetadataLock.h" #include "vm/Method.h" #include "vm/Runtime.h" #include "vm/Type.h" #include "utils/Il2CppHashMap.h" #include "class-internals.h" #include "metadata.h" #include using il2cpp::metadata::GenericMetadata; using il2cpp::metadata::GenericSharing; using il2cpp::os::FastAutoLock; using il2cpp::vm::Class; using il2cpp::vm::GenericClass; using il2cpp::vm::MetadataCalloc; using il2cpp::vm::MetadataCache; using il2cpp::vm::Method; using il2cpp::vm::Runtime; using il2cpp::vm::Type; namespace il2cpp { namespace metadata { typedef Il2CppHashMap Il2CppGenericMethodMap; static Il2CppGenericMethodMap s_GenericMethodMap; const MethodInfo* GenericMethod::GetMethod(const Il2CppGenericMethod* gmethod) { FastAutoLock lock(&il2cpp::vm::g_MetadataLock); // This can be NULL only when we have hit the generic recursion depth limit. if (gmethod == NULL) return NULL; Il2CppGenericMethodMap::const_iterator iter = s_GenericMethodMap.find(gmethod); if (iter != s_GenericMethodMap.end()) return iter->second; const MethodInfo* methodDefinition = gmethod->methodDefinition; Il2CppClass* declaringClass = methodDefinition->declaring_type; if (gmethod->context.class_inst) { IL2CPP_ASSERT(!declaringClass->generic_class); Il2CppGenericClass* genericClassDeclaringType = GenericMetadata::GetGenericClass(methodDefinition->declaring_type, gmethod->context.class_inst); declaringClass = GenericClass::GetClass(genericClassDeclaringType); // we may fail if we cannot construct generic type if (!declaringClass) return NULL; } MethodInfo* newMethod = (MethodInfo*)MetadataCalloc(1, sizeof(MethodInfo)); // we set this here because the initialization may recurse and try to retrieve the same generic method // this is safe because we *always* take the lock when retrieving the MethodInfo from a generic method. // if we move lock to only if MethodInfo needs constructed then we need to revisit this since we could return a partially initialized MethodInfo s_GenericMethodMap.insert(std::make_pair(gmethod, newMethod)); newMethod->declaring_type = declaringClass; newMethod->flags = methodDefinition->flags; newMethod->iflags = methodDefinition->iflags; newMethod->slot = methodDefinition->slot; newMethod->name = methodDefinition->name; newMethod->is_generic = false; newMethod->is_inflated = true; newMethod->customAttributeIndex = methodDefinition->customAttributeIndex; newMethod->token = methodDefinition->token; newMethod->return_type = GenericMetadata::InflateIfNeeded(methodDefinition->return_type, &gmethod->context, true); newMethod->parameters_count = methodDefinition->parameters_count; newMethod->parameters = GenericMetadata::InflateParameters(methodDefinition->parameters, methodDefinition->parameters_count, &gmethod->context, true); newMethod->genericMethod = gmethod; if (!gmethod->context.method_inst) { if (methodDefinition->is_generic) newMethod->is_generic = true; if (!declaringClass->generic_class) { const Il2CppGenericContainer* container = methodDefinition->genericContainer; newMethod->genericContainer = container; } newMethod->methodDefinition = methodDefinition->methodDefinition; } else { // we only need RGCTX for generic instance methods newMethod->rgctx_data = GenericMetadata::InflateRGCTX(methodDefinition->methodDefinition->rgctxStartIndex, methodDefinition->methodDefinition->rgctxCount, &gmethod->context); } newMethod->invoker_method = MetadataCache::GetInvokerMethodPointer(methodDefinition, &gmethod->context); newMethod->methodPointer = MetadataCache::GetMethodPointer(methodDefinition, &gmethod->context); ++il2cpp_runtime_stats.inflated_method_count; return newMethod; } const Il2CppGenericContext* GenericMethod::GetContext(const Il2CppGenericMethod* gmethod) { return &gmethod->context; } static std::string FormatGenericArguments(const Il2CppGenericInst* inst) { std::ostringstream sstream; if (inst) { sstream << "<"; for (size_t i = 0; i < inst->type_argc; ++i) { if (i != 0) sstream << ", "; sstream << Type::GetName(inst->type_argv[i], IL2CPP_TYPE_NAME_FORMAT_FULL_NAME); } sstream << ">"; } return sstream.str(); } std::string GenericMethod::GetFullName(const Il2CppGenericMethod* gmethod) { const MethodInfo* method = gmethod->methodDefinition; std::ostringstream sstream; sstream << Type::GetName(gmethod->methodDefinition->declaring_type->byval_arg, IL2CPP_TYPE_NAME_FORMAT_FULL_NAME); sstream << FormatGenericArguments(gmethod->context.class_inst); sstream << "::"; sstream << Method::GetName(method); sstream << FormatGenericArguments(gmethod->context.method_inst); return sstream.str(); } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/GenericMethod.h ================================================ #pragma once #include struct MethodInfo; struct Il2CppGenericMethod; struct Il2CppGenericContext; namespace il2cpp { namespace metadata { class GenericMethod { public: // exported public: //internal static const MethodInfo* GetMethod(const Il2CppGenericMethod* gmethod); static const Il2CppGenericContext* GetContext(const Il2CppGenericMethod* gmethod); static std::string GetFullName(const Il2CppGenericMethod* gmethod); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/GenericSharing.cpp ================================================ #include "il2cpp-config.h" #include "metadata/GenericSharing.h" #include "vm/Type.h" #include "metadata.h" using il2cpp::vm::Type; namespace il2cpp { namespace metadata { bool GenericSharing::IsShareable(Il2CppGenericClass* gclass) { const Il2CppGenericInst* classInst = gclass->context.class_inst; if (classInst) { for (uint32_t i = 0; i < classInst->type_argc; ++i) { if (!Type::IsReference(classInst->type_argv[i])) return false; } } return true; } bool GenericSharing::IsShareable(Il2CppGenericMethod* gmethod) { const Il2CppGenericInst* methodInst = gmethod->context.method_inst; if (methodInst) { for (uint32_t i = 0; i < methodInst->type_argc; ++i) { if (!Type::IsReference(methodInst->type_argv[i])) return false; } } return true; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/GenericSharing.h ================================================ #pragma once struct Il2CppGenericClass; struct Il2CppGenericMethod; namespace il2cpp { namespace metadata { class GenericSharing { public: static bool IsShareable(Il2CppGenericClass* gclass); static bool IsShareable(Il2CppGenericMethod* gmethod); }; } /* namespace metadata */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppGenericClassCompare.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "Il2CppGenericClassCompare.h" #include "Il2CppGenericInstCompare.h" namespace il2cpp { namespace metadata { bool Il2CppGenericClassCompare::operator()(const Il2CppGenericClass* gc1, const Il2CppGenericClass* gc2) const { return Compare(gc1, gc2); } bool Il2CppGenericClassCompare::Compare(const Il2CppGenericClass* gc1, const Il2CppGenericClass* gc2) { if (gc1->typeDefinitionIndex != gc2->typeDefinitionIndex) return false; return Il2CppGenericInstCompare::Compare(gc1->context.class_inst, gc2->context.class_inst); } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppGenericClassCompare.h ================================================ #pragma once #include "utils/KeyWrapper.h" struct Il2CppGenericClass; namespace il2cpp { namespace metadata { class Il2CppGenericClassCompare { public: bool operator()(const Il2CppGenericClass* t1, const Il2CppGenericClass* t2) const; static bool Compare(const Il2CppGenericClass* t1, const Il2CppGenericClass* t2); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppGenericClassHash.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "Il2CppGenericClassHash.h" #include "Il2CppGenericContextHash.h" #include "Il2CppTypeHash.h" #include "utils/HashUtils.h" using il2cpp::utils::HashUtils; namespace il2cpp { namespace metadata { size_t Il2CppGenericClassHash::operator()(const Il2CppGenericClass* item) const { return Hash(item); } size_t Il2CppGenericClassHash::Hash(const Il2CppGenericClass* item) { size_t containerHash = item->typeDefinitionIndex; size_t contextHash = Il2CppGenericContextHash::Hash(&item->context); return HashUtils::Combine(containerHash, contextHash); } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppGenericClassHash.h ================================================ #pragma once struct Il2CppGenericClass; namespace il2cpp { namespace metadata { class Il2CppGenericClassHash { public: size_t operator()(const Il2CppGenericClass* ea) const; static size_t Hash(const Il2CppGenericClass* t1); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppGenericContextCompare.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "Il2CppGenericContextCompare.h" #include "Il2CppGenericInstCompare.h" namespace il2cpp { namespace metadata { bool Il2CppGenericContextCompare::operator()(const Il2CppGenericContext* gc1, const Il2CppGenericContext* gc2) const { return Compare(gc1, gc2); } bool Il2CppGenericContextCompare::Compare(const Il2CppGenericContext* gc1, const Il2CppGenericContext* gc2) { NOT_IMPLEMENTED_NO_ASSERT(Il2CppGenericContextCompare::Compare, "We should ensure GenericInst uniqueness and do direct comparison"); // return gc1->class_inst == gc2->class_inst && gc1->method_inst == gc2->method_inst; if ((!gc1->class_inst && gc2->class_inst) || (gc1->class_inst && !gc2->class_inst)) return false; if ((!gc1->method_inst && gc2->method_inst) || (gc1->method_inst && !gc2->method_inst)) return false; return (!gc1->class_inst || Il2CppGenericInstCompare::Compare(gc1->class_inst, gc2->class_inst)) && (!gc1->method_inst || Il2CppGenericInstCompare::Compare(gc1->method_inst, gc2->method_inst)); } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppGenericContextCompare.h ================================================ #pragma once struct Il2CppGenericContext; namespace il2cpp { namespace metadata { class Il2CppGenericContextCompare { public: bool operator()(const Il2CppGenericContext* t1, const Il2CppGenericContext* t2) const; static bool Compare(const Il2CppGenericContext* t1, const Il2CppGenericContext* t2); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppGenericContextHash.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "Il2CppGenericContextHash.h" #include "Il2CppGenericInstHash.h" #include "Il2CppTypeHash.h" #include "utils/HashUtils.h" using il2cpp::utils::HashUtils; namespace il2cpp { namespace metadata { size_t Il2CppGenericContextHash::operator()(const Il2CppGenericContext* context) const { return Hash(context); } size_t Il2CppGenericContextHash::Hash(const Il2CppGenericContext* context) { size_t classInstHash = 0; size_t methodInstHash = 0; if (context->class_inst) classInstHash = Il2CppGenericInstHash::Hash(context->class_inst); if (context->method_inst) methodInstHash = Il2CppGenericInstHash::Hash(context->method_inst); return HashUtils::Combine(classInstHash, methodInstHash); } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppGenericContextHash.h ================================================ #pragma once struct Il2CppGenericContext; namespace il2cpp { namespace metadata { class Il2CppGenericContextHash { public: size_t operator()(const Il2CppGenericContext* ea) const; static size_t Hash(const Il2CppGenericContext* t1); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppGenericInstCompare.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "Il2CppGenericInstCompare.h" #include "Il2CppTypeCompare.h" namespace il2cpp { namespace metadata { bool Il2CppGenericInstCompare::operator()(const KeyWrapper& t1, const KeyWrapper& t2) const { return Compare(t1, t2); } bool Il2CppGenericInstCompare::Compare(const KeyWrapper& t1, const KeyWrapper& t2) { if (t1.type != t2.type) return false; else if (!t1.isNormal()) return true; if (t1.key->type_argc != t2.key->type_argc) return false; for (size_t i = 0; i < t1.key->type_argc; ++i) { if (!Il2CppTypeEqualityComparer::AreEqual(t1.key->type_argv[i], t2.key->type_argv[i])) return false; } return true; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppGenericInstCompare.h ================================================ #pragma once #include "utils/KeyWrapper.h" struct Il2CppGenericInst; namespace il2cpp { namespace metadata { class Il2CppGenericInstCompare { public: bool operator()(const KeyWrapper& t1, const KeyWrapper& t2) const; static bool Compare(const KeyWrapper& t1, const KeyWrapper& t2); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppGenericInstHash.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "Il2CppGenericInstHash.h" #include "Il2CppTypeHash.h" #include "utils/HashUtils.h" using il2cpp::utils::HashUtils; namespace il2cpp { namespace metadata { size_t Il2CppGenericInstHash::operator()(const Il2CppGenericInst* item) const { return Hash(item); } size_t Il2CppGenericInstHash::Hash(const Il2CppGenericInst* item) { size_t hash = item->type_argc; for (size_t i = 0; i < item->type_argc; ++i) hash = HashUtils::Combine(hash, Il2CppTypeHash::Hash(item->type_argv[i])); return hash; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppGenericInstHash.h ================================================ #pragma once struct Il2CppGenericInst; namespace il2cpp { namespace metadata { class Il2CppGenericInstHash { public: size_t operator()(const Il2CppGenericInst* ea) const; static size_t Hash(const Il2CppGenericInst* t1); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppGenericMethodCompare.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "Il2CppGenericMethodCompare.h" #include "Il2CppGenericContextCompare.h" namespace il2cpp { namespace metadata { bool Il2CppGenericMethodCompare::operator()(const Il2CppGenericMethod* m1, const Il2CppGenericMethod* m2) const { return Equals(m1, m2); } bool Il2CppGenericMethodCompare::Equals(const Il2CppGenericMethod* m1, const Il2CppGenericMethod* m2) { if (m1->methodDefinition != m2->methodDefinition) return false; return Il2CppGenericContextCompare::Compare(&m1->context, &m2->context); } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppGenericMethodCompare.h ================================================ #pragma once #include "utils/KeyWrapper.h" struct Il2CppGenericMethod; namespace il2cpp { namespace metadata { struct Il2CppGenericMethodCompare { bool operator()(const Il2CppGenericMethod* m1, const Il2CppGenericMethod* m2) const; static bool Equals(const Il2CppGenericMethod* m1, const Il2CppGenericMethod* m2); }; } /* namespace metadata */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppGenericMethodHash.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "Il2CppGenericMethodHash.h" #include "Il2CppGenericContextHash.h" #include "utils/HashUtils.h" using il2cpp::utils::HashUtils; namespace il2cpp { namespace metadata { size_t Il2CppGenericMethodHash::operator()(const Il2CppGenericMethod* method) const { return Hash(method); } size_t Il2CppGenericMethodHash::Hash(const Il2CppGenericMethod* method) { size_t tokenHash = method->methodDefinition->token; size_t contextHash = Il2CppGenericContextHash::Hash(&method->context); return HashUtils::Combine(tokenHash, contextHash); } } /* namespace metadata */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppGenericMethodHash.h ================================================ #pragma once struct Il2CppGenericMethod; namespace il2cpp { namespace metadata { struct Il2CppGenericMethodHash { public: size_t operator()(const Il2CppGenericMethod* method) const; static size_t Hash(const Il2CppGenericMethod* method); }; } /* namespace metadata */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppSignatureCompare.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "Il2CppTypeCompare.h" #include "Il2CppSignatureCompare.h" #include "utils/KeyWrapper.h" namespace il2cpp { namespace metadata { bool Il2CppSignatureCompare::operator()(const il2cpp::utils::dynamic_array& s1, const il2cpp::utils::dynamic_array& s2) const { return Equals(s1, s2); } bool Il2CppSignatureCompare::Equals(const il2cpp::utils::dynamic_array& s1, const il2cpp::utils::dynamic_array& s2) { if (s1.size() != s2.size()) return false; il2cpp::utils::dynamic_array::const_iterator s1Iter, s1End = s1.end(), s2Iter; for (s1Iter = s1.begin(), s2Iter = s2.begin(); s1Iter != s1End; ++s1Iter, ++s2Iter) { if (!Il2CppTypeEqualityComparer::AreEqual(*s1Iter, *s2Iter)) return false; } return true; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppSignatureCompare.h ================================================ #pragma once #include "utils/dynamic_array.h" struct Il2CppType; namespace il2cpp { namespace metadata { struct Il2CppSignatureCompare { bool operator()(const il2cpp::utils::dynamic_array& s1, const il2cpp::utils::dynamic_array& s2) const; static bool Equals(const il2cpp::utils::dynamic_array& s1, const il2cpp::utils::dynamic_array& s2); }; } /* namespace metadata */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppSignatureHash.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "Il2CppTypeHash.h" #include "Il2CppSignatureHash.h" #include "utils/HashUtils.h" using il2cpp::utils::HashUtils; namespace il2cpp { namespace metadata { size_t Il2CppSignatureHash::operator()(const il2cpp::utils::dynamic_array& signature) const { return Hash(signature); } size_t Il2CppSignatureHash::Hash(const il2cpp::utils::dynamic_array& signature) { il2cpp::utils::dynamic_array::const_iterator iter, end = signature.end(); size_t retVal = 0; for (iter = signature.begin(); iter != end; ++iter) retVal = HashUtils::Combine(retVal, Il2CppTypeHash::Hash(*iter)); return retVal; } } /* namespace metadata */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppSignatureHash.h ================================================ #pragma once #include "utils/dynamic_array.h" struct Il2CppType; namespace il2cpp { namespace metadata { struct Il2CppSignatureHash { public: size_t operator()(const il2cpp::utils::dynamic_array& signature) const; static size_t Hash(const il2cpp::utils::dynamic_array& signature); }; } /* namespace metadata */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppTypeCompare.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "Il2CppTypeCompare.h" namespace il2cpp { namespace metadata { template static inline int Compare(const T& left, const T& right) { if (left == right) return 0; if (left < right) return -1; return 1; } static int Compare(const Il2CppType* t1, const Il2CppType* t2) { int result = Compare(t1->type, t2->type); if (result != 0) return result; result = Compare(t1->byref, t2->byref); if (result != 0) return result; switch (t1->type) { case IL2CPP_TYPE_VALUETYPE: case IL2CPP_TYPE_CLASS: return Compare(t1->data.klassIndex, t2->data.klassIndex); case IL2CPP_TYPE_PTR: case IL2CPP_TYPE_SZARRAY: return Compare(t1->data.type, t2->data.type); case IL2CPP_TYPE_ARRAY: { result = Compare(t1->data.array->rank, t2->data.array->rank); if (result != 0) return result; return Compare(t1->data.array->etype, t2->data.array->etype); } case IL2CPP_TYPE_GENERICINST: { const Il2CppGenericInst *i1 = t1->data.generic_class->context.class_inst; const Il2CppGenericInst *i2 = t2->data.generic_class->context.class_inst; // this happens when maximum generic recursion is hit if (i1 == NULL || i2 == NULL) { if (i1 == i2) return 0; return (i1 == NULL) ? -1 : 1; } result = Compare(i1->type_argc, i2->type_argc); if (result != 0) return result; result = Compare(t1->data.generic_class->typeDefinitionIndex, t2->data.generic_class->typeDefinitionIndex); if (result != 0) return result; /* FIXME: we should probably just compare the instance pointers directly. */ for (uint32_t i = 0; i < i1->type_argc; ++i) { result = Compare(i1->type_argv[i], i2->type_argv[i]); if (result != 0) return result; } return 0; } case IL2CPP_TYPE_VAR: case IL2CPP_TYPE_MVAR: return Compare(t1->data.genericParameterIndex, t2->data.genericParameterIndex); default: return 0; } NOT_IMPLEMENTED(Il2CppTypeEqualityComparer::compare); return Compare(static_cast(t1), static_cast(t2)); } bool Il2CppTypeEqualityComparer::AreEqual(const Il2CppType* t1, const Il2CppType* t2) { return Compare(t1, t2) == 0; } bool Il2CppTypeLess::operator()(const Il2CppType * t1, const Il2CppType * t2) const { return Compare(t1, t2) < 0; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppTypeCompare.h ================================================ #pragma once #include "utils/KeyWrapper.h" struct Il2CppType; namespace il2cpp { namespace metadata { class Il2CppTypeEqualityComparer { public: bool operator()(const Il2CppType* t1, const Il2CppType* t2) const { return AreEqual(t1, t2); } static bool AreEqual(const Il2CppType* t1, const Il2CppType* t2); }; class Il2CppTypeLess { public: bool operator()(const Il2CppType* t1, const Il2CppType* t2) const; }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppTypeHash.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "Il2CppTypeHash.h" #include "utils/StringUtils.h" #include "utils/HashUtils.h" using il2cpp::utils::HashUtils; using il2cpp::utils::StringUtils; namespace il2cpp { namespace metadata { size_t Il2CppTypeHash::operator()(const Il2CppType* t1) const { return Hash(t1); } size_t Il2CppTypeHash::Hash(const Il2CppType* t1) { size_t hash = t1->type; hash = HashUtils::Combine(hash, t1->byref); switch (t1->type) { case IL2CPP_TYPE_VALUETYPE: case IL2CPP_TYPE_CLASS: { return HashUtils::Combine(hash, t1->data.klassIndex); } case IL2CPP_TYPE_SZARRAY: case IL2CPP_TYPE_PTR: { return HashUtils::Combine(hash, Hash(t1->data.type)); } case IL2CPP_TYPE_GENERICINST: { const Il2CppGenericInst *inst = t1->data.generic_class->context.class_inst; hash = HashUtils::Combine(hash, t1->data.generic_class->typeDefinitionIndex); for (uint32_t i = 0; i < inst->type_argc; ++i) { hash = HashUtils::Combine(hash, Hash(inst->type_argv[i])); } return hash; } default: return hash; } return hash; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppTypeHash.h ================================================ #pragma once struct Il2CppType; namespace il2cpp { namespace metadata { class Il2CppTypeHash { public: size_t operator()(const Il2CppType* t1) const; static size_t Hash(const Il2CppType* t1); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata/Il2CppTypeVector.h ================================================ #pragma once #include struct Il2CppType; namespace il2cpp { namespace metadata { typedef std::vector Il2CppTypeVector; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/metadata.h ================================================ #pragma once #include #include "blob.h" #include "il2cpp-metadata.h" struct Il2CppClass; struct MethodInfo; struct Il2CppType; struct Il2CppArrayType { const Il2CppType* etype; uint8_t rank; uint8_t numsizes; uint8_t numlobounds; int *sizes; int *lobounds; }; struct Il2CppGenericInst { uint32_t type_argc; const Il2CppType **type_argv; }; struct Il2CppGenericContext { /* The instantiation corresponding to the class generic parameters */ const Il2CppGenericInst *class_inst; /* The instantiation corresponding to the method generic parameters */ const Il2CppGenericInst *method_inst; }; struct Il2CppGenericParameter { GenericContainerIndex ownerIndex; /* Type or method this parameter was defined in. */ StringIndex nameIndex; GenericParameterConstraintIndex constraintsStart; int16_t constraintsCount; uint16_t num; uint16_t flags; }; struct Il2CppGenericContainer { /* index of the generic type definition or the generic method definition corresponding to this container */ int32_t ownerIndex; // either index into Il2CppClass metadata array or Il2CppMethodDefinition array int32_t type_argc; /* If true, we're a generic method, otherwise a generic type definition. */ int32_t is_method; /* Our type parameters. */ GenericParameterIndex genericParameterStart; }; struct Il2CppGenericClass { TypeDefinitionIndex typeDefinitionIndex; /* the generic type definition */ Il2CppGenericContext context; /* a context that contains the type instantiation doesn't contain any method instantiation */ Il2CppClass *cached_class; /* if present, the Il2CppClass corresponding to the instantiation. */ }; struct Il2CppGenericMethod { const MethodInfo* methodDefinition; Il2CppGenericContext context; }; struct Il2CppType { union { // We have this dummy field first because pre C99 compilers (MSVC) can only initializer the first value in a union. void* dummy; TypeDefinitionIndex klassIndex; /* for VALUETYPE and CLASS */ const Il2CppType *type; /* for PTR and SZARRAY */ Il2CppArrayType *array; /* for ARRAY */ //MonoMethodSignature *method; GenericParameterIndex genericParameterIndex; /* for VAR and MVAR */ Il2CppGenericClass *generic_class; /* for GENERICINST */ } data; unsigned int attrs : 16; /* param attributes or field flags */ Il2CppTypeEnum type : 8; unsigned int num_mods : 6; /* max 64 modifiers follow at the end */ unsigned int byref : 1; unsigned int pinned : 1; /* valid when included in a local var signature */ //MonoCustomMod modifiers [MONO_ZERO_LEN_ARRAY]; /* this may grow */ }; typedef enum { IL2CPP_CALL_DEFAULT, IL2CPP_CALL_C, IL2CPP_CALL_STDCALL, IL2CPP_CALL_THISCALL, IL2CPP_CALL_FASTCALL, IL2CPP_CALL_VARARG } Il2CppCallConvention; enum Il2CppCharSet { CHARSET_ANSI, CHARSET_UNICODE }; ================================================ FILE: unity_decoder/libil2cpp/mono/ThreadPool/ThreadPoolDataStructures.h ================================================ #pragma once #if NET_4_0 #include #include "os/ConditionVariable.h" #include "os/Mutex.h" struct Il2CppDomain; struct Il2CppInternalThread; union ThreadPoolCounter { struct { int16_t max_working; /* determined by heuristic */ int16_t active; /* executing worker_thread */ int16_t working; /* actively executing worker_thread, not parked */ int16_t parked; /* parked */ } _; int64_t as_int64_t; }; struct ThreadPoolDomain { Il2CppDomain* domain; int32_t outstanding_request; }; struct ThreadPoolHillClimbing { int32_t wave_period; int32_t samples_to_measure; double target_throughput_ratio; double target_signal_to_noise_ratio; double max_change_per_second; double max_change_per_sample; int32_t max_thread_wave_magnitude; int32_t sample_interval_low; double thread_magnitude_multiplier; int32_t sample_interval_high; double throughput_error_smoothing_factor; double gain_exponent; double max_sample_error; double current_control_setting; int64_t total_samples; int16_t last_thread_count; double elapsed_since_last_change; double completions_since_last_change; double average_throughput_noise; double *samples; double *thread_counts; uint32_t current_sample_interval; void* random_interval_generator; int32_t accumulated_completion_count; double accumulated_sample_duration; }; struct ThreadPool { ThreadPoolCounter counters; std::vector domains; il2cpp::os::FastMutex domains_lock; std::vector working_threads; int32_t parked_threads_count; il2cpp::os::ConditionVariable parked_threads_cond; il2cpp::os::FastMutex active_threads_lock; /* protect access to working_threads and parked_threads */ uint32_t worker_creation_current_second; uint32_t worker_creation_current_count; il2cpp::os::FastMutex worker_creation_lock; int32_t heuristic_completions; int64_t heuristic_sample_start; int64_t heuristic_last_dequeue; // ms int64_t heuristic_last_adjustment; // ms int64_t heuristic_adjustment_interval; // ms ThreadPoolHillClimbing heuristic_hill_climbing; il2cpp::os::Mutex heuristic_lock; int32_t limit_worker_min; int32_t limit_worker_max; int32_t limit_io_min; int32_t limit_io_max; void* cpu_usage_state; int32_t cpu_usage; /* suspended by the debugger */ bool suspended; }; enum ThreadPoolHeuristicStateTransition { TRANSITION_WARMUP, TRANSITION_INITIALIZING, TRANSITION_RANDOM_MOVE, TRANSITION_CLIMBING_MOVE, TRANSITION_CHANGE_POINT, TRANSITION_STABILIZING, TRANSITION_STARVATION, TRANSITION_THREAD_TIMED_OUT, TRANSITION_UNDEFINED, }; #endif // NET_4_0 ================================================ FILE: unity_decoder/libil2cpp/mono/ThreadPool/ThreadPoolMacros.h ================================================ #pragma once #if NET_4_0 #include "vm/Atomic.h" #define COUNTER_CHECK(counter) \ do { \ IL2CPP_ASSERT(counter._.max_working > 0); \ IL2CPP_ASSERT(counter._.working >= 0); \ IL2CPP_ASSERT(counter._.active >= 0); \ } while (0) #define COUNTER_READ() (il2cpp::vm::Atomic::Read64 (&g_ThreadPool->counters.as_int64_t)) #define COUNTER_ATOMIC(var, block) \ do { \ ThreadPoolCounter __old; \ do { \ IL2CPP_ASSERT(g_ThreadPool); \ __old.as_int64_t = COUNTER_READ (); \ (var) = __old; \ { block; } \ COUNTER_CHECK (var); \ } while (il2cpp::vm::Atomic::CompareExchange64 (&g_ThreadPool->counters.as_int64_t, (var).as_int64_t, __old.as_int64_t) != __old.as_int64_t); \ } while (0) #define COUNTER_TRY_ATOMIC(res, var, block) \ do { \ ThreadPoolCounter __old; \ do { \ IL2CPP_ASSERT(g_ThreadPool); \ __old.as_int64_t = COUNTER_READ (); \ (var) = __old; \ (res) = false; \ { block; } \ COUNTER_CHECK (var); \ (res) = il2cpp::vm::Atomic::CompareExchange64 (&g_ThreadPool->counters.as_int64_t, (var).as_int64_t, __old.as_int64_t) == __old.as_int64_t; \ } while (0); \ } while (0) #define CPU_USAGE_LOW 80 #define CPU_USAGE_HIGH 95 #endif // NET_4_0 ================================================ FILE: unity_decoder/libil2cpp/mono/ThreadPool/ThreadPoolMonitorThread.cpp ================================================ #include "il2cpp-config.h" #if NET_4_0 #include "gc/GarbageCollector.h" #include "mono/ThreadPool/threadpool-ms.h" #include "mono/ThreadPool/ThreadPoolDataStructures.h" #include "mono/ThreadPool/ThreadPoolMacros.h" #include "mono/ThreadPool/ThreadPoolMonitorThread.h" #include "mono/ThreadPool/ThreadPoolWorkerThread.h" #include "vm/Runtime.h" #include "vm/Thread.h" #include "os/Time.h" #define MONITOR_INTERVAL 500 // ms #define MONITOR_MINIMAL_LIFETIME 60 * 1000 // ms static int32_t s_MonitorStatus = MONITOR_STATUS_NOT_RUNNING; MonitorStatus GetMonitorStatus() { return static_cast(s_MonitorStatus); } static int32_t cpu_info_usage(void* prev) { // Note : Implementing CpuInfo on all platforms will be challenging, so for now we are going to cheat // and always say it's low #if IL2CPP_ENABLE_CPU_INFO return il2cpp::os::CpuInfo::Usage(prev); #else return CPU_USAGE_LOW; #endif } static Il2CppException* mono_thread_interruption_checkpoint(void) { // For now just do nothing. The one place this is used doesn't care about the return value return NULL; } /* LOCKING: threadpool->domains_lock must be held */ static bool domain_any_has_request(void) { unsigned int i; for (i = 0; i < g_ThreadPool->domains.size(); ++i) { ThreadPoolDomain *tmp = g_ThreadPool->domains[i]; if (tmp->outstanding_request > 0) return true; } return false; } static bool monitor_sufficient_delay_since_last_dequeue(void) { int64_t threshold; IL2CPP_ASSERT(g_ThreadPool); if (g_ThreadPool->cpu_usage < CPU_USAGE_LOW) { threshold = MONITOR_INTERVAL; } else { ThreadPoolCounter counter; counter.as_int64_t = COUNTER_READ(); threshold = counter._.max_working * MONITOR_INTERVAL * 2; } return il2cpp::os::Time::GetTicksMillisecondsMonotonic() >= g_ThreadPool->heuristic_last_dequeue + threshold; } static bool monitor_should_keep_running(void) { static int64_t last_should_keep_running = -1; IL2CPP_ASSERT(s_MonitorStatus == MONITOR_STATUS_WAITING_FOR_REQUEST || s_MonitorStatus == MONITOR_STATUS_REQUESTED); if (il2cpp::vm::Atomic::Exchange(&s_MonitorStatus, MONITOR_STATUS_WAITING_FOR_REQUEST) == MONITOR_STATUS_WAITING_FOR_REQUEST) { bool should_keep_running = true, force_should_keep_running = false; if (il2cpp::vm::Runtime::IsShuttingDown()) { should_keep_running = false; } else { g_ThreadPool->domains_lock.Lock(); if (!domain_any_has_request()) should_keep_running = false; g_ThreadPool->domains_lock.Unlock(); if (!should_keep_running) { if (last_should_keep_running == -1 || il2cpp::os::Time::GetTicks100NanosecondsMonotonic() - last_should_keep_running < MONITOR_MINIMAL_LIFETIME * 1000 * 10) { should_keep_running = force_should_keep_running = true; } } } if (should_keep_running) { if (last_should_keep_running == -1 || !force_should_keep_running) last_should_keep_running = il2cpp::os::Time::GetTicks100NanosecondsMonotonic(); } else { last_should_keep_running = -1; if (il2cpp::vm::Atomic::CompareExchange(&s_MonitorStatus, MONITOR_STATUS_NOT_RUNNING, MONITOR_STATUS_WAITING_FOR_REQUEST) == MONITOR_STATUS_WAITING_FOR_REQUEST) return false; } } IL2CPP_ASSERT(s_MonitorStatus == MONITOR_STATUS_WAITING_FOR_REQUEST || s_MonitorStatus == MONITOR_STATUS_REQUESTED); return true; } static void monitor_thread(void* data) { Il2CppInternalThread *current_thread = il2cpp::vm::Thread::CurrentInternal(); unsigned int i; cpu_info_usage(g_ThreadPool->cpu_usage_state); //mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] monitor thread, started", mono_native_thread_id_get ()); do { ThreadPoolCounter counter; bool limit_worker_max_reached; int32_t interval_left = MONITOR_INTERVAL; int32_t awake = 0; /* number of spurious awakes we tolerate before doing a round of rebalancing */ IL2CPP_ASSERT(s_MonitorStatus != MONITOR_STATUS_NOT_RUNNING); il2cpp::gc::GarbageCollector::SetSkipThread(true); do { int64_t ts; bool alerted = false; if (il2cpp::vm::Runtime::IsShuttingDown()) break; ts = il2cpp::os::Time::GetTicksMillisecondsMonotonic(); il2cpp::vm::Thread::Sleep(interval_left); /*if (mono_thread_info_sleep (interval_left, &alerted) == 0) break;*/ interval_left -= (int32_t)(il2cpp::os::Time::GetTicksMillisecondsMonotonic() - ts); il2cpp::gc::GarbageCollector::SetSkipThread(false); if ((current_thread->state & (il2cpp::vm::kThreadStateStopRequested | il2cpp::vm::kThreadStateSuspendRequested)) != 0) mono_thread_interruption_checkpoint(); il2cpp::gc::GarbageCollector::SetSkipThread(true); } while (interval_left > 0 && ++awake < 10); il2cpp::gc::GarbageCollector::SetSkipThread(false); if (g_ThreadPool->suspended) continue; if (il2cpp::vm::Runtime::IsShuttingDown()) continue; g_ThreadPool->domains_lock.Lock(); if (!domain_any_has_request()) { g_ThreadPool->domains_lock.Unlock(); continue; } g_ThreadPool->domains_lock.Unlock(); g_ThreadPool->cpu_usage = cpu_info_usage(g_ThreadPool->cpu_usage_state); if (!monitor_sufficient_delay_since_last_dequeue()) continue; limit_worker_max_reached = false; COUNTER_ATOMIC(counter, { if (counter._.max_working >= g_ThreadPool->limit_worker_max) { limit_worker_max_reached = true; break; } counter._.max_working++; }); if (limit_worker_max_reached) continue; hill_climbing_force_change(counter._.max_working, TRANSITION_STARVATION); for (i = 0; i < 5; ++i) { if (il2cpp::vm::Runtime::IsShuttingDown()) break; if (worker_try_unpark()) { //mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] monitor thread, unparked", mono_native_thread_id_get ()); break; } if (worker_try_create()) { //mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] monitor thread, created", mono_native_thread_id_get ()); break; } } } while (monitor_should_keep_running()); //mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] monitor thread, finished", mono_native_thread_id_get ()); } void monitor_ensure_running() { for (;;) { switch (s_MonitorStatus) { case MONITOR_STATUS_REQUESTED: return; case MONITOR_STATUS_WAITING_FOR_REQUEST: il2cpp::vm::Atomic::CompareExchange(&s_MonitorStatus, MONITOR_STATUS_REQUESTED, MONITOR_STATUS_WAITING_FOR_REQUEST); break; case MONITOR_STATUS_NOT_RUNNING: if (il2cpp::vm::Runtime::IsShuttingDown()) return; if (il2cpp::vm::Atomic::CompareExchange(&s_MonitorStatus, MONITOR_STATUS_REQUESTED, MONITOR_STATUS_NOT_RUNNING) == MONITOR_STATUS_NOT_RUNNING) { if (!il2cpp::vm::Thread::CreateInternal(monitor_thread, NULL, true, SMALL_STACK)) s_MonitorStatus = MONITOR_STATUS_NOT_RUNNING; return; } break; default: IL2CPP_ASSERT(0 && "should not be reached"); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/mono/ThreadPool/ThreadPoolMonitorThread.h ================================================ #pragma once #if NET_4_0 enum MonitorStatus { MONITOR_STATUS_REQUESTED, MONITOR_STATUS_WAITING_FOR_REQUEST, MONITOR_STATUS_NOT_RUNNING, }; void monitor_ensure_running(); MonitorStatus GetMonitorStatus(); #endif // NET_4_0 ================================================ FILE: unity_decoder/libil2cpp/mono/ThreadPool/ThreadPoolWorkerThread.cpp ================================================ #include "il2cpp-config.h" #if NET_4_0 #include "gc/GarbageCollector.h" #include "mono/ThreadPool/threadpool-ms.h" #include "mono/ThreadPool/ThreadPoolDataStructures.h" #include "mono/ThreadPool/ThreadPoolMacros.h" #include "vm/String.h" #include "vm/Object.h" #include "vm/Random.h" #include "vm/Runtime.h" #include "vm/Thread.h" #include "os/Time.h" #define WORKER_CREATION_MAX_PER_SEC 10 static void remove_working_thread(Il2CppInternalThread *thread) { int index = 0; for (unsigned i = 0; i < g_ThreadPool->working_threads.size(); ++i) { if (g_ThreadPool->working_threads[i] == thread) { index = i; break; } } g_ThreadPool->working_threads.erase(g_ThreadPool->working_threads.begin() + index); } /* * mono_thread_info_install_interrupt: install an interruption token for the current thread. * * - @callback: must be able to be called from another thread and always cancel the wait * - @data: passed to the callback * - @interrupted: will be set to TRUE if a token is already installed, FALSE otherwise * if set to TRUE, it must mean that the thread is in interrupted state */ static void thread_info_install_interrupt(void(*callback)(void* data), void* data, bool *interrupted) { // We can get by without this for the time being. Not needed until we have cooperative threading } static void thread_info_uninstall_interrupt(bool *interrupted) { // We can get by without this for the time being. Not needed until we have cooperative threading } static void worker_wait_interrupt(void* data) { g_ThreadPool->active_threads_lock.Lock(); g_ThreadPool->parked_threads_cond.Signal(); g_ThreadPool->active_threads_lock.Unlock(); } /* return true if timeout, false otherwise (worker unpark or interrupt) */ static bool worker_park(void) { bool timeout = false; //mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] current worker parking", mono_native_thread_id_get ()); il2cpp::gc::GarbageCollector::SetSkipThread(true); g_ThreadPool->active_threads_lock.Lock(); if (!il2cpp::vm::Runtime::IsShuttingDown()) { static void* rand_handle = NULL; Il2CppInternalThread *thread_internal; bool interrupted = false; if (!rand_handle) rand_handle = il2cpp::vm::Random::Create(); IL2CPP_ASSERT(rand_handle); thread_internal = il2cpp::vm::Thread::CurrentInternal(); IL2CPP_ASSERT(thread_internal); g_ThreadPool->parked_threads_count += 1; remove_working_thread(thread_internal); thread_info_install_interrupt(worker_wait_interrupt, NULL, &interrupted); if (interrupted) goto done; if (g_ThreadPool->parked_threads_cond.TimedWait(&g_ThreadPool->active_threads_lock, il2cpp::vm::Random::Next(&rand_handle, 5 * 1000, 60 * 1000)) != 0) timeout = true; thread_info_uninstall_interrupt(&interrupted); done: g_ThreadPool->working_threads.push_back(thread_internal); g_ThreadPool->parked_threads_count -= 1; } g_ThreadPool->active_threads_lock.Unlock(); il2cpp::gc::GarbageCollector::SetSkipThread(false); //mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] current worker unparking, timeout? %s", mono_native_thread_id_get (), timeout ? "yes" : "no"); return timeout; } /* LOCKING: threadpool->domains_lock must be held */ static ThreadPoolDomain* domain_get_next(ThreadPoolDomain *current) { ThreadPoolDomain *tpdomain = NULL; unsigned int len; len = (unsigned int)g_ThreadPool->domains.size(); if (len > 0) { unsigned int i, current_idx = -1; if (current) { for (i = 0; i < len; ++i) { if (current == g_ThreadPool->domains[i]) { current_idx = i; break; } } IL2CPP_ASSERT(current_idx >= 0); } for (i = current_idx + 1; i < len + current_idx + 1; ++i) { ThreadPoolDomain *tmp = (ThreadPoolDomain*)g_ThreadPool->domains[i % len]; if (tmp->outstanding_request > 0) { tpdomain = tmp; break; } } } return tpdomain; } struct WorkerThreadStateHolder { Il2CppInternalThread *thread; ThreadPoolDomain* tpdomain; ThreadPoolDomain* previous_tpdomain; ThreadPoolCounter counter; bool retire; WorkerThreadStateHolder() : thread(il2cpp::vm::Thread::CurrentInternal()), tpdomain(NULL), previous_tpdomain(NULL), retire(false) { IL2CPP_ASSERT(thread); il2cpp::vm::Thread::SetName(thread, il2cpp::vm::String::New("IL2CPP Threadpool worker")); il2cpp::os::FastAutoLock activeThreadsLock(&g_ThreadPool->active_threads_lock); g_ThreadPool->working_threads.push_back(thread); } ~WorkerThreadStateHolder() { { il2cpp::os::FastAutoLock activeThreadsLock(&g_ThreadPool->active_threads_lock); remove_working_thread(thread); } COUNTER_ATOMIC(counter, { counter._.working--; counter._.active--; }); } }; struct WorkerThreadParkStateHolder { ThreadPoolCounter& counter; il2cpp::os::FastAutoUnlock domainUnlock; WorkerThreadParkStateHolder(WorkerThreadStateHolder& workerThreadState) : counter(workerThreadState.counter), domainUnlock(&g_ThreadPool->domains_lock) { COUNTER_ATOMIC(counter, { counter._.working--; counter._.parked++; }); } ~WorkerThreadParkStateHolder() { COUNTER_ATOMIC(counter, { counter._.working++; counter._.parked--; }); } }; struct WorkerThreadJobStateHolder { ThreadPoolDomain* tpdomain; WorkerThreadJobStateHolder(const WorkerThreadStateHolder& workerThreadState) : tpdomain(workerThreadState.tpdomain) { tpdomain->outstanding_request--; IL2CPP_ASSERT(tpdomain->outstanding_request >= 0); IL2CPP_ASSERT(tpdomain->domain); IL2CPP_ASSERT(tpdomain->domain->threadpool_jobs >= 0); tpdomain->domain->threadpool_jobs++; } ~WorkerThreadJobStateHolder() { tpdomain->domain->threadpool_jobs--; IL2CPP_ASSERT(tpdomain->domain->threadpool_jobs >= 0); } }; static void worker_thread(void* data) { IL2CPP_ASSERT(g_ThreadPool); WorkerThreadStateHolder workerThreadState; il2cpp::os::FastAutoLock domainsLock(&g_ThreadPool->domains_lock); while (!il2cpp::vm::Runtime::IsShuttingDown()) { workerThreadState.previous_tpdomain = workerThreadState.tpdomain; if (workerThreadState.retire || !(workerThreadState.tpdomain = domain_get_next(workerThreadState.previous_tpdomain))) { WorkerThreadParkStateHolder threadParkState(workerThreadState); if (worker_park()) break; workerThreadState.retire = false; continue; } WorkerThreadJobStateHolder threadJobState(workerThreadState); il2cpp::os::FastAutoUnlock domainUnlock(&g_ThreadPool->domains_lock); Il2CppObject* res = il2cpp::vm::Runtime::InvokeWithThrow(il2cpp_defaults.threadpool_perform_wait_callback_method, NULL, NULL); if (res && *(bool*)il2cpp::vm::Object::Unbox(res) == false) workerThreadState.retire = true; il2cpp::vm::Thread::ClrState(workerThreadState.thread, static_cast(~il2cpp::vm::kThreadStateBackground)); if (!il2cpp::vm::Thread::TestState(workerThreadState.thread, il2cpp::vm::kThreadStateBackground)) il2cpp::vm::Thread::SetState(workerThreadState.thread, il2cpp::vm::kThreadStateBackground); } } bool worker_try_create() { ThreadPoolCounter counter; Il2CppInternalThread *thread; int64_t current_ticks; int32_t now; il2cpp::os::FastAutoLock lock(&g_ThreadPool->worker_creation_lock); current_ticks = il2cpp::os::Time::GetTicks100NanosecondsMonotonic(); now = (int32_t)(current_ticks / (10 * 1000 * 1000)); if (current_ticks != 0) { if (g_ThreadPool->worker_creation_current_second != now) { g_ThreadPool->worker_creation_current_second = now; g_ThreadPool->worker_creation_current_count = 0; } else { IL2CPP_ASSERT(g_ThreadPool->worker_creation_current_count <= WORKER_CREATION_MAX_PER_SEC); if (g_ThreadPool->worker_creation_current_count == WORKER_CREATION_MAX_PER_SEC) { // Worker creation failed because maximum number of workers already created in the last second return false; } } } COUNTER_ATOMIC(counter, { if (counter._.working >= counter._.max_working) { // Worked creation failed because maximum number of workers are running return false; } counter._.working++; counter._.active++; }); if ((thread = il2cpp::vm::Thread::CreateInternal(worker_thread, NULL, true, 0)) != NULL) { g_ThreadPool->worker_creation_current_count += 1; return true; } // Failed creating native thread :( COUNTER_ATOMIC(counter, { counter._.working--; counter._.active--; }); return false; } #endif ================================================ FILE: unity_decoder/libil2cpp/mono/ThreadPool/ThreadPoolWorkerThread.h ================================================ #pragma once #if NET_4_0 bool worker_try_create(); #endif // NET_4_0 ================================================ FILE: unity_decoder/libil2cpp/mono/ThreadPool/threadpool-ms-io-poll.cpp ================================================ #include "il2cpp-config.h" #if NET_4_0 #include "gc/GarbageCollector.h" #include "mono/ThreadPool/threadpool-ms-io-poll.h" #include "os/Socket.h" #include "utils/Memory.h" #include "vm/Thread.h" #include "vm/ThreadPool.h" #include static std::vector *poll_fds; static unsigned int poll_fds_capacity; static unsigned int poll_fds_size; static inline void POLL_INIT_FD(il2cpp::os::PollRequest *poll_fd, int fd, il2cpp::os::PollFlags events) { poll_fd->fd = fd; poll_fd->events = events; poll_fd->revents = il2cpp::os::kPollFlagsNone; } bool poll_init(int wakeup_pipe_fd) { IL2CPP_ASSERT(wakeup_pipe_fd >= 0); poll_fds_size = 1; poll_fds_capacity = 64; poll_fds = new std::vector(poll_fds_capacity); POLL_INIT_FD(&(*poll_fds)[0], wakeup_pipe_fd, il2cpp::os::kPollFlagsIn); return true; } void poll_register_fd(int fd, int events, bool is_new) { unsigned int i; il2cpp::os::PollFlags poll_event; IL2CPP_ASSERT(fd >= 0); IL2CPP_ASSERT(poll_fds_size <= poll_fds_capacity); IL2CPP_ASSERT((events & ~(EVENT_IN | EVENT_OUT)) == 0); poll_event = il2cpp::os::kPollFlagsNone; if (events & EVENT_IN) poll_event |= il2cpp::os::kPollFlagsIn; if (events & EVENT_OUT) poll_event |= il2cpp::os::kPollFlagsOut; for (i = 0; i < poll_fds_size; ++i) { if ((*poll_fds)[i].fd == fd) { IL2CPP_ASSERT(!is_new); POLL_INIT_FD(&(*poll_fds)[i], fd, poll_event); return; } } IL2CPP_ASSERT(is_new); for (i = 0; i < poll_fds_size; ++i) { if ((*poll_fds)[i].fd == -1) { POLL_INIT_FD(&(*poll_fds)[i], fd, poll_event); return; } } poll_fds_size += 1; if (poll_fds_size > poll_fds_capacity) { poll_fds_capacity *= 2; IL2CPP_ASSERT(poll_fds_size <= poll_fds_capacity); poll_fds->reserve(poll_fds_capacity); } POLL_INIT_FD(&(*poll_fds)[poll_fds_size - 1], fd, poll_event); } void poll_remove_fd(int fd) { unsigned int i; IL2CPP_ASSERT(fd >= 0); for (i = 0; i < poll_fds_size; ++i) { if ((*poll_fds)[i].fd == fd) { POLL_INIT_FD(&(*poll_fds)[i], -1, il2cpp::os::kPollFlagsNone); break; } } /* if we don't find the fd in poll_fds, * it means we try to delete it twice */ IL2CPP_ASSERT(i < poll_fds_size); /* if we find it again, it means we added * it twice */ for (; i < poll_fds_size; ++i) IL2CPP_ASSERT((*poll_fds)[i].fd != fd); /* reduce the value of poll_fds_size so we * do not keep it too big */ while (poll_fds_size > 1 && (*poll_fds)[poll_fds_size - 1].fd == -1) poll_fds_size -= 1; } static inline int poll_mark_bad_fds(std::vector *poll_fds, int poll_fds_size) { int i, ready = 0; int32_t result, error = 0; for (i = 0; i < poll_fds_size; i++) { if ((*poll_fds)[i].fd == -1) continue; il2cpp::os::WaitStatus status = il2cpp::os::Socket::Poll((*poll_fds)[i], 0, &result, &error); if (status == il2cpp::os::kWaitStatusFailure) { if ((il2cpp::os::SocketError)error == il2cpp::os::kInvalidHandle) { (*poll_fds)[i].revents |= il2cpp::os::kPollFlagsNVal; ready++; } } else if (result > 0) ready++; } return ready; } int poll_event_wait(void (*callback)(int fd, int events, void* user_data), void* user_data) { unsigned int i; for (i = 0; i < poll_fds_size; ++i) (*poll_fds)[i].revents = il2cpp::os::kPollFlagsNone; il2cpp::gc::GarbageCollector::SetSkipThread(true); int32_t ready; int32_t error; il2cpp::os::WaitStatus status = il2cpp::os::Socket::Poll((*poll_fds), poll_fds_size , -1, &ready, &error); il2cpp::gc::GarbageCollector::SetSkipThread(false); if (ready == -1 || status == il2cpp::os::kWaitStatusFailure) { /* * Apart from EINTR, we only check EBADF, for the rest: * EINVAL: mono_poll() 'protects' us from descriptor * numbers above the limit if using select() by marking * then as POLLERR. If a system poll() is being * used, the number of descriptor we're passing will not * be over sysconf(_SC_OPEN_MAX), as the error would have * happened when opening. * * EFAULT: we own the memory pointed by pfds. * ENOMEM: we're doomed anyway * */ if ((il2cpp::os::SocketError)error == il2cpp::os::kInterrupted) { il2cpp::vm::Thread::CheckCurrentThreadForInterruptAndThrowIfNecessary(); ready = 0; } else if ((il2cpp::os::SocketError)error == il2cpp::os::kInvalidHandle) { ready = poll_mark_bad_fds(poll_fds, poll_fds_size); } } if (ready == -1) return -1; if (ready == 0) return 0; IL2CPP_ASSERT(ready > 0); for (i = 0; i < poll_fds_size; ++i) { int fd, events = 0; if ((*poll_fds)[i].fd == -1) continue; if ((*poll_fds)[i].revents == 0) continue; fd = (int)(*poll_fds)[i].fd; if ((*poll_fds)[i].revents & (il2cpp::os::kPollFlagsIn | il2cpp::os::kPollFlagsErr | il2cpp::os::kPollFlagsHup | il2cpp::os::kPollFlagsNVal)) events |= EVENT_IN; if ((*poll_fds)[i].revents & (il2cpp::os::kPollFlagsOut | il2cpp::os::kPollFlagsErr | il2cpp::os::kPollFlagsHup | il2cpp::os::kPollFlagsNVal)) events |= EVENT_OUT; if ((*poll_fds)[i].revents & (il2cpp::os::kPollFlagsErr | il2cpp::os::kPollFlagsHup | il2cpp::os::kPollFlagsNVal)) events |= EVENT_ERR; callback(fd, events, user_data); if (--ready == 0) break; } return 0; } #endif ================================================ FILE: unity_decoder/libil2cpp/mono/ThreadPool/threadpool-ms-io-poll.h ================================================ #pragma once #if NET_4_0 #include "il2cpp-config.h" bool poll_init(int wakeup_pipe_fd); void poll_register_fd(int fd, int events, bool is_new); int poll_event_wait(void(*callback)(int fd, int events, void* user_data), void* user_data); void poll_remove_fd(int fd); #endif ================================================ FILE: unity_decoder/libil2cpp/mono/ThreadPool/threadpool-ms-io.cpp ================================================ /* * threadpool-ms-io.c: Microsoft IO threadpool runtime support * * Author: * Ludovic Henry (ludovic.henry@xamarin.com) * * Copyright 2015 Xamarin, Inc (http://www.xamarin.com) * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ #include "il2cpp-config.h" #if NET_4_0 #ifndef DISABLE_SOCKETS #if IL2CPP_PLATFORM_WIN32 #include "os/Win32/WindowsHeaders.h" #else #include #include #endif #include #include "gc/Allocator.h" #include "mono/ThreadPool/threadpool-ms.h" #include "mono/ThreadPool/threadpool-ms-io.h" #include "mono/ThreadPool/threadpool-ms-io-poll.h" #include "object-internals.h" #include "os/ConditionVariable.h" #include "os/Mutex.h" #include "os/Socket.h" #include "utils/CallOnce.h" #include "utils/Il2CppHashMap.h" #include "vm/Domain.h" #include "vm/Runtime.h" #include "vm/Thread.h" #include "vm/ThreadPool.h" #define UPDATES_CAPACITY 128 typedef std::vector > ManagedList; struct ThreadPoolStateHasher { size_t operator()(int thread) const { return thread; } }; typedef Il2CppHashMap ThreadPoolStateHash; typedef enum { UPDATE_EMPTY = 0, UPDATE_ADD, UPDATE_REMOVE_SOCKET, UPDATE_REMOVE_DOMAIN, } ThreadPoolIOUpdateType; typedef struct { int fd; Il2CppIOSelectorJob *job; } ThreadPoolIOUpdate_Add; typedef struct { int fd; } ThreadPoolIOUpdate_RemoveSocket; typedef struct { Il2CppDomain *domain; } ThreadPoolIOUpdate_RemoveDomain; typedef struct { ThreadPoolIOUpdateType type; union { ThreadPoolIOUpdate_Add add; ThreadPoolIOUpdate_RemoveSocket remove_socket; ThreadPoolIOUpdate_RemoveDomain remove_domain; } data; } ThreadPoolIOUpdate; typedef struct { il2cpp::vm::ThreadPool::ThreadPoolIOBackend backend; ThreadPoolIOUpdate* updates; int updates_size; il2cpp::os::FastMutex updates_lock; il2cpp::os::ConditionVariable updates_cond; il2cpp::os::Socket* wakeup_pipes [2]; } ThreadPoolIO; static il2cpp::utils::OnceFlag lazy_init_io_status; static bool io_selector_running = false; static ThreadPoolIO* threadpool_io; static il2cpp::vm::ThreadPool::ThreadPoolIOBackend backend_poll = { poll_init, poll_register_fd, poll_remove_fd, poll_event_wait }; static Il2CppIOSelectorJob* get_job_for_event (ManagedList *list, int32_t event) { IL2CPP_ASSERT(list); Il2CppIOSelectorJob* foundJob = NULL; int matchIndex = -1; for (size_t i = 0; i < list->size(); i++) { Il2CppIOSelectorJob *job = (Il2CppIOSelectorJob*)(*list)[i]; if (job->operation == event) { foundJob = job; matchIndex = (int)i; break; } } if (foundJob == NULL) return NULL; list->erase(list->begin() + matchIndex); return foundJob; } static int get_operations_for_jobs (ManagedList *list) { int operations = 0; for (size_t i = 0; i < list->size(); i++) { operations |= ((Il2CppIOSelectorJob*)(*list)[i])->operation; } return operations; } static void selector_thread_wakeup (void) { const char msg = 'c'; for (;;) { int32_t written = 0; const il2cpp::os::WaitStatus status = threadpool_io->wakeup_pipes[1]->Send((const uint8_t*)&msg, 1, il2cpp::os::kSocketFlagsNone, &written); if (written == 1) break; if (written == -1) { //g_warning ("selector_thread_wakeup: write () failed, error (%d)\n", WSAGetLastError ()); break; } if (status == il2cpp::os::kWaitStatusFailure) break; } } static void selector_thread_wakeup_drain_pipes (void) { uint8_t buffer [128]; for (;;) { int32_t received; il2cpp::os::WaitStatus status = threadpool_io->wakeup_pipes[0]->Receive(buffer, 128, il2cpp::os::kSocketFlagsNone, &received); if (received == 0) break; if (status == il2cpp::os::kWaitStatusFailure) break; } } typedef struct { Il2CppDomain *domain; ThreadPoolStateHash *states; } FilterSockaresForDomainData; static void filter_jobs_for_domain (void* key, void* value, void* user_data) { //FilterSockaresForDomainData *data; //MonoMList *list = (MonoMList *)value, *element; //MonoDomain *domain; //MonoGHashTable *states; //IL2CPP_ASSERT(user_data); //data = (FilterSockaresForDomainData *)user_data; //domain = data->domain; //states = data->states; //for (element = list; element; element = mono_mlist_next (element)) { // Il2CppIOSelectorJob *job = (Il2CppIOSelectorJob*) mono_mlist_get_data (element); // if (il2cpp::vm::Domain::GetCurrent() == domain) // mono_mlist_set_data (element, NULL); //} ///* we skip all the first elements which are NULL */ //for (; list; list = mono_mlist_next (list)) { // if (mono_mlist_get_data (list)) // break; //} //if (list) { // IL2CPP_ASSERT(mono_mlist_get_data (list)); // /* we delete all the NULL elements after the first one */ // for (element = list; element;) { // MonoMList *next; // if (!(next = mono_mlist_next (element))) // break; // if (mono_mlist_get_data (next)) // element = next; // else // mono_mlist_set_next (element, mono_mlist_next (next)); // } //} //mono_g_hash_table_replace (states, key, list); NOT_IMPLEMENTED("TODO"); } static void wait_callback (int fd, int events, void* user_data) { //Il2CppError error; if (il2cpp::vm::Runtime::IsShuttingDown ()) return; if (fd == threadpool_io->wakeup_pipes [0]->GetDescriptor()) { //mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_THREADPOOL, "io threadpool: wke"); selector_thread_wakeup_drain_pipes (); } else { ThreadPoolStateHash *states; ManagedList *list = NULL; //void* k; bool remove_fd = false; int operations; IL2CPP_ASSERT(user_data); states = (ThreadPoolStateHash *)user_data; /*mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_THREADPOOL, "io threadpool: cal fd %3d, events = %2s | %2s | %3s", fd, (events & EVENT_IN) ? "RD" : "..", (events & EVENT_OUT) ? "WR" : "..", (events & EVENT_ERR) ? "ERR" : "...");*/ ThreadPoolStateHash::iterator iter = states->find(fd); bool exists = iter != states->end(); if (!exists) IL2CPP_ASSERT("wait_callback: fd not found in states table"); else list = iter->second; if (list && (events & EVENT_IN) != 0) { Il2CppIOSelectorJob *job = get_job_for_event (list, EVENT_IN); if (job) { threadpool_ms_enqueue_work_item (il2cpp::vm::Domain::GetCurrent(), (Il2CppObject*) job); } } if (list && (events & EVENT_OUT) != 0) { Il2CppIOSelectorJob *job = get_job_for_event (list, EVENT_OUT); if (job) { threadpool_ms_enqueue_work_item (il2cpp::vm::Domain::GetCurrent(), (Il2CppObject*) job); } } remove_fd = (events & EVENT_ERR) == EVENT_ERR; if (!remove_fd) { //mono_g_hash_table_replace (states, int_TO_POINTER (fd), list); states->insert(ThreadPoolStateHash::value_type(fd, list)); operations = get_operations_for_jobs (list); /*mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_THREADPOOL, "io threadpool: res fd %3d, events = %2s | %2s | %3s", fd, (operations & EVENT_IN) ? "RD" : "..", (operations & EVENT_OUT) ? "WR" : "..", (operations & EVENT_ERR) ? "ERR" : "...");*/ threadpool_io->backend.register_fd (fd, operations, false); } else { //mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_THREADPOOL, "io threadpool: err fd %d", fd); states->erase(ThreadPoolStateHash::key_type(fd)); //mono_g_hash_table_remove (states, int_TO_POINTER (fd)); threadpool_io->backend.remove_fd (fd); } } } static void selector_thread (void* data) { //Il2CppError error; ThreadPoolStateHash *states; io_selector_running = true; if (il2cpp::vm::Runtime::IsShuttingDown ()) { io_selector_running = false; return; } states = new ThreadPoolStateHash(); //states = mono_g_hash_table_new_type (g_direct_hash, g_direct_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_THREAD_POOL, "i/o thread pool states table"); for (;;) { int i, j; int res; threadpool_io->updates_lock.Lock(); for (i = 0; i < threadpool_io->updates_size; ++i) { ThreadPoolIOUpdate *update = &threadpool_io->updates [i]; switch (update->type) { case UPDATE_EMPTY: break; case UPDATE_ADD: { int fd; int operations; //void* k; bool exists; ManagedList *list = NULL; Il2CppIOSelectorJob *job; fd = update->data.add.fd; IL2CPP_ASSERT(fd >= 0); job = update->data.add.job; IL2CPP_ASSERT(job); ThreadPoolStateHash::iterator iter = states->find(fd); exists = iter != states->end(); if (!exists) list = new ManagedList(); else list = iter->second; //exists = mono_g_hash_table_lookup_extended (states, int_TO_POINTER (fd), &k, (void**) &list); list->push_back((Il2CppObject*)job); states->insert(ThreadPoolStateHash::value_type(fd, list)); //mono_g_hash_table_replace (states, int_TO_POINTER (fd), list); operations = get_operations_for_jobs (list); /*mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_THREADPOOL, "io threadpool: %3s fd %3d, operations = %2s | %2s | %3s", exists ? "mod" : "add", fd, (operations & EVENT_IN) ? "RD" : "..", (operations & EVENT_OUT) ? "WR" : "..", (operations & EVENT_ERR) ? "ERR" : "...");*/ threadpool_io->backend.register_fd (fd, operations, !exists); break; } case UPDATE_REMOVE_SOCKET: { int fd; //void* k; ManagedList *list = NULL; fd = update->data.remove_socket.fd; IL2CPP_ASSERT(fd >= 0); ThreadPoolStateHash::iterator iter = states->find(fd); bool exists = iter != states->end(); /*if (mono_g_hash_table_lookup_extended (states, int_TO_POINTER (fd), &k, (void**) &list))*/ if (exists) { states->erase(ThreadPoolStateHash::key_type(fd)); //mono_g_hash_table_remove (states, int_TO_POINTER (fd)); for (j = i + 1; j < threadpool_io->updates_size; ++j) { ThreadPoolIOUpdate *update = &threadpool_io->updates [j]; if (update->type == UPDATE_ADD && update->data.add.fd == fd) memset (update, 0, sizeof (ThreadPoolIOUpdate)); } for (size_t i = 0; i < list->size(); i++) { threadpool_ms_enqueue_work_item(il2cpp::vm::Domain::GetCurrent(), (*list)[i]); } list->clear(); //mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_THREADPOOL, "io threadpool: del fd %3d", fd); threadpool_io->backend.remove_fd (fd); } break; } case UPDATE_REMOVE_DOMAIN: { Il2CppDomain *domain; domain = update->data.remove_domain.domain; IL2CPP_ASSERT(domain); FilterSockaresForDomainData user_data = { domain, states }; //mono_g_hash_table_foreach (states, filter_jobs_for_domain, &user_data); for (j = i + 1; j < threadpool_io->updates_size; ++j) { ThreadPoolIOUpdate *update = &threadpool_io->updates [j]; if (update->type == UPDATE_ADD && il2cpp::vm::Domain::GetCurrent() == domain) memset (update, 0, sizeof (ThreadPoolIOUpdate)); } break; } default: IL2CPP_ASSERT(0 && "Should not be reached"); } } threadpool_io->updates_cond.Broadcast(); if (threadpool_io->updates_size > 0) { threadpool_io->updates_size = 0; memset (threadpool_io->updates, 0, UPDATES_CAPACITY * sizeof (ThreadPoolIOUpdate)); } threadpool_io->updates_lock.Unlock(); //mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_THREADPOOL, "io threadpool: wai"); res = threadpool_io->backend.event_wait (wait_callback, states); if (res == -1 || il2cpp::vm::Runtime::IsShuttingDown ()) break; } delete states; io_selector_running = false; } /* Locking: threadpool_io->updates_lock must be held */ static ThreadPoolIOUpdate* update_get_new (void) { ThreadPoolIOUpdate *update = NULL; IL2CPP_ASSERT(threadpool_io->updates_size <= UPDATES_CAPACITY); while (threadpool_io->updates_size == UPDATES_CAPACITY) { /* we wait for updates to be applied in the selector_thread and we loop * as long as none are available. if it happends too much, then we need * to increase UPDATES_CAPACITY */ threadpool_io->updates_cond.Wait(&threadpool_io->updates_lock); } IL2CPP_ASSERT(threadpool_io->updates_size < UPDATES_CAPACITY); update = &threadpool_io->updates [threadpool_io->updates_size ++]; return update; } static void wakeup_pipes_init(void) { il2cpp::os::Socket serverSock(NULL); serverSock.Create(il2cpp::os::kAddressFamilyInterNetwork, il2cpp::os::kSocketTypeStream, il2cpp::os::kProtocolTypeTcp); threadpool_io->wakeup_pipes[1] = new il2cpp::os::Socket(NULL); il2cpp::os::WaitStatus status = threadpool_io->wakeup_pipes[1]->Create(il2cpp::os::kAddressFamilyInterNetwork, il2cpp::os::kSocketTypeStream, il2cpp::os::kProtocolTypeTcp); IL2CPP_ASSERT(status != il2cpp::os::kWaitStatusFailure); if (serverSock.Bind("127.0.0.1", 0) == il2cpp::os::kWaitStatusFailure) { serverSock.Close(); IL2CPP_ASSERT(0 && "wakeup_pipes_init: bind () failed"); } il2cpp::os::EndPointInfo info; memset(&info, 0x00, sizeof(il2cpp::os::EndPointInfo)); if (serverSock.GetLocalEndPointInfo(info) == il2cpp::os::kWaitStatusFailure) { serverSock.Close(); IL2CPP_ASSERT(0 && "wakeup_pipes_init: getsockname () failed"); } if (serverSock.Listen(1024) == il2cpp::os::kWaitStatusFailure) { serverSock.Close(); IL2CPP_ASSERT(0 && "wakeup_pipes_init: listen () failed"); } if (threadpool_io->wakeup_pipes[1]->Connect(info.data.inet.address, info.data.inet.port) == il2cpp::os::kWaitStatusFailure) { serverSock.Close(); IL2CPP_ASSERT(0 && "wakeup_pipes_init: connect () failed"); } status = serverSock.Accept(&threadpool_io->wakeup_pipes[0]); IL2CPP_ASSERT(status != il2cpp::os::kWaitStatusFailure); status = threadpool_io->wakeup_pipes[0]->SetBlocking(false); if (status == il2cpp::os::kWaitStatusFailure) { threadpool_io->wakeup_pipes[0]->Close(); serverSock.Close(); } serverSock.Close(); } static bool lazy_is_initialized() { return lazy_init_io_status.IsSet(); } static void initialize(void* args) { IL2CPP_ASSERT(!threadpool_io); threadpool_io = new ThreadPoolIO(); IL2CPP_ASSERT(threadpool_io); threadpool_io->updates = (ThreadPoolIOUpdate*)il2cpp::gc::GarbageCollector::AllocateFixed(sizeof(ThreadPoolIOUpdate) * UPDATES_CAPACITY, NULL); threadpool_io->updates_size = 0; threadpool_io->backend = backend_poll; // if (g_getenv ("MONO_ENABLE_AIO") != NULL) { //#if defined(HAVE_EPOLL) // threadpool_io->backend = backend_epoll; //#elif defined(HAVE_KQUEUE) // threadpool_io->backend = backend_kqueue; //#endif // } wakeup_pipes_init (); if (!threadpool_io->backend.init ((int)threadpool_io->wakeup_pipes [0]->GetDescriptor())) IL2CPP_ASSERT(0 && "initialize: backend->init () failed"); if (!il2cpp::vm::Thread::CreateInternal(selector_thread, NULL, true, SMALL_STACK)) IL2CPP_ASSERT(0 && "initialize: vm::Thread::CreateInternal () failed "); } static void lazy_initialize() { il2cpp::utils::CallOnce(lazy_init_io_status, initialize, NULL); } static void cleanup (void) { /* we make the assumption along the code that we are * cleaning up only if the runtime is shutting down */ IL2CPP_ASSERT(il2cpp::vm::Runtime::IsShuttingDown ()); selector_thread_wakeup (); while (io_selector_running) il2cpp::vm::Thread::Sleep(1000); } void threadpool_ms_io_cleanup (void) { if (lazy_init_io_status.IsSet()) cleanup(); } void ves_icall_System_IOSelector_Add (Il2CppIntPtr handle, Il2CppIOSelectorJob *job) { ThreadPoolIOUpdate *update; IL2CPP_ASSERT(handle.m_value >= 0); IL2CPP_ASSERT((job->operation == EVENT_IN) ^ (job->operation == EVENT_OUT)); IL2CPP_ASSERT(job->callback); if (il2cpp::vm::Runtime::IsShuttingDown ()) return; /*if (mono_domain_is_unloading (mono_object_domain (job))) return;*/ lazy_initialize (); threadpool_io->updates_lock.Lock(); update = update_get_new (); il2cpp::os::SocketHandleWrapper socketHandle(il2cpp::os::PointerToSocketHandle(handle.m_value)); update->type = UPDATE_ADD; update->data.add.fd = (int)socketHandle.GetSocket()->GetDescriptor(); update->data.add.job = job; il2cpp::os::Atomic::MemoryBarrier(); /* Ensure this is safely published before we wake up the selector */ selector_thread_wakeup (); threadpool_io->updates_lock.Unlock(); } void ves_icall_System_IOSelector_Remove (Il2CppIntPtr handle) { il2cpp::os::SocketHandleWrapper socketHandle(il2cpp::os::PointerToSocketHandle(handle.m_value)); threadpool_ms_io_remove_socket ((int)socketHandle.GetSocket()->GetDescriptor()); } void threadpool_ms_io_remove_socket (int fd) { ThreadPoolIOUpdate *update; if (!lazy_is_initialized ()) return; threadpool_io->updates_lock.Lock(); update = update_get_new (); update->type = UPDATE_REMOVE_SOCKET; update->data.add.fd = fd; il2cpp::os::Atomic::MemoryBarrier(); /* Ensure this is safely published before we wake up the selector */ selector_thread_wakeup (); threadpool_io->updates_cond.Wait(&threadpool_io->updates_lock); threadpool_io->updates_lock.Unlock(); } #else void ves_icall_System_IOSelector_Add (Il2CppIntPtr handle, Il2CppIOSelectorJob *job) { IL2CPP_ASSERT(0 && "Should not be called"); } void ves_icall_System_IOSelector_Remove (Il2CppIntPtr handle) { IL2CPP_ASSERT(0 && "Should not be called"); } void threadpool_ms_io_cleanup (void) { IL2CPP_ASSERT(0 && "Should not be called"); } void threadpool_ms_io_remove_socket (int fd) { IL2CPP_ASSERT(0 && "Should not be called"); } #endif #endif ================================================ FILE: unity_decoder/libil2cpp/mono/ThreadPool/threadpool-ms-io.h ================================================ #pragma once #if NET_4_0 #include "il2cpp-config.h" struct Il2CppIOSelectorJob; struct Il2CppIntPtr; void threadpool_ms_io_remove_socket(int fd); //void mono_threadpool_ms_io_remove_domain_jobs (MonoDomain *domain); void threadpool_ms_io_cleanup(void); LIBIL2CPP_CODEGEN_API void ves_icall_System_IOSelector_Add(Il2CppIntPtr handle, Il2CppIOSelectorJob *job); LIBIL2CPP_CODEGEN_API void ves_icall_System_IOSelector_Remove(Il2CppIntPtr handle); #endif ================================================ FILE: unity_decoder/libil2cpp/mono/ThreadPool/threadpool-ms.cpp ================================================ /* * threadpool-ms.c: Microsoft threadpool runtime support * * Author: * Ludovic Henry (ludovic.henry@xamarin.com) * * Copyright 2015 Xamarin, Inc (http://www.xamarin.com) * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ // // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. // // Files: // - src/vm/comthreadpool.cpp // - src/vm/win32threadpoolcpp // - src/vm/threadpoolrequest.cpp // - src/vm/hillclimbing.cpp // // Ported from C++ to C and adjusted to Mono runtime #include "il2cpp-config.h" #if NET_4_0 #include #define _USE_MATH_DEFINES // needed by MSVC to define math constants #include #include #include #include "il2cpp-api.h" #include "gc/GarbageCollector.h" #include "gc/GCHandle.h" #include "icalls/mscorlib/System.Threading/ThreadPool.h" #include "icalls/mscorlib/System.Runtime.Remoting.Messaging/MonoMethodMessage.h" #include "mono/ThreadPool/threadpool-ms.h" #include "mono/ThreadPool/threadpool-ms-io.h" #include "mono/ThreadPool/ThreadPoolDataStructures.h" #include "mono/ThreadPool/ThreadPoolMacros.h" #include "mono/ThreadPool/ThreadPoolMonitorThread.h" #include "mono/ThreadPool/ThreadPoolWorkerThread.h" #include "object-internals.h" #include "os/CpuInfo.h" #include "os/Environment.h" #include "os/Mutex.h" #include "os/Time.h" #include "utils/CallOnce.h" #include "vm/Atomic.h" #include "vm/Array.h" #include "vm/Class.h" #include "vm/Domain.h" #include "vm/Exception.h" #include "vm/Object.h" #include "vm/Reflection.h" #include "vm/Random.h" #include "vm/Runtime.h" #include "vm/String.h" #include "vm/Thread.h" #include "vm/ThreadPool.h" #include "vm/WaitHandle.h" #ifndef CLAMP #define CLAMP(a,low,high) (((a) < (low)) ? (low) : (((a) > (high)) ? (high) : (a))) #endif ThreadPool* g_ThreadPool; /* The exponent to apply to the gain. 1.0 means to use linear gain, * higher values will enhance large moves and damp small ones. * default: 2.0 */ #define HILL_CLIMBING_GAIN_EXPONENT 2.0 /* The 'cost' of a thread. 0 means drive for increased throughput regardless * of thread count, higher values bias more against higher thread counts. * default: 0.15 */ #define HILL_CLIMBING_BIAS 0.15 #define HILL_CLIMBING_WAVE_PERIOD 4 #define HILL_CLIMBING_MAX_WAVE_MAGNITUDE 20 #define HILL_CLIMBING_WAVE_MAGNITUDE_MULTIPLIER 1.0 #define HILL_CLIMBING_WAVE_HISTORY_SIZE 8 #define HILL_CLIMBING_TARGET_SIGNAL_TO_NOISE_RATIO 3.0 #define HILL_CLIMBING_MAX_CHANGE_PER_SECOND 4 #define HILL_CLIMBING_MAX_CHANGE_PER_SAMPLE 20 #define HILL_CLIMBING_SAMPLE_INTERVAL_LOW 10 #define HILL_CLIMBING_SAMPLE_INTERVAL_HIGH 200 #define HILL_CLIMBING_ERROR_SMOOTHING_FACTOR 0.01 #define HILL_CLIMBING_MAX_SAMPLE_ERROR_PERCENT 0.15 static il2cpp::utils::OnceFlag lazy_init_status; static Il2CppMethodMessage * mono_method_call_message_new(MethodInfo *method, void* *params, MethodInfo *invoke, Il2CppDelegate **cb, Il2CppObject **state) { Il2CppDomain *domain = il2cpp::vm::Domain::GetCurrent(); Il2CppMethodMessage *msg; int i, count; msg = (Il2CppMethodMessage *)il2cpp::vm::Object::New(il2cpp_defaults.mono_method_message_class); if (invoke) { Il2CppReflectionMethod *rm = il2cpp::vm::Reflection::GetMethodObject(invoke, NULL); il2cpp::icalls::mscorlib::System::Runtime::Remoting::Messaging::MonoMethodMessage::InitMessage(msg, rm, NULL); count = method->parameters_count - 2; } else { Il2CppReflectionMethod *rm = il2cpp::vm::Reflection::GetMethodObject(method, NULL); il2cpp::icalls::mscorlib::System::Runtime::Remoting::Messaging::MonoMethodMessage::InitMessage(msg, rm, NULL); count = method->parameters_count; } for (i = 0; i < count; i++) { void* vpos; Il2CppClass *klass; Il2CppObject *arg; vpos = params[i]; klass = il2cpp_class_from_type(method->parameters[i].parameter_type); arg = (Il2CppObject*)vpos; il2cpp_array_setref(msg->args, i, arg); } if (cb != NULL && state != NULL) { *cb = (Il2CppDelegate *)params[i]; i++; *state = (Il2CppObject *)params[i]; } return msg; } static void* cpu_info_create() { // Note : Implementing CpuInfo on all platforms will be challenging, so for now we are going to cheat // and not actually calculate the usage #if IL2CPP_ENABLE_CPU_INFO return il2cpp::os::CpuInfo::Create(); #else return NULL; #endif } static void initialize(void* arg) { ThreadPoolHillClimbing *hc; //const char *threads_per_cpu_env; int threads_per_cpu; int threads_count; IL2CPP_ASSERT(!g_ThreadPool); g_ThreadPool = new ThreadPool(); IL2CPP_ASSERT(g_ThreadPool); g_ThreadPool->parked_threads_count = 0; g_ThreadPool->worker_creation_current_second = -1; g_ThreadPool->heuristic_adjustment_interval = 10; il2cpp::vm::Random::Open(); hc = &g_ThreadPool->heuristic_hill_climbing; hc->wave_period = HILL_CLIMBING_WAVE_PERIOD; hc->max_thread_wave_magnitude = HILL_CLIMBING_MAX_WAVE_MAGNITUDE; hc->thread_magnitude_multiplier = (double) HILL_CLIMBING_WAVE_MAGNITUDE_MULTIPLIER; hc->samples_to_measure = hc->wave_period * HILL_CLIMBING_WAVE_HISTORY_SIZE; hc->target_throughput_ratio = (double) HILL_CLIMBING_BIAS; hc->target_signal_to_noise_ratio = (double) HILL_CLIMBING_TARGET_SIGNAL_TO_NOISE_RATIO; hc->max_change_per_second = (double) HILL_CLIMBING_MAX_CHANGE_PER_SECOND; hc->max_change_per_sample = (double) HILL_CLIMBING_MAX_CHANGE_PER_SAMPLE; hc->sample_interval_low = HILL_CLIMBING_SAMPLE_INTERVAL_LOW; hc->sample_interval_high = HILL_CLIMBING_SAMPLE_INTERVAL_HIGH; hc->throughput_error_smoothing_factor = (double) HILL_CLIMBING_ERROR_SMOOTHING_FACTOR; hc->gain_exponent = (double) HILL_CLIMBING_GAIN_EXPONENT; hc->max_sample_error = (double) HILL_CLIMBING_MAX_SAMPLE_ERROR_PERCENT; hc->current_control_setting = 0; hc->total_samples = 0; hc->last_thread_count = 0; hc->average_throughput_noise = 0; hc->elapsed_since_last_change = 0; hc->accumulated_completion_count = 0; hc->accumulated_sample_duration = 0; hc->samples = (double*)IL2CPP_MALLOC_ZERO (sizeof(double) * hc->samples_to_measure); hc->thread_counts = (double*)IL2CPP_MALLOC_ZERO(sizeof(double) * hc->samples_to_measure); hc->random_interval_generator = il2cpp::vm::Random::Create (); hc->current_sample_interval = il2cpp::vm::Random::Next (&hc->random_interval_generator, hc->sample_interval_low, hc->sample_interval_high); //std::string threads_per_cpu_env = il2cpp::os::Environment::GetEnvironmentVariable("IL2CPP_THREADS_PER_CPU"); //if (threads_per_cpu_env.empty()) threads_per_cpu = 1; /*else threads_per_cpu = CLAMP (atoi (threads_per_cpu_env.c_str()), 1, 50);*/ threads_count = il2cpp::os::Environment::GetProcessorCount() * threads_per_cpu; g_ThreadPool->limit_worker_min = g_ThreadPool->limit_io_min = threads_count; #if IL2CPP_TARGET_ANDROID || IL2CPP_TARGET_IOS g_ThreadPool->limit_worker_max = g_ThreadPool->limit_io_max = CLAMP (threads_count * 100, std::min (threads_count, 200), std::max (threads_count, 200)); #else g_ThreadPool->limit_worker_max = g_ThreadPool->limit_io_max = threads_count * 100; #endif g_ThreadPool->counters._.max_working = g_ThreadPool->limit_worker_min; g_ThreadPool->cpu_usage_state = cpu_info_create(); g_ThreadPool->suspended = false; } static void lazy_initialize() { il2cpp::utils::CallOnce(lazy_init_status, initialize, NULL); } static void worker_kill(Il2CppInternalThread* thread) { if (thread == il2cpp::vm::Thread::CurrentInternal()) return; il2cpp::vm::Thread::Stop(thread); } static void cleanup (void) { unsigned int i; /* we make the assumption along the code that we are * cleaning up only if the runtime is shutting down */ IL2CPP_ASSERT(il2cpp::vm::Runtime::IsShuttingDown ()); while (GetMonitorStatus() != MONITOR_STATUS_NOT_RUNNING) il2cpp::vm::Thread::Sleep(1); std::vector working_threads; g_ThreadPool->active_threads_lock.Lock(); working_threads = g_ThreadPool->working_threads; g_ThreadPool->active_threads_lock.Unlock(); /* stop all threadpool->working_threads */ for (i = 0; i < working_threads.size(); ++i) worker_kill (working_threads[i]); /* unpark all g_ThreadPool->parked_threads */ g_ThreadPool->parked_threads_cond.Broadcast(); } bool threadpool_ms_enqueue_work_item (Il2CppDomain *domain, Il2CppObject *work_item) { static Il2CppClass *threadpool_class = NULL; static MethodInfo *unsafe_queue_custom_work_item_method = NULL; //Il2CppDomain *current_domain; bool f; void* args [2]; IL2CPP_ASSERT(work_item); if (!threadpool_class) threadpool_class = il2cpp::vm::Class::FromName(il2cpp_defaults.corlib, "System.Threading", "ThreadPool"); if (!unsafe_queue_custom_work_item_method) unsafe_queue_custom_work_item_method = (MethodInfo*)il2cpp::vm::Class::GetMethodFromName(threadpool_class, "UnsafeQueueCustomWorkItem", 2); IL2CPP_ASSERT(unsafe_queue_custom_work_item_method); f = false; args [0] = (void*) work_item; args [1] = (void*) &f; Il2CppObject *result = il2cpp::vm::Runtime::InvokeWithThrow(unsafe_queue_custom_work_item_method, NULL, args); return true; } /* LOCKING: threadpool->domains_lock must be held */ static ThreadPoolDomain* domain_get(Il2CppDomain *domain, bool create) { ThreadPoolDomain *tpdomain = NULL; unsigned int i; IL2CPP_ASSERT(domain); for (i = 0; i < g_ThreadPool->domains.size(); ++i) { tpdomain = g_ThreadPool->domains[i]; if (tpdomain->domain == domain) return tpdomain; } if (create) { tpdomain = new ThreadPoolDomain(); tpdomain->domain = domain; g_ThreadPool->domains.push_back(tpdomain); } return tpdomain; } bool worker_try_unpark() { il2cpp::os::FastAutoLock lock(&g_ThreadPool->active_threads_lock); if (g_ThreadPool->parked_threads_count == 0) return false; g_ThreadPool->parked_threads_cond.Signal(); return true; } static bool worker_request (Il2CppDomain *domain) { ThreadPoolDomain *tpdomain; IL2CPP_ASSERT(domain); IL2CPP_ASSERT(g_ThreadPool); if (il2cpp::vm::Runtime::IsShuttingDown ()) return false; g_ThreadPool->domains_lock.Lock(); /* synchronize check with worker_thread */ //if (mono_domain_is_unloading (domain)) { //mono_coop_mutex_unlock (&threadpool->domains_lock); /*return false; }*/ tpdomain = domain_get (domain, true); IL2CPP_ASSERT(tpdomain); tpdomain->outstanding_request ++; /*mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] request worker, domain = %p, outstanding_request = %d", mono_native_thread_id_get (), tpdomain->domain, tpdomain->outstanding_request);*/ g_ThreadPool->domains_lock.Unlock(); if (g_ThreadPool->suspended) return false; monitor_ensure_running (); if (worker_try_unpark ()) { //mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] request worker, unparked", mono_native_thread_id_get ()); return true; } if (worker_try_create ()) { //mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] request worker, created", mono_native_thread_id_get ()); return true; } //mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] request worker, failed", mono_native_thread_id_get ()); return false; } static void hill_climbing_change_thread_count (int16_t new_thread_count, ThreadPoolHeuristicStateTransition transition) { ThreadPoolHillClimbing *hc; IL2CPP_ASSERT(g_ThreadPool); hc = &g_ThreadPool->heuristic_hill_climbing; //mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_THREADPOOL, "[%p] hill climbing, change max number of threads %d", mono_native_thread_id_get (), new_thread_count); hc->last_thread_count = new_thread_count; hc->current_sample_interval = il2cpp::vm::Random::Next(&hc->random_interval_generator, hc->sample_interval_low, hc->sample_interval_high); hc->elapsed_since_last_change = 0; hc->completions_since_last_change = 0; } void hill_climbing_force_change (int16_t new_thread_count, ThreadPoolHeuristicStateTransition transition) { ThreadPoolHillClimbing *hc; IL2CPP_ASSERT(g_ThreadPool); hc = &g_ThreadPool->heuristic_hill_climbing; if (new_thread_count != hc->last_thread_count) { hc->current_control_setting += new_thread_count - hc->last_thread_count; hill_climbing_change_thread_count (new_thread_count, transition); } } static std::complex hill_climbing_get_wave_component (double *samples, unsigned int sample_count, double period) { ThreadPoolHillClimbing *hc; double w, cosine, sine, coeff, q0, q1, q2; unsigned int i; IL2CPP_ASSERT(g_ThreadPool); IL2CPP_ASSERT(sample_count >= period); IL2CPP_ASSERT(period >= 2); hc = &g_ThreadPool->heuristic_hill_climbing; w = 2.0 * M_PI / period; cosine = cos (w); sine = sin (w); coeff = 2.0 * cosine; q0 = q1 = q2 = 0; for (i = 0; i < sample_count; ++i) { q0 = coeff * q1 - q2 + samples [(hc->total_samples - sample_count + i) % hc->samples_to_measure]; q2 = q1; q1 = q0; } return (std::complex (q1 - q2 * cosine, (q2 * sine)) / ((double)sample_count)); } static int16_t hill_climbing_update (int16_t current_thread_count, uint32_t sample_duration, int32_t completions, int64_t *adjustment_interval) { ThreadPoolHillClimbing *hc; ThreadPoolHeuristicStateTransition transition; double throughput; double throughput_error_estimate; double confidence; double move; double gain; int sample_index; int sample_count; int new_thread_wave_magnitude; int new_thread_count; std::complex thread_wave_component; std::complex throughput_wave_component; std::complex ratio; IL2CPP_ASSERT(g_ThreadPool); IL2CPP_ASSERT(adjustment_interval); hc = &g_ThreadPool->heuristic_hill_climbing; /* If someone changed the thread count without telling us, update our records accordingly. */ if (current_thread_count != hc->last_thread_count) hill_climbing_force_change (current_thread_count, TRANSITION_INITIALIZING); /* Update the cumulative stats for this thread count */ hc->elapsed_since_last_change += sample_duration; hc->completions_since_last_change += completions; /* Add in any data we've already collected about this sample */ sample_duration += (uint32_t)hc->accumulated_sample_duration; completions += hc->accumulated_completion_count; /* We need to make sure we're collecting reasonably accurate data. Since we're just counting the end * of each work item, we are goinng to be missing some data about what really happened during the * sample interval. The count produced by each thread includes an initial work item that may have * started well before the start of the interval, and each thread may have been running some new * work item for some time before the end of the interval, which did not yet get counted. So * our count is going to be off by +/- threadCount workitems. * * The exception is that the thread that reported to us last time definitely wasn't running any work * at that time, and the thread that's reporting now definitely isn't running a work item now. So * we really only need to consider threadCount-1 threads. * * Thus the percent error in our count is +/- (threadCount-1)/numCompletions. * * We cannot rely on the frequency-domain analysis we'll be doing later to filter out this error, because * of the way it accumulates over time. If this sample is off by, say, 33% in the negative direction, * then the next one likely will be too. The one after that will include the sum of the completions * we missed in the previous samples, and so will be 33% positive. So every three samples we'll have * two "low" samples and one "high" sample. This will appear as periodic variation right in the frequency * range we're targeting, which will not be filtered by the frequency-domain translation. */ if (hc->total_samples > 0 && ((current_thread_count - 1.0) / completions) >= hc->max_sample_error) { /* Not accurate enough yet. Let's accumulate the data so * far, and tell the ThreadPool to collect a little more. */ hc->accumulated_sample_duration = sample_duration; hc->accumulated_completion_count = completions; *adjustment_interval = 10; return current_thread_count; } /* We've got enouugh data for our sample; reset our accumulators for next time. */ hc->accumulated_sample_duration = 0; hc->accumulated_completion_count = 0; /* Add the current thread count and throughput sample to our history. */ throughput = ((double) completions) / sample_duration; sample_index = hc->total_samples % hc->samples_to_measure; hc->samples [sample_index] = throughput; hc->thread_counts [sample_index] = current_thread_count; hc->total_samples ++; /* Set up defaults for our metrics. */ throughput_error_estimate = 0; confidence = 0; transition = TRANSITION_WARMUP; /* How many samples will we use? It must be at least the three wave periods we're looking for, and it must also * be a whole multiple of the primary wave's period; otherwise the frequency we're looking for will fall between * two frequency bands in the Fourier analysis, and we won't be able to measure it accurately. */ sample_count = ((int) std::min (hc->total_samples - 1, (int64_t)hc->samples_to_measure) / hc->wave_period) * hc->wave_period; if (sample_count > hc->wave_period) { int i; double average_throughput; double average_thread_count; double sample_sum = 0; double thread_sum = 0; /* Average the throughput and thread count samples, so we can scale the wave magnitudes later. */ for (i = 0; i < sample_count; ++i) { unsigned int j = (hc->total_samples - sample_count + i) % hc->samples_to_measure; sample_sum += hc->samples [j]; thread_sum += hc->thread_counts [j]; } average_throughput = sample_sum / sample_count; average_thread_count = thread_sum / sample_count; if (average_throughput > 0 && average_thread_count > 0) { double noise_for_confidence, adjacent_period_1, adjacent_period_2; /* Calculate the periods of the adjacent frequency bands we'll be using to * measure noise levels. We want the two adjacent Fourier frequency bands. */ adjacent_period_1 = sample_count / (((double) sample_count) / ((double) hc->wave_period) + 1); adjacent_period_2 = sample_count / (((double) sample_count) / ((double) hc->wave_period) - 1); /* Get the the three different frequency components of the throughput (scaled by average * throughput). Our "error" estimate (the amount of noise that might be present in the * frequency band we're really interested in) is the average of the adjacent bands. */ throughput_wave_component = hill_climbing_get_wave_component(hc->samples, sample_count, hc->wave_period) / average_throughput; //throughput_wave_component = mono_double_complex_scalar_div (hill_climbing_get_wave_component (hc->samples, sample_count, hc->wave_period), average_throughput); throughput_error_estimate = std::abs(hill_climbing_get_wave_component(hc->samples, sample_count, adjacent_period_1) / average_throughput); //throughput_error_estimate = cabs (mono_double_complex_scalar_div (hill_climbing_get_wave_component (hc->samples, sample_count, adjacent_period_1), average_throughput)); if (adjacent_period_2 <= sample_count) { throughput_error_estimate = std::max (throughput_error_estimate, std::abs (hill_climbing_get_wave_component ( hc->samples, sample_count, adjacent_period_2) / average_throughput)); } /* Do the same for the thread counts, so we have something to compare to. We don't * measure thread count noise, because there is none; these are exact measurements. */ thread_wave_component = hill_climbing_get_wave_component (hc->thread_counts, sample_count, hc->wave_period) / average_thread_count; /* Update our moving average of the throughput noise. We'll use this * later as feedback to determine the new size of the thread wave. */ if (hc->average_throughput_noise == 0) { hc->average_throughput_noise = throughput_error_estimate; } else { hc->average_throughput_noise = (hc->throughput_error_smoothing_factor * throughput_error_estimate) + ((1.0 + hc->throughput_error_smoothing_factor) * hc->average_throughput_noise); } if (std::abs (thread_wave_component) > 0) { /* Adjust the throughput wave so it's centered around the target wave, * and then calculate the adjusted throughput/thread ratio. */ ratio = ((throughput_wave_component - (thread_wave_component * hc->target_throughput_ratio)) / thread_wave_component); transition = TRANSITION_CLIMBING_MOVE; } else { //ratio = mono_double_complex_make (0, 0); transition = TRANSITION_STABILIZING; } noise_for_confidence = std::max (hc->average_throughput_noise, throughput_error_estimate); if (noise_for_confidence > 0) { confidence = std::abs (thread_wave_component) / noise_for_confidence / hc->target_signal_to_noise_ratio; } else { /* there is no noise! */ confidence = 1.0; } } } /* We use just the real part of the complex ratio we just calculated. If the throughput signal * is exactly in phase with the thread signal, this will be the same as taking the magnitude of * the complex move and moving that far up. If they're 180 degrees out of phase, we'll move * backward (because this indicates that our changes are having the opposite of the intended effect). * If they're 90 degrees out of phase, we won't move at all, because we can't tell wether we're * having a negative or positive effect on throughput. */ move = std::real (ratio); move = CLAMP (move, -1.0, 1.0); /* Apply our confidence multiplier. */ move *= CLAMP (confidence, -1.0, 1.0); /* Now apply non-linear gain, such that values around zero are attenuated, while higher values * are enhanced. This allows us to move quickly if we're far away from the target, but more slowly * if we're getting close, giving us rapid ramp-up without wild oscillations around the target. */ gain = hc->max_change_per_second * sample_duration; move = pow (fabs (move), hc->gain_exponent) * (move >= 0.0 ? 1 : -1) * gain; move = std::min (move, hc->max_change_per_sample); /* If the result was positive, and CPU is > 95%, refuse the move. */ if (move > 0.0 && g_ThreadPool->cpu_usage > CPU_USAGE_HIGH) move = 0.0; /* Apply the move to our control setting. */ hc->current_control_setting += move; /* Calculate the new thread wave magnitude, which is based on the moving average we've been keeping of the * throughput error. This average starts at zero, so we'll start with a nice safe little wave at first. */ new_thread_wave_magnitude = (int)(0.5 + (hc->current_control_setting * hc->average_throughput_noise * hc->target_signal_to_noise_ratio * hc->thread_magnitude_multiplier * 2.0)); new_thread_wave_magnitude = CLAMP (new_thread_wave_magnitude, 1, hc->max_thread_wave_magnitude); /* Make sure our control setting is within the ThreadPool's limits. */ hc->current_control_setting = CLAMP (hc->current_control_setting, g_ThreadPool->limit_worker_min, g_ThreadPool->limit_worker_max - new_thread_wave_magnitude); /* Calculate the new thread count (control setting + square wave). */ new_thread_count = (int)(hc->current_control_setting + new_thread_wave_magnitude * ((hc->total_samples / (hc->wave_period / 2)) % 2)); /* Make sure the new thread count doesn't exceed the ThreadPool's limits. */ new_thread_count = CLAMP (new_thread_count, g_ThreadPool->limit_worker_min, g_ThreadPool->limit_worker_max); if (new_thread_count != current_thread_count) hill_climbing_change_thread_count (new_thread_count, transition); if (std::real (ratio) < 0.0 && new_thread_count == g_ThreadPool->limit_worker_min) *adjustment_interval = (int)(0.5 + hc->current_sample_interval * (10.0 * std::max (-1.0 * std::real (ratio), 1.0))); else *adjustment_interval = hc->current_sample_interval; return new_thread_count; } static void heuristic_notify_work_completed (void) { IL2CPP_ASSERT(g_ThreadPool); il2cpp::vm::Atomic::Increment(&g_ThreadPool->heuristic_completions); g_ThreadPool->heuristic_last_dequeue = il2cpp::os::Time::GetTicksMillisecondsMonotonic(); } static bool heuristic_should_adjust (void) { IL2CPP_ASSERT(g_ThreadPool); if (g_ThreadPool->heuristic_last_dequeue > g_ThreadPool->heuristic_last_adjustment + g_ThreadPool->heuristic_adjustment_interval) { ThreadPoolCounter counter; counter.as_int64_t = COUNTER_READ(); if (counter._.working <= counter._.max_working) return true; } return false; } static void heuristic_adjust (void) { IL2CPP_ASSERT(g_ThreadPool); if (g_ThreadPool->heuristic_lock.TryLock()) { int32_t completions = il2cpp::vm::Atomic::Exchange (&g_ThreadPool->heuristic_completions, 0); int64_t sample_end = il2cpp::os::Time::GetTicksMillisecondsMonotonic(); int64_t sample_duration = sample_end - g_ThreadPool->heuristic_sample_start; if (sample_duration >= g_ThreadPool->heuristic_adjustment_interval / 2) { ThreadPoolCounter counter; int16_t new_thread_count; counter.as_int64_t = COUNTER_READ (); new_thread_count = hill_climbing_update (counter._.max_working, (uint32_t)sample_duration, completions, &g_ThreadPool->heuristic_adjustment_interval); COUNTER_ATOMIC (counter, { counter._.max_working = new_thread_count; }); if (new_thread_count > counter._.max_working) worker_request (il2cpp::vm::Domain::GetCurrent()); g_ThreadPool->heuristic_sample_start = sample_end; g_ThreadPool->heuristic_last_adjustment = il2cpp::os::Time::GetTicksMillisecondsMonotonic(); } g_ThreadPool->heuristic_lock.Unlock(); } } void threadpool_ms_cleanup (void) { #ifndef DISABLE_SOCKETS threadpool_ms_io_cleanup (); #endif if (lazy_init_status.IsSet()) cleanup(); } Il2CppAsyncResult* threadpool_ms_begin_invoke (Il2CppDomain *domain, Il2CppObject *target, MethodInfo *method, void* *params) { Il2CppMethodMessage *message; Il2CppDelegate *async_callback = NULL; Il2CppObject *state = NULL; Il2CppAsyncCall* async_call = (Il2CppAsyncCall*)il2cpp::vm::Object::New(il2cpp_defaults.async_call_class); lazy_initialize (); MethodInfo *invoke = (MethodInfo*)il2cpp::vm::Class::GetMethodFromName(method->declaring_type, "Invoke", -1); message = mono_method_call_message_new (method, params, invoke, (params != NULL) ? (&async_callback) : NULL, (params != NULL) ? (&state) : NULL); IL2CPP_OBJECT_SETREF (async_call, msg, message); IL2CPP_OBJECT_SETREF (async_call, state, state); if (async_callback) { IL2CPP_OBJECT_SETREF (async_call, cb_method, (MethodInfo*)il2cpp::vm::Runtime::GetDelegateInvoke(il2cpp::vm::Object::GetClass((Il2CppObject*)async_callback))); IL2CPP_OBJECT_SETREF (async_call, cb_target, async_callback); } Il2CppAsyncResult* async_result = (Il2CppAsyncResult*)il2cpp::vm::Object::New(il2cpp_defaults.asyncresult_class); IL2CPP_OBJECT_SETREF(async_result, async_delegate, (Il2CppDelegate*)target); IL2CPP_OBJECT_SETREF(async_result, object_data, async_call); IL2CPP_OBJECT_SETREF(async_result, async_state, async_call->state); threadpool_ms_enqueue_work_item (domain, (Il2CppObject*) async_result); return async_result; } Il2CppObject* threadpool_ms_end_invoke (Il2CppAsyncResult *ares, Il2CppArray **out_args, Il2CppObject **exc) { Il2CppAsyncCall *ac; IL2CPP_ASSERT(exc); IL2CPP_ASSERT(out_args); *exc = NULL; *out_args = NULL; /* check if already finished */ il2cpp_monitor_enter((Il2CppObject*) ares); if (ares->endinvoke_called) { il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetInvalidOperationException("Cannot call EndInvoke() repeatedly or concurrently on the same AsyncResult!")); il2cpp_monitor_exit((Il2CppObject*) ares); return NULL; } ares->endinvoke_called = 1; /* wait until we are really finished */ if (ares->completed) { il2cpp_monitor_exit((Il2CppObject *) ares); } else { if (!ares->handle) { Il2CppWaitHandle *wait_handle = il2cpp::vm::WaitHandle::NewManualResetEvent(false); IL2CPP_OBJECT_SETREF(ares, handle, wait_handle); } il2cpp::os::Handle* wait_event = il2cpp::vm::WaitHandle::GetPlatformHandle((Il2CppWaitHandle*)ares->handle); il2cpp_monitor_exit((Il2CppObject*) ares); //MONO_ENTER_GC_SAFE; wait_event->Wait(); //MONO_EXIT_GC_SAFE; } ac = (Il2CppAsyncCall*) ares->object_data; IL2CPP_ASSERT(ac); *exc = ((Il2CppMethodMessage*)ac->msg)->exc; /* FIXME: GC add write barrier */ *out_args = ac->out_args; return ac->res; } void threadpool_ms_suspend (void) { if (g_ThreadPool) g_ThreadPool->suspended = true; } void threadpool_ms_resume (void) { if (g_ThreadPool) g_ThreadPool->suspended = false; } void ves_icall_System_Threading_ThreadPool_GetAvailableThreadsNative (int32_t *worker_threads, int32_t *completion_port_threads) { ThreadPoolCounter counter; if (!worker_threads || !completion_port_threads) return; lazy_initialize (); counter.as_int64_t = COUNTER_READ (); *worker_threads = std::max (0, g_ThreadPool->limit_worker_max - counter._.active); *completion_port_threads = g_ThreadPool->limit_io_max; } void ves_icall_System_Threading_ThreadPool_GetMinThreadsNative (int32_t *worker_threads, int32_t *completion_port_threads) { if (!worker_threads || !completion_port_threads) return; lazy_initialize (); *worker_threads = g_ThreadPool->limit_worker_min; *completion_port_threads = g_ThreadPool->limit_io_min; } void ves_icall_System_Threading_ThreadPool_GetMaxThreadsNative (int32_t *worker_threads, int32_t *completion_port_threads) { if (!worker_threads || !completion_port_threads) return; lazy_initialize (); *worker_threads = g_ThreadPool->limit_worker_max; *completion_port_threads = g_ThreadPool->limit_io_max; } bool ves_icall_System_Threading_ThreadPool_SetMinThreadsNative (int32_t worker_threads, int32_t completion_port_threads) { lazy_initialize (); if (worker_threads <= 0 || worker_threads > g_ThreadPool->limit_worker_max) return false; if (completion_port_threads <= 0 || completion_port_threads > g_ThreadPool->limit_io_max) return false; g_ThreadPool->limit_worker_min = worker_threads; g_ThreadPool->limit_io_min = completion_port_threads; return true; } bool ves_icall_System_Threading_ThreadPool_SetMaxThreadsNative (int32_t worker_threads, int32_t completion_port_threads) { int cpu_count = il2cpp::os::Environment::GetProcessorCount (); lazy_initialize (); if (worker_threads < g_ThreadPool->limit_worker_min || worker_threads < cpu_count) return false; if (completion_port_threads < g_ThreadPool->limit_io_min || completion_port_threads < cpu_count) return false; g_ThreadPool->limit_worker_max = worker_threads; g_ThreadPool->limit_io_max = completion_port_threads; return true; } void ves_icall_System_Threading_ThreadPool_InitializeVMTp (bool *enable_worker_tracking) { if (enable_worker_tracking) { // TODO implement some kind of switch to have the possibily to use it *enable_worker_tracking = false; } lazy_initialize (); } bool ves_icall_System_Threading_ThreadPool_NotifyWorkItemComplete (void) { ThreadPoolCounter counter; if (il2cpp::vm::Runtime::IsShuttingDown ()) return false; heuristic_notify_work_completed (); if (heuristic_should_adjust ()) heuristic_adjust (); counter.as_int64_t = COUNTER_READ (); return counter._.working <= counter._.max_working; } void ves_icall_System_Threading_ThreadPool_NotifyWorkItemProgressNative (void) { heuristic_notify_work_completed (); if (heuristic_should_adjust ()) heuristic_adjust (); } void ves_icall_System_Threading_ThreadPool_ReportThreadStatus (bool is_working) { // Mono raises a not implemented exception NOT_IMPLEMENTED_ICALL(ves_icall_System_Threading_ThreadPool_PostQueuedCompletionStatus); IL2CPP_UNREACHABLE; } bool ves_icall_System_Threading_ThreadPool_RequestWorkerThread (void) { return worker_request (il2cpp::vm::Domain::GetCurrent()); } bool ves_icall_System_Threading_ThreadPool_PostQueuedCompletionStatus (Il2CppNativeOverlapped *native_overlapped) { // Mono raises a not implemented exception NOT_IMPLEMENTED_ICALL(ves_icall_System_Threading_ThreadPool_PostQueuedCompletionStatus); IL2CPP_UNREACHABLE; } bool ves_icall_System_Threading_ThreadPool_BindIOCompletionCallbackNative (void* file_handle) { /* This copy the behavior of the current Mono implementation */ return true; } bool ves_icall_System_Threading_ThreadPool_IsThreadPoolHosted (void) { return false; } #endif ================================================ FILE: unity_decoder/libil2cpp/mono/ThreadPool/threadpool-ms.h ================================================ #pragma once #if NET_4_0 #include "il2cpp-config.h" #include "mono/ThreadPool/ThreadPoolDataStructures.h" struct Il2CppObject; struct Il2CppDomain; struct Il2CppArray; struct Il2CppAsyncResult; struct MethodInfo; struct Il2CppNativeOverlapped; #define SMALL_STACK (sizeof (void*) * 32 * 1024) void threadpool_ms_cleanup(void); Il2CppAsyncResult * threadpool_ms_begin_invoke(Il2CppDomain *domain, Il2CppObject *target, MethodInfo *method, void* *params); Il2CppObject * threadpool_ms_end_invoke(Il2CppAsyncResult *ares, Il2CppArray **out_args, Il2CppObject **exc); void threadpool_ms_suspend(void); void threadpool_ms_resume(void); LIBIL2CPP_CODEGEN_API void ves_icall_System_Threading_ThreadPool_GetAvailableThreadsNative(int32_t *worker_threads, int32_t *completion_port_threads); LIBIL2CPP_CODEGEN_API void ves_icall_System_Threading_ThreadPool_GetMinThreadsNative(int32_t *worker_threads, int32_t *completion_port_threads); LIBIL2CPP_CODEGEN_API void ves_icall_System_Threading_ThreadPool_GetMaxThreadsNative(int32_t *worker_threads, int32_t *completion_port_threads); LIBIL2CPP_CODEGEN_API bool ves_icall_System_Threading_ThreadPool_SetMinThreadsNative(int32_t worker_threads, int32_t completion_port_threads); LIBIL2CPP_CODEGEN_API bool ves_icall_System_Threading_ThreadPool_SetMaxThreadsNative(int32_t worker_threads, int32_t completion_port_threads); LIBIL2CPP_CODEGEN_API void ves_icall_System_Threading_ThreadPool_InitializeVMTp(bool *enable_worker_tracking); LIBIL2CPP_CODEGEN_API bool ves_icall_System_Threading_ThreadPool_NotifyWorkItemComplete(void); LIBIL2CPP_CODEGEN_API void ves_icall_System_Threading_ThreadPool_NotifyWorkItemProgressNative(void); LIBIL2CPP_CODEGEN_API void ves_icall_System_Threading_ThreadPool_ReportThreadStatus(bool is_working); LIBIL2CPP_CODEGEN_API bool ves_icall_System_Threading_ThreadPool_RequestWorkerThread(void); LIBIL2CPP_CODEGEN_API bool ves_icall_System_Threading_ThreadPool_PostQueuedCompletionStatus(Il2CppNativeOverlapped *native_overlapped); LIBIL2CPP_CODEGEN_API bool ves_icall_System_Threading_ThreadPool_BindIOCompletionCallbackNative(void* file_handle); LIBIL2CPP_CODEGEN_API bool ves_icall_System_Threading_ThreadPool_IsThreadPoolHosted(void); /* Internals */ bool threadpool_ms_enqueue_work_item(Il2CppDomain *domain, Il2CppObject *work_item); extern ThreadPool* g_ThreadPool; bool worker_try_unpark(); void hill_climbing_force_change(int16_t new_thread_count, ThreadPoolHeuristicStateTransition transition); #endif ================================================ FILE: unity_decoder/libil2cpp/mono-runtime/il2cpp-callbacks.cpp ================================================ #if RUNTIME_MONO #include #include #include "mono-api.h" #include "../libmono/icalls/mscorlib/System.Diagnostics/StackFrame.h" #include "../libmono/icalls/mscorlib/System.Diagnostics/StackTrace.h" #include "../libmono/icalls/mscorlib/System.Runtime.InteropServices/Marshal.h" #include "../libmono/vm/StackTrace.h" #include "../libmono/vm/MetadataCache.h" #include "il2cpp-callbacks.h" #include "il2cpp-mono-support.h" #include "class-internals.h" #include "object-internals.h" #include #include "os/Thread.h" #include "utils/PathUtils.h" #include "utils/StringUtils.h" #include "utils/Environment.h" #include "utils/utf8-cpp/source/utf8.h" #include "vm-utils/NativeSymbol.h" static void* il2cpp_get_vtable_trampoline(MonoVTable *vtable, int slot_index) { return 0; } static void* il2cpp_get_imt_trampoline(MonoVTable *vtable, int imt_slot_index) { return 0; } static void mono_thread_start_cb(intptr_t tid, void* stack_start, void* func) { mono::vm::StackTrace::InitializeStackTracesForCurrentThread(); } static void mono_thread_attach_cb(intptr_t tid, void* stack_start) { mono::vm::StackTrace::InitializeStackTracesForCurrentThread(); } static void mono_thread_cleanup_cb(intptr_t tid) { //assert(tid == il2cpp::os::Thread::CurrentThreadId()); //mono::vm::StackTrace::CleanupStackTracesForCurrentThread(); } static void il2cpp_throw_exception(MonoException* ex) { if (mono_unity_exception_get_trace_ips(ex) == NULL) { // Only write the stack trace if there is not one already in the exception. // When we exit managed try/finally and try/catch blocks with an exception, this method is // called with the original exception which already has the proper stack trace. // Getting the stack trace again here will lose the frames between the original throw // and the finally or catch block. const mono::vm::StackFrames& frames = *mono::vm::StackTrace::GetStackFrames(); size_t i = frames.size() - 1; MonoArray* ips = MonoArrayNew(mono_unity_defaults_get_int_class(), frames.size()); for (mono::vm::StackFrames::const_iterator iter = frames.begin(); iter != frames.end(); ++iter, --i) { mono_array_set(ips, const MonoMethod*, i, (*iter).method); } mono_unity_exception_set_trace_ips(ex, ips); } throw Il2CppExceptionWrapper(ex); } static void il2cpp_walk_stack_with_ctx(MonoInternalStackWalk func, MonoContext *ctx, MonoUnwindOptions options, void *user_data) { mono::vm::StackTrace::WalkFrameStack(func, ctx, user_data); } static int32_t il2cpp_exception_walk_trace(MonoException *ex, MonoInternalExceptionFrameWalk func, void* user_data) { MonoArray *ta = mono_unity_exception_get_trace_ips(ex); int len, i; if (ta == NULL) return 0; len = (int)mono_array_length(ta) >> 1; for (i = 0; i < len; i++) { void* ip = mono_array_get(ta, void*, i * 2 + 0); void* generic_info = mono_array_get(ta, void*, i * 2 + 1); const MonoMethod* method = il2cpp::utils::NativeSymbol::GetMethodFromNativeSymbol((Il2CppMethodPointer)ip); if (method == NULL) { if (func(NULL, ip, 0, 0, user_data)) return 1; } else { if (func(const_cast(method), ip, 0, 1, user_data)) return 1; } } return len > 0; } static int32_t il2cpp_current_thread_has_handle_block_guard() { return 0; } static gboolean il2cpp_install_handler_block_guard(MonoThreadUnwindState *ctx) { return false; } static MonoObject* il2cpp_mono_fake_box(void *ptr) { return ((MonoObject*)ptr) - 1; } MonoObject* il2cpp_mono_determine_target_object(MonoMethod *method, MonoObject *obj) { if (!obj) return NULL; if (mono_class_is_valuetype(mono_unity_method_get_class(method))) return obj; MonoClass *klass = mono_unity_object_get_class(obj); if (mono_unity_class_is_delegate(klass) && (strcmp(mono_unity_method_get_name(method), "Invoke") != 0)) return mono_unity_delegate_get_target((MonoDelegate*)obj); return obj; } MonoObject* il2cpp_mono_runtime_invoke(MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error) { il2cpp_mono_method_initialize_function_pointers(method, error); if (!il2cpp_mono_error_ok(error)) return NULL; if (exc) *exc = NULL; MonoObject *target = il2cpp_mono_determine_target_object(method, (MonoObject*)obj); void **newParams = params; std::vector newParamsVec; std::vector byRefParams; if (params && mono_method_signature(method)) { int numParams = mono_unity_signature_num_parameters(mono_method_signature(method)); if (numParams > 0) { newParamsVec.resize(numParams); for (int i = 0; i < numParams; ++i) { MonoClass *paramSigClass = mono_unity_signature_get_class_for_param(mono_method_signature(method), i); if (mono_class_is_nullable(paramSigClass)) { if (mono_unity_signature_param_is_byref(mono_method_signature(method), i)) byRefParams.push_back(i); MonoObject *paramObj = (MonoObject*)params[i]; void *nullable = alloca(mono_unity_class_get_instance_size(paramSigClass)); mono_nullable_init((uint8_t*)nullable, paramObj, paramSigClass); newParamsVec[i] = nullable; } else { newParamsVec[i] = params[i]; } } newParams = &newParamsVec[0]; } } if (mono_class_is_nullable(mono_unity_method_get_class(method))) target = mono_value_box(mono_domain_get(), mono_unity_class_get_castclass(mono_unity_method_get_class(method)), target); else if (target != NULL && mono_class_is_valuetype(mono_unity_method_get_class(method))) target = il2cpp_mono_fake_box(target); try { if (strcmp(mono_unity_method_get_name(method), ".ctor") == 0) mono_runtime_class_init_full(mono_class_vtable(mono_domain_get(), mono_unity_method_get_class(method)), error); void *retVal = ((InvokerMethod)mono_unity_method_get_invoke_pointer(method))((Il2CppMethodPointer)mono_unity_method_get_method_pointer(method), method, target, newParams); std::vector::const_iterator end = byRefParams.end(); for (std::vector::const_iterator it = byRefParams.begin(); it != end; ++it) { MonoClass *paramSigClass = mono_unity_signature_get_class_for_param(mono_method_signature(method), *it); params[*it] = mono_value_box(mono_domain_get(), paramSigClass, newParamsVec[*it]); } return mono_unity_method_convert_return_type_if_needed(method, retVal); } catch (Il2CppExceptionWrapper& ex) { if (exc) *exc = (MonoObject*)ex.ex; else mono_set_pending_exception((MonoException*)ex.ex); return NULL; } } MonoObject* il2cpp_mono_finalize_runtime_invoke(MonoObject *this_obj, void **params, MonoObject **exc, void* compiled_method) { MonoMethod* finalizer = mono_class_get_finalizer(mono_object_get_class(this_obj)); if (finalizer == NULL) { assert(0 && "Why did we get a NULL finalizer? Something may not be correct."); return NULL; } MonoError unused; return il2cpp_mono_runtime_invoke(finalizer, this_obj, params, exc, &unused); } void il2cpp_mono_set_cast_details(MonoClass *from, MonoClass *to) { } MonoObject* il2cpp_mono_capture_context_runtime_invoke(MonoObject *this_obj, void **params, MonoObject **exc, void* compiled_method) { return NULL; } void il2cpp_mono_dummy_callback() { } void* il2cpp_mono_delegate_trampoline(MonoDomain *domain, MonoClass *klass) { int vtableSize = mono_class_get_vtable_size(klass); MonoMethod *method = NULL; for (int i = 0; i < vtableSize; ++i) { MonoMethod *vtableMethod = mono_class_get_vtable_entry(klass, i); const char *vtableMethodName = mono_unity_method_get_name(vtableMethod); const char *substr = strstr(vtableMethodName, "Invoke"); if (substr == vtableMethodName) //if the pointers are equal, vtableMethodName starts with "Invoke" { method = vtableMethod; break; } } if (!method) return NULL; MonoError unused; il2cpp_mono_method_initialize_function_pointers(method, &unused); return mono_unity_method_get_method_pointer(method); } void* il2cpp_mono_create_jump_trampoline(MonoDomain *domain, MonoMethod *method, gboolean add_sync_wrapper, MonoError *error) { il2cpp_mono_method_initialize_function_pointers(method, error); return mono_unity_method_get_method_pointer(method); } void* il2cpp_mono_create_ftnptr(MonoDomain *domain, void* addr) { return addr; } char* il2cpp_mono_get_runtime_build_info() { return mono_unity_get_runtime_build_info(__DATE__, __TIME__); } void il2cpp_install_callbacks() { MonoRuntimeCallbacks callbacks; memset(&callbacks, 0, sizeof(callbacks)); callbacks.get_vtable_trampoline = il2cpp_get_vtable_trampoline; callbacks.get_imt_trampoline = il2cpp_get_imt_trampoline; callbacks.runtime_invoke = il2cpp_mono_runtime_invoke; callbacks.set_cast_details = il2cpp_mono_set_cast_details; callbacks.create_jump_trampoline = il2cpp_mono_create_jump_trampoline; callbacks.create_ftnptr = il2cpp_mono_create_ftnptr; callbacks.get_runtime_build_info = il2cpp_mono_get_runtime_build_info; mono_install_callbacks(&callbacks); MonoRuntimeExceptionHandlingCallbacks cbs; memset(&cbs, 0, sizeof(cbs)); cbs.mono_raise_exception = il2cpp_throw_exception; cbs.mono_walk_stack_with_ctx = il2cpp_walk_stack_with_ctx; cbs.mono_install_handler_block_guard = il2cpp_install_handler_block_guard; cbs.mono_exception_walk_trace = il2cpp_exception_walk_trace; cbs.mono_current_thread_has_handle_block_guard = il2cpp_current_thread_has_handle_block_guard; mono_install_eh_callbacks(&cbs); mono_unity_domain_install_finalize_runtime_invoke(mono_domain_get(), il2cpp_mono_finalize_runtime_invoke); mono_unity_domain_install_capture_context_runtime_invoke(mono_domain_get(), il2cpp_mono_capture_context_runtime_invoke); mono_unity_domain_install_capture_context_method(mono_domain_get(), (void*)il2cpp_mono_dummy_callback); mono_install_delegate_trampoline(il2cpp_mono_delegate_trampoline); MonoThreadInfoRuntimeCallbacks ticallbacks; memset(&ticallbacks, 0, sizeof(ticallbacks)); ticallbacks.thread_state_init_from_handle = mono_unity_thread_state_init_from_handle; mono_threads_runtime_init(&ticallbacks); } void il2cpp_mono_runtime_init() { MonoDomain* domain = mono_domain_get(); mono_runtime_init(domain, mono_thread_start_cb, mono_thread_attach_cb); mono_threads_install_cleanup(mono_thread_cleanup_cb); mono_thread_attach(domain); mono_class_set_allow_gc_aware_layout(false); mono_add_internal_call("System.Diagnostics.StackFrame::get_frame_info", (void*)mono::icalls::mscorlib::System::Diagnostics::StackFrame::get_frame_info); mono_add_internal_call("System.Diagnostics.StackTrace::get_trace", (void*)mono::icalls::mscorlib::System::Diagnostics::StackTrace::get_trace); mono_add_internal_call("System.Runtime.InteropServices.Marshal::GetFunctionPointerForDelegateInternal", (void*)mono::icalls::mscorlib::System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegateInternal); mono_add_internal_call("System.Runtime.InteropServices.Marshal::GetDelegateForFunctionPointerInternal", (void*)mono::icalls::mscorlib::System::Runtime::InteropServices::Marshal::GetDelegateForFunctionPointerInternal); RegisterAllManagedMethods(); initialize_interop_data_map(); } static void MonoSetConfigStr(const std::string& executablePath) { std::string appBase = il2cpp::utils::PathUtils::DirectoryName(executablePath); std::string configFileName = il2cpp::utils::PathUtils::Basename(executablePath); configFileName.append(".config"); mono_domain_set_config(mono_domain_get(), appBase.c_str(), configFileName.c_str()); } void il2cpp_mono_set_config_utf16(const Il2CppChar* executablePath) { IL2CPP_ASSERT(executablePath); std::string exePathUtf8 = il2cpp::utils::StringUtils::Utf16ToUtf8(executablePath, -1); MonoSetConfigStr(exePathUtf8); } void il2cpp_mono_set_config(const char* executablePath) { IL2CPP_ASSERT(executablePath); std::string executablePathStr(executablePath); MonoSetConfigStr(executablePathStr); } void il2cpp_mono_set_commandline_arguments_utf16(int argc, const Il2CppChar* const* argv) { std::vector args(argc); for (int i = 0; i < argc; ++i) args[i] = il2cpp::utils::StringUtils::Utf16ToUtf8(argv[i], -1); std::vector cargs(argc); for (int i = 0; i < argc; ++i) cargs[i] = args[i].c_str(); mono_runtime_set_main_args(argc, const_cast(&cargs[0])); il2cpp::utils::Environment::SetMainArgs(argv, argc); } void il2cpp_mono_set_commandline_arguments(int argc, const char* const* argv) { mono_runtime_set_main_args(argc, const_cast(argv)); il2cpp::utils::Environment::SetMainArgs(argv, argc); } void il2cpp_mono_initialize_metadata() { mono::vm::MetadataCache::Initialize(); } #endif ================================================ FILE: unity_decoder/libil2cpp/mono-runtime/il2cpp-callbacks.h ================================================ #pragma once #if RUNTIME_MONO #if _MSC_VER typedef wchar_t Il2CppChar; #elif __has_feature(cxx_unicode_literals) typedef char16_t Il2CppChar; #else typedef uint16_t Il2CppChar; #endif void il2cpp_install_callbacks(); void il2cpp_mono_runtime_init(); void il2cpp_mono_set_config_utf16(const Il2CppChar* executablePath); void il2cpp_mono_set_config(const char* executablePath); void il2cpp_mono_set_commandline_arguments_utf16(int argc, const Il2CppChar* const* argv); void il2cpp_mono_set_commandline_arguments(int argc, const char* const* argv); void il2cpp_mono_initialize_metadata(); #endif ================================================ FILE: unity_decoder/libil2cpp/mono-runtime/il2cpp-mapping.h ================================================ #pragma once #include "il2cpp-metadata.h" struct MonoMethodInfo { int64_t hash; int32_t invoker_index; int32_t method_pointer_index; }; struct MonoRGCTXDefinition { Il2CppRGCTXDataType type; AssemblyIndex assemblyIndex; int32_t token; int32_t generic_parameter_index; }; struct RuntimeGenericContextInfo { uint64_t hash; int32_t rgctxStart; int32_t rgctxCount; }; struct MonoMetadataToken { AssemblyIndex assemblyIndex; int32_t token; }; #pragma pack(push, p1,4) struct MonoMethodMetadata { MonoMetadataToken metadataToken; MethodIndex reversePInvokeWrapperIndex; uint64_t hash; }; #pragma pack(pop, p1) #pragma pack(push, p1,4) struct MonoClassMetadata { MonoMetadataToken metadataToken; int32_t genericParametersOffset; int32_t genericParametersCount; int32_t isPointer; int32_t rank; //if rank == 0, the token is for a non-array type, otherwise the rank is valid and the token represents the element type of the array int32_t elementTypeIndex; }; #pragma pack(pop, p1) struct MonoFieldMetadata { TypeIndex parentTypeIndex; int32_t token; }; struct MonoGenericInstMetadata { uint32_t type_argc; const TypeIndex *type_argv_indices; }; ================================================ FILE: unity_decoder/libil2cpp/mono-runtime/il2cpp-mono-support.cpp ================================================ #if RUNTIME_MONO #include #include "class-internals.h" #include "object-internals.h" #include "il2cpp-mapping.h" #include "il2cpp-mono-support.h" #include "../libmono/mono-api.h" #include "utils/dynamic_array.h" #if IL2CPP_ENABLE_NATIVE_STACKTRACES #include "vm-utils/NativeSymbol.h" #endif // IL2CPP_ENABLE_NATIVE_STACKTRACES #include "utils/MarshalingUtils.h" #include "../libmono/vm/MetadataCache.h" #include #include "utils/Il2CppHashMap.h" #include "utils/HashUtils.h" #include "os/Mutex.h" Il2CppIntPtr Il2CppIntPtr::Zero; extern const Il2CppCodeRegistration g_CodeRegistration IL2CPP_ATTRIBUTE_WEAK; extern const Il2CppMethodSpec g_Il2CppMethodSpecTable[] IL2CPP_ATTRIBUTE_WEAK; #if IL2CPP_ENABLE_NATIVE_STACKTRACES #endif // IL2CPP_ENABLE_NATIVE_STACKTRACES // Mono-specific metadata emitted by IL2CPP extern void** const g_MetadataUsages[] IL2CPP_ATTRIBUTE_WEAK; extern const MonoGenericInstMetadata* const g_MonoGenericInstMetadataTable[] IL2CPP_ATTRIBUTE_WEAK; extern const Il2CppCodeGenOptions s_Il2CppCodeGenOptions IL2CPP_ATTRIBUTE_WEAK; extern const int g_Il2CppInteropDataCount IL2CPP_ATTRIBUTE_WEAK; extern Il2CppInteropData g_Il2CppInteropData[] IL2CPP_ATTRIBUTE_WEAK; static MonoGenericContext GetSharedContext(const MonoGenericContext* context); static MonoAssembly** s_MonoAssemblies; static int s_MonoAssembliesCount = 0; MonoAssembly* il2cpp_mono_assembly_from_name(const char* name); typedef Il2CppHashMap > InteropDataMap; static InteropDataMap s_InteropDataMap; typedef Il2CppHashMap > InteropDataPointerCacheMap; static InteropDataPointerCacheMap s_InteropDataPointerCacheMap; static il2cpp::os::FastMutex s_InteropPointerCacheMutex; void il2cpp_mono_error_init(MonoError *oerror) { MonoErrorInternal *error = (MonoErrorInternal*)oerror; error->error_code = MONO_ERROR_NONE; error->flags = 0; } bool il2cpp_mono_error_ok(MonoError *error) { return error->error_code == MONO_ERROR_NONE; } static MonoGenericInst* GetSharedGenericInst(MonoGenericInst* inst) { std::vector types; unsigned int type_argc = mono_unity_generic_inst_get_type_argc(inst); for (uint32_t i = 0; i < type_argc; ++i) { MonoType *type = mono_unity_generic_inst_get_type_argument(inst, i); if (mono_type_is_reference(type)) { types.push_back(mono_class_get_type(mono_get_object_class())); } else if (mono_unity_type_is_generic_instance(type)) { MonoGenericClass *gclass = mono_unity_type_get_generic_class(type); MonoGenericContext context = mono_unity_generic_class_get_context(gclass); MonoGenericContext sharedContext = GetSharedContext(&context); MonoClass *container_class = mono_unity_generic_class_get_container_class(gclass); MonoError unused; MonoClass *klass = mono_class_inflate_generic_class_checked(container_class, &sharedContext, &unused); types.push_back(mono_class_get_type(klass)); } else if (mono_unity_type_is_enum_type(type) && s_Il2CppCodeGenOptions.enablePrimitiveValueTypeGenericSharing) { types.push_back(mono_class_get_type(mono_unity_type_get_element_class(type))); } else if (mono_unity_type_is_boolean(type) && s_Il2CppCodeGenOptions.enablePrimitiveValueTypeGenericSharing) { types.push_back(mono_class_get_type(mono_unity_defaults_get_byte_class())); } else { types.push_back(mono_unity_generic_inst_get_type_argument(inst, i)); } } return mono_metadata_get_generic_inst(type_argc, &types[0]); } static MonoGenericContext GetSharedContext(const MonoGenericContext* context) { MonoGenericContext newContext = {0}; if (context->class_inst != NULL) newContext.class_inst = GetSharedGenericInst(context->class_inst); if (context->method_inst != NULL) newContext.method_inst = GetSharedGenericInst(context->method_inst); return newContext; } static MonoMethod* InflateGenericMethodWithContext(MonoMethod* method, MonoGenericContext* context, bool useSharedVersion) { if (useSharedVersion) { MonoGenericContext sharedContext = GetSharedContext(context); return mono_class_inflate_generic_method(method, &sharedContext); } return mono_class_inflate_generic_method(method, context); } void initialize_interop_data_map() { for (int i = 0; i < g_Il2CppInteropDataCount; ++i) s_InteropDataMap.add(g_Il2CppInteropData[i].hash, &g_Il2CppInteropData[i]); } const Il2CppInteropData* FindInteropDataFor(MonoClass* klass) { il2cpp::os::FastAutoLock cacheLock(&s_InteropPointerCacheMutex); InteropDataPointerCacheMap::const_iterator itCache = s_InteropDataPointerCacheMap.find(klass); if (itCache != s_InteropDataPointerCacheMap.end()) return itCache->second; uint64_t hash = mono_unity_type_get_hash(mono_class_get_type(klass), true); InteropDataMap::const_iterator it = s_InteropDataMap.find(hash); if (it != s_InteropDataMap.end()) { const Il2CppInteropData *value = it->second; s_InteropDataPointerCacheMap.add(klass, value); return value; } return NULL; } static void StructureToPtr(MonoObject* structure, void* ptr, bool deleteOld) { if (structure == NULL) mono_raise_exception(mono_get_exception_argument_null("structure")); if (ptr == NULL) mono_raise_exception(mono_get_exception_argument_null("ptr")); MonoClass* klass = mono_object_get_class(structure); const Il2CppInteropData* interopData = FindInteropDataFor(klass); if (interopData != NULL && interopData->pinvokeMarshalToNativeFunction != NULL) { if (deleteOld) il2cpp::utils::MarshalingUtils::MarshalFreeStruct(ptr, interopData); void* objectPtr = mono_unity_class_is_class_type(klass) ? structure : mono_object_unbox(structure); il2cpp::utils::MarshalingUtils::MarshalStructToNative(objectPtr, ptr, interopData); return; } // If there's no custom marshal function, it means it's either a primitive, or invalid argument uint32_t nativeSize = mono_unity_class_get_native_size(klass); if (nativeSize != -1) { // StructureToPtr is supposed to throw on strings and enums if (!mono_class_is_enum(klass) && !mono_unity_class_is_string(klass)) { memcpy(ptr, mono_object_unbox(structure), nativeSize); return; } } // If we got this far, throw an exception MonoException* exception; if (mono_class_is_generic(klass)) { exception = mono_get_exception_argument("structure", "The specified object must not be an instance of a generic type."); } else { exception = mono_get_exception_argument("structure", "The specified structure must be blittable or have layout information."); } mono_raise_exception(exception); } static void* MarshalInvokerMethod(Il2CppMethodPointer func, const MonoMethod* method, void* thisArg, void** params) { if (strcmp(mono_unity_method_get_name(method), "PtrToStructure") == 0) { const Il2CppInteropData* interopData = FindInteropDataFor(mono_unity_method_get_class(method)); if (interopData != NULL && mono_unity_class_is_class_type(mono_unity_method_get_class(method))) il2cpp::utils::MarshalingUtils::MarshalStructFromNative((void*)(*(intptr_t*)params[0]), params[1], interopData); else if (interopData != NULL) il2cpp::utils::MarshalingUtils::MarshalStructFromNative((void*)(*(intptr_t*)params[0]), mono_object_unbox((MonoObject*)params[1]), interopData); else // The type is blittable memcpy(mono_object_unbox((MonoObject*)params[1]), (void*)(*(intptr_t*)params[0]), mono_unity_class_get_native_size(mono_unity_method_get_class(method))); } else if (strcmp(mono_unity_method_get_name(method), "StructureToPtr") == 0) StructureToPtr((MonoObject*)params[0], (void*)(*(intptr_t*)params[1]), *(bool*)params[2]); else assert(0 && "Handle another special marshaling method"); return (MonoObject*)params[1]; } void il2cpp_mono_method_initialize_function_pointers(MonoMethod* method, MonoError* error) { bool* isSpecialMarshalingMethod = NULL; assert(method != NULL); int32_t invokerIndex = -1; int32_t methodPointerIndex = -1; il2cpp_mono_error_init(error); if (method->invoke_pointer || method->method_pointer) return; //char *methodName = mono_method_get_name_full(method, true, false, MONO_TYPE_NAME_FORMAT_IL); if (unity_mono_method_is_inflated(method)) { // Use the fully shared version to look up the method pointer, as we will invoke the fully shared version. MonoMethod* definition = mono_method_get_method_definition(method); MonoMethod* sharedMethod = InflateGenericMethodWithContext(definition, mono_method_get_context(method), true); //char *newMethodName = mono_method_get_name_full(sharedMethod, true, false, MONO_TYPE_NAME_FORMAT_IL); uint64_t hash = mono_unity_method_get_hash(sharedMethod, true); const MonoMethodInfo *methodInfo = mono::vm::MetadataCache::GetMonoGenericMethodInfoFromMethodHash(hash); if (methodInfo) { invokerIndex = methodInfo->invoker_index; methodPointerIndex = methodInfo->method_pointer_index; } else { mono_error_set_execution_engine(error, "Unable to create the method '%s' at runtime", mono_unity_method_get_name(method)); return; } assert(invokerIndex != -1 && "The method does not have an invoker, is it a generic method?"); assert((uint32_t)invokerIndex < g_CodeRegistration.invokerPointersCount); mono_unity_method_set_invoke_pointer(method, (void*)g_CodeRegistration.invokerPointers[invokerIndex]); assert((uint32_t)methodPointerIndex < g_CodeRegistration.genericMethodPointersCount); mono_unity_method_set_method_pointer(method, (void*)g_CodeRegistration.genericMethodPointers[methodPointerIndex]); } else { uint64_t hash = mono_unity_method_get_hash(method, true); const MonoMethodInfo *methodInfo = mono::vm::MetadataCache::GetMonoMethodInfoFromMethodHash(hash); if (methodInfo) { invokerIndex = methodInfo->invoker_index; methodPointerIndex = methodInfo->method_pointer_index; } else if (strcmp(mono_unity_method_get_name(method), "PtrToStructure") == 0 || strcmp(mono_unity_method_get_name(method), "StructureToPtr") == 0) { mono_unity_method_set_invoke_pointer(method, (void*)&MarshalInvokerMethod); return; } else { // Throw a missing method exception if we did not convert it. Once we know this code works for all runtime invoke cases, // we should throw this exception more often. Until then, we will leave theassert below when we don't find a method. mono_error_set_method_load(error, mono_unity_method_get_class(method), mono_unity_method_get_name(method), "This method was not converted ahead-of-time by IL2CPP."); return; } assert(invokerIndex != -1 && "The method does not have an invoker, is it a generic method?"); assert((uint32_t)invokerIndex < g_CodeRegistration.invokerPointersCount); mono_unity_method_set_invoke_pointer(method, (void*)g_CodeRegistration.invokerPointers[invokerIndex]); assert((uint32_t)methodPointerIndex < g_CodeRegistration.methodPointersCount); mono_unity_method_set_method_pointer(method, (void*)g_CodeRegistration.methodPointers[methodPointerIndex]); } } void il2cpp_mono_init_assemblies() { s_MonoAssembliesCount = mono::vm::MetadataCache::GetMonoAssemblyCount(); s_MonoAssemblies = new MonoAssembly*[mono::vm::MetadataCache::GetMonoAssemblyCount()]; for (int i = 0; i < s_MonoAssembliesCount; ++i) s_MonoAssemblies[i] = il2cpp_mono_assembly_from_name(mono::vm::MetadataCache::GetMonoAssemblyNameFromIndex(i)); } MonoAssembly* il2cpp_mono_assembly_from_index(AssemblyIndex index) { if (s_MonoAssembliesCount == 0) il2cpp_mono_init_assemblies(); assert(index < s_MonoAssembliesCount && "assembly index is out of range"); return s_MonoAssemblies[index]; } MonoAssembly* il2cpp_mono_assembly_from_name(const char* name) { // First look for the cached assembly in the domain. MonoAssembly* assembly = mono_domain_assembly_open(mono_domain_get(), name); if (assembly == NULL) { // If we can't find it, look in the path we've set to find assemblies. MonoImageOpenStatus unused; assembly = mono_assembly_load_with_partial_name(name, &unused); } return assembly; } MonoMethod* il2cpp_mono_get_virtual_target_method(MonoMethod* method, MonoObject* obj) { // This is *very* slow, and likely not good enough for production. It is good enough for proof of concept though. MonoMethod* target_method = mono_object_get_virtual_method(obj, method); if (mono_unity_class_is_array(mono_unity_method_get_class(target_method))) target_method = mono_unity_method_get_aot_array_helper_from_wrapper(target_method); return target_method; } MonoMethod* il2cpp_mono_get_virtual_target_method_fast(MonoMethod* method, MonoObject* obj) { if (method->flags & METHOD_ATTRIBUTE_FINAL) return method; MonoClass *klass = obj->vtable->klass; if (!klass->vtable) mono_class_setup_vtable(klass); MonoMethod* target_method = klass->vtable[method->slot]; if (target_method->klass->rank > 0) target_method = mono_unity_method_get_aot_array_helper_from_wrapper(target_method); return target_method; } MonoMethod* il2cpp_mono_get_interface_target_method_fast(MonoMethod* method, MonoObject* obj) { if (method->flags & METHOD_ATTRIBUTE_FINAL) return method; MonoClass *klass = obj->vtable->klass; if (!klass->vtable) mono_class_setup_vtable(klass); gboolean variance_used = 0; int iface_offset = mono_class_interface_offset_with_variance(klass, method->klass, &variance_used); MonoMethod* target_method = klass->vtable[iface_offset + method->slot]; if (target_method->klass->rank > 0) target_method = mono_unity_method_get_aot_array_helper_from_wrapper(target_method); return target_method; } void il2cpp_mono_get_invoke_data(MonoMethod* method, void* obj, VirtualInvokeData* invokeData) { MonoMethod* target_method = il2cpp_mono_get_virtual_target_method(method, (MonoObject*)obj); MonoError error; il2cpp_mono_method_initialize_function_pointers(target_method, &error); if (!il2cpp_mono_error_ok(&error)) mono_error_raise_exception(&error); invokeData->methodPtr = (Il2CppMethodPointer)mono_unity_method_get_method_pointer(target_method); invokeData->method = target_method; } void il2cpp_mono_get_virtual_invoke_data(MonoMethod* method, void* obj, VirtualInvokeData* invokeData) { MonoMethod* target_method = il2cpp_mono_get_virtual_target_method_fast(method, (MonoObject*)obj); MonoError error; il2cpp_mono_method_initialize_function_pointers(target_method, &error); if (!il2cpp_mono_error_ok(&error)) mono_error_raise_exception(&error); invokeData->methodPtr = (Il2CppMethodPointer)mono_unity_method_get_method_pointer(target_method); invokeData->method = target_method; } void il2cpp_mono_get_interface_invoke_data(MonoMethod* method, void* obj, VirtualInvokeData* invokeData) { MonoMethod* target_method = il2cpp_mono_get_interface_target_method_fast(method, (MonoObject*)obj); MonoError error; il2cpp_mono_method_initialize_function_pointers(target_method, &error); if (!il2cpp_mono_error_ok(&error)) mono_error_raise_exception(&error); invokeData->methodPtr = (Il2CppMethodPointer)mono_unity_method_get_method_pointer(target_method); invokeData->method = target_method; } static MonoClass* InflateGenericParameter(MonoGenericContainer* genericContainer, MonoGenericContext* context, const MonoRGCTXDefinition* rgctxDefintion) { MonoClass* genericParameter = mono_unity_generic_container_get_parameter_class(genericContainer, rgctxDefintion->generic_parameter_index); return mono_unity_class_inflate_generic_class(genericParameter, context); } static MonoClass* LookupGenericClassMetadata(MonoGenericContext* context, const MonoRGCTXDefinition* rgctxDefintion) { return mono_class_get_full(mono_assembly_get_image(il2cpp_mono_assembly_from_index(rgctxDefintion->assemblyIndex)), rgctxDefintion->token, context); } static void* LookupMetadataFromRGCTX(const MonoRGCTXDefinition* definition, bool useSharedVersion, MonoGenericContext* context, MonoGenericContainer* genericContainer) { if (definition->type == IL2CPP_RGCTX_DATA_CLASS) { if (mono_metadata_token_table(definition->token) == MONO_TABLE_GENERICPARAM) return InflateGenericParameter(genericContainer, context, definition); else if (mono_metadata_token_table(definition->token) == MONO_TABLE_TYPESPEC) return LookupGenericClassMetadata(context, definition); else assert(0 && "RGCTX case is not implemented yet."); } else if (definition->type == IL2CPP_RGCTX_DATA_ARRAY) { if (mono_metadata_token_table(definition->token) == MONO_TABLE_GENERICPARAM) return mono_array_class_get(InflateGenericParameter(genericContainer, context, definition), 1); else if (mono_metadata_token_table(definition->token) == MONO_TABLE_TYPESPEC) return mono_array_class_get(LookupGenericClassMetadata(context, definition), 1); else assert(0 && "RGCTX case is not implemented yet."); } else if (definition->type == IL2CPP_RGCTX_DATA_METHOD) { MonoMethod* methodDefinition = mono_get_method(mono_assembly_get_image(il2cpp_mono_assembly_from_index(definition->assemblyIndex)), definition->token, NULL); return InflateGenericMethodWithContext(methodDefinition, context, useSharedVersion); } else if (definition->type == IL2CPP_RGCTX_DATA_TYPE) { if (mono_metadata_token_table(definition->token) == MONO_TABLE_GENERICPARAM) return mono_class_get_type(InflateGenericParameter(genericContainer, context, definition)); else if (mono_metadata_token_table(definition->token) == MONO_TABLE_TYPESPEC) return mono_class_get_type(LookupGenericClassMetadata(context, definition)); else assert(0 && "RGCTX case is not implemented yet."); } else { assert(0 && "RGCTX case is not implemented yet."); } return NULL; } void* LookupMetadataFromHash(uint64_t hash, Il2CppRGCTXDataType rgctxType, int rgctxIndex, bool useSharedVersion, MonoGenericContext* context, MonoGenericContainer* genericContainer) { const RuntimeGenericContextInfo* rgctxInfo = mono::vm::MetadataCache::GetRGCTXInfoFromHash(hash); if (rgctxInfo) { const MonoRGCTXDefinition* definition = mono::vm::MetadataCache::GetMonoRGCTXDefinition(rgctxInfo->rgctxStart + rgctxIndex); if (definition->type == rgctxType) return LookupMetadataFromRGCTX(definition, useSharedVersion, context, genericContainer); } return NULL; } void* il2cpp_mono_class_rgctx(MonoClass* klass, Il2CppRGCTXDataType rgctxType, int rgctxIndex, bool useSharedVersion) { uint64_t hash = mono_unity_type_get_hash(mono_class_get_type(klass), false); return LookupMetadataFromHash(hash, rgctxType, rgctxIndex, useSharedVersion, mono_class_get_context(klass), mono_class_get_generic_container(mono_unity_class_get_generic_definition(klass))); } void* il2cpp_mono_method_rgctx(MonoMethod* method, Il2CppRGCTXDataType rgctxType, int rgctxIndex, bool useSharedVersion) { uint64_t hash = mono_unity_method_get_hash(method, false); return LookupMetadataFromHash(hash, rgctxType, rgctxIndex, useSharedVersion, mono_method_get_context(method), mono_method_get_generic_container(mono_unity_method_get_generic_definition(method))); } static MonoClass* ClassFromIndex(TypeIndex index); static MonoClass* InflateGenericClass(MonoClass* generic_class, uint32_t num_indices, const TypeIndex *generic_indices) { std::vector arguments(num_indices); for (uint32_t i = 0; i < num_indices; ++i) arguments[i] = mono_class_get_type(ClassFromIndex(generic_indices[i])); MonoGenericInst* generic_instance = mono_metadata_get_generic_inst(num_indices, &arguments[0]); MonoGenericContext context; context.class_inst = generic_instance; context.method_inst = NULL; MonoError unused; MonoClass* inflated_class = mono_class_inflate_generic_class_checked(generic_class, &context, &unused); mono_class_init(inflated_class); return inflated_class; } static MonoClass* ClassFromMetadata(const MonoClassMetadata *classMetadata) { if (classMetadata->rank > 0) { MonoClass *klass = ClassFromIndex(classMetadata->elementTypeIndex); MonoClass *aklass = mono_array_class_get(klass, classMetadata->rank); mono_class_init(aklass); return aklass; } MonoClass *klass = mono_class_get(mono_assembly_get_image(il2cpp_mono_assembly_from_index(classMetadata->metadataToken.assemblyIndex)), classMetadata->metadataToken.token); mono_class_init(klass); return klass; } static MonoClass* ClassFromIndex(TypeIndex index) { if (index == kTypeIndexInvalid) return NULL; const MonoClassMetadata* classMetadata = mono::vm::MetadataCache::GetClassMetadataFromIndex(index); MonoClass* klass = ClassFromMetadata(classMetadata); if (classMetadata->genericParametersCount != 0) klass = InflateGenericClass(klass, classMetadata->genericParametersCount, mono::vm::MetadataCache::GetGenericArgumentIndices(classMetadata->genericParametersOffset)); if (classMetadata->isPointer) klass = mono_ptr_class_get(mono_class_get_type(klass)); return klass; } static MonoClassField* FieldFromIndex(EncodedMethodIndex index) { const MonoFieldMetadata* fieldMetadata = mono::vm::MetadataCache::GetFieldMetadataFromIndex(index); return mono_class_get_field(ClassFromIndex(fieldMetadata->parentTypeIndex), fieldMetadata->token); } static MonoType* TypeFromIndex(TypeIndex index) { if (index == kTypeIndexInvalid) return NULL; return mono_class_get_type(ClassFromIndex(index)); } MonoMethod* MethodFromIndex(MethodIndex index) { const MonoMetadataToken* method = &mono::vm::MetadataCache::GetMonoMethodMetadataFromIndex(index)->metadataToken; return mono_get_method(mono_assembly_get_image(il2cpp_mono_assembly_from_index(method->assemblyIndex)), method->token, NULL); } static std::vector GenericArgumentsFromInst(const MonoGenericInstMetadata *inst) { std::vector arguments; uint32_t numberOfGenericArguments = inst->type_argc; if (numberOfGenericArguments == 0) return arguments; for (uint32_t i = 0; i < numberOfGenericArguments; ++i) { const TypeIndex argIndex = inst->type_argv_indices[i]; arguments.push_back(mono_class_get_type(ClassFromIndex(argIndex))); } return arguments; } static MonoGenericInst* GenericInstFromIndex(GenericInstIndex index) { if (index == -1) return NULL; const MonoGenericInstMetadata* inst = g_MonoGenericInstMetadataTable[index]; // Replace this with dynamic_array later when we get the libil2cpp utilities build sorted out. std::vector genericArguments = GenericArgumentsFromInst(inst); size_t numberOfGenericArguments = genericArguments.size(); if (numberOfGenericArguments == 0) return NULL; return mono_metadata_get_generic_inst((int)numberOfGenericArguments, &genericArguments[0]); } MonoMethod* GenericMethodFromIndex(MethodIndex index) { const Il2CppMethodSpec* methodSpec = &g_Il2CppMethodSpecTable[index]; MonoMethod* methodDefinition = MethodFromIndex(methodSpec->methodDefinitionIndex); MonoGenericContext generic_context = { GenericInstFromIndex(methodSpec->classIndexIndex) , GenericInstFromIndex(methodSpec->methodIndexIndex) }; return mono_class_inflate_generic_method(methodDefinition, &generic_context); } static MonoString* StringFromIndex(StringIndex index) { const MonoMetadataToken* stringMetadata = mono::vm::MetadataCache::GetMonoStringTokenFromIndex(index); return mono_ldstr(mono_domain_get(), mono_assembly_get_image(il2cpp_mono_assembly_from_index(stringMetadata->assemblyIndex)), mono_metadata_token_index(stringMetadata->token)); } void il2cpp_mono_initialize_method_metadata(uint32_t index) { const Il2CppMetadataUsageList* usageList = mono::vm::MetadataCache::GetMetadataUsageList(index); uint32_t start = usageList->start; uint32_t count = usageList->count; for (uint32_t i = 0; i < count; i++) { uint32_t offset = start + i; const Il2CppMetadataUsagePair* usagePair = mono::vm::MetadataCache::GetMetadataUsagePair(offset); uint32_t destinationIndex = usagePair->destinationIndex; uint32_t encodedSourceIndex = usagePair->encodedSourceIndex; Il2CppMetadataUsage usage = GetEncodedIndexType(encodedSourceIndex); uint32_t decodedIndex = GetDecodedMethodIndex(encodedSourceIndex); switch (usage) { case kIl2CppMetadataUsageTypeInfo: *g_MetadataUsages[destinationIndex] = ClassFromIndex(decodedIndex); break; case kIl2CppMetadataUsageFieldInfo: *g_MetadataUsages[destinationIndex] = FieldFromIndex(decodedIndex); break; case kIl2CppMetadataUsageIl2CppType: *g_MetadataUsages[destinationIndex] = TypeFromIndex(decodedIndex); break; case kIl2CppMetadataUsageMethodDef: *g_MetadataUsages[destinationIndex] = MethodFromIndex(decodedIndex); break; case kIl2CppMetadataUsageMethodRef: *g_MetadataUsages[destinationIndex] = GenericMethodFromIndex(decodedIndex); break; case kIl2CppMetadataUsageStringLiteral: *g_MetadataUsages[destinationIndex] = StringFromIndex(decodedIndex); break; default: assert(0 && "Unimplemented case for method metadata usage."); break; } } } void il2cpp_mono_raise_execution_engine_exception_if_method_is_not_found(MonoMethod* method) { MonoError unused; il2cpp_mono_method_initialize_function_pointers(method, &unused); if (mono_unity_method_get_method_pointer(method) == NULL) { MonoException *exc; if (mono_unity_method_get_class(method) != NULL) exc = mono_get_exception_execution_engine(mono_method_get_name_full(method, true, false, MONO_TYPE_NAME_FORMAT_IL)); else exc = mono_get_exception_execution_engine(mono_unity_method_get_name(method)); mono_raise_exception(exc); } } std::vector il2cpp_to_mono_array_dimensions(il2cpp_array_size_t* il2cppDimensions, int32_t numberOfElements) { std::vector monoDimensions(numberOfElements); for (int32_t i = 0; i < numberOfElements; ++i) monoDimensions[i] = il2cppDimensions[i]; return monoDimensions; } Il2CppAsyncResult* il2cpp_mono_delegate_begin_invoke(Il2CppDelegate* delegate, void** params, Il2CppDelegate* asyncCallback, MonoObject* state) { int numParams = mono_signature_get_param_count(mono_method_signature((MonoMethod*)delegate->method)); MonoObject *nullState = NULL; Il2CppDelegate *nullCallback = NULL; std::vector newParams(numParams + 2); for (int i = 0; i < numParams; ++i) newParams[i] = params[i]; //If the state and the callback are both null and there are no other params, we will send null for the params array newParams[numParams] = &nullCallback; newParams[numParams + 1] = &nullState; int numNewParams = numParams; if (asyncCallback) { newParams[numParams] = &asyncCallback; ++numNewParams; } if (state) { newParams[numParams + 1] = &state; ++numNewParams; } MonoError unused; return (Il2CppAsyncResult*)mono_threadpool_ms_begin_invoke(mono_domain_get(), (MonoObject*)delegate, (MonoMethod*)delegate->method, numNewParams != 0 ? &newParams[0] : NULL, &unused); } static void MonoArrayGetGenericValue(MonoArray* array, int32_t pos, void* value) { MonoObject *obj = mono_array_get(array, MonoObject*, pos); MonoClass *klass = mono_unity_object_get_class(obj); if (mono_class_is_valuetype(klass)) memcpy(value, mono_object_unbox(obj), mono_class_instance_size(klass) - sizeof(MonoObject)); else memcpy(value, &obj, mono_unity_array_get_element_size(array)); } MonoObject* il2cpp_mono_delegate_end_invoke(Il2CppAsyncResult* asyncResult, void **out_args) { MonoError unused; MonoObject *exc = NULL; MonoArray *mono_out_args = NULL; MonoObject *retVal = (MonoObject*)mono_threadpool_ms_end_invoke((MonoAsyncResult*)asyncResult, &mono_out_args, &exc, &unused); if (exc) mono_raise_exception((MonoException*)exc); uint32_t numArgs = mono_unity_array_get_max_length(mono_out_args); for (uint32_t i = 0; i < numArgs; ++i) MonoArrayGetGenericValue(mono_out_args, i, out_args[i]); return retVal; } MonoArray* MonoArrayNew(MonoClass* elementType, uintptr_t length) { MonoError unused; return mono_array_new_specific_checked(mono_class_vtable(mono_domain_get(), mono_array_class_get(elementType, 1)), length, &unused); } #if IL2CPP_ENABLE_NATIVE_STACKTRACES void RegisterAllManagedMethods() { uint32_t numberOfMethods = g_CodeRegistration.methodPointersCount; uint32_t numberOfGenericMethods = g_CodeRegistration.genericMethodPointersCount; std::vector managedMethods(numberOfMethods + numberOfGenericMethods); for (uint32_t i = 0; i < numberOfMethods; ++i) { MethodDefinitionKey currentMethod; currentMethod.methodIndex = mono::vm::MetadataCache::GetMethodIndex(i); currentMethod.method = g_CodeRegistration.methodPointers[i]; currentMethod.isGeneric = false; managedMethods.push_back(currentMethod); } for (uint32_t i = 0; i < numberOfGenericMethods; ++i) { MethodDefinitionKey currentMethod; currentMethod.methodIndex = mono::vm::MetadataCache::GetGenericMethodIndex(i); currentMethod.method = g_CodeRegistration.genericMethodPointers[i]; currentMethod.isGeneric = true; managedMethods.push_back(currentMethod); } il2cpp::utils::NativeSymbol::RegisterMethods(managedMethods); } #endif // IL2CPP_ENABLE_NATIVE_STACKTRACES void RuntimeInit(MonoClass* klass) { MonoError error; mono_runtime_class_init_full(mono_class_vtable(mono_domain_get(), klass), &error); if (!il2cpp_mono_error_ok(&error)) mono_error_raise_exception(&error); } std::string il2cpp_mono_format_exception(const MonoException *exc) { MonoClass *klass = mono_object_get_class((MonoObject*)exc); std::string exception_namespace = mono_class_get_namespace(klass); std::string exception_type = mono_class_get_name(klass); MonoString *message = mono_unity_exception_get_message(const_cast(exc)); if (message) return exception_namespace + "." + exception_type + ": " + mono_string_to_utf8(message); else return exception_namespace + "." + exception_type; } extern "C" { void il2cpp_set_temp_dir(char *temp_dir) { assert(0 && "This needs to be implemented for Android"); } } #endif //RUNTIME_MONO ================================================ FILE: unity_decoder/libil2cpp/mono-runtime/il2cpp-mono-support.h ================================================ #pragma once #if RUNTIME_MONO #include "il2cpp-metadata.h" #include struct MethodInfo; struct VirtualInvokeData; struct Il2CppInteropData; void il2cpp_mono_method_initialize_function_pointers(MonoMethod* method, MonoError* error); MonoAssembly* il2cpp_mono_assembly_from_index(AssemblyIndex index); void* il2cpp_mono_class_rgctx(MonoClass* klass, Il2CppRGCTXDataType rgctxType, int rgctxIndex, bool useSharedVersion); void* il2cpp_mono_method_rgctx(MonoMethod* method, Il2CppRGCTXDataType rgctxType, int rgctxIndex, bool useSharedVersion); MonoMethod* il2cpp_mono_get_virtual_target_method(MonoMethod* method, MonoObject* obj); void il2cpp_mono_get_invoke_data(MonoMethod* method, void* obj, VirtualInvokeData* invokeData); void il2cpp_mono_get_virtual_invoke_data(MonoMethod* method, void* obj, VirtualInvokeData* invokeData); void il2cpp_mono_get_interface_invoke_data(MonoMethod* method, void* obj, VirtualInvokeData* invokeData); void il2cpp_mono_initialize_method_metadata(uint32_t index); void il2cpp_mono_raise_execution_engine_exception_if_method_is_not_found(MonoMethod* method); std::vector il2cpp_to_mono_array_dimensions(il2cpp_array_size_t* il2cppDimensions, int32_t numberOfElements); Il2CppAsyncResult* il2cpp_mono_delegate_begin_invoke(Il2CppDelegate* delegate, void** params, Il2CppDelegate* asyncCallback, MonoObject* state); MonoObject* il2cpp_mono_delegate_end_invoke(Il2CppAsyncResult* asyncResult, void **out_args); MonoArray* MonoArrayNew(MonoClass* elementType, uintptr_t length); MonoMethod* MethodFromIndex(MethodIndex index); MonoMethod* GenericMethodFromIndex(MethodIndex index); const Il2CppInteropData* FindInteropDataFor(MonoClass* klass); void RuntimeInit(MonoClass* klass); std::string il2cpp_mono_format_exception(const MonoException *exc); void initialize_interop_data_map(); bool il2cpp_mono_error_ok(MonoError *error); #if IL2CPP_ENABLE_NATIVE_STACKTRACES struct MethodDefinitionKey { Il2CppMethodPointer method; MethodIndex methodIndex; bool isGeneric; }; void RegisterAllManagedMethods(); #endif // IL2CPP_ENABLE_NATIVE_STACKTRACES #endif ================================================ FILE: unity_decoder/libil2cpp/mono-structs.cpp ================================================ #include "il2cpp-config.h" #include "mono-structs.h" #include "utils/Memory.h" GPtrArray* void_ptr_array_to_gptr_array(const VoidPtrArray& array) { GPtrArray *pRetVal; pRetVal = (GPtrArray*)IL2CPP_MALLOC(sizeof(GPtrArray)); pRetVal->len = (unsigned int)array.size(); if (pRetVal->len > 0) { size_t numBytes = sizeof(void*) * pRetVal->len; pRetVal->pdata = IL2CPP_MALLOC(numBytes); memcpy(pRetVal->pdata, array.data(), numBytes); } else { pRetVal->pdata = NULL; } return pRetVal; } GPtrArray* empty_gptr_array() { GPtrArray *pRetVal = (GPtrArray*)IL2CPP_MALLOC(sizeof(GPtrArray)); pRetVal->len = 0; pRetVal->pdata = NULL; return pRetVal; } void free_gptr_array(GPtrArray *pArray) { if (!pArray) return; if (pArray->pdata) { IL2CPP_FREE(pArray->pdata); pArray->pdata = NULL; } IL2CPP_FREE(pArray); } ================================================ FILE: unity_decoder/libil2cpp/mono-structs.h ================================================ #pragma once #include "utils/dynamic_array.h" #include "object-internals.h" struct GPtrArray { void *pdata; unsigned int len; }; typedef il2cpp::utils::dynamic_array VoidPtrArray; GPtrArray* void_ptr_array_to_gptr_array(const VoidPtrArray& array); GPtrArray* empty_gptr_array(); void free_gptr_array(GPtrArray *pArray); struct MonoGenericParameterInfo { Il2CppClass *pklass; /* The corresponding `MonoClass'. */ const char *name; // See GenericParameterAttributes unsigned short flags; unsigned int token; // Constraints on type parameters Il2CppClass** constraints; /* NULL means end of list */ }; struct PublicKeyTokenFixedBuffer { union { struct { // System.Byte Mono.MonoAssemblyName/__FixedBuffer0::FixedElementField uint8_t FixedElementField; }; uint8_t padding[17]; }; }; struct Il2CppMonoAssemblyName { // System.IntPtr Mono.MonoAssemblyName::name Il2CppIntPtr name; // System.IntPtr Mono.MonoAssemblyName::culture Il2CppIntPtr culture; // System.IntPtr Mono.MonoAssemblyName::hash_value Il2CppIntPtr hash_value; // System.IntPtr Mono.MonoAssemblyName::public_key Il2CppIntPtr public_key; // Mono.MonoAssemblyName/__FixedBuffer0 Mono.MonoAssemblyName::public_key_token PublicKeyTokenFixedBuffer public_key_token; // System.UInt32 Mono.MonoAssemblyName::hash_alg uint32_t hash_alg; // System.UInt32 Mono.MonoAssemblyName::hash_len uint32_t hash_len; // System.UInt32 Mono.MonoAssemblyName::flags uint32_t flags; // System.UInt16 Mono.MonoAssemblyName::major uint16_t major; // System.UInt16 Mono.MonoAssemblyName::minor uint16_t minor; // System.UInt16 Mono.MonoAssemblyName::build uint16_t build; // System.UInt16 Mono.MonoAssemblyName::revision uint16_t revision; // System.UInt16 Mono.MonoAssemblyName::arch uint16_t arch; }; ================================================ FILE: unity_decoder/libil2cpp/normalization-tables.h ================================================ static const uint8_t props[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, 0, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 146, 0, 18, 0, 0, 0, 0, 18, 0, 0, 18, 18, 146, 18, 0, 128, 18, 18, 18, 0, 18, 18, 18, 0, 3, 3, 131, 3, 131, 131, 128, 131, 3, 3, 131, 3, 3, 3, 3, 131, 0, 3, 3, 3, 131, 131, 131, 0, 128, 3, 3, 3, 131, 3, 0, 0, 3, 3, 131, 3, 131, 131, 128, 131, 3, 3, 131, 3, 3, 3, 3, 131, 0, 3, 3, 3, 131, 131, 131, 0, 128, 3, 3, 3, 131, 3, 0, 3, 3, 3, 131, 131, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 131, 131, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 18, 18, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 18, 18, 0, 0, 3, 3, 3, 3, 3, 3, 18, 0, 0, 131, 131, 3, 3, 3, 3, 0, 0, 3, 3, 3, 3, 3, 3, 131, 131, 3, 3, 3, 3, 131, 131, 3, 3, 3, 3, 0, 0, 131, 131, 131, 131, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 131, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 0, 0, 3, 3, 3, 3, 131, 131, 3, 3, 3, 3, 3, 18, 18, 18, 3, 3, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 131, 131, 131, 131, 3, 3, 3, 3, 131, 131, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 0, 0, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 168, 168, 168, 168, 0, 168, 168, 168, 168, 168, 168, 168, 0, 0, 168, 0, 168, 0, 168, 168, 0, 0, 0, 0, 0, 0, 168, 0, 0, 0, 0, 0, 0, 0, 168, 168, 168, 168, 168, 168, 0, 0, 0, 0, 168, 168, 0, 168, 168, 0, 0, 0, 0, 0, 0, 168, 0, 0, 0, 0, 0, 0, 0, 87, 87, 168, 87, 87, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 0, 0, 0, 0, 0, 18, 0, 0, 0, 87, 0, 0, 0, 0, 0, 18, 147, 131, 87, 131, 131, 131, 0, 131, 0, 131, 131, 131, 128, 0, 0, 0, 128, 0, 128, 0, 128, 0, 0, 0, 0, 0, 128, 0, 128, 0, 0, 0, 128, 0, 0, 0, 128, 3, 3, 131, 131, 131, 131, 131, 128, 0, 0, 0, 128, 0, 128, 0, 128, 0, 0, 0, 0, 0, 128, 0, 128, 0, 0, 0, 128, 0, 0, 0, 128, 131, 131, 131, 131, 131, 0, 18, 18, 146, 19, 19, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 0, 18, 18, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 3, 3, 0, 3, 0, 0, 128, 3, 0, 0, 0, 0, 3, 3, 3, 0, 128, 0, 0, 128, 0, 128, 128, 128, 128, 3, 128, 0, 0, 0, 128, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 0, 0, 128, 0, 0, 128, 0, 128, 128, 128, 128, 3, 128, 0, 0, 0, 128, 0, 0, 0, 0, 128, 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 0, 0, 3, 3, 0, 3, 0, 0, 128, 3, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 3, 3, 128, 128, 3, 3, 3, 3, 3, 3, 0, 0, 3, 3, 3, 3, 3, 3, 128, 128, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 128, 128, 128, 0, 0, 128, 0, 0, 128, 0, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, 128, 128, 128, 0, 128, 128, 128, 128, 128, 0, 128, 0, 128, 128, 0, 128, 128, 0, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 168, 168, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 128, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 3, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 0, 0, 0, 0, 128, 0, 0, 0, 0, 128, 128, 0, 0, 0, 0, 0, 128, 3, 0, 128, 0, 0, 0, 128, 128, 3, 0, 128, 3, 0, 0, 0, 0, 0, 0, 0, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 87, 87, 87, 87, 87, 87, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 168, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 0, 0, 0, 0, 87, 87, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 128, 87, 0, 0, 87, 0, 128, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 87, 87, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 168, 0, 0, 0, 0, 0, 0, 0, 0, 128, 3, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 168, 0, 0, 0, 0, 87, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 0, 0, 0, 0, 0, 0, 0, 128, 128, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 3, 0, 168, 0, 0, 0, 128, 3, 3, 0, 131, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 0, 0, 0, 0, 0, 0, 0, 128, 128, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 0, 0, 0, 0, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 3, 0, 131, 3, 3, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 128, 87, 0, 0, 0, 0, 0, 0, 0, 0, 128, 87, 0, 0, 0, 128, 87, 0, 0, 0, 128, 87, 0, 0, 0, 128, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 128, 128, 87, 128, 87, 87, 18, 87, 18, 0, 0, 0, 0, 0, 0, 128, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 128, 87, 0, 0, 0, 0, 0, 0, 0, 0, 128, 87, 0, 0, 0, 128, 87, 0, 0, 0, 128, 87, 0, 0, 0, 128, 87, 0, 0, 0, 0, 0, 128, 128, 0, 128, 0, 128, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 3, 0, 0, 0, 0, 0, 0, 0, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 3, 128, 3, 128, 3, 128, 3, 128, 3, 0, 0, 128, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 168, 0, 0, 0, 0, 128, 3, 128, 3, 128, 128, 3, 3, 128, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 131, 131, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 131, 131, 3, 3, 3, 3, 3, 3, 131, 131, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 18, 19, 0, 0, 0, 0, 131, 131, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 131, 131, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 131, 131, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 3, 3, 3, 3, 0, 0, 131, 131, 3, 3, 3, 3, 0, 0, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 3, 3, 3, 3, 3, 3, 131, 131, 3, 3, 3, 3, 3, 3, 131, 131, 3, 3, 3, 3, 0, 0, 131, 131, 3, 3, 3, 3, 0, 0, 131, 131, 3, 3, 3, 3, 3, 3, 0, 131, 0, 3, 0, 3, 0, 3, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 87, 3, 87, 131, 87, 3, 87, 3, 87, 3, 87, 131, 87, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 131, 3, 3, 3, 3, 87, 3, 18, 87, 146, 18, 19, 3, 3, 3, 0, 131, 3, 3, 87, 3, 87, 3, 19, 19, 19, 3, 3, 3, 87, 0, 0, 3, 3, 3, 3, 3, 87, 0, 19, 19, 19, 3, 3, 3, 87, 3, 3, 3, 3, 3, 3, 3, 87, 3, 19, 87, 87, 0, 0, 3, 3, 3, 0, 131, 3, 3, 87, 3, 87, 3, 87, 146, 0, 87, 87, 146, 146, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 18, 18, 0, 18, 18, 0, 0, 0, 0, 18, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 0, 18, 18, 18, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 18, 18, 0, 0, 18, 18, 18, 18, 18, 0, 0, 18, 18, 18, 0, 18, 0, 87, 0, 18, 0, 87, 87, 18, 18, 0, 18, 18, 18, 0, 18, 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 128, 0, 128, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 128, 0, 128, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 3, 0, 0, 0, 128, 3, 0, 128, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 3, 128, 3, 0, 0, 0, 0, 0, 18, 18, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 3, 0, 128, 3, 128, 0, 3, 128, 3, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 128, 3, 0, 128, 128, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 128, 128, 3, 3, 128, 128, 3, 3, 128, 128, 128, 128, 0, 0, 3, 3, 128, 128, 3, 3, 128, 128, 3, 3, 0, 0, 0, 0, 0, 0, 0, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 128, 128, 0, 128, 3, 3, 3, 3, 0, 0, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 87, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 128, 3, 128, 3, 128, 3, 128, 3, 128, 3, 128, 3, 128, 3, 128, 3, 128, 3, 128, 3, 128, 3, 128, 3, 0, 128, 3, 128, 3, 128, 3, 0, 0, 0, 0, 0, 128, 3, 3, 128, 3, 3, 128, 3, 3, 128, 3, 3, 128, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 168, 168, 18, 18, 128, 3, 18, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 128, 3, 128, 3, 128, 3, 128, 3, 128, 3, 128, 3, 128, 3, 128, 3, 128, 3, 128, 3, 128, 3, 128, 3, 0, 128, 3, 128, 3, 128, 3, 0, 0, 0, 0, 0, 128, 3, 3, 128, 3, 3, 128, 3, 3, 128, 3, 3, 128, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, 0, 3, 0, 0, 3, 3, 3, 3, 0, 0, 128, 3, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 0, 0, 87, 0, 87, 0, 0, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 0, 87, 0, 87, 0, 0, 87, 87, 0, 0, 0, 87, 87, 87, 87, 0, 0, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 0, 0, 0, 0, 0, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 87, 0, 87, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 0, 87, 87, 87, 87, 87, 0, 87, 0, 87, 87, 0, 87, 87, 0, 87, 87, 87, 215, 87, 87, 87, 87, 87, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 18, 0, 0, 0, 0, 18, 18, 18, 0, 18, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 18, 18, 18, 18, 18, 18, 0, 0, 18, 18, 18, 18, 18, 18, 0, 0, 18, 18, 18, 18, 18, 18, 0, 0, 18, 18, 18, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const uint32_t mappedChars[] = { 0, 32, 0, 32, 769, 0, 32, 771, 0, 32, 772, 0, 32, 773, 0, 32, 774, 0, 32, 775, 0, 32, 776, 0, 32, 778, 0, 32, 779, 0, 32, 787, 0, 32, 788, 0, 32, 807, 0, 32, 808, 0, 32, 819, 0, 32, 834, 0, 32, 837, 0, 32, 1611, 0, 32, 1612, 0, 32, 1612, 1617, 0, 32, 1613, 0, 32, 1613, 1617, 0, 32, 1614, 0, 32, 1614, 1617, 0, 32, 1615, 0, 32, 1615, 1617, 0, 32, 1616, 0, 32, 1616, 1617, 0, 32, 1617, 0, 32, 1617, 1648, 0, 32, 1618, 0, 32, 12441, 0, 32, 12442, 0, 33, 0, 33, 33, 0, 33, 63, 0, 34, 0, 35, 0, 36, 0, 37, 0, 38, 0, 39, 0, 40, 0, 40, 49, 41, 0, 40, 49, 48, 41, 0, 40, 49, 49, 41, 0, 40, 49, 50, 41, 0, 40, 49, 51, 41, 0, 40, 49, 52, 41, 0, 40, 49, 53, 41, 0, 40, 49, 54, 41, 0, 40, 49, 55, 41, 0, 40, 49, 56, 41, 0, 40, 49, 57, 41, 0, 40, 50, 41, 0, 40, 50, 48, 41, 0, 40, 51, 41, 0, 40, 52, 41, 0, 40, 53, 41, 0, 40, 54, 41, 0, 40, 55, 41, 0, 40, 56, 41, 0, 40, 57, 41, 0, 40, 97, 41, 0, 40, 98, 41, 0, 40, 99, 41, 0, 40, 100, 41, 0, 40, 101, 41, 0, 40, 102, 41, 0, 40, 103, 41, 0, 40, 104, 41, 0, 40, 105, 41, 0, 40, 106, 41, 0, 40, 107, 41, 0, 40, 108, 41, 0, 40, 109, 41, 0, 40, 110, 41, 0, 40, 111, 41, 0, 40, 112, 41, 0, 40, 113, 41, 0, 40, 114, 41, 0, 40, 115, 41, 0, 40, 116, 41, 0, 40, 117, 41, 0, 40, 118, 41, 0, 40, 119, 41, 0, 40, 120, 41, 0, 40, 121, 41, 0, 40, 122, 41, 0, 40, 4352, 41, 0, 40, 4352, 4449, 41, 0, 40, 4354, 41, 0, 40, 4354, 4449, 41, 0, 40, 4355, 41, 0, 40, 4355, 4449, 41, 0, 40, 4357, 41, 0, 40, 4357, 4449, 41, 0, 40, 4358, 41, 0, 40, 4358, 4449, 41, 0, 40, 4359, 41, 0, 40, 4359, 4449, 41, 0, 40, 4361, 41, 0, 40, 4361, 4449, 41, 0, 40, 4363, 41, 0, 40, 4363, 4449, 41, 0, 40, 4363, 4457, 4364, 4453, 4523, 41, 0, 40, 4363, 4457, 4370, 4462, 41, 0, 40, 4364, 41, 0, 40, 4364, 4449, 41, 0, 40, 4364, 4462, 41, 0, 40, 4366, 41, 0, 40, 4366, 4449, 41, 0, 40, 4367, 41, 0, 40, 4367, 4449, 41, 0, 40, 4368, 41, 0, 40, 4368, 4449, 41, 0, 40, 4369, 41, 0, 40, 4369, 4449, 41, 0, 40, 4370, 41, 0, 40, 4370, 4449, 41, 0, 40, 19968, 41, 0, 40, 19971, 41, 0, 40, 19977, 41, 0, 40, 20061, 41, 0, 40, 20108, 41, 0, 40, 20116, 41, 0, 40, 20195, 41, 0, 40, 20225, 41, 0, 40, 20241, 41, 0, 40, 20843, 41, 0, 40, 20845, 41, 0, 40, 21172, 41, 0, 40, 21313, 41, 0, 40, 21332, 41, 0, 40, 21517, 41, 0, 40, 21628, 41, 0, 40, 22235, 41, 0, 40, 22303, 41, 0, 40, 23398, 41, 0, 40, 26085, 41, 0, 40, 26376, 41, 0, 40, 26377, 41, 0, 40, 26408, 41, 0, 40, 26666, 41, 0, 40, 27700, 41, 0, 40, 28779, 41, 0, 40, 29305, 41, 0, 40, 30435, 41, 0, 40, 31038, 41, 0, 40, 31069, 41, 0, 40, 31085, 41, 0, 40, 33258, 41, 0, 40, 33267, 41, 0, 40, 36001, 41, 0, 40, 36039, 41, 0, 40, 37329, 41, 0, 41, 0, 42, 0, 43, 0, 44, 0, 45, 0, 46, 0, 46, 46, 0, 46, 46, 46, 0, 47, 0, 48, 0, 48, 28857, 0, 49, 0, 49, 46, 0, 49, 48, 0, 49, 48, 46, 0, 49, 48, 26085, 0, 49, 48, 26376, 0, 49, 48, 28857, 0, 49, 49, 0, 49, 49, 46, 0, 49, 49, 26085, 0, 49, 49, 26376, 0, 49, 49, 28857, 0, 49, 50, 0, 49, 50, 46, 0, 49, 50, 26085, 0, 49, 50, 26376, 0, 49, 50, 28857, 0, 49, 51, 0, 49, 51, 46, 0, 49, 51, 26085, 0, 49, 51, 28857, 0, 49, 52, 0, 49, 52, 46, 0, 49, 52, 26085, 0, 49, 52, 28857, 0, 49, 53, 0, 49, 53, 46, 0, 49, 53, 26085, 0, 49, 53, 28857, 0, 49, 54, 0, 49, 54, 46, 0, 49, 54, 26085, 0, 49, 54, 28857, 0, 49, 55, 0, 49, 55, 46, 0, 49, 55, 26085, 0, 49, 55, 28857, 0, 49, 56, 0, 49, 56, 46, 0, 49, 56, 26085, 0, 49, 56, 28857, 0, 49, 57, 0, 49, 57, 46, 0, 49, 57, 26085, 0, 49, 57, 28857, 0, 49, 8260, 0, 49, 8260, 50, 0, 49, 8260, 51, 0, 49, 8260, 52, 0, 49, 8260, 53, 0, 49, 8260, 54, 0, 49, 8260, 56, 0, 49, 26085, 0, 49, 26376, 0, 49, 28857, 0, 50, 0, 50, 46, 0, 50, 48, 0, 50, 48, 46, 0, 50, 48, 26085, 0, 50, 48, 28857, 0, 50, 49, 0, 50, 49, 26085, 0, 50, 49, 28857, 0, 50, 50, 0, 50, 50, 26085, 0, 50, 50, 28857, 0, 50, 51, 0, 50, 51, 26085, 0, 50, 51, 28857, 0, 50, 52, 0, 50, 52, 26085, 0, 50, 52, 28857, 0, 50, 53, 0, 50, 53, 26085, 0, 50, 54, 0, 50, 54, 26085, 0, 50, 55, 0, 50, 55, 26085, 0, 50, 56, 0, 50, 56, 26085, 0, 50, 57, 0, 50, 57, 26085, 0, 50, 8260, 51, 0, 50, 8260, 53, 0, 50, 26085, 0, 50, 26376, 0, 50, 28857, 0, 51, 0, 51, 46, 0, 51, 48, 0, 51, 48, 26085, 0, 51, 49, 0, 51, 49, 26085, 0, 51, 50, 0, 51, 51, 0, 51, 52, 0, 51, 53, 0, 51, 54, 0, 51, 55, 0, 51, 56, 0, 51, 57, 0, 51, 8260, 52, 0, 51, 8260, 53, 0, 51, 8260, 56, 0, 51, 26085, 0, 51, 26376, 0, 51, 28857, 0, 52, 0, 52, 46, 0, 52, 48, 0, 52, 49, 0, 52, 50, 0, 52, 51, 0, 52, 52, 0, 52, 53, 0, 52, 54, 0, 52, 55, 0, 52, 56, 0, 52, 57, 0, 52, 8260, 53, 0, 52, 26085, 0, 52, 26376, 0, 52, 28857, 0, 53, 0, 53, 46, 0, 53, 48, 0, 53, 8260, 54, 0, 53, 8260, 56, 0, 53, 26085, 0, 53, 26376, 0, 53, 28857, 0, 54, 0, 54, 46, 0, 54, 26085, 0, 54, 26376, 0, 54, 28857, 0, 55, 0, 55, 46, 0, 55, 8260, 56, 0, 55, 26085, 0, 55, 26376, 0, 55, 28857, 0, 56, 0, 56, 46, 0, 56, 26085, 0, 56, 26376, 0, 56, 28857, 0, 57, 0, 57, 46, 0, 57, 26085, 0, 57, 26376, 0, 57, 28857, 0, 58, 0, 58, 58, 61, 0, 59, 0, 60, 0, 60, 824, 0, 61, 0, 61, 61, 0, 61, 61, 61, 0, 61, 824, 0, 62, 0, 62, 824, 0, 63, 0, 63, 33, 0, 63, 63, 0, 64, 0, 65, 0, 65, 85, 0, 65, 768, 0, 65, 769, 0, 65, 770, 0, 65, 771, 0, 65, 772, 0, 65, 774, 0, 65, 775, 0, 65, 776, 0, 65, 777, 0, 65, 778, 0, 65, 780, 0, 65, 783, 0, 65, 785, 0, 65, 803, 0, 65, 805, 0, 65, 808, 0, 65, 8725, 109, 0, 66, 0, 66, 113, 0, 66, 775, 0, 66, 803, 0, 66, 817, 0, 67, 0, 67, 111, 46, 0, 67, 769, 0, 67, 770, 0, 67, 775, 0, 67, 780, 0, 67, 807, 0, 67, 8725, 107, 103, 0, 68, 0, 68, 90, 0, 68, 122, 0, 68, 381, 0, 68, 382, 0, 68, 775, 0, 68, 780, 0, 68, 803, 0, 68, 807, 0, 68, 813, 0, 68, 817, 0, 69, 0, 69, 768, 0, 69, 769, 0, 69, 770, 0, 69, 771, 0, 69, 772, 0, 69, 774, 0, 69, 775, 0, 69, 776, 0, 69, 777, 0, 69, 780, 0, 69, 783, 0, 69, 785, 0, 69, 803, 0, 69, 807, 0, 69, 808, 0, 69, 813, 0, 69, 816, 0, 70, 0, 70, 65, 88, 0, 70, 775, 0, 71, 0, 71, 66, 0, 71, 72, 122, 0, 71, 80, 97, 0, 71, 121, 0, 71, 769, 0, 71, 770, 0, 71, 772, 0, 71, 774, 0, 71, 775, 0, 71, 780, 0, 71, 807, 0, 72, 0, 72, 80, 0, 72, 103, 0, 72, 122, 0, 72, 770, 0, 72, 775, 0, 72, 776, 0, 72, 780, 0, 72, 803, 0, 72, 807, 0, 72, 814, 0, 73, 0, 73, 73, 0, 73, 73, 73, 0, 73, 74, 0, 73, 85, 0, 73, 86, 0, 73, 88, 0, 73, 768, 0, 73, 769, 0, 73, 770, 0, 73, 771, 0, 73, 772, 0, 73, 774, 0, 73, 775, 0, 73, 776, 0, 73, 777, 0, 73, 780, 0, 73, 783, 0, 73, 785, 0, 73, 803, 0, 73, 808, 0, 73, 816, 0, 74, 0, 74, 770, 0, 75, 0, 75, 66, 0, 75, 75, 0, 75, 77, 0, 75, 769, 0, 75, 780, 0, 75, 803, 0, 75, 807, 0, 75, 817, 0, 76, 0, 76, 74, 0, 76, 84, 68, 0, 76, 106, 0, 76, 183, 0, 76, 769, 0, 76, 780, 0, 76, 803, 0, 76, 807, 0, 76, 813, 0, 76, 817, 0, 77, 0, 77, 66, 0, 77, 72, 122, 0, 77, 80, 97, 0, 77, 86, 0, 77, 87, 0, 77, 769, 0, 77, 775, 0, 77, 803, 0, 77, 937, 0, 78, 0, 78, 74, 0, 78, 106, 0, 78, 111, 0, 78, 768, 0, 78, 769, 0, 78, 771, 0, 78, 775, 0, 78, 780, 0, 78, 803, 0, 78, 807, 0, 78, 813, 0, 78, 817, 0, 79, 0, 79, 768, 0, 79, 769, 0, 79, 770, 0, 79, 771, 0, 79, 772, 0, 79, 774, 0, 79, 775, 0, 79, 776, 0, 79, 777, 0, 79, 779, 0, 79, 780, 0, 79, 783, 0, 79, 785, 0, 79, 795, 0, 79, 803, 0, 79, 808, 0, 80, 0, 80, 72, 0, 80, 80, 77, 0, 80, 82, 0, 80, 84, 69, 0, 80, 97, 0, 80, 769, 0, 80, 775, 0, 81, 0, 82, 0, 82, 115, 0, 82, 769, 0, 82, 775, 0, 82, 780, 0, 82, 783, 0, 82, 785, 0, 82, 803, 0, 82, 807, 0, 82, 817, 0, 83, 0, 83, 77, 0, 83, 118, 0, 83, 769, 0, 83, 770, 0, 83, 775, 0, 83, 780, 0, 83, 803, 0, 83, 806, 0, 83, 807, 0, 84, 0, 84, 69, 76, 0, 84, 72, 122, 0, 84, 77, 0, 84, 775, 0, 84, 780, 0, 84, 803, 0, 84, 806, 0, 84, 807, 0, 84, 813, 0, 84, 817, 0, 85, 0, 85, 768, 0, 85, 769, 0, 85, 770, 0, 85, 771, 0, 85, 772, 0, 85, 774, 0, 85, 776, 0, 85, 777, 0, 85, 778, 0, 85, 779, 0, 85, 780, 0, 85, 783, 0, 85, 785, 0, 85, 795, 0, 85, 803, 0, 85, 804, 0, 85, 808, 0, 85, 813, 0, 85, 816, 0, 86, 0, 86, 73, 0, 86, 73, 73, 0, 86, 73, 73, 73, 0, 86, 771, 0, 86, 803, 0, 86, 8725, 109, 0, 87, 0, 87, 98, 0, 87, 768, 0, 87, 769, 0, 87, 770, 0, 87, 775, 0, 87, 776, 0, 87, 803, 0, 88, 0, 88, 73, 0, 88, 73, 73, 0, 88, 775, 0, 88, 776, 0, 89, 0, 89, 768, 0, 89, 769, 0, 89, 770, 0, 89, 771, 0, 89, 772, 0, 89, 775, 0, 89, 776, 0, 89, 777, 0, 89, 803, 0, 90, 0, 90, 769, 0, 90, 770, 0, 90, 775, 0, 90, 780, 0, 90, 803, 0, 90, 817, 0, 91, 0, 92, 0, 93, 0, 94, 0, 95, 0, 96, 0, 97, 0, 97, 46, 109, 46, 0, 97, 47, 99, 0, 97, 47, 115, 0, 97, 702, 0, 97, 768, 0, 97, 769, 0, 97, 770, 0, 97, 771, 0, 97, 772, 0, 97, 774, 0, 97, 775, 0, 97, 776, 0, 97, 777, 0, 97, 778, 0, 97, 780, 0, 97, 783, 0, 97, 785, 0, 97, 803, 0, 97, 805, 0, 97, 808, 0, 98, 0, 98, 97, 114, 0, 98, 775, 0, 98, 803, 0, 98, 817, 0, 99, 0, 99, 47, 111, 0, 99, 47, 117, 0, 99, 97, 108, 0, 99, 99, 0, 99, 100, 0, 99, 109, 0, 99, 109, 178, 0, 99, 109, 179, 0, 99, 769, 0, 99, 770, 0, 99, 775, 0, 99, 780, 0, 99, 807, 0, 100, 0, 100, 66, 0, 100, 97, 0, 100, 109, 0, 100, 109, 178, 0, 100, 109, 179, 0, 100, 122, 0, 100, 382, 0, 100, 775, 0, 100, 780, 0, 100, 803, 0, 100, 807, 0, 100, 813, 0, 100, 817, 0, 100, 8467, 0, 101, 0, 101, 86, 0, 101, 114, 103, 0, 101, 768, 0, 101, 769, 0, 101, 770, 0, 101, 771, 0, 101, 772, 0, 101, 774, 0, 101, 775, 0, 101, 776, 0, 101, 777, 0, 101, 780, 0, 101, 783, 0, 101, 785, 0, 101, 803, 0, 101, 807, 0, 101, 808, 0, 101, 813, 0, 101, 816, 0, 102, 0, 102, 102, 0, 102, 102, 105, 0, 102, 102, 108, 0, 102, 105, 0, 102, 108, 0, 102, 109, 0, 102, 775, 0, 103, 0, 103, 97, 108, 0, 103, 769, 0, 103, 770, 0, 103, 772, 0, 103, 774, 0, 103, 775, 0, 103, 780, 0, 103, 807, 0, 104, 0, 104, 80, 97, 0, 104, 97, 0, 104, 770, 0, 104, 775, 0, 104, 776, 0, 104, 780, 0, 104, 803, 0, 104, 807, 0, 104, 814, 0, 104, 817, 0, 105, 0, 105, 105, 0, 105, 105, 105, 0, 105, 106, 0, 105, 110, 0, 105, 118, 0, 105, 120, 0, 105, 768, 0, 105, 769, 0, 105, 770, 0, 105, 771, 0, 105, 772, 0, 105, 774, 0, 105, 776, 0, 105, 777, 0, 105, 780, 0, 105, 783, 0, 105, 785, 0, 105, 803, 0, 105, 808, 0, 105, 816, 0, 106, 0, 106, 770, 0, 106, 780, 0, 107, 0, 107, 65, 0, 107, 72, 122, 0, 107, 80, 97, 0, 107, 86, 0, 107, 87, 0, 107, 99, 97, 108, 0, 107, 103, 0, 107, 109, 0, 107, 109, 178, 0, 107, 109, 179, 0, 107, 116, 0, 107, 769, 0, 107, 780, 0, 107, 803, 0, 107, 807, 0, 107, 817, 0, 107, 937, 0, 107, 8467, 0, 108, 0, 108, 106, 0, 108, 109, 0, 108, 110, 0, 108, 111, 103, 0, 108, 120, 0, 108, 183, 0, 108, 769, 0, 108, 780, 0, 108, 803, 0, 108, 807, 0, 108, 813, 0, 108, 817, 0, 109, 0, 109, 65, 0, 109, 86, 0, 109, 87, 0, 109, 98, 0, 109, 103, 0, 109, 105, 108, 0, 109, 109, 0, 109, 109, 178, 0, 109, 109, 179, 0, 109, 111, 108, 0, 109, 115, 0, 109, 178, 0, 109, 179, 0, 109, 769, 0, 109, 775, 0, 109, 803, 0, 109, 8467, 0, 109, 8725, 115, 0, 109, 8725, 115, 178, 0, 110, 0, 110, 65, 0, 110, 70, 0, 110, 86, 0, 110, 87, 0, 110, 106, 0, 110, 109, 0, 110, 115, 0, 110, 768, 0, 110, 769, 0, 110, 771, 0, 110, 775, 0, 110, 780, 0, 110, 803, 0, 110, 807, 0, 110, 813, 0, 110, 817, 0, 111, 0, 111, 86, 0, 111, 768, 0, 111, 769, 0, 111, 770, 0, 111, 771, 0, 111, 772, 0, 111, 774, 0, 111, 775, 0, 111, 776, 0, 111, 777, 0, 111, 779, 0, 111, 780, 0, 111, 783, 0, 111, 785, 0, 111, 795, 0, 111, 803, 0, 111, 808, 0, 112, 0, 112, 46, 109, 46, 0, 112, 65, 0, 112, 70, 0, 112, 86, 0, 112, 87, 0, 112, 99, 0, 112, 115, 0, 112, 769, 0, 112, 775, 0, 113, 0, 114, 0, 114, 97, 100, 0, 114, 97, 100, 8725, 115, 0, 114, 97, 100, 8725, 115, 178, 0, 114, 769, 0, 114, 775, 0, 114, 780, 0, 114, 783, 0, 114, 785, 0, 114, 803, 0, 114, 807, 0, 114, 817, 0, 115, 0, 115, 114, 0, 115, 116, 0, 115, 769, 0, 115, 770, 0, 115, 775, 0, 115, 780, 0, 115, 803, 0, 115, 806, 0, 115, 807, 0, 116, 0, 116, 775, 0, 116, 776, 0, 116, 780, 0, 116, 803, 0, 116, 806, 0, 116, 807, 0, 116, 813, 0, 116, 817, 0, 117, 0, 117, 768, 0, 117, 769, 0, 117, 770, 0, 117, 771, 0, 117, 772, 0, 117, 774, 0, 117, 776, 0, 117, 777, 0, 117, 778, 0, 117, 779, 0, 117, 780, 0, 117, 783, 0, 117, 785, 0, 117, 795, 0, 117, 803, 0, 117, 804, 0, 117, 808, 0, 117, 813, 0, 117, 816, 0, 118, 0, 118, 105, 0, 118, 105, 105, 0, 118, 105, 105, 105, 0, 118, 771, 0, 118, 803, 0, 119, 0, 119, 768, 0, 119, 769, 0, 119, 770, 0, 119, 775, 0, 119, 776, 0, 119, 778, 0, 119, 803, 0, 120, 0, 120, 105, 0, 120, 105, 105, 0, 120, 775, 0, 120, 776, 0, 121, 0, 121, 768, 0, 121, 769, 0, 121, 770, 0, 121, 771, 0, 121, 772, 0, 121, 775, 0, 121, 776, 0, 121, 777, 0, 121, 778, 0, 121, 803, 0, 122, 0, 122, 769, 0, 122, 770, 0, 122, 775, 0, 122, 780, 0, 122, 803, 0, 122, 817, 0, 123, 0, 124, 0, 125, 0, 126, 0, 162, 0, 163, 0, 165, 0, 166, 0, 168, 768, 0, 168, 769, 0, 168, 834, 0, 172, 0, 175, 0, 176, 67, 0, 176, 70, 0, 180, 0, 183, 0, 194, 768, 0, 194, 769, 0, 194, 771, 0, 194, 777, 0, 196, 772, 0, 197, 0, 197, 769, 0, 198, 0, 198, 769, 0, 198, 772, 0, 199, 769, 0, 202, 768, 0, 202, 769, 0, 202, 771, 0, 202, 777, 0, 207, 769, 0, 212, 768, 0, 212, 769, 0, 212, 771, 0, 212, 777, 0, 213, 769, 0, 213, 772, 0, 213, 776, 0, 214, 772, 0, 216, 769, 0, 220, 768, 0, 220, 769, 0, 220, 772, 0, 220, 780, 0, 226, 768, 0, 226, 769, 0, 226, 771, 0, 226, 777, 0, 228, 772, 0, 229, 769, 0, 230, 769, 0, 230, 772, 0, 231, 769, 0, 234, 768, 0, 234, 769, 0, 234, 771, 0, 234, 777, 0, 239, 769, 0, 240, 0, 244, 768, 0, 244, 769, 0, 244, 771, 0, 244, 777, 0, 245, 769, 0, 245, 772, 0, 245, 776, 0, 246, 772, 0, 248, 769, 0, 252, 768, 0, 252, 769, 0, 252, 772, 0, 252, 780, 0, 258, 768, 0, 258, 769, 0, 258, 771, 0, 258, 777, 0, 259, 768, 0, 259, 769, 0, 259, 771, 0, 259, 777, 0, 274, 768, 0, 274, 769, 0, 275, 768, 0, 275, 769, 0, 295, 0, 331, 0, 332, 768, 0, 332, 769, 0, 333, 768, 0, 333, 769, 0, 346, 775, 0, 347, 775, 0, 352, 775, 0, 353, 775, 0, 360, 769, 0, 361, 769, 0, 362, 776, 0, 363, 776, 0, 383, 116, 0, 383, 775, 0, 398, 0, 400, 0, 416, 768, 0, 416, 769, 0, 416, 771, 0, 416, 777, 0, 416, 803, 0, 417, 768, 0, 417, 769, 0, 417, 771, 0, 417, 777, 0, 417, 803, 0, 427, 0, 431, 768, 0, 431, 769, 0, 431, 771, 0, 431, 777, 0, 431, 803, 0, 432, 768, 0, 432, 769, 0, 432, 771, 0, 432, 777, 0, 432, 803, 0, 439, 780, 0, 490, 772, 0, 491, 772, 0, 546, 0, 550, 772, 0, 551, 772, 0, 552, 774, 0, 553, 774, 0, 558, 772, 0, 559, 772, 0, 592, 0, 593, 0, 594, 0, 596, 0, 597, 0, 601, 0, 603, 0, 604, 0, 607, 0, 609, 0, 611, 0, 613, 0, 614, 0, 616, 0, 617, 0, 618, 0, 621, 0, 623, 0, 624, 0, 625, 0, 626, 0, 627, 0, 628, 0, 629, 0, 632, 0, 633, 0, 635, 0, 641, 0, 642, 0, 643, 0, 649, 0, 650, 0, 651, 0, 652, 0, 656, 0, 657, 0, 658, 0, 658, 780, 0, 661, 0, 669, 0, 671, 0, 697, 0, 700, 110, 0, 768, 0, 769, 0, 776, 769, 0, 787, 0, 901, 0, 902, 0, 904, 0, 905, 0, 906, 0, 908, 0, 910, 0, 911, 0, 912, 0, 913, 768, 0, 913, 769, 0, 913, 772, 0, 913, 774, 0, 913, 787, 0, 913, 788, 0, 913, 837, 0, 915, 0, 917, 768, 0, 917, 769, 0, 917, 787, 0, 917, 788, 0, 919, 768, 0, 919, 769, 0, 919, 787, 0, 919, 788, 0, 919, 837, 0, 920, 0, 921, 768, 0, 921, 769, 0, 921, 772, 0, 921, 774, 0, 921, 776, 0, 921, 787, 0, 921, 788, 0, 927, 768, 0, 927, 769, 0, 927, 787, 0, 927, 788, 0, 928, 0, 929, 788, 0, 931, 0, 933, 0, 933, 768, 0, 933, 769, 0, 933, 772, 0, 933, 774, 0, 933, 776, 0, 933, 788, 0, 937, 0, 937, 768, 0, 937, 769, 0, 937, 787, 0, 937, 788, 0, 937, 837, 0, 940, 0, 940, 837, 0, 941, 0, 942, 0, 942, 837, 0, 943, 0, 944, 0, 945, 768, 0, 945, 769, 0, 945, 772, 0, 945, 774, 0, 945, 787, 0, 945, 788, 0, 945, 834, 0, 945, 837, 0, 946, 0, 947, 0, 948, 0, 949, 0, 949, 768, 0, 949, 769, 0, 949, 787, 0, 949, 788, 0, 951, 768, 0, 951, 769, 0, 951, 787, 0, 951, 788, 0, 951, 834, 0, 951, 837, 0, 952, 0, 953, 0, 953, 768, 0, 953, 769, 0, 953, 772, 0, 953, 774, 0, 953, 776, 0, 953, 787, 0, 953, 788, 0, 953, 834, 0, 954, 0, 956, 0, 956, 65, 0, 956, 70, 0, 956, 86, 0, 956, 87, 0, 956, 103, 0, 956, 109, 0, 956, 115, 0, 956, 8467, 0, 959, 768, 0, 959, 769, 0, 959, 787, 0, 959, 788, 0, 960, 0, 961, 0, 961, 787, 0, 961, 788, 0, 962, 0, 965, 768, 0, 965, 769, 0, 965, 772, 0, 965, 774, 0, 965, 776, 0, 965, 787, 0, 965, 788, 0, 965, 834, 0, 966, 0, 967, 0, 969, 768, 0, 969, 769, 0, 969, 787, 0, 969, 788, 0, 969, 834, 0, 969, 837, 0, 970, 768, 0, 970, 769, 0, 970, 834, 0, 971, 768, 0, 971, 769, 0, 971, 834, 0, 972, 0, 973, 0, 974, 0, 974, 837, 0, 978, 769, 0, 978, 776, 0, 1030, 776, 0, 1040, 774, 0, 1040, 776, 0, 1043, 769, 0, 1045, 768, 0, 1045, 774, 0, 1045, 776, 0, 1046, 774, 0, 1046, 776, 0, 1047, 776, 0, 1048, 768, 0, 1048, 772, 0, 1048, 774, 0, 1048, 776, 0, 1050, 769, 0, 1054, 776, 0, 1059, 772, 0, 1059, 774, 0, 1059, 776, 0, 1059, 779, 0, 1063, 776, 0, 1067, 776, 0, 1069, 776, 0, 1072, 774, 0, 1072, 776, 0, 1075, 769, 0, 1077, 768, 0, 1077, 774, 0, 1077, 776, 0, 1078, 774, 0, 1078, 776, 0, 1079, 776, 0, 1080, 768, 0, 1080, 772, 0, 1080, 774, 0, 1080, 776, 0, 1082, 769, 0, 1085, 0, 1086, 776, 0, 1091, 772, 0, 1091, 774, 0, 1091, 776, 0, 1091, 779, 0, 1095, 776, 0, 1099, 776, 0, 1101, 776, 0, 1110, 776, 0, 1140, 783, 0, 1141, 783, 0, 1240, 776, 0, 1241, 776, 0, 1256, 776, 0, 1257, 776, 0, 1381, 1410, 0, 1396, 1381, 0, 1396, 1387, 0, 1396, 1389, 0, 1396, 1398, 0, 1406, 1398, 0, 1488, 0, 1488, 1463, 0, 1488, 1464, 0, 1488, 1468, 0, 1488, 1500, 0, 1489, 0, 1489, 1468, 0, 1489, 1471, 0, 1490, 0, 1490, 1468, 0, 1491, 0, 1491, 1468, 0, 1492, 0, 1492, 1468, 0, 1493, 1465, 0, 1493, 1468, 0, 1494, 1468, 0, 1496, 1468, 0, 1497, 1460, 0, 1497, 1468, 0, 1498, 1468, 0, 1499, 0, 1499, 1468, 0, 1499, 1471, 0, 1500, 0, 1500, 1468, 0, 1501, 0, 1502, 1468, 0, 1504, 1468, 0, 1505, 1468, 0, 1506, 0, 1507, 1468, 0, 1508, 1468, 0, 1508, 1471, 0, 1510, 1468, 0, 1511, 1468, 0, 1512, 0, 1512, 1468, 0, 1513, 1468, 0, 1513, 1473, 0, 1513, 1474, 0, 1514, 0, 1514, 1468, 0, 1522, 1463, 0, 1569, 0, 1570, 0, 1571, 0, 1572, 0, 1573, 0, 1574, 0, 1574, 1575, 0, 1574, 1580, 0, 1574, 1581, 0, 1574, 1582, 0, 1574, 1585, 0, 1574, 1586, 0, 1574, 1605, 0, 1574, 1606, 0, 1574, 1607, 0, 1574, 1608, 0, 1574, 1609, 0, 1574, 1610, 0, 1574, 1734, 0, 1574, 1735, 0, 1574, 1736, 0, 1574, 1744, 0, 1574, 1749, 0, 1575, 0, 1575, 1603, 1576, 1585, 0, 1575, 1604, 1604, 1607, 0, 1575, 1611, 0, 1575, 1619, 0, 1575, 1620, 0, 1575, 1621, 0, 1575, 1652, 0, 1576, 0, 1576, 1580, 0, 1576, 1581, 0, 1576, 1581, 1610, 0, 1576, 1582, 0, 1576, 1582, 1610, 0, 1576, 1585, 0, 1576, 1586, 0, 1576, 1605, 0, 1576, 1606, 0, 1576, 1607, 0, 1576, 1609, 0, 1576, 1610, 0, 1577, 0, 1578, 0, 1578, 1580, 0, 1578, 1580, 1605, 0, 1578, 1580, 1609, 0, 1578, 1580, 1610, 0, 1578, 1581, 0, 1578, 1581, 1580, 0, 1578, 1581, 1605, 0, 1578, 1582, 0, 1578, 1582, 1605, 0, 1578, 1582, 1609, 0, 1578, 1582, 1610, 0, 1578, 1585, 0, 1578, 1586, 0, 1578, 1605, 0, 1578, 1605, 1580, 0, 1578, 1605, 1581, 0, 1578, 1605, 1582, 0, 1578, 1605, 1609, 0, 1578, 1605, 1610, 0, 1578, 1606, 0, 1578, 1607, 0, 1578, 1609, 0, 1578, 1610, 0, 1579, 0, 1579, 1580, 0, 1579, 1585, 0, 1579, 1586, 0, 1579, 1605, 0, 1579, 1606, 0, 1579, 1607, 0, 1579, 1609, 0, 1579, 1610, 0, 1580, 0, 1580, 1581, 0, 1580, 1581, 1609, 0, 1580, 1581, 1610, 0, 1580, 1604, 32, 1580, 1604, 1575, 1604, 1607, 0, 1580, 1605, 0, 1580, 1605, 1581, 0, 1580, 1605, 1609, 0, 1580, 1605, 1610, 0, 1580, 1609, 0, 1580, 1610, 0, 1581, 0, 1581, 1580, 0, 1581, 1580, 1610, 0, 1581, 1605, 0, 1581, 1605, 1609, 0, 1581, 1605, 1610, 0, 1581, 1609, 0, 1581, 1610, 0, 1582, 0, 1582, 1580, 0, 1582, 1581, 0, 1582, 1605, 0, 1582, 1609, 0, 1582, 1610, 0, 1583, 0, 1584, 0, 1584, 1648, 0, 1585, 0, 1585, 1587, 1608, 1604, 0, 1585, 1648, 0, 1585, 1740, 1575, 1604, 0, 1586, 0, 1587, 0, 1587, 1580, 0, 1587, 1580, 1581, 0, 1587, 1580, 1609, 0, 1587, 1581, 0, 1587, 1581, 1580, 0, 1587, 1582, 0, 1587, 1582, 1609, 0, 1587, 1582, 1610, 0, 1587, 1585, 0, 1587, 1605, 0, 1587, 1605, 1580, 0, 1587, 1605, 1581, 0, 1587, 1605, 1605, 0, 1587, 1607, 0, 1587, 1609, 0, 1587, 1610, 0, 1588, 0, 1588, 1580, 0, 1588, 1580, 1610, 0, 1588, 1581, 0, 1588, 1581, 1605, 0, 1588, 1581, 1610, 0, 1588, 1582, 0, 1588, 1585, 0, 1588, 1605, 0, 1588, 1605, 1582, 0, 1588, 1605, 1605, 0, 1588, 1607, 0, 1588, 1609, 0, 1588, 1610, 0, 1589, 0, 1589, 1581, 0, 1589, 1581, 1581, 0, 1589, 1581, 1610, 0, 1589, 1582, 0, 1589, 1585, 0, 1589, 1604, 1593, 1605, 0, 1589, 1604, 1609, 0, 1589, 1604, 1609, 32, 1575, 1604, 1604, 1607, 32, 1593, 1604, 1610, 1607, 32, 1608, 1587, 1604, 1605, 0, 1589, 1604, 1746, 0, 1589, 1605, 0, 1589, 1605, 1605, 0, 1589, 1609, 0, 1589, 1610, 0, 1590, 0, 1590, 1580, 0, 1590, 1581, 0, 1590, 1581, 1609, 0, 1590, 1581, 1610, 0, 1590, 1582, 0, 1590, 1582, 1605, 0, 1590, 1585, 0, 1590, 1605, 0, 1590, 1609, 0, 1590, 1610, 0, 1591, 0, 1591, 1581, 0, 1591, 1605, 0, 1591, 1605, 1581, 0, 1591, 1605, 1605, 0, 1591, 1605, 1610, 0, 1591, 1609, 0, 1591, 1610, 0, 1592, 0, 1592, 1605, 0, 1593, 0, 1593, 1580, 0, 1593, 1580, 1605, 0, 1593, 1604, 1610, 1607, 0, 1593, 1605, 0, 1593, 1605, 1605, 0, 1593, 1605, 1609, 0, 1593, 1605, 1610, 0, 1593, 1609, 0, 1593, 1610, 0, 1594, 0, 1594, 1580, 0, 1594, 1605, 0, 1594, 1605, 1605, 0, 1594, 1605, 1609, 0, 1594, 1605, 1610, 0, 1594, 1609, 0, 1594, 1610, 0, 1600, 1611, 0, 1600, 1614, 0, 1600, 1614, 1617, 0, 1600, 1615, 0, 1600, 1615, 1617, 0, 1600, 1616, 0, 1600, 1616, 1617, 0, 1600, 1617, 0, 1600, 1618, 0, 1601, 0, 1601, 1580, 0, 1601, 1581, 0, 1601, 1582, 0, 1601, 1582, 1605, 0, 1601, 1605, 0, 1601, 1605, 1610, 0, 1601, 1609, 0, 1601, 1610, 0, 1602, 0, 1602, 1581, 0, 1602, 1604, 1746, 0, 1602, 1605, 0, 1602, 1605, 1581, 0, 1602, 1605, 1605, 0, 1602, 1605, 1610, 0, 1602, 1609, 0, 1602, 1610, 0, 1603, 0, 1603, 1575, 0, 1603, 1580, 0, 1603, 1581, 0, 1603, 1582, 0, 1603, 1604, 0, 1603, 1605, 0, 1603, 1605, 1605, 0, 1603, 1605, 1610, 0, 1603, 1609, 0, 1603, 1610, 0, 1604, 0, 1604, 1570, 0, 1604, 1571, 0, 1604, 1573, 0, 1604, 1575, 0, 1604, 1580, 0, 1604, 1580, 1580, 0, 1604, 1580, 1605, 0, 1604, 1580, 1610, 0, 1604, 1581, 0, 1604, 1581, 1605, 0, 1604, 1581, 1609, 0, 1604, 1581, 1610, 0, 1604, 1582, 0, 1604, 1582, 1605, 0, 1604, 1605, 0, 1604, 1605, 1581, 0, 1604, 1605, 1610, 0, 1604, 1607, 0, 1604, 1609, 0, 1604, 1610, 0, 1605, 0, 1605, 1575, 0, 1605, 1580, 0, 1605, 1580, 1581, 0, 1605, 1580, 1582, 0, 1605, 1580, 1605, 0, 1605, 1580, 1610, 0, 1605, 1581, 0, 1605, 1581, 1580, 0, 1605, 1581, 1605, 0, 1605, 1581, 1605, 1583, 0, 1605, 1581, 1610, 0, 1605, 1582, 0, 1605, 1582, 1580, 0, 1605, 1582, 1605, 0, 1605, 1582, 1610, 0, 1605, 1605, 0, 1605, 1605, 1610, 0, 1605, 1609, 0, 1605, 1610, 0, 1606, 0, 1606, 1580, 0, 1606, 1580, 1581, 0, 1606, 1580, 1605, 0, 1606, 1580, 1609, 0, 1606, 1580, 1610, 0, 1606, 1581, 0, 1606, 1581, 1605, 0, 1606, 1581, 1609, 0, 1606, 1581, 1610, 0, 1606, 1582, 0, 1606, 1585, 0, 1606, 1586, 0, 1606, 1605, 0, 1606, 1605, 1609, 0, 1606, 1605, 1610, 0, 1606, 1606, 0, 1606, 1607, 0, 1606, 1609, 0, 1606, 1610, 0, 1607, 0, 1607, 1580, 0, 1607, 1605, 0, 1607, 1605, 1580, 0, 1607, 1605, 1605, 0, 1607, 1609, 0, 1607, 1610, 0, 1607, 1648, 0, 1608, 0, 1608, 1587, 1604, 1605, 0, 1608, 1620, 0, 1608, 1652, 0, 1609, 0, 1609, 1648, 0, 1610, 0, 1610, 1580, 0, 1610, 1580, 1610, 0, 1610, 1581, 0, 1610, 1581, 1610, 0, 1610, 1582, 0, 1610, 1585, 0, 1610, 1586, 0, 1610, 1605, 0, 1610, 1605, 1605, 0, 1610, 1605, 1610, 0, 1610, 1606, 0, 1610, 1607, 0, 1610, 1609, 0, 1610, 1610, 0, 1610, 1620, 0, 1610, 1652, 0, 1649, 0, 1655, 0, 1657, 0, 1658, 0, 1659, 0, 1662, 0, 1663, 0, 1664, 0, 1667, 0, 1668, 0, 1670, 0, 1671, 0, 1672, 0, 1676, 0, 1677, 0, 1678, 0, 1681, 0, 1688, 0, 1700, 0, 1702, 0, 1705, 0, 1709, 0, 1711, 0, 1713, 0, 1715, 0, 1722, 0, 1723, 0, 1726, 0, 1728, 0, 1729, 0, 1729, 1620, 0, 1733, 0, 1734, 0, 1735, 0, 1735, 1652, 0, 1736, 0, 1737, 0, 1739, 0, 1740, 0, 1744, 0, 1746, 0, 1746, 1620, 0, 1747, 0, 1749, 1620, 0, 2325, 2364, 0, 2326, 2364, 0, 2327, 2364, 0, 2332, 2364, 0, 2337, 2364, 0, 2338, 2364, 0, 2344, 2364, 0, 2347, 2364, 0, 2351, 2364, 0, 2352, 2364, 0, 2355, 2364, 0, 2465, 2492, 0, 2466, 2492, 0, 2479, 2492, 0, 2503, 2494, 0, 2503, 2519, 0, 2582, 2620, 0, 2583, 2620, 0, 2588, 2620, 0, 2603, 2620, 0, 2610, 2620, 0, 2616, 2620, 0, 2849, 2876, 0, 2850, 2876, 0, 2887, 2878, 0, 2887, 2902, 0, 2887, 2903, 0, 2962, 3031, 0, 3014, 3006, 0, 3014, 3031, 0, 3015, 3006, 0, 3142, 3158, 0, 3263, 3285, 0, 3270, 3266, 0, 3270, 3285, 0, 3270, 3286, 0, 3274, 3285, 0, 3398, 3390, 0, 3398, 3415, 0, 3399, 3390, 0, 3545, 3530, 0, 3545, 3535, 0, 3545, 3551, 0, 3548, 3530, 0, 3661, 3634, 0, 3755, 3737, 0, 3755, 3745, 0, 3789, 3762, 0, 3851, 0, 3904, 4021, 0, 3906, 4023, 0, 3916, 4023, 0, 3921, 4023, 0, 3926, 4023, 0, 3931, 4023, 0, 3953, 3954, 0, 3953, 3956, 0, 3953, 3968, 0, 3984, 4021, 0, 3986, 4023, 0, 3996, 4023, 0, 4001, 4023, 0, 4006, 4023, 0, 4011, 4023, 0, 4018, 3968, 0, 4018, 3969, 0, 4019, 3968, 0, 4019, 3969, 0, 4133, 4142, 0, 4316, 0, 4352, 0, 4352, 4449, 0, 4353, 0, 4354, 0, 4354, 4449, 0, 4355, 0, 4355, 4449, 0, 4356, 0, 4357, 0, 4357, 4449, 0, 4358, 0, 4358, 4449, 0, 4359, 0, 4359, 4449, 0, 4360, 0, 4361, 0, 4361, 4449, 0, 4362, 0, 4363, 0, 4363, 4449, 0, 4363, 4462, 0, 4364, 0, 4364, 4449, 0, 4364, 4462, 4363, 4468, 0, 4365, 0, 4366, 0, 4366, 4449, 0, 4366, 4449, 4535, 4352, 4457, 0, 4367, 0, 4367, 4449, 0, 4368, 0, 4368, 4449, 0, 4369, 0, 4369, 4449, 0, 4370, 0, 4370, 4449, 0, 4372, 0, 4373, 0, 4378, 0, 4380, 0, 4381, 0, 4382, 0, 4384, 0, 4385, 0, 4386, 0, 4387, 0, 4391, 0, 4393, 0, 4395, 0, 4396, 0, 4397, 0, 4398, 0, 4399, 0, 4402, 0, 4406, 0, 4416, 0, 4423, 0, 4428, 0, 4439, 0, 4440, 0, 4441, 0, 4448, 0, 4449, 0, 4450, 0, 4451, 0, 4452, 0, 4453, 0, 4454, 0, 4455, 0, 4456, 0, 4457, 0, 4458, 0, 4459, 0, 4460, 0, 4461, 0, 4462, 0, 4463, 0, 4464, 0, 4465, 0, 4466, 0, 4467, 0, 4468, 0, 4469, 0, 4484, 0, 4485, 0, 4488, 0, 4497, 0, 4498, 0, 4500, 0, 4510, 0, 4513, 0, 4522, 0, 4524, 0, 4525, 0, 4528, 0, 4529, 0, 4530, 0, 4531, 0, 4532, 0, 4533, 0, 4551, 0, 4552, 0, 4556, 0, 4558, 0, 4563, 0, 4567, 0, 4569, 0, 4573, 0, 4575, 0, 4593, 0, 4594, 0, 6917, 6965, 0, 6919, 6965, 0, 6921, 6965, 0, 6923, 6965, 0, 6925, 6965, 0, 6929, 6965, 0, 6970, 6965, 0, 6972, 6965, 0, 6974, 6965, 0, 6975, 6965, 0, 6978, 6965, 0, 7426, 0, 7446, 0, 7447, 0, 7452, 0, 7453, 0, 7461, 0, 7547, 0, 7557, 0, 7734, 772, 0, 7735, 772, 0, 7770, 772, 0, 7771, 772, 0, 7778, 775, 0, 7779, 775, 0, 7840, 770, 0, 7840, 774, 0, 7841, 770, 0, 7841, 774, 0, 7864, 770, 0, 7865, 770, 0, 7884, 770, 0, 7885, 770, 0, 7936, 768, 0, 7936, 769, 0, 7936, 834, 0, 7936, 837, 0, 7937, 768, 0, 7937, 769, 0, 7937, 834, 0, 7937, 837, 0, 7938, 837, 0, 7939, 837, 0, 7940, 837, 0, 7941, 837, 0, 7942, 837, 0, 7943, 837, 0, 7944, 768, 0, 7944, 769, 0, 7944, 834, 0, 7944, 837, 0, 7945, 768, 0, 7945, 769, 0, 7945, 834, 0, 7945, 837, 0, 7946, 837, 0, 7947, 837, 0, 7948, 837, 0, 7949, 837, 0, 7950, 837, 0, 7951, 837, 0, 7952, 768, 0, 7952, 769, 0, 7953, 768, 0, 7953, 769, 0, 7960, 768, 0, 7960, 769, 0, 7961, 768, 0, 7961, 769, 0, 7968, 768, 0, 7968, 769, 0, 7968, 834, 0, 7968, 837, 0, 7969, 768, 0, 7969, 769, 0, 7969, 834, 0, 7969, 837, 0, 7970, 837, 0, 7971, 837, 0, 7972, 837, 0, 7973, 837, 0, 7974, 837, 0, 7975, 837, 0, 7976, 768, 0, 7976, 769, 0, 7976, 834, 0, 7976, 837, 0, 7977, 768, 0, 7977, 769, 0, 7977, 834, 0, 7977, 837, 0, 7978, 837, 0, 7979, 837, 0, 7980, 837, 0, 7981, 837, 0, 7982, 837, 0, 7983, 837, 0, 7984, 768, 0, 7984, 769, 0, 7984, 834, 0, 7985, 768, 0, 7985, 769, 0, 7985, 834, 0, 7992, 768, 0, 7992, 769, 0, 7992, 834, 0, 7993, 768, 0, 7993, 769, 0, 7993, 834, 0, 8000, 768, 0, 8000, 769, 0, 8001, 768, 0, 8001, 769, 0, 8008, 768, 0, 8008, 769, 0, 8009, 768, 0, 8009, 769, 0, 8016, 768, 0, 8016, 769, 0, 8016, 834, 0, 8017, 768, 0, 8017, 769, 0, 8017, 834, 0, 8025, 768, 0, 8025, 769, 0, 8025, 834, 0, 8032, 768, 0, 8032, 769, 0, 8032, 834, 0, 8032, 837, 0, 8033, 768, 0, 8033, 769, 0, 8033, 834, 0, 8033, 837, 0, 8034, 837, 0, 8035, 837, 0, 8036, 837, 0, 8037, 837, 0, 8038, 837, 0, 8039, 837, 0, 8040, 768, 0, 8040, 769, 0, 8040, 834, 0, 8040, 837, 0, 8041, 768, 0, 8041, 769, 0, 8041, 834, 0, 8041, 837, 0, 8042, 837, 0, 8043, 837, 0, 8044, 837, 0, 8045, 837, 0, 8046, 837, 0, 8047, 837, 0, 8048, 837, 0, 8052, 837, 0, 8060, 837, 0, 8118, 837, 0, 8127, 768, 0, 8127, 769, 0, 8127, 834, 0, 8134, 837, 0, 8182, 837, 0, 8190, 768, 0, 8190, 769, 0, 8190, 834, 0, 8194, 0, 8195, 0, 8208, 0, 8211, 0, 8212, 0, 8229, 0, 8230, 0, 8242, 8242, 0, 8242, 8242, 8242, 0, 8242, 8242, 8242, 8242, 0, 8245, 8245, 0, 8245, 8245, 8245, 0, 8254, 0, 8361, 0, 8592, 0, 8592, 824, 0, 8593, 0, 8594, 0, 8594, 824, 0, 8595, 0, 8596, 824, 0, 8656, 824, 0, 8658, 824, 0, 8660, 824, 0, 8707, 824, 0, 8712, 824, 0, 8715, 824, 0, 8721, 0, 8722, 0, 8739, 824, 0, 8741, 824, 0, 8747, 8747, 0, 8747, 8747, 8747, 0, 8747, 8747, 8747, 8747, 0, 8750, 8750, 0, 8750, 8750, 8750, 0, 8764, 824, 0, 8771, 824, 0, 8773, 824, 0, 8776, 824, 0, 8781, 824, 0, 8801, 824, 0, 8804, 824, 0, 8805, 824, 0, 8818, 824, 0, 8819, 824, 0, 8822, 824, 0, 8823, 824, 0, 8826, 824, 0, 8827, 824, 0, 8828, 824, 0, 8829, 824, 0, 8834, 824, 0, 8835, 824, 0, 8838, 824, 0, 8839, 824, 0, 8849, 824, 0, 8850, 824, 0, 8866, 824, 0, 8872, 824, 0, 8873, 824, 0, 8875, 824, 0, 8882, 824, 0, 8883, 824, 0, 8884, 824, 0, 8885, 824, 0, 9474, 0, 9632, 0, 9675, 0, 10629, 0, 10630, 0, 10973, 824, 0, 11617, 0, 12289, 0, 12290, 0, 12296, 0, 12297, 0, 12298, 0, 12299, 0, 12300, 0, 12301, 0, 12302, 0, 12303, 0, 12304, 0, 12305, 0, 12306, 0, 12308, 0, 12309, 0, 12310, 0, 12311, 0, 12358, 12441, 0, 12363, 12441, 0, 12365, 12441, 0, 12367, 12441, 0, 12369, 12441, 0, 12371, 12441, 0, 12373, 12441, 0, 12375, 12441, 0, 12377, 12441, 0, 12379, 12441, 0, 12381, 12441, 0, 12383, 12441, 0, 12385, 12441, 0, 12388, 12441, 0, 12390, 12441, 0, 12392, 12441, 0, 12399, 12441, 0, 12399, 12442, 0, 12402, 12441, 0, 12402, 12442, 0, 12405, 12441, 0, 12405, 12442, 0, 12408, 12441, 0, 12408, 12442, 0, 12411, 12441, 0, 12411, 12442, 0, 12424, 12426, 0, 12441, 0, 12442, 0, 12445, 12441, 0, 12449, 0, 12450, 0, 12450, 12497, 12540, 12488, 0, 12450, 12523, 12501, 12449, 0, 12450, 12531, 12506, 12450, 0, 12450, 12540, 12523, 0, 12451, 0, 12452, 0, 12452, 12491, 12531, 12464, 0, 12452, 12531, 12481, 0, 12453, 0, 12454, 0, 12454, 12441, 0, 12454, 12457, 12531, 0, 12455, 0, 12456, 0, 12456, 12473, 12463, 12540, 12489, 0, 12456, 12540, 12459, 12540, 0, 12457, 0, 12458, 0, 12458, 12531, 12473, 0, 12458, 12540, 12512, 0, 12459, 0, 12459, 12441, 0, 12459, 12452, 12522, 0, 12459, 12521, 12483, 12488, 0, 12459, 12525, 12522, 12540, 0, 12460, 12525, 12531, 0, 12460, 12531, 12510, 0, 12461, 0, 12461, 12441, 0, 12461, 12517, 12522, 12540, 0, 12461, 12525, 0, 12461, 12525, 12464, 12521, 12512, 0, 12461, 12525, 12513, 12540, 12488, 12523, 0, 12461, 12525, 12527, 12483, 12488, 0, 12462, 12460, 0, 12462, 12491, 12540, 0, 12462, 12523, 12480, 12540, 0, 12463, 0, 12463, 12441, 0, 12463, 12523, 12476, 12452, 12525, 0, 12463, 12525, 12540, 12493, 0, 12464, 12521, 12512, 0, 12464, 12521, 12512, 12488, 12531, 0, 12465, 0, 12465, 12441, 0, 12465, 12540, 12473, 0, 12467, 0, 12467, 12441, 0, 12467, 12488, 0, 12467, 12523, 12490, 0, 12467, 12540, 12509, 0, 12469, 0, 12469, 12441, 0, 12469, 12452, 12463, 12523, 0, 12469, 12531, 12481, 12540, 12512, 0, 12471, 0, 12471, 12441, 0, 12471, 12522, 12531, 12464, 0, 12473, 0, 12473, 12441, 0, 12475, 0, 12475, 12441, 0, 12475, 12531, 12481, 0, 12475, 12531, 12488, 0, 12477, 0, 12477, 12441, 0, 12479, 0, 12479, 12441, 0, 12480, 12540, 12473, 0, 12481, 0, 12481, 12441, 0, 12483, 0, 12484, 0, 12484, 12441, 0, 12486, 0, 12486, 12441, 0, 12487, 12471, 0, 12488, 0, 12488, 12441, 0, 12488, 12531, 0, 12489, 12523, 0, 12490, 0, 12490, 12494, 0, 12491, 0, 12492, 0, 12493, 0, 12494, 0, 12494, 12483, 12488, 0, 12495, 0, 12495, 12441, 0, 12495, 12442, 0, 12495, 12452, 12484, 0, 12496, 12540, 12524, 12523, 0, 12497, 12540, 12475, 12531, 12488, 0, 12497, 12540, 12484, 0, 12498, 0, 12498, 12441, 0, 12498, 12442, 0, 12499, 12523, 0, 12500, 12450, 12473, 12488, 12523, 0, 12500, 12463, 12523, 0, 12500, 12467, 0, 12501, 0, 12501, 12441, 0, 12501, 12442, 0, 12501, 12449, 12521, 12483, 12489, 0, 12501, 12451, 12540, 12488, 0, 12501, 12521, 12531, 0, 12502, 12483, 12471, 12455, 12523, 0, 12504, 0, 12504, 12441, 0, 12504, 12442, 0, 12504, 12463, 12479, 12540, 12523, 0, 12504, 12523, 12484, 0, 12505, 12540, 12479, 0, 12506, 12477, 0, 12506, 12491, 12498, 0, 12506, 12531, 12473, 0, 12506, 12540, 12472, 0, 12507, 0, 12507, 12441, 0, 12507, 12442, 0, 12507, 12531, 0, 12507, 12540, 12523, 0, 12507, 12540, 12531, 0, 12508, 12523, 12488, 0, 12509, 12452, 12531, 12488, 0, 12509, 12531, 12489, 0, 12510, 0, 12510, 12452, 12463, 12525, 0, 12510, 12452, 12523, 0, 12510, 12483, 12495, 0, 12510, 12523, 12463, 0, 12510, 12531, 12471, 12519, 12531, 0, 12511, 0, 12511, 12463, 12525, 12531, 0, 12511, 12522, 0, 12511, 12522, 12496, 12540, 12523, 0, 12512, 0, 12513, 0, 12513, 12460, 0, 12513, 12460, 12488, 12531, 0, 12513, 12540, 12488, 12523, 0, 12514, 0, 12515, 0, 12516, 0, 12516, 12540, 12489, 0, 12516, 12540, 12523, 0, 12517, 0, 12518, 0, 12518, 12450, 12531, 0, 12519, 0, 12520, 0, 12521, 0, 12522, 0, 12522, 12483, 12488, 12523, 0, 12522, 12521, 0, 12523, 0, 12523, 12500, 12540, 0, 12523, 12540, 12502, 12523, 0, 12524, 0, 12524, 12512, 0, 12524, 12531, 12488, 12466, 12531, 0, 12525, 0, 12527, 0, 12527, 12441, 0, 12527, 12483, 12488, 0, 12528, 0, 12528, 12441, 0, 12529, 0, 12529, 12441, 0, 12530, 0, 12530, 12441, 0, 12531, 0, 12539, 0, 12540, 0, 12541, 12441, 0, 12593, 0, 12594, 0, 12595, 0, 12596, 0, 12597, 0, 12598, 0, 12599, 0, 12600, 0, 12601, 0, 12602, 0, 12603, 0, 12604, 0, 12605, 0, 12606, 0, 12607, 0, 12608, 0, 12609, 0, 12610, 0, 12611, 0, 12612, 0, 12613, 0, 12614, 0, 12615, 0, 12616, 0, 12617, 0, 12618, 0, 12619, 0, 12620, 0, 12621, 0, 12622, 0, 12623, 0, 12624, 0, 12625, 0, 12626, 0, 12627, 0, 12628, 0, 12629, 0, 12630, 0, 12631, 0, 12632, 0, 12633, 0, 12634, 0, 12635, 0, 12636, 0, 12637, 0, 12638, 0, 12639, 0, 12640, 0, 12641, 0, 12642, 0, 12643, 0, 12644, 0, 15261, 0, 16408, 0, 16441, 0, 19968, 0, 19969, 0, 19971, 0, 19977, 0, 19978, 0, 19979, 0, 19981, 0, 19993, 0, 20006, 0, 20008, 0, 20013, 0, 20018, 0, 20022, 0, 20025, 0, 20031, 0, 20057, 0, 20061, 0, 20098, 0, 20101, 0, 20102, 0, 20108, 0, 20116, 0, 20128, 0, 20142, 0, 20154, 0, 20160, 0, 20196, 0, 20225, 0, 20241, 0, 20352, 0, 20358, 0, 20363, 0, 20398, 0, 20415, 0, 20523, 0, 20698, 0, 20711, 0, 20778, 0, 20799, 0, 20800, 0, 20805, 0, 20813, 0, 20837, 0, 20840, 0, 20841, 0, 20843, 0, 20845, 0, 20864, 0, 20866, 0, 20886, 0, 20889, 0, 20907, 0, 20917, 0, 20919, 0, 20937, 0, 20940, 0, 20956, 0, 20958, 0, 20960, 0, 20981, 0, 20992, 0, 20999, 0, 21015, 0, 21033, 0, 21050, 0, 21129, 0, 21147, 0, 21155, 0, 21172, 0, 21191, 0, 21193, 0, 21202, 0, 21214, 0, 21220, 0, 21237, 0, 21241, 0, 21242, 0, 21269, 0, 21271, 0, 21274, 0, 21304, 0, 21307, 0, 21311, 0, 21313, 0, 21316, 0, 21317, 0, 21329, 0, 21332, 0, 21340, 0, 21353, 0, 21360, 0, 21365, 0, 21378, 0, 21430, 0, 21443, 0, 21448, 0, 21475, 0, 21477, 0, 21491, 0, 21517, 0, 21519, 0, 21533, 0, 21570, 0, 21693, 0, 21845, 0, 21895, 0, 21913, 0, 21917, 0, 21952, 0, 21986, 0, 22022, 0, 22120, 0, 22231, 0, 22235, 0, 22265, 0, 22303, 0, 22320, 0, 22592, 0, 22618, 0, 22622, 0, 22696, 0, 22707, 0, 22744, 0, 22751, 0, 22763, 0, 22786, 0, 22794, 0, 22805, 0, 22812, 0, 22823, 0, 22823, 27491, 0, 22825, 0, 22852, 0, 22856, 0, 22865, 0, 22868, 0, 22899, 0, 23138, 0, 23336, 0, 23376, 0, 23398, 0, 23424, 0, 23429, 0, 23447, 0, 23527, 0, 23534, 0, 23544, 0, 23567, 0, 23586, 0, 23608, 0, 23615, 0, 23650, 0, 23652, 0, 23653, 0, 23662, 0, 23665, 0, 23833, 0, 23888, 0, 23994, 0, 24027, 0, 24037, 0, 24038, 0, 24049, 0, 24062, 0, 24178, 0, 24179, 25104, 0, 24180, 0, 24186, 0, 24191, 0, 24230, 0, 24265, 0, 24266, 0, 24274, 0, 24275, 0, 24281, 0, 24300, 0, 24308, 0, 24318, 0, 24324, 0, 24331, 0, 24339, 0, 24400, 0, 24417, 0, 24425, 0, 24435, 0, 24459, 0, 24489, 0, 24493, 0, 24515, 0, 24565, 0, 24594, 0, 24604, 0, 24724, 0, 24792, 0, 24801, 0, 24840, 0, 24900, 0, 24910, 0, 24928, 0, 24936, 0, 24974, 0, 24976, 0, 25074, 0, 25078, 0, 25088, 0, 25096, 0, 25134, 0, 25140, 0, 25142, 0, 25163, 0, 25289, 0, 25295, 0, 25299, 0, 25342, 0, 25467, 0, 25504, 0, 25540, 0, 25628, 0, 25682, 0, 25754, 0, 25796, 0, 25903, 0, 25908, 0, 25935, 0, 25942, 0, 25976, 0, 25991, 0, 26007, 0, 26009, 0, 26020, 0, 26041, 0, 26053, 0, 26080, 0, 26082, 0, 26085, 0, 26126, 27835, 0, 26131, 0, 26157, 21644, 0, 26228, 0, 26248, 0, 26257, 0, 26292, 0, 26310, 0, 26352, 0, 26356, 0, 26376, 0, 26377, 0, 26391, 0, 26395, 0, 26408, 0, 26446, 0, 26454, 0, 26491, 0, 26519, 0, 26611, 0, 26647, 0, 26666, 0, 26666, 24335, 20250, 31038, 0, 26753, 0, 26757, 0, 26792, 0, 27138, 0, 27155, 0, 27347, 0, 27396, 0, 27424, 0, 27490, 0, 27491, 0, 27511, 0, 27513, 0, 27566, 0, 27571, 0, 27578, 0, 27595, 0, 27597, 0, 27604, 0, 27611, 0, 27663, 0, 27668, 0, 27700, 0, 27784, 0, 27852, 0, 27877, 0, 27880, 0, 27931, 0, 27934, 0, 27969, 0, 28010, 0, 28023, 0, 28107, 0, 28122, 0, 28138, 0, 28186, 0, 28316, 0, 28346, 0, 28363, 0, 28369, 0, 28379, 0, 28431, 0, 28450, 0, 28451, 0, 28651, 0, 28670, 0, 28702, 0, 28779, 0, 28825, 0, 28872, 0, 28889, 0, 29001, 0, 29038, 0, 29134, 0, 29136, 0, 29200, 0, 29211, 0, 29226, 0, 29227, 0, 29237, 0, 29238, 0, 29243, 0, 29247, 0, 29255, 0, 29273, 0, 29275, 0, 29282, 0, 29305, 0, 29356, 0, 29359, 0, 29376, 0, 29436, 0, 29482, 0, 29557, 0, 29572, 0, 29575, 0, 29577, 0, 29618, 0, 29662, 0, 29702, 0, 29705, 0, 29730, 0, 29801, 0, 29809, 0, 29833, 0, 29848, 0, 29916, 0, 29926, 0, 29958, 0, 29976, 0, 29983, 0, 29992, 0, 30000, 0, 30002, 0, 30007, 0, 30011, 0, 30041, 0, 30053, 0, 30064, 0, 30091, 0, 30098, 0, 30178, 0, 30237, 0, 30239, 0, 30274, 0, 30313, 0, 30326, 0, 30333, 0, 30382, 0, 30399, 0, 30410, 0, 30427, 0, 30435, 0, 30439, 0, 30446, 0, 30452, 0, 30465, 0, 30528, 0, 30538, 0, 30631, 0, 30683, 0, 30690, 0, 30707, 0, 30827, 0, 30860, 0, 30865, 0, 30922, 0, 30924, 0, 30971, 0, 31018, 0, 31034, 0, 31036, 0, 31038, 0, 31048, 0, 31049, 0, 31056, 0, 31062, 0, 31069, 0, 31070, 0, 31077, 0, 31103, 0, 31117, 0, 31118, 0, 31119, 0, 31150, 0, 31160, 0, 31166, 0, 31178, 0, 31192, 0, 31260, 0, 31296, 0, 31348, 0, 31361, 0, 31409, 0, 31435, 0, 31481, 0, 31520, 0, 31680, 0, 31806, 0, 31840, 0, 31859, 0, 31867, 0, 31890, 0, 31934, 0, 31958, 0, 31975, 0, 31992, 0, 32016, 0, 32034, 0, 32047, 0, 32091, 0, 32160, 0, 32190, 0, 32244, 0, 32265, 0, 32311, 0, 32321, 0, 32566, 0, 32574, 0, 32593, 0, 32626, 0, 32633, 0, 32645, 0, 32650, 0, 32666, 0, 32701, 0, 32769, 0, 32773, 0, 32780, 0, 32786, 0, 32819, 0, 32838, 0, 32879, 0, 32894, 0, 32895, 0, 32905, 0, 32907, 0, 33240, 0, 33251, 0, 33256, 0, 33258, 0, 33261, 0, 33267, 0, 33276, 0, 33292, 0, 33307, 0, 33311, 0, 33390, 0, 33391, 0, 33394, 0, 33400, 0, 33401, 0, 33509, 0, 33590, 0, 33618, 0, 33737, 0, 33775, 0, 33777, 0, 33853, 0, 33865, 0, 33879, 0, 34030, 0, 34044, 0, 34253, 0, 34298, 0, 34310, 0, 34322, 0, 34349, 0, 34367, 0, 34381, 0, 34396, 0, 34411, 0, 34681, 0, 34746, 0, 34847, 0, 34880, 0, 34892, 0, 34915, 0, 35010, 0, 35023, 0, 35041, 0, 35064, 0, 35088, 0, 35137, 0, 35172, 0, 35198, 0, 35206, 0, 35211, 0, 35222, 0, 35282, 0, 35328, 0, 35498, 0, 35519, 0, 35531, 0, 35538, 0, 35542, 0, 35565, 0, 35576, 0, 35582, 0, 35585, 0, 35641, 0, 35672, 0, 35712, 0, 35722, 0, 35895, 0, 35910, 0, 35912, 0, 35925, 0, 35960, 0, 35997, 0, 36001, 0, 36034, 0, 36039, 0, 36040, 0, 36051, 0, 36104, 0, 36196, 0, 36208, 0, 36275, 0, 36335, 0, 36523, 0, 36554, 0, 36646, 0, 36650, 0, 36664, 0, 36667, 0, 36706, 0, 36763, 0, 36784, 0, 36789, 0, 36790, 0, 36899, 0, 36920, 0, 36969, 0, 36978, 0, 36988, 0, 37007, 0, 37009, 0, 37070, 0, 37117, 0, 37193, 0, 37226, 0, 37273, 0, 37300, 0, 37318, 0, 37324, 0, 37327, 0, 37329, 0, 37428, 0, 37494, 0, 37636, 0, 37706, 0, 38263, 0, 38272, 0, 38317, 0, 38428, 0, 38446, 0, 38475, 0, 38477, 0, 38517, 0, 38520, 0, 38524, 0, 38534, 0, 38563, 0, 38582, 0, 38584, 0, 38585, 0, 38626, 0, 38627, 0, 38632, 0, 38646, 0, 38647, 0, 38706, 0, 38728, 0, 38737, 0, 38742, 0, 38750, 0, 38754, 0, 38761, 0, 38859, 0, 38875, 0, 38893, 0, 38899, 0, 38911, 0, 38913, 0, 38917, 0, 38923, 0, 38936, 0, 38971, 0, 39006, 0, 39080, 0, 39131, 0, 39135, 0, 39151, 0, 39164, 0, 39208, 0, 39318, 0, 39321, 0, 39340, 0, 39409, 0, 39530, 0, 39592, 0, 39640, 0, 39647, 0, 39698, 0, 39717, 0, 39727, 0, 39730, 0, 39740, 0, 39770, 0, 39791, 0, 40023, 0, 40165, 0, 40372, 0, 40442, 0, 40478, 0, 40565, 0, 40575, 0, 40599, 0, 40607, 0, 40613, 0, 40635, 0, 40643, 0, 40653, 0, 40654, 0, 40657, 0, 40697, 0, 40701, 0, 40718, 0, 40723, 0, 40736, 0, 40763, 0, 40771, 0, 40778, 0, 40786, 0, 40845, 0, 40846, 0, 40860, 0, 40863, 0, 40864, 0, 42863, 0, 64329, 1473, 0, 64329, 1474, 0, 141380, 0, 141386, 0, 144341, 0, 152137, 0, 154832, 0, 163539, 0, 0 }; static const uint16_t charMapIndex[] = { 8599, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 21, 0, 2004, 0, 0, 0, 0, 9, 0, 0, 841, 957, 3, 3699, 0, 0, 36, 638, 2610, 0, 816, 808, 1000, 0, 1199, 1202, 1205, 1208, 1220, 1226, 0, 1283, 1325, 1328, 1331, 1346, 1475, 1478, 1481, 1496, 0, 1632, 1655, 1658, 1661, 1664, 1676, 0, 0, 1824, 1827, 1830, 1842, 1948, 0, 0, 2022, 2025, 2028, 2031, 2043, 2049, 0, 2128, 2186, 2189, 2192, 2207, 2343, 2346, 2349, 2361, 0, 2589, 2615, 2618, 2621, 2624, 2636, 0, 0, 2796, 2799, 2802, 2814, 2916, 0, 2931, 1211, 2034, 1214, 2037, 1244, 2067, 1271, 2116, 1274, 2119, 1277, 2122, 1280, 2125, 1308, 2159, 0, 0, 1337, 2198, 1340, 2201, 1343, 2204, 1367, 2228, 1352, 2213, 1404, 2271, 1410, 2277, 1413, 2280, 1419, 2286, 1433, 2298, 0, 0, 1484, 2352, 1487, 2355, 1490, 2358, 1514, 2379, 1493, 0, 1463, 2331, 1522, 2387, 1545, 2443, 0, 1566, 2476, 1575, 2485, 1569, 2479, 1563, 2473, 0, 0, 1629, 2586, 1644, 2601, 1638, 2595, 3432, 0, 0, 1667, 2627, 1670, 2630, 1682, 2642, 0, 0, 1735, 2715, 1753, 2733, 1741, 2721, 1767, 2747, 1770, 2750, 1785, 2765, 1776, 2756, 1813, 2785, 1804, 2776, 0, 0, 1833, 2805, 1836, 2808, 1839, 2811, 1848, 2820, 1851, 2823, 1872, 2844, 1916, 2881, 1951, 2919, 1963, 1974, 2945, 1980, 2951, 1983, 2954, 2739, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1694, 2654, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1863, 2835, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1299, 1302, 2153, 1553, 1560, 2457, 1617, 1620, 2574, 1229, 2052, 1502, 2367, 1685, 2645, 1854, 2826, 3081, 3164, 3078, 3161, 3084, 3167, 3075, 3158, 0, 3014, 3099, 3329, 3332, 3027, 3108, 0, 0, 1416, 2283, 1539, 2437, 1700, 2660, 3321, 3324, 3318, 3421, 2390, 1293, 1296, 2150, 1401, 2268, 0, 0, 1626, 2583, 3019, 3102, 3024, 3105, 3072, 3155, 1232, 2055, 1235, 2058, 1355, 2216, 1358, 2219, 1505, 2370, 1508, 2373, 1688, 2648, 1691, 2651, 1744, 2724, 1747, 2727, 1857, 2829, 1860, 2832, 1782, 2762, 1810, 2782, 0, 0, 1442, 2307, 0, 0, 0, 0, 0, 0, 1217, 2040, 1364, 2225, 3069, 3152, 3063, 3146, 1673, 2633, 3341, 3344, 1957, 2925, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2289, 3371, 2385, 2696, 3397, 3399, 3401, 2873, 2911, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 18, 24, 39, 6, 27, 0, 0, 3367, 2455, 2739, 2896, 3424, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3435, 3437, 0, 3442, 3439, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3430, 0, 0, 0, 0, 0, 48, 0, 0, 0, 1160, 0, 0, 0, 0, 0, 3, 2982, 3465, 3000, 3488, 3500, 3517, 0, 3538, 0, 3559, 3579, 3798, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3526, 3568, 3610, 3642, 3654, 3676, 3807, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3685, 3761, 3728, 3752, 3780, 0, 3631, 3669, 3554, 3822, 3825, 3773, 3737, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3697, 3739, 3747, 0, 3512, 3637, 0, 0, 0, 3552, 0, 0, 0, 0, 0, 0, 3840, 3846, 0, 3837, 0, 0, 0, 3828, 0, 0, 0, 0, 3870, 3858, 3879, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3864, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3930, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3906, 3912, 0, 3903, 0, 0, 0, 3965, 0, 0, 0, 0, 3936, 3924, 3947, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3968, 3971, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3849, 3915, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3831, 3897, 3834, 3900, 0, 0, 3843, 3909, 0, 0, 3974, 3977, 3852, 3918, 3855, 3921, 0, 0, 3861, 3927, 3867, 3933, 3873, 3941, 0, 0, 3980, 3983, 3894, 3962, 3876, 3944, 3882, 3950, 3885, 3953, 3888, 3956, 0, 0, 3891, 3959, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3986, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4203, 4206, 5137, 4209, 5196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4212, 5140, 5271, 5199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5291, 0, 5262, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5286, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5312, 0, 0, 0, 0, 0, 0, 0, 5321, 0, 0, 5324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5294, 5297, 5300, 5303, 5306, 5309, 5315, 5318, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5336, 5339, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5327, 5330, 0, 5333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5354, 0, 0, 5357, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5342, 5345, 5348, 0, 0, 5351, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5369, 0, 0, 5366, 5372, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5360, 5363, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5375, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5378, 5384, 5381, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5387, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5390, 0, 0, 0, 0, 0, 0, 5396, 5399, 0, 5393, 5402, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5405, 5411, 5408, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5414, 0, 5417, 5423, 5420, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5435, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5429, 5432, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5438, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5446, 0, 0, 0, 0, 5449, 0, 0, 0, 0, 5452, 0, 0, 0, 0, 5455, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5458, 0, 5461, 5485, 5488, 5491, 5494, 0, 0, 0, 0, 0, 0, 0, 5464, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5470, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5473, 0, 0, 0, 0, 5476, 0, 0, 0, 0, 5479, 0, 0, 0, 0, 5482, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5467, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1194, 3022, 1251, 0, 1291, 1323, 3252, 1385, 1422, 1454, 1520, 1525, 1551, 1584, 1615, 0, 1653, 3327, 1703, 1730, 1788, 1822, 1905, 2004, 3347, 3349, 5779, 2070, 2131, 2177, 3357, 3359, 3361, 2262, 0, 2393, 2494, 3208, 2610, 3353, 5781, 5783, 2663, 2768, 2794, 5787, 3381, 2853, 5789, 3631, 3633, 3635, 3773, 3775, 2322, 2696, 2794, 2853, 3631, 3633, 3739, 3773, 3775, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3939, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3351, 2085, 3355, 3129, 3361, 2237, 3363, 3365, 3369, 3373, 3375, 3377, 5791, 3426, 3379, 5793, 3428, 3385, 3383, 3387, 3389, 3391, 3393, 3395, 3403, 3405, 3286, 3407, 3409, 5785, 3411, 3413, 2943, 3415, 3417, 3419, 3669, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1241, 2064, 1256, 2076, 1259, 2079, 1262, 2082, 3030, 3111, 1305, 2156, 1311, 2162, 1320, 2171, 1314, 2165, 1317, 2168, 3194, 3200, 3197, 3203, 1370, 2231, 1373, 2234, 3335, 3338, 1382, 2259, 1407, 2274, 1436, 2301, 1445, 2310, 1439, 2304, 1448, 2313, 1451, 2316, 1517, 2382, 3045, 3126, 1536, 2434, 1542, 2440, 1548, 2446, 1572, 2482, 5795, 5798, 1581, 2491, 1578, 2488, 1603, 2539, 1606, 2542, 1609, 2545, 1635, 2592, 1641, 2598, 1650, 2607, 1647, 2604, 3060, 3143, 3066, 3149, 3210, 3216, 3213, 3219, 1722, 2688, 1725, 2691, 1738, 2718, 1750, 2730, 5801, 5804, 1756, 2736, 1773, 2753, 1779, 2759, 3222, 3225, 3228, 3231, 5807, 5810, 1801, 2770, 1807, 2779, 1819, 2791, 1816, 2788, 1869, 2841, 1878, 2850, 1875, 2847, 3234, 3237, 3240, 3243, 1895, 2867, 1898, 2870, 1910, 2875, 1913, 2878, 1922, 2887, 1919, 2884, 1925, 2893, 1937, 2905, 1940, 2908, 1960, 2928, 1977, 2948, 1986, 2957, 1989, 2960, 2319, 2773, 2890, 2937, 2019, 3249, 0, 0, 0, 0, 1238, 2061, 1223, 2046, 3005, 3090, 3002, 3087, 3011, 3096, 3008, 3093, 5813, 5819, 3173, 3185, 3170, 3182, 3179, 3191, 3176, 3188, 5816, 5822, 1361, 2222, 1349, 2210, 1334, 2195, 3036, 3117, 3033, 3114, 3042, 3123, 3039, 3120, 5825, 5828, 1499, 2364, 1511, 2376, 1697, 2657, 1679, 2639, 3051, 3134, 3048, 3131, 3057, 3140, 3054, 3137, 5831, 5834, 3259, 3274, 3256, 3271, 3265, 3280, 3262, 3277, 3268, 3283, 1866, 2838, 1845, 2817, 3291, 3306, 3288, 3303, 3297, 3312, 3294, 3309, 3300, 3315, 1945, 2913, 1969, 2940, 1966, 2934, 1954, 2922, 0, 0, 0, 0, 0, 0, 3619, 3622, 5837, 5849, 5840, 5852, 5843, 5855, 3474, 3477, 5879, 5891, 5882, 5894, 5885, 5897, 3645, 3648, 5921, 5927, 5924, 5930, 0, 0, 3491, 3494, 5933, 5939, 5936, 5942, 0, 0, 3657, 3660, 5945, 5957, 5948, 5960, 5951, 5963, 3503, 3506, 5987, 5999, 5990, 6002, 5993, 6005, 3688, 3691, 6029, 6038, 6032, 6041, 6035, 6044, 3529, 3532, 6047, 6056, 6050, 6059, 6053, 6062, 3731, 3734, 6065, 6071, 6068, 6074, 0, 0, 3541, 3544, 6077, 6083, 6080, 6086, 0, 0, 3764, 3767, 6089, 6098, 6092, 6101, 6095, 6104, 0, 3571, 0, 6107, 0, 6110, 0, 6113, 3783, 3786, 6116, 6128, 6119, 6131, 6122, 6134, 3582, 3585, 6158, 6170, 6161, 6173, 6164, 6176, 3607, 3591, 3639, 3596, 3651, 3598, 3673, 3603, 3725, 3813, 3749, 3815, 3777, 3817, 0, 0, 5846, 5858, 5861, 5864, 5867, 5870, 5873, 5876, 5888, 5900, 5903, 5906, 5909, 5912, 5915, 5918, 5954, 5966, 5969, 5972, 5975, 5978, 5981, 5984, 5996, 6008, 6011, 6014, 6017, 6020, 6023, 6026, 6125, 6137, 6140, 6143, 6146, 6149, 6152, 6155, 6167, 6179, 6182, 6185, 6188, 6191, 6194, 6197, 3616, 3613, 6200, 3628, 3593, 0, 3625, 6209, 3471, 3468, 3462, 3446, 3480, 30, 3671, 30, 45, 2985, 6203, 3666, 3600, 0, 3663, 6221, 3485, 3448, 3497, 3450, 3509, 6212, 6215, 6218, 3682, 3679, 3795, 3460, 0, 0, 3694, 3801, 3523, 3520, 3514, 3452, 0, 6227, 6230, 6233, 3758, 3755, 3804, 3605, 3741, 3744, 3770, 3810, 3565, 3562, 3556, 3456, 3549, 2979, 3444, 2002, 0, 0, 6206, 3792, 3819, 0, 3789, 6224, 3535, 3454, 3576, 3458, 3588, 2998, 33, 0, 6236, 6238, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 6240, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 622, 624, 627, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 6250, 6253, 0, 6262, 6265, 0, 0, 0, 0, 107, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 1189, 1186, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6257, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 633, 2322, 0, 0, 1021, 1069, 1094, 1108, 1126, 1140, 616, 6310, 1167, 125, 612, 2560, 633, 638, 841, 957, 1021, 1069, 1094, 1108, 1126, 1140, 616, 6310, 1167, 125, 612, 0, 2004, 2177, 2610, 2896, 3357, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1732, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2011, 2015, 1265, 2992, 0, 2087, 2091, 3254, 0, 2995, 2262, 1422, 1422, 1422, 2289, 3206, 1454, 1454, 1551, 2455, 0, 1615, 1623, 0, 0, 1703, 1728, 1730, 1730, 1730, 0, 0, 1761, 1790, 1798, 0, 1972, 0, 3574, 0, 1972, 0, 1525, 3017, 1251, 1265, 0, 2177, 1323, 1376, 0, 1584, 2610, 4004, 4018, 4026, 4031, 2322, 0, 1378, 3737, 3633, 3483, 3547, 6308, 0, 0, 0, 0, 1291, 2131, 2177, 2322, 2385, 0, 0, 0, 0, 0, 0, 0, 0, 0, 812, 940, 820, 944, 1004, 1056, 824, 1077, 828, 1008, 1081, 1113, 805, 1454, 1456, 1459, 1469, 1881, 1883, 1886, 1890, 1472, 1928, 1930, 1933, 1551, 1265, 1291, 1584, 2322, 2324, 2327, 2337, 2853, 2855, 2858, 2862, 2340, 2896, 2898, 2901, 2455, 2085, 2131, 2494, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6275, 6282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6290, 6296, 6293, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6299, 0, 0, 0, 0, 6302, 0, 0, 6305, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6312, 0, 6315, 0, 0, 0, 0, 0, 6318, 6321, 0, 6330, 6333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6337, 0, 0, 6340, 0, 0, 6343, 0, 6346, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1176, 0, 6352, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6349, 1164, 1181, 6355, 6358, 0, 0, 6361, 6364, 0, 0, 6367, 6370, 0, 0, 0, 0, 0, 0, 6373, 6376, 0, 0, 6385, 6388, 0, 0, 6391, 6394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6403, 6406, 6409, 6412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6379, 6382, 6397, 6400, 0, 0, 0, 0, 0, 0, 6415, 6418, 6421, 6424, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6446, 6448, 0, 0, 0, 0, 0, 638, 841, 957, 1021, 1069, 1094, 1108, 1126, 1140, 643, 662, 681, 700, 715, 730, 745, 760, 775, 790, 846, 127, 181, 190, 194, 198, 202, 206, 210, 214, 131, 136, 141, 146, 151, 156, 161, 166, 171, 176, 185, 640, 843, 959, 1023, 1071, 1096, 1110, 1128, 1142, 646, 665, 684, 703, 718, 733, 748, 763, 778, 793, 849, 218, 222, 226, 230, 234, 238, 242, 246, 250, 254, 258, 262, 266, 270, 274, 278, 282, 286, 290, 294, 298, 302, 306, 310, 314, 318, 1194, 1251, 1265, 1291, 1323, 1376, 1385, 1422, 1454, 1520, 1525, 1551, 1584, 1615, 1653, 1703, 1728, 1730, 1759, 1788, 1822, 1881, 1905, 1928, 1943, 1972, 2004, 2070, 2085, 2131, 2177, 2237, 2262, 2289, 2322, 2385, 2393, 2455, 2494, 2560, 2610, 2663, 2694, 2696, 2739, 2768, 2794, 2853, 2873, 2896, 2911, 2943, 633, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1156, 1169, 1172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6437, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7833, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8595, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7278, 7296, 7302, 7306, 7308, 7314, 7318, 7322, 7326, 7354, 7362, 7368, 7374, 7376, 7380, 7394, 7396, 7398, 7410, 7428, 7432, 7436, 7438, 7444, 7454, 7456, 7462, 7464, 7468, 7470, 7502, 7508, 7526, 7528, 7530, 7532, 7536, 7551, 7557, 7561, 7571, 7573, 7575, 7577, 7587, 7589, 7597, 7599, 7603, 7605, 7607, 7614, 7616, 7632, 7634, 7638, 7640, 7642, 7644, 7648, 7656, 7690, 7696, 7698, 7722, 7724, 7732, 7734, 7738, 7740, 7744, 7748, 7768, 7772, 7780, 7815, 7817, 7823, 7827, 7831, 7835, 7837, 7839, 7841, 7843, 7893, 7913, 7919, 7921, 7923, 7925, 7927, 7929, 7935, 7947, 7951, 7971, 7973, 7977, 7979, 7981, 7983, 7997, 7999, 8011, 8013, 8015, 8017, 8027, 8039, 8041, 8043, 8059, 8089, 8091, 8101, 8107, 8109, 8119, 8131, 8153, 8157, 8165, 8169, 8171, 8175, 8177, 8179, 8187, 8189, 8195, 8199, 8203, 8205, 8207, 8209, 8211, 8213, 8217, 8219, 8257, 8261, 8269, 8271, 8273, 8289, 8293, 8297, 8299, 8327, 8329, 8333, 8335, 8337, 8351, 8353, 8355, 8359, 8361, 8373, 8375, 8377, 8393, 8399, 8407, 8409, 8413, 8423, 8425, 8429, 8447, 8451, 8457, 8467, 8471, 8473, 8475, 8477, 8481, 8483, 8487, 8499, 8501, 8503, 8511, 8513, 8515, 8521, 8523, 8525, 8529, 8531, 8533, 8535, 8537, 8543, 8551, 8553, 8559, 8561, 8563, 8565, 8569, 8571, 8573, 8575, 8577, 8579, 8581, 8585, 8587, 8589, 8593, 8597, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6466, 0, 7444, 7446, 7448, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6479, 0, 6482, 0, 6485, 0, 6488, 0, 6491, 0, 6494, 0, 6497, 0, 6500, 0, 6503, 0, 6506, 0, 6509, 0, 6512, 0, 0, 6515, 0, 6518, 0, 6521, 0, 0, 0, 0, 0, 0, 6524, 6527, 0, 6530, 6533, 0, 6536, 6539, 0, 6542, 6545, 0, 6548, 6551, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6476, 0, 0, 0, 0, 0, 0, 99, 102, 0, 6561, 6554, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6640, 0, 6667, 0, 6711, 0, 6737, 0, 6746, 0, 6762, 0, 6778, 0, 6788, 0, 6793, 0, 6806, 0, 6811, 0, 6820, 0, 0, 6827, 0, 6832, 0, 6840, 0, 0, 0, 0, 0, 0, 6868, 6871, 0, 6895, 6898, 0, 6919, 6922, 0, 6948, 6951, 0, 6985, 6988, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6604, 0, 0, 7137, 7146, 7151, 7156, 0, 0, 0, 7165, 6749, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5502, 5507, 5706, 5509, 5708, 5710, 5514, 5519, 5521, 5712, 5714, 5716, 5718, 5720, 5722, 5600, 5526, 5531, 5536, 5610, 5538, 5543, 5545, 5553, 5563, 5565, 5576, 5581, 5586, 5591, 5648, 5650, 5652, 5654, 5656, 5658, 5660, 5662, 5664, 5666, 5668, 5670, 5672, 5674, 5676, 5678, 5680, 5682, 5684, 5686, 5688, 5646, 5596, 5598, 5724, 5726, 5728, 5730, 5732, 5734, 5736, 5602, 5738, 5740, 5604, 5606, 5608, 5612, 5614, 5616, 5618, 5620, 5622, 5624, 5626, 5628, 5630, 5632, 5634, 5636, 5638, 5742, 5744, 5640, 5642, 5644, 5690, 5692, 5694, 5696, 5698, 5700, 5702, 5704, 0, 0, 0, 7278, 7318, 7284, 7504, 7286, 7298, 7288, 7985, 7308, 7292, 7280, 7541, 7510, 7326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 322, 331, 340, 349, 358, 367, 376, 385, 409, 423, 432, 441, 450, 459, 326, 335, 344, 353, 362, 371, 380, 389, 413, 427, 436, 445, 454, 463, 418, 394, 402, 0, 468, 484, 476, 532, 488, 508, 472, 504, 480, 516, 548, 568, 564, 556, 608, 536, 544, 560, 552, 580, 524, 572, 600, 584, 512, 492, 528, 540, 576, 496, 604, 520, 588, 500, 592, 596, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1715, 861, 872, 883, 894, 905, 912, 919, 926, 933, 962, 969, 976, 979, 982, 985, 5502, 5509, 5514, 5521, 5526, 5531, 5538, 5545, 5553, 5565, 5576, 5581, 5586, 5591, 5504, 5511, 5516, 5523, 5528, 5533, 5540, 5547, 5555, 5567, 5578, 5583, 5588, 5593, 5570, 5558, 5550, 0, 7278, 7318, 7284, 7504, 7320, 7370, 7282, 7368, 7310, 7444, 7772, 7893, 7843, 7780, 8413, 7508, 7748, 7794, 7774, 8063, 7476, 7933, 8339, 8073, 7414, 8095, 7987, 7551, 8385, 7352, 7458, 7851, 8489, 7334, 7378, 7819, 7286, 7298, 7288, 7601, 7474, 7440, 7565, 7559, 8023, 7332, 8343, 7452, 7534, 988, 991, 994, 997, 1026, 1029, 1032, 1035, 1038, 1041, 1044, 1047, 1050, 1053, 1074, 835, 951, 1015, 1063, 1088, 1102, 1120, 1134, 1148, 654, 673, 692, 1427, 2182, 2179, 1556, 6566, 6589, 6602, 6613, 6628, 6638, 6665, 6709, 6735, 6744, 6760, 6776, 6786, 6791, 6804, 6809, 6818, 6825, 6830, 6838, 6849, 6854, 6856, 6858, 6860, 6866, 6893, 6917, 6946, 6983, 7015, 7040, 7056, 7058, 7073, 7077, 7089, 7097, 7099, 7101, 7111, 7122, 7133, 7135, 7144, 7149, 7154, 0, 6568, 6573, 6578, 6583, 6591, 6596, 6607, 6615, 6621, 6630, 6634, 6643, 6647, 6652, 6657, 6661, 6697, 6700, 6670, 6704, 6675, 6678, 6684, 6691, 6725, 6729, 6714, 6720, 6740, 6752, 6756, 6765, 6770, 6781, 6796, 6800, 6814, 6835, 6846, 6843, 6851, 6862, 6874, 6883, 6889, 6878, 6904, 6910, 6914, 6901, 6925, 6931, 6940, 6936, 6954, 6968, 6971, 6960, 6975, 6979, 6964, 7006, 7002, 6991, 7011, 6994, 6998, 7017, 7022, 7026, 7030, 7034, 7042, 7047, 7050, 7060, 7063, 7068, 7079, 7083, 7091, 7103, 7108, 7113, 7117, 7124, 7127, 7140, 635, 838, 954, 1018, 1066, 1091, 1105, 1123, 1137, 1151, 658, 677, 696, 711, 726, 741, 756, 771, 786, 801, 857, 868, 879, 890, 901, 2291, 2136, 1196, 2072, 2612, 2682, 2139, 2142, 2146, 1466, 7609, 7755, 7538, 7750, 7796, 2670, 2562, 3701, 2496, 2395, 1527, 1586, 1387, 2095, 2412, 2673, 2565, 3704, 3713, 2508, 2417, 1430, 2398, 1589, 1390, 1794, 3722, 2548, 2174, 2452, 2256, 2577, 3716, 2515, 2105, 2420, 2518, 2108, 2533, 2423, 2522, 2112, 2536, 2427, 2551, 2555, 1719, 2402, 1593, 1394, 2698, 2702, 2708, 2685, 2580, 3719, 2530, 2676, 2568, 3707, 2499, 2406, 1597, 2679, 2571, 3710, 2502, 2409, 1600, 2449, 1612, 2006, 1253, 2099, 2102, 1286, 1267, 2133, 1398, 2295, 1424, 2334, 1530, 1533, 2431, 2460, 2463, 2466, 2470, 2505, 2511, 2526, 1705, 2665, 1708, 1712, 2741, 1764, 1907, 1901, 1247, 832, 948, 1012, 1060, 1085, 1099, 1117, 1131, 1145, 650, 669, 688, 707, 722, 737, 752, 767, 782, 797, 853, 864, 875, 886, 897, 908, 915, 922, 929, 936, 965, 972, 2264, 8331, 7770, 8361, 8345, 7877, 7300, 7472, 8593, 8593, 7547, 8413, 7488, 7545, 7686, 8009, 8163, 8255, 8265, 8281, 8391, 7807, 7853, 7899, 7955, 8235, 8401, 8517, 7312, 7460, 7813, 7911, 8253, 8549, 7593, 7887, 8245, 8287, 7700, 8193, 8267, 7622, 7776, 7859, 7941, 8395, 7338, 7384, 7422, 7720, 7811, 7909, 8025, 8171, 8249, 8259, 8357, 8463, 8539, 8547, 8047, 8079, 8141, 8229, 8419, 8553, 8309, 7524, 7636, 8117, 8185, 7931, 8051, 8341, 8461, 7522, 7581, 7809, 7865, 7881, 8137, 8149, 8433, 7420, 8191, 7390, 7388, 8097, 8143, 8233, 8437, 8323, 7702, 7807, 8315, 7304, 7567, 7660, 7949, 7995, 7434, 8055, 7344, 7652, 7290, 7847, 7730, 8135, 7466, 7516, 8031, 8237, 8301, 7829, 8375, 7845, 7706, 8223, 7710, 7993, 7324, 7366, 7386, 7801, 8129, 8215, 8307, 8411, 7426, 7482, 7551, 7630, 7742, 7889, 8057, 8427, 8519, 8555, 8567, 7410, 7766, 7821, 8371, 7612, 7682, 7688, 7718, 7885, 7901, 7967, 8093, 8145, 8183, 8363, 8241, 8381, 8421, 7402, 7412, 7484, 7897, 8275, 8301, 7620, 7658, 7708, 7825, 8115, 7945, 7330, 7506, 7567, 7595, 7662, 7953, 7963, 8167, 8181, 8415, 8459, 8465, 8493, 7340, 8087, 8405, 8449, 7668, 7316, 7348, 7569, 7579, 7736, 7807, 7905, 8007, 8243, 8389, 8589, 7760, 8431, 7408, 7786, 7790, 7857, 7871, 7959, 7991, 8045, 8133, 8497, 7370, 7692, 8439, 7346, 7591, 7867, 8365, 7650, 7672, 7792, 7949, 8443, 7404, 7478, 7585, 7753, 7782, 7805, 7849, 7957, 8001, 8161, 8277, 8279, 8409, 8453, 7442, 7873, 7480, 7907, 7969, 8247, 8445, 8541, 8557, 7788, 7863, 8197, 8107, 8111, 8123, 7939, 7895, 8321, 7328, 8225, 7406, 7400, 7618, 7704, 8127, 7563, 7855, 7764, 8369, 8271, 8435, 8293, 7626, 7356, 7494, 0, 0, 7514, 0, 7758, 0, 0, 7392, 7943, 8019, 8061, 8075, 8077, 8085, 8469, 8125, 8169, 0, 8251, 0, 8313, 0, 0, 8383, 8397, 0, 0, 0, 8505, 8507, 8509, 8545, 0, 0, 7342, 7350, 7360, 7418, 7424, 7450, 7492, 7498, 7500, 7512, 7518, 7583, 7587, 7664, 7678, 7680, 7684, 7726, 7746, 7762, 7803, 7861, 7869, 7883, 7903, 7915, 7961, 8049, 8063, 8067, 8065, 8069, 8071, 8073, 8081, 8083, 8099, 8103, 8113, 8145, 8147, 8151, 8159, 8173, 8201, 8221, 8221, 8239, 8283, 8295, 8317, 8319, 8347, 8349, 8379, 8383, 8455, 8485, 8495, 0, 0, 0, 0, 0, 7294, 7382, 7364, 7336, 7358, 7372, 7416, 7430, 7492, 7486, 7490, 7496, 7514, 7520, 7543, 7549, 7553, 7555, 7624, 7628, 7646, 7654, 7666, 7674, 7670, 7680, 7676, 7684, 7694, 7712, 7714, 7716, 7728, 7758, 7776, 7778, 7784, 7823, 7829, 7857, 7879, 7875, 7883, 7891, 7903, 8037, 7917, 7937, 7943, 7965, 7975, 7989, 8003, 8005, 8019, 8021, 8029, 8035, 8033, 8053, 8105, 8113, 8121, 8139, 8145, 8155, 8173, 8227, 8231, 8263, 8285, 8291, 8295, 8303, 8313, 8305, 8317, 8315, 8311, 8319, 8325, 8349, 8367, 8387, 8403, 8417, 8441, 8455, 8469, 8479, 8485, 8491, 8495, 8527, 8593, 8609, 8607, 8611, 7272, 7274, 7276, 8613, 8615, 8617, 8583, 8591, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2239, 2250, 2253, 2242, 2246, 3246, 2744, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3998, 3989, 3992, 4001, 3995, 0, 0, 0, 0, 0, 4053, 0, 4122, 4086, 4004, 4031, 4036, 4062, 4070, 4075, 4103, 4117, 616, 4111, 4114, 8601, 8604, 4006, 4009, 4012, 4020, 4028, 4033, 4038, 4044, 4047, 0, 4050, 4056, 4059, 4064, 4072, 0, 4077, 0, 4080, 4083, 0, 4088, 4091, 0, 4097, 4100, 4105, 4108, 4119, 4041, 4023, 4067, 4094, 4015, 5202, 5202, 5210, 5210, 5210, 5210, 5212, 5212, 5212, 5212, 5216, 5216, 5216, 5216, 5208, 5208, 5208, 5208, 5214, 5214, 5214, 5214, 5206, 5206, 5206, 5206, 5238, 5238, 5238, 5238, 5240, 5240, 5240, 5240, 5220, 5220, 5220, 5220, 5218, 5218, 5218, 5218, 5222, 5222, 5222, 5222, 5224, 5224, 5224, 5224, 5230, 5230, 5228, 5228, 5232, 5232, 5226, 5226, 5236, 5236, 5234, 5234, 5242, 5242, 5242, 5242, 5246, 5246, 5246, 5246, 5250, 5250, 5250, 5250, 5248, 5248, 5248, 5248, 5252, 5252, 5254, 5254, 5254, 5254, 5258, 5258, 5260, 5260, 5260, 5260, 5256, 5256, 5256, 5256, 5284, 5284, 5289, 5289, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5244, 5244, 5244, 5244, 5269, 5269, 5267, 5267, 5274, 5274, 5204, 5278, 5278, 5265, 5265, 5276, 5276, 5282, 5282, 5282, 5282, 5143, 5143, 4137, 4137, 4185, 4185, 4164, 4164, 4176, 4176, 4173, 4173, 4179, 4179, 4182, 4182, 4182, 4167, 4167, 4167, 5280, 5280, 5280, 5280, 4140, 4143, 4155, 4167, 4170, 4217, 4220, 4227, 4240, 4249, 4252, 4259, 4274, 4285, 4306, 4335, 4338, 4343, 4352, 4361, 4364, 4369, 4389, 4412, 4419, 4438, 4441, 4444, 4479, 4490, 4497, 4511, 4583, 4632, 4647, 4650, 4661, 4671, 4682, 4685, 4708, 4713, 4725, 4748, 4751, 4804, 4807, 4810, 4817, 4824, 4827, 4832, 4839, 4854, 4857, 4862, 4865, 4868, 4871, 4874, 4877, 4888, 4891, 4908, 4923, 4938, 4945, 4959, 4962, 4970, 4989, 5009, 5024, 5031, 5034, 5039, 5058, 5073, 5082, 5099, 5102, 5107, 5110, 5121, 5124, 5150, 5157, 5164, 5173, 5190, 5193, 4457, 4467, 5145, 57, 64, 71, 78, 85, 92, 4149, 4152, 4155, 4158, 4167, 4170, 4234, 4237, 4240, 4243, 4249, 4252, 4300, 4303, 4306, 4329, 4335, 4338, 4346, 4349, 4352, 4355, 4361, 4364, 4824, 4827, 4854, 4857, 4862, 4874, 4877, 4888, 4891, 4945, 4959, 4962, 4967, 5024, 5076, 5079, 5082, 5093, 5099, 5102, 5145, 5167, 5170, 5173, 5184, 5190, 5193, 4140, 4143, 4146, 4155, 4161, 4217, 4220, 4227, 4240, 4246, 4259, 4274, 4285, 4306, 4332, 4352, 4369, 4389, 4412, 4419, 4438, 4444, 4479, 4490, 4497, 4511, 4583, 4594, 4632, 4647, 4650, 4661, 4671, 4682, 4708, 4713, 4725, 4748, 4751, 4804, 4807, 4810, 4817, 4832, 4839, 4865, 4868, 4871, 4874, 4877, 4908, 4923, 4938, 4945, 4956, 4970, 4989, 5009, 5024, 5039, 5058, 5073, 5082, 5096, 5107, 5110, 5127, 5150, 5157, 5164, 5173, 5187, 4155, 4161, 4240, 4246, 4306, 4332, 4352, 4358, 4511, 4526, 4561, 4572, 4874, 4877, 4945, 5082, 5096, 5173, 5187, 4778, 4785, 4792, 4700, 4703, 4740, 4743, 4766, 4769, 4529, 4532, 4575, 4578, 4430, 4433, 4404, 4407, 4447, 4450, 4639, 4642, 4674, 4677, 4537, 4544, 4555, 4561, 4558, 4508, 4597, 4668, 4700, 4703, 4740, 4743, 4766, 4769, 4529, 4532, 4575, 4578, 4430, 4433, 4404, 4407, 4447, 4450, 4639, 4642, 4674, 4677, 4537, 4544, 4555, 4561, 4558, 4508, 4597, 4668, 4537, 4544, 4555, 4561, 4526, 4572, 4685, 4479, 4490, 4497, 4537, 4544, 4555, 4685, 4708, 4200, 4200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4262, 4277, 4277, 4281, 4288, 4309, 4313, 4317, 4392, 4392, 4426, 4422, 4493, 4482, 4486, 4518, 4518, 4514, 4522, 4522, 4586, 4586, 4635, 4547, 4547, 4540, 4564, 4564, 4568, 4568, 4653, 4664, 4664, 4688, 4688, 4692, 4696, 4716, 4728, 4728, 4732, 4754, 4762, 4758, 4813, 4813, 4842, 4846, 4926, 4934, 4930, 4911, 4911, 4941, 4941, 4948, 4948, 4992, 4996, 5005, 4973, 4981, 5012, 5016, 0, 0, 4977, 5113, 5117, 5061, 5065, 5046, 5046, 5050, 5089, 5085, 5176, 5176, 4230, 4270, 4266, 4296, 4292, 4325, 4321, 4400, 4372, 4396, 4500, 4590, 4551, 4657, 4919, 4952, 5160, 5153, 5180, 5027, 4850, 5069, 4842, 4926, 4736, 4884, 5042, 5020, 4915, 4880, 4915, 5042, 4376, 4415, 4985, 4820, 4223, 4880, 4716, 4635, 4504, 5054, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4628, 4835, 4195, 4190, 5000, 4600, 4462, 4720, 5132, 4605, 4609, 4380, 4470, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 618, 6442, 6444, 1154, 1160, 105, 1184, 6472, 6474, 6248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6246, 6244, 6242, 2000, 2000, 125, 612, 2963, 2967, 6468, 6470, 6462, 6464, 6450, 6452, 6446, 6448, 6454, 6456, 6458, 6460, 0, 0, 1992, 1996, 6269, 6269, 6269, 6269, 2000, 2000, 2000, 618, 6442, 622, 0, 1160, 1154, 1184, 105, 6244, 125, 612, 2963, 2967, 6468, 6470, 115, 121, 614, 616, 620, 1162, 1179, 1167, 0, 1994, 117, 119, 1192, 0, 0, 0, 0, 51, 4772, 54, 0, 61, 0, 68, 4775, 75, 4782, 82, 4789, 89, 4796, 96, 4799, 4125, 4127, 4127, 4129, 4129, 4131, 4131, 4133, 4133, 4135, 4135, 4135, 4135, 4188, 4188, 4215, 4215, 4215, 4215, 4255, 4255, 4257, 4257, 4257, 4257, 4341, 4341, 4341, 4341, 4367, 4367, 4367, 4367, 4410, 4410, 4410, 4410, 4436, 4436, 4436, 4436, 4453, 4453, 4455, 4455, 4460, 4460, 4475, 4475, 4477, 4477, 4477, 4477, 4535, 4535, 4535, 4535, 4581, 4581, 4581, 4581, 4645, 4645, 4645, 4645, 4680, 4680, 4680, 4680, 4706, 4706, 4706, 4706, 4711, 4711, 4711, 4711, 4746, 4746, 4746, 4746, 4802, 4802, 4802, 4802, 4830, 4830, 4830, 4830, 4860, 4860, 4860, 4860, 4894, 4894, 4894, 4894, 4965, 4965, 4965, 4965, 5037, 5037, 5037, 5037, 5105, 5105, 5105, 5105, 5130, 5130, 5143, 5143, 5148, 5148, 5148, 5148, 4896, 4896, 4899, 4899, 4902, 4902, 4905, 4905, 0, 0, 0, 0, 105, 113, 115, 117, 119, 121, 123, 125, 612, 614, 616, 618, 620, 622, 631, 633, 638, 841, 957, 1021, 1069, 1094, 1108, 1126, 1140, 1154, 1160, 1162, 1167, 1179, 1184, 1192, 1194, 1251, 1265, 1291, 1323, 1376, 1385, 1422, 1454, 1520, 1525, 1551, 1584, 1615, 1653, 1703, 1728, 1730, 1759, 1788, 1822, 1881, 1905, 1928, 1943, 1972, 1992, 1994, 1996, 1998, 2000, 2002, 2004, 2070, 2085, 2131, 2177, 2237, 2262, 2289, 2322, 2385, 2393, 2455, 2494, 2560, 2610, 2663, 2694, 2696, 2739, 2768, 2794, 2853, 2873, 2896, 2911, 2943, 2963, 2965, 2967, 2969, 6433, 6435, 6444, 6454, 6456, 6442, 7161, 7154, 6564, 6587, 6600, 6611, 6626, 7075, 7087, 7095, 6823, 7163, 6566, 6589, 6602, 6613, 6628, 6638, 6665, 6709, 6735, 6744, 6760, 6776, 6786, 6791, 6804, 6809, 6818, 6825, 6830, 6838, 6849, 6854, 6856, 6858, 6860, 6866, 6893, 6917, 6946, 6983, 7015, 7040, 7056, 7058, 7073, 7077, 7089, 7097, 7099, 7101, 7111, 7122, 7133, 7135, 7159, 6557, 6559, 7270, 7168, 7170, 7172, 7174, 7176, 7178, 7180, 7182, 7184, 7186, 7188, 7190, 7192, 7194, 7196, 7198, 7200, 7202, 7204, 7206, 7208, 7210, 7212, 7214, 7216, 7218, 7220, 7222, 7224, 7226, 0, 0, 0, 7228, 7230, 7232, 7234, 7236, 7238, 0, 0, 7240, 7242, 7244, 7246, 7248, 7250, 0, 0, 7252, 7254, 7256, 7258, 7260, 7262, 0, 0, 7264, 7266, 7268, 0, 0, 0, 2971, 2973, 2988, 2990, 2977, 2975, 6271, 0, 6427, 6273, 6278, 6280, 6285, 6429, 6431, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const uint16_t helperIndex[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1160, 1164, 1176, 1181, 0, 0, 1199, 1256, 1271, 1305, 1325, 1382, 1401, 1433, 1475, 1522, 1525, 1566, 1603, 1626, 1655, 1722, 0, 1735, 1767, 1801, 1824, 1895, 1910, 1937, 1945, 1974, 0, 0, 0, 0, 0, 2002, 2022, 2076, 2116, 2156, 2186, 2259, 2268, 2298, 2343, 2387, 2434, 2476, 2539, 2583, 2615, 2688, 0, 2715, 2747, 2770, 2796, 2867, 2875, 2905, 2913, 2945, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2979, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2998, 0, 0, 3000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3002, 0, 3014, 3017, 3024, 3030, 0, 0, 3033, 0, 0, 0, 0, 3045, 0, 0, 0, 0, 3048, 3060, 3069, 0, 3072, 0, 0, 0, 3075, 0, 0, 0, 0, 0, 3087, 0, 3099, 3102, 3105, 3111, 0, 0, 3114, 0, 0, 0, 0, 3126, 0, 0, 0, 0, 3131, 3143, 3152, 0, 3155, 0, 0, 0, 3158, 0, 0, 0, 0, 0, 3170, 3182, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3194, 3200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3210, 3216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3222, 3225, 0, 0, 0, 0, 3228, 3231, 0, 0, 0, 0, 0, 0, 3234, 3237, 3240, 3243, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3249, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3256, 3271, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3288, 3303, 0, 0, 0, 0, 0, 0, 3318, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3321, 3324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3329, 3332, 3335, 3338, 0, 0, 0, 0, 3341, 3344, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3421, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3430, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3435, 3437, 0, 0, 0, 0, 0, 0, 3439, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3442, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3444, 3446, 0, 3448, 3450, 3452, 0, 3454, 0, 3456, 3458, 3460, 3462, 0, 0, 0, 3485, 0, 3497, 0, 3514, 0, 0, 0, 0, 0, 3535, 0, 3549, 0, 0, 0, 3556, 0, 0, 0, 3574, 0, 0, 3591, 3596, 3598, 3603, 3605, 3607, 0, 0, 0, 3639, 0, 3651, 0, 3671, 0, 0, 0, 0, 0, 3725, 0, 3741, 0, 0, 0, 3749, 0, 0, 0, 3777, 3795, 3804, 3813, 3815, 3817, 0, 0, 0, 3822, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3828, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3831, 0, 0, 3837, 0, 3840, 3849, 3855, 3858, 0, 3870, 0, 0, 0, 3873, 0, 0, 0, 0, 3876, 0, 0, 0, 3888, 0, 0, 0, 3891, 0, 3894, 0, 0, 3897, 0, 0, 3903, 0, 3906, 3915, 3921, 3924, 0, 3936, 0, 0, 0, 3941, 0, 0, 0, 0, 3944, 0, 0, 0, 3956, 0, 0, 0, 3959, 0, 3962, 0, 0, 0, 0, 0, 0, 0, 0, 3965, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3968, 3971, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3974, 3977, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3980, 3983, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4006, 4020, 4028, 4033, 4038, 4041, 4047, 0, 4050, 4053, 4059, 4064, 4072, 0, 4077, 0, 4080, 4083, 0, 4088, 4091, 0, 4097, 4100, 4105, 4108, 4119, 0, 0, 0, 0, 0, 0, 0, 4122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5137, 0, 5196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5262, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5286, 0, 0, 5291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5294, 5297, 5300, 0, 0, 0, 0, 5303, 0, 0, 0, 0, 5306, 5309, 0, 0, 0, 0, 0, 5312, 0, 0, 5315, 0, 0, 0, 5318, 5321, 0, 0, 5324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5327, 5330, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5342, 5345, 0, 0, 0, 0, 5348, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5351, 0, 0, 0, 0, 0, 0, 5354, 0, 0, 0, 0, 0, 5357, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5360, 5363, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5366, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5375, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5378, 5384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5387, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5390, 0, 0, 0, 0, 0, 0, 5393, 0, 0, 0, 5402, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5405, 5411, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5414, 0, 0, 5423, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5440, 0, 5443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5446, 0, 0, 0, 0, 5449, 0, 0, 0, 0, 5452, 0, 0, 0, 0, 5455, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5458, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5467, 0, 5470, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5473, 0, 0, 0, 0, 5476, 0, 0, 0, 0, 5479, 0, 0, 0, 0, 5482, 0, 0, 0, 0, 0, 0, 5485, 5491, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5795, 5798, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5801, 5804, 0, 0, 0, 0, 0, 0, 5807, 5810, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5813, 5819, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5825, 5828, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5831, 5834, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5837, 5849, 5861, 5864, 5867, 5870, 5873, 5876, 5879, 5891, 5903, 5906, 5909, 5912, 5915, 5918, 5921, 5927, 0, 0, 0, 0, 0, 0, 5933, 5939, 0, 0, 0, 0, 0, 0, 5945, 5957, 5969, 5972, 5975, 5978, 5981, 5984, 5987, 5999, 6011, 6014, 6017, 6020, 6023, 6026, 6029, 6038, 0, 0, 0, 0, 0, 0, 6047, 6056, 0, 0, 0, 0, 0, 0, 6065, 6071, 0, 0, 0, 0, 0, 0, 6077, 6083, 0, 0, 0, 0, 0, 0, 6089, 6098, 0, 0, 0, 0, 0, 0, 0, 6107, 0, 0, 0, 0, 0, 0, 6116, 6128, 6140, 6143, 6146, 6149, 6152, 6155, 6158, 6170, 6182, 6185, 6188, 6191, 6194, 6197, 6200, 0, 0, 0, 6203, 0, 0, 0, 0, 0, 0, 0, 6206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6209, 0, 0, 0, 0, 0, 0, 0, 0, 6212, 0, 0, 0, 0, 0, 0, 6221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6224, 0, 0, 0, 0, 0, 0, 0, 6227, 0, 0, 0, 6236, 6238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6275, 0, 6282, 0, 6287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6290, 0, 6293, 0, 6296, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6299, 0, 0, 0, 0, 6302, 0, 0, 6305, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6312, 0, 6315, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6337, 0, 0, 0, 0, 0, 0, 6340, 0, 6343, 0, 0, 6346, 0, 0, 0, 0, 6349, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6352, 0, 0, 6355, 6358, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6361, 6364, 0, 0, 6367, 6370, 0, 0, 6373, 6376, 6379, 6382, 0, 0, 0, 0, 6385, 6388, 0, 0, 6391, 6394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6397, 6400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6403, 0, 0, 0, 0, 0, 6406, 6409, 0, 6412, 0, 0, 0, 0, 0, 0, 6415, 6418, 6421, 6424, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6446, 6448, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6476, 0, 0, 0, 0, 6479, 0, 6482, 0, 6485, 0, 6488, 0, 6491, 0, 6494, 0, 6497, 0, 6500, 0, 6503, 0, 6506, 0, 6509, 0, 6512, 0, 0, 6515, 0, 6518, 0, 6521, 0, 0, 0, 0, 0, 0, 6524, 0, 0, 6530, 0, 0, 6536, 0, 0, 6542, 0, 0, 6548, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6561, 0, 0, 0, 0, 0, 0, 0, 0, 6604, 0, 0, 0, 0, 6640, 0, 6667, 0, 6711, 0, 6737, 0, 6746, 0, 6762, 0, 6778, 0, 6788, 0, 6793, 0, 6806, 0, 6811, 0, 6820, 0, 0, 6827, 0, 6832, 0, 6840, 0, 0, 0, 0, 0, 0, 6868, 0, 0, 6895, 0, 0, 6919, 0, 0, 6948, 0, 0, 6985, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7137, 7146, 7151, 7156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7272, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7274, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7294, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7300, 0, 0, 0, 0, 0, 0, 7304, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7312, 0, 0, 0, 7316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7324, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7328, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7330, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7336, 0, 0, 0, 0, 0, 7338, 0, 0, 0, 0, 7340, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7342, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7344, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7346, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7348, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7350, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7356, 0, 0, 0, 0, 7358, 0, 0, 0, 0, 0, 0, 0, 7360, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7364, 7366, 0, 0, 0, 7370, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7372, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7382, 0, 7384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7386, 0, 0, 7388, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7390, 0, 7392, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7402, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7404, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7406, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7408, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7410, 0, 0, 0, 0, 0, 0, 0, 7412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7416, 0, 7418, 0, 0, 0, 0, 0, 0, 0, 0, 7420, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7422, 0, 0, 0, 0, 0, 7424, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7426, 0, 0, 0, 0, 7430, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7434, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7442, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7450, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7460, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7466, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7472, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7478, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7480, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7482, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7484, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7486, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7488, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7490, 0, 0, 0, 7492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7494, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7496, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7498, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7506, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7514, 0, 0, 0, 7516, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7518, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7520, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7522, 0, 0, 0, 0, 0, 0, 7524, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7543, 0, 0, 0, 7545, 0, 0, 0, 0, 0, 0, 0, 0, 7547, 0, 0, 7549, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7551, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7555, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7563, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7567, 0, 0, 0, 0, 0, 0, 7569, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7579, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7581, 0, 7583, 7585, 0, 0, 0, 0, 0, 0, 0, 0, 7587, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7591, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7593, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7595, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7612, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7618, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7620, 7622, 0, 0, 0, 0, 0, 0, 0, 7624, 7626, 0, 0, 0, 0, 0, 7628, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7630, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7636, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7646, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7650, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7652, 0, 0, 0, 7654, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7658, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7660, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7662, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7664, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7666, 0, 0, 0, 0, 0, 0, 0, 0, 7668, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7670, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7674, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7676, 0, 0, 0, 0, 0, 0, 0, 7678, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7680, 0, 7682, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7684, 0, 0, 0, 7686, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7688, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7692, 0, 0, 0, 0, 0, 7694, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7700, 0, 0, 0, 0, 0, 7702, 0, 0, 0, 7704, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7706, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7708, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7710, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7712, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7714, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7716, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7718, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7720, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7726, 0, 0, 0, 0, 0, 0, 7728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7736, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7742, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7746, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7753, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7758, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7760, 0, 0, 0, 0, 0, 0, 0, 0, 7762, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7770, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7776, 0, 0, 0, 7778, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7782, 0, 0, 0, 0, 0, 0, 0, 7784, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7786, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7788, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7790, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7792, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7801, 0, 0, 0, 7803, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7805, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7807, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7809, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7811, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7813, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7821, 0, 7823, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7825, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7829, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7845, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7847, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7849, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7853, 0, 0, 7855, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7857, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7859, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7861, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7863, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7865, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7867, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7869, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7871, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7873, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7875, 0, 0, 0, 0, 0, 7877, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7879, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7881, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7883, 7885, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7887, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7889, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7891, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7895, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7897, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7899, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7901, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7903, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7905, 0, 7907, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7909, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7911, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7915, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7917, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7931, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7937, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7939, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7941, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7943, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7945, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7949, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7953, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7955, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7957, 0, 0, 7959, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7961, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7963, 0, 0, 0, 0, 0, 0, 0, 7965, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7967, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7969, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7975, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7989, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7991, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7993, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7995, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8001, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8003, 0, 8005, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8007, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8009, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8019, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8021, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8025, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8029, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8031, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8033, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8035, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8037, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8045, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8047, 0, 0, 0, 0, 8049, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8051, 0, 8053, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8055, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8057, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8061, 0, 8063, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8065, 8067, 0, 0, 0, 0, 0, 0, 8069, 0, 0, 0, 0, 0, 8071, 0, 0, 0, 0, 0, 0, 8073, 8075, 0, 0, 0, 0, 0, 0, 8077, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8079, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8081, 8083, 8085, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8087, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8093, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8097, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8099, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8133, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8137, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8145, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8151, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8159, 0, 0, 0, 0, 0, 0, 8161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8171, 0, 0, 0, 8173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8183, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8185, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8197, 0, 0, 0, 0, 8201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8215, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8225, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8227, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8231, 0, 8233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8237, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8243, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8249, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8259, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8263, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8265, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8267, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8271, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8277, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8279, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8281, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8285, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8291, 0, 0, 0, 0, 8293, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8295, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8301, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8303, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8305, 0, 0, 0, 0, 0, 0, 8307, 0, 0, 0, 8309, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8311, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8313, 0, 0, 0, 0, 0, 8315, 0, 0, 8317, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8319, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8321, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8323, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8325, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8331, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8341, 0, 0, 0, 0, 0, 8345, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8347, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8349, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8357, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8361, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8363, 0, 0, 0, 8365, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8367, 0, 0, 8369, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8371, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8375, 0, 0, 0, 0, 0, 8379, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8381, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8387, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8389, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8391, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8395, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8397, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8401, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8403, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8405, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8409, 0, 0, 8411, 0, 8413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8415, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8417, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8419, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8421, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8427, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8431, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8433, 0, 8435, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8437, 0, 0, 8439, 0, 0, 0, 8441, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8449, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8453, 8455, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8459, 8461, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8463, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8465, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8469, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8479, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8485, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8491, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8493, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8495, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8505, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8509, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8517, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8519, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8527, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8539, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8541, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8545, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8547, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8549, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8553, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8555, 0, 0, 0, 0, 0, 0, 0, 8557, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8567, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8583, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8589, 8591, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8593, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8601, 0, 0, 0, 0, 0, 0, 0 }; static const uint16_t mapIdxToComposite[] = { 0, 0, 0, 0, 0, 0, 0, 0, 894, 0, 0, 0, 8814, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8800, 0, 0, 0, 0, 8815, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 193, 0, 0, 194, 0, 0, 195, 0, 0, 256, 0, 0, 258, 0, 0, 550, 0, 0, 196, 0, 0, 7842, 0, 0, 197, 0, 0, 461, 0, 0, 512, 0, 0, 514, 0, 0, 7840, 0, 0, 7680, 0, 0, 260, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7682, 0, 0, 7684, 0, 0, 7686, 0, 0, 0, 0, 0, 0, 0, 0, 262, 0, 0, 264, 0, 0, 266, 0, 0, 268, 0, 0, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7690, 0, 0, 270, 0, 0, 7692, 0, 0, 7696, 0, 0, 7698, 0, 0, 7694, 0, 0, 0, 0, 200, 0, 0, 201, 0, 0, 202, 0, 0, 7868, 0, 0, 274, 0, 0, 276, 0, 0, 278, 0, 0, 203, 0, 0, 7866, 0, 0, 282, 0, 0, 516, 0, 0, 518, 0, 0, 7864, 0, 0, 552, 0, 0, 280, 0, 0, 7704, 0, 0, 7706, 0, 0, 0, 0, 0, 0, 0, 0, 7710, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 500, 0, 0, 284, 0, 0, 7712, 0, 0, 286, 0, 0, 288, 0, 0, 486, 0, 0, 290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 292, 0, 0, 7714, 0, 0, 7718, 0, 0, 542, 0, 0, 7716, 0, 0, 7720, 0, 0, 7722, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 0, 0, 205, 0, 0, 206, 0, 0, 296, 0, 0, 298, 0, 0, 300, 0, 0, 304, 0, 0, 207, 0, 0, 7880, 0, 0, 463, 0, 0, 520, 0, 0, 522, 0, 0, 7882, 0, 0, 302, 0, 0, 7724, 0, 0, 0, 0, 308, 0, 0, 8490, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7728, 0, 0, 488, 0, 0, 7730, 0, 0, 310, 0, 0, 7732, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 313, 0, 0, 317, 0, 0, 7734, 0, 0, 315, 0, 0, 7740, 0, 0, 7738, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7742, 0, 0, 7744, 0, 0, 7746, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504, 0, 0, 323, 0, 0, 209, 0, 0, 7748, 0, 0, 327, 0, 0, 7750, 0, 0, 325, 0, 0, 7754, 0, 0, 7752, 0, 0, 0, 0, 210, 0, 0, 211, 0, 0, 212, 0, 0, 213, 0, 0, 332, 0, 0, 334, 0, 0, 558, 0, 0, 214, 0, 0, 7886, 0, 0, 336, 0, 0, 465, 0, 0, 524, 0, 0, 526, 0, 0, 416, 0, 0, 7884, 0, 0, 490, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7764, 0, 0, 7766, 0, 0, 0, 0, 0, 0, 0, 0, 0, 340, 0, 0, 7768, 0, 0, 344, 0, 0, 528, 0, 0, 530, 0, 0, 7770, 0, 0, 342, 0, 0, 7774, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 346, 0, 0, 348, 0, 0, 7776, 0, 0, 352, 0, 0, 7778, 0, 0, 536, 0, 0, 350, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7786, 0, 0, 356, 0, 0, 7788, 0, 0, 538, 0, 0, 354, 0, 0, 7792, 0, 0, 7790, 0, 0, 0, 0, 217, 0, 0, 218, 0, 0, 219, 0, 0, 360, 0, 0, 362, 0, 0, 364, 0, 0, 220, 0, 0, 7910, 0, 0, 366, 0, 0, 368, 0, 0, 467, 0, 0, 532, 0, 0, 534, 0, 0, 431, 0, 0, 7908, 0, 0, 7794, 0, 0, 370, 0, 0, 7798, 0, 0, 7796, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7804, 0, 0, 7806, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7808, 0, 0, 7810, 0, 0, 372, 0, 0, 7814, 0, 0, 7812, 0, 0, 7816, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7818, 0, 0, 7820, 0, 0, 0, 0, 7922, 0, 0, 221, 0, 0, 374, 0, 0, 7928, 0, 0, 562, 0, 0, 7822, 0, 0, 376, 0, 0, 7926, 0, 0, 7924, 0, 0, 0, 0, 377, 0, 0, 7824, 0, 0, 379, 0, 0, 381, 0, 0, 7826, 0, 0, 7828, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 0, 0, 225, 0, 0, 226, 0, 0, 227, 0, 0, 257, 0, 0, 259, 0, 0, 551, 0, 0, 228, 0, 0, 7843, 0, 0, 229, 0, 0, 462, 0, 0, 513, 0, 0, 515, 0, 0, 7841, 0, 0, 7681, 0, 0, 261, 0, 0, 0, 0, 0, 0, 0, 0, 7683, 0, 0, 7685, 0, 0, 7687, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 263, 0, 0, 265, 0, 0, 267, 0, 0, 269, 0, 0, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7691, 0, 0, 271, 0, 0, 7693, 0, 0, 7697, 0, 0, 7699, 0, 0, 7695, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 0, 0, 233, 0, 0, 234, 0, 0, 7869, 0, 0, 275, 0, 0, 277, 0, 0, 279, 0, 0, 235, 0, 0, 7867, 0, 0, 283, 0, 0, 517, 0, 0, 519, 0, 0, 7865, 0, 0, 553, 0, 0, 281, 0, 0, 7705, 0, 0, 7707, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7711, 0, 0, 0, 0, 0, 0, 0, 0, 501, 0, 0, 285, 0, 0, 7713, 0, 0, 287, 0, 0, 289, 0, 0, 487, 0, 0, 291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 293, 0, 0, 7715, 0, 0, 7719, 0, 0, 543, 0, 0, 7717, 0, 0, 7721, 0, 0, 7723, 0, 0, 7830, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 0, 0, 237, 0, 0, 238, 0, 0, 297, 0, 0, 299, 0, 0, 301, 0, 0, 239, 0, 0, 7881, 0, 0, 464, 0, 0, 521, 0, 0, 523, 0, 0, 7883, 0, 0, 303, 0, 0, 7725, 0, 0, 0, 0, 309, 0, 0, 496, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7729, 0, 0, 489, 0, 0, 7731, 0, 0, 311, 0, 0, 7733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 314, 0, 0, 318, 0, 0, 7735, 0, 0, 316, 0, 0, 7741, 0, 0, 7739, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7743, 0, 0, 7745, 0, 0, 7747, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 505, 0, 0, 324, 0, 0, 241, 0, 0, 7749, 0, 0, 328, 0, 0, 7751, 0, 0, 326, 0, 0, 7755, 0, 0, 7753, 0, 0, 0, 0, 0, 0, 0, 242, 0, 0, 243, 0, 0, 244, 0, 0, 245, 0, 0, 333, 0, 0, 335, 0, 0, 559, 0, 0, 246, 0, 0, 7887, 0, 0, 337, 0, 0, 466, 0, 0, 525, 0, 0, 527, 0, 0, 417, 0, 0, 7885, 0, 0, 491, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7765, 0, 0, 7767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 341, 0, 0, 7769, 0, 0, 345, 0, 0, 529, 0, 0, 531, 0, 0, 7771, 0, 0, 343, 0, 0, 7775, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 347, 0, 0, 349, 0, 0, 7777, 0, 0, 353, 0, 0, 7779, 0, 0, 537, 0, 0, 351, 0, 0, 0, 0, 7787, 0, 0, 7831, 0, 0, 357, 0, 0, 7789, 0, 0, 539, 0, 0, 355, 0, 0, 7793, 0, 0, 7791, 0, 0, 0, 0, 249, 0, 0, 250, 0, 0, 251, 0, 0, 361, 0, 0, 363, 0, 0, 365, 0, 0, 252, 0, 0, 7911, 0, 0, 367, 0, 0, 369, 0, 0, 468, 0, 0, 533, 0, 0, 535, 0, 0, 432, 0, 0, 7909, 0, 0, 7795, 0, 0, 371, 0, 0, 7799, 0, 0, 7797, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7805, 0, 0, 7807, 0, 0, 0, 0, 7809, 0, 0, 7811, 0, 0, 373, 0, 0, 7815, 0, 0, 7813, 0, 0, 7832, 0, 0, 7817, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7819, 0, 0, 7821, 0, 0, 0, 0, 7923, 0, 0, 253, 0, 0, 375, 0, 0, 7929, 0, 0, 563, 0, 0, 7823, 0, 0, 255, 0, 0, 7927, 0, 0, 7833, 0, 0, 7925, 0, 0, 0, 0, 378, 0, 0, 7825, 0, 0, 380, 0, 0, 382, 0, 0, 7827, 0, 0, 7829, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8173, 0, 0, 901, 0, 0, 8129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8189, 0, 903, 0, 7846, 0, 0, 7844, 0, 0, 7850, 0, 0, 7848, 0, 0, 478, 0, 0, 8491, 0, 506, 0, 0, 0, 0, 508, 0, 0, 482, 0, 0, 7688, 0, 0, 7872, 0, 0, 7870, 0, 0, 7876, 0, 0, 7874, 0, 0, 7726, 0, 0, 7890, 0, 0, 7888, 0, 0, 7894, 0, 0, 7892, 0, 0, 7756, 0, 0, 556, 0, 0, 7758, 0, 0, 554, 0, 0, 510, 0, 0, 475, 0, 0, 471, 0, 0, 469, 0, 0, 473, 0, 0, 7847, 0, 0, 7845, 0, 0, 7851, 0, 0, 7849, 0, 0, 479, 0, 0, 507, 0, 0, 509, 0, 0, 483, 0, 0, 7689, 0, 0, 7873, 0, 0, 7871, 0, 0, 7877, 0, 0, 7875, 0, 0, 7727, 0, 0, 0, 0, 7891, 0, 0, 7889, 0, 0, 7895, 0, 0, 7893, 0, 0, 7757, 0, 0, 557, 0, 0, 7759, 0, 0, 555, 0, 0, 511, 0, 0, 476, 0, 0, 472, 0, 0, 470, 0, 0, 474, 0, 0, 7856, 0, 0, 7854, 0, 0, 7860, 0, 0, 7858, 0, 0, 7857, 0, 0, 7855, 0, 0, 7861, 0, 0, 7859, 0, 0, 7700, 0, 0, 7702, 0, 0, 7701, 0, 0, 7703, 0, 0, 0, 0, 0, 0, 7760, 0, 0, 7762, 0, 0, 7761, 0, 0, 7763, 0, 0, 7780, 0, 0, 7781, 0, 0, 7782, 0, 0, 7783, 0, 0, 7800, 0, 0, 7801, 0, 0, 7802, 0, 0, 7803, 0, 0, 0, 0, 0, 7835, 0, 0, 0, 0, 0, 0, 7900, 0, 0, 7898, 0, 0, 7904, 0, 0, 7902, 0, 0, 7906, 0, 0, 7901, 0, 0, 7899, 0, 0, 7905, 0, 0, 7903, 0, 0, 7907, 0, 0, 0, 0, 7914, 0, 0, 7912, 0, 0, 7918, 0, 0, 7916, 0, 0, 7920, 0, 0, 7915, 0, 0, 7913, 0, 0, 7919, 0, 0, 7917, 0, 0, 7921, 0, 0, 494, 0, 0, 492, 0, 0, 493, 0, 0, 0, 0, 480, 0, 0, 481, 0, 0, 7708, 0, 0, 7709, 0, 0, 560, 0, 0, 561, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 495, 0, 0, 0, 0, 0, 0, 0, 0, 884, 0, 0, 0, 0, 832, 0, 833, 0, 836, 0, 0, 835, 0, 8174, 0, 8123, 0, 8137, 0, 8139, 0, 8155, 0, 8185, 0, 8171, 0, 8187, 0, 8147, 0, 8122, 0, 0, 902, 0, 0, 8121, 0, 0, 8120, 0, 0, 7944, 0, 0, 7945, 0, 0, 8124, 0, 0, 0, 0, 8136, 0, 0, 904, 0, 0, 7960, 0, 0, 7961, 0, 0, 8138, 0, 0, 905, 0, 0, 7976, 0, 0, 7977, 0, 0, 8140, 0, 0, 0, 0, 8154, 0, 0, 906, 0, 0, 8153, 0, 0, 8152, 0, 0, 938, 0, 0, 7992, 0, 0, 7993, 0, 0, 8184, 0, 0, 908, 0, 0, 8008, 0, 0, 8009, 0, 0, 0, 0, 8172, 0, 0, 0, 0, 0, 0, 8170, 0, 0, 910, 0, 0, 8169, 0, 0, 8168, 0, 0, 939, 0, 0, 8025, 0, 0, 8486, 0, 8186, 0, 0, 911, 0, 0, 8040, 0, 0, 8041, 0, 0, 8188, 0, 0, 8049, 0, 8116, 0, 0, 8051, 0, 8053, 0, 8132, 0, 0, 8055, 0, 8163, 0, 8048, 0, 0, 940, 0, 0, 8113, 0, 0, 8112, 0, 0, 7936, 0, 0, 7937, 0, 0, 8118, 0, 0, 8115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8050, 0, 0, 941, 0, 0, 7952, 0, 0, 7953, 0, 0, 8052, 0, 0, 942, 0, 0, 7968, 0, 0, 7969, 0, 0, 8134, 0, 0, 8131, 0, 0, 0, 0, 8126, 0, 8054, 0, 0, 943, 0, 0, 8145, 0, 0, 8144, 0, 0, 970, 0, 0, 7984, 0, 0, 7985, 0, 0, 8150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8056, 0, 0, 972, 0, 0, 8000, 0, 0, 8001, 0, 0, 0, 0, 0, 0, 8164, 0, 0, 8165, 0, 0, 0, 0, 8058, 0, 0, 973, 0, 0, 8161, 0, 0, 8160, 0, 0, 971, 0, 0, 8016, 0, 0, 8017, 0, 0, 8166, 0, 0, 0, 0, 0, 0, 8060, 0, 0, 974, 0, 0, 8032, 0, 0, 8033, 0, 0, 8182, 0, 0, 8179, 0, 0, 8146, 0, 0, 912, 0, 0, 8151, 0, 0, 8162, 0, 0, 944, 0, 0, 8167, 0, 0, 8057, 0, 8059, 0, 8061, 0, 8180, 0, 0, 979, 0, 0, 980, 0, 0, 1031, 0, 0, 1232, 0, 0, 1234, 0, 0, 1027, 0, 0, 1024, 0, 0, 1238, 0, 0, 1025, 0, 0, 1217, 0, 0, 1244, 0, 0, 1246, 0, 0, 1037, 0, 0, 1250, 0, 0, 1049, 0, 0, 1252, 0, 0, 1036, 0, 0, 1254, 0, 0, 1262, 0, 0, 1038, 0, 0, 1264, 0, 0, 1266, 0, 0, 1268, 0, 0, 1272, 0, 0, 1260, 0, 0, 1233, 0, 0, 1235, 0, 0, 1107, 0, 0, 1104, 0, 0, 1239, 0, 0, 1105, 0, 0, 1218, 0, 0, 1245, 0, 0, 1247, 0, 0, 1117, 0, 0, 1251, 0, 0, 1081, 0, 0, 1253, 0, 0, 1116, 0, 0, 0, 0, 1255, 0, 0, 1263, 0, 0, 1118, 0, 0, 1265, 0, 0, 1267, 0, 0, 1269, 0, 0, 1273, 0, 0, 1261, 0, 0, 1111, 0, 0, 1142, 0, 0, 1143, 0, 0, 1242, 0, 0, 1243, 0, 0, 1258, 0, 0, 1259, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64302, 0, 0, 64303, 0, 0, 64304, 0, 0, 0, 0, 0, 0, 0, 64305, 0, 0, 64332, 0, 0, 0, 0, 64306, 0, 0, 0, 0, 64307, 0, 0, 0, 0, 64308, 0, 0, 64331, 0, 0, 64309, 0, 0, 64310, 0, 0, 64312, 0, 0, 64285, 0, 0, 64313, 0, 0, 64314, 0, 0, 0, 0, 64315, 0, 0, 64333, 0, 0, 0, 0, 64316, 0, 0, 0, 0, 64318, 0, 0, 64320, 0, 0, 64321, 0, 0, 0, 0, 64323, 0, 0, 64324, 0, 0, 64334, 0, 0, 64326, 0, 0, 64327, 0, 0, 0, 0, 64328, 0, 0, 64329, 0, 0, 64298, 0, 0, 64299, 0, 0, 0, 0, 64330, 0, 0, 64287, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1570, 0, 0, 1571, 0, 0, 1573, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1572, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1574, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1730, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1747, 0, 0, 0, 0, 1728, 0, 0, 2392, 0, 0, 2393, 0, 0, 2394, 0, 0, 2395, 0, 0, 2396, 0, 0, 2397, 0, 0, 2345, 0, 0, 2398, 0, 0, 2399, 0, 0, 2353, 0, 0, 2356, 0, 0, 2524, 0, 0, 2525, 0, 0, 2527, 0, 0, 2507, 0, 0, 2508, 0, 0, 2649, 0, 0, 2650, 0, 0, 2651, 0, 0, 2654, 0, 0, 2611, 0, 0, 2614, 0, 0, 2908, 0, 0, 2909, 0, 0, 2891, 0, 0, 2888, 0, 0, 2892, 0, 0, 2964, 0, 0, 3018, 0, 0, 3020, 0, 0, 3019, 0, 0, 3144, 0, 0, 3264, 0, 0, 3274, 0, 0, 3271, 0, 0, 3272, 0, 0, 3275, 0, 0, 3402, 0, 0, 3404, 0, 0, 3403, 0, 0, 3546, 0, 0, 3548, 0, 0, 3550, 0, 0, 3549, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3945, 0, 0, 3907, 0, 0, 3917, 0, 0, 3922, 0, 0, 3927, 0, 0, 3932, 0, 0, 3955, 0, 0, 3957, 0, 0, 3969, 0, 0, 4025, 0, 0, 3987, 0, 0, 3997, 0, 0, 4002, 0, 0, 4007, 0, 0, 4012, 0, 0, 3958, 0, 0, 0, 0, 0, 3960, 0, 0, 0, 0, 0, 4134, 0, 0, 0, 0, 0, 0, 0, 0, 6918, 0, 0, 6920, 0, 0, 6922, 0, 0, 6924, 0, 0, 6926, 0, 0, 6930, 0, 0, 6971, 0, 0, 6973, 0, 0, 6976, 0, 0, 6977, 0, 0, 6979, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7736, 0, 0, 7737, 0, 0, 7772, 0, 0, 7773, 0, 0, 7784, 0, 0, 7785, 0, 0, 7852, 0, 0, 7862, 0, 0, 7853, 0, 0, 7863, 0, 0, 7878, 0, 0, 7879, 0, 0, 7896, 0, 0, 7897, 0, 0, 7938, 0, 0, 7940, 0, 0, 7942, 0, 0, 8064, 0, 0, 7939, 0, 0, 7941, 0, 0, 7943, 0, 0, 8065, 0, 0, 8066, 0, 0, 8067, 0, 0, 8068, 0, 0, 8069, 0, 0, 8070, 0, 0, 8071, 0, 0, 7946, 0, 0, 7948, 0, 0, 7950, 0, 0, 8072, 0, 0, 7947, 0, 0, 7949, 0, 0, 7951, 0, 0, 8073, 0, 0, 8074, 0, 0, 8075, 0, 0, 8076, 0, 0, 8077, 0, 0, 8078, 0, 0, 8079, 0, 0, 7954, 0, 0, 7956, 0, 0, 7955, 0, 0, 7957, 0, 0, 7962, 0, 0, 7964, 0, 0, 7963, 0, 0, 7965, 0, 0, 7970, 0, 0, 7972, 0, 0, 7974, 0, 0, 8080, 0, 0, 7971, 0, 0, 7973, 0, 0, 7975, 0, 0, 8081, 0, 0, 8082, 0, 0, 8083, 0, 0, 8084, 0, 0, 8085, 0, 0, 8086, 0, 0, 8087, 0, 0, 7978, 0, 0, 7980, 0, 0, 7982, 0, 0, 8088, 0, 0, 7979, 0, 0, 7981, 0, 0, 7983, 0, 0, 8089, 0, 0, 8090, 0, 0, 8091, 0, 0, 8092, 0, 0, 8093, 0, 0, 8094, 0, 0, 8095, 0, 0, 7986, 0, 0, 7988, 0, 0, 7990, 0, 0, 7987, 0, 0, 7989, 0, 0, 7991, 0, 0, 7994, 0, 0, 7996, 0, 0, 7998, 0, 0, 7995, 0, 0, 7997, 0, 0, 7999, 0, 0, 8002, 0, 0, 8004, 0, 0, 8003, 0, 0, 8005, 0, 0, 8010, 0, 0, 8012, 0, 0, 8011, 0, 0, 8013, 0, 0, 8018, 0, 0, 8020, 0, 0, 8022, 0, 0, 8019, 0, 0, 8021, 0, 0, 8023, 0, 0, 8027, 0, 0, 8029, 0, 0, 8031, 0, 0, 8034, 0, 0, 8036, 0, 0, 8038, 0, 0, 8096, 0, 0, 8035, 0, 0, 8037, 0, 0, 8039, 0, 0, 8097, 0, 0, 8098, 0, 0, 8099, 0, 0, 8100, 0, 0, 8101, 0, 0, 8102, 0, 0, 8103, 0, 0, 8042, 0, 0, 8044, 0, 0, 8046, 0, 0, 8104, 0, 0, 8043, 0, 0, 8045, 0, 0, 8047, 0, 0, 8105, 0, 0, 8106, 0, 0, 8107, 0, 0, 8108, 0, 0, 8109, 0, 0, 8110, 0, 0, 8111, 0, 0, 8114, 0, 0, 8130, 0, 0, 8178, 0, 0, 8119, 0, 0, 8141, 0, 0, 8142, 0, 0, 8143, 0, 0, 8135, 0, 0, 8183, 0, 0, 8157, 0, 0, 8158, 0, 0, 8159, 0, 0, 8192, 0, 8193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8602, 0, 0, 0, 0, 0, 0, 8603, 0, 0, 0, 0, 8622, 0, 0, 8653, 0, 0, 8655, 0, 0, 8654, 0, 0, 8708, 0, 0, 8713, 0, 0, 8716, 0, 0, 0, 0, 0, 0, 8740, 0, 0, 8742, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8769, 0, 0, 8772, 0, 0, 8775, 0, 0, 8777, 0, 0, 8813, 0, 0, 8802, 0, 0, 8816, 0, 0, 8817, 0, 0, 8820, 0, 0, 8821, 0, 0, 8824, 0, 0, 8825, 0, 0, 8832, 0, 0, 8833, 0, 0, 8928, 0, 0, 8929, 0, 0, 8836, 0, 0, 8837, 0, 0, 8840, 0, 0, 8841, 0, 0, 8930, 0, 0, 8931, 0, 0, 8876, 0, 0, 8877, 0, 0, 8878, 0, 0, 8879, 0, 0, 8938, 0, 0, 8939, 0, 0, 8940, 0, 0, 8941, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10972, 0, 0, 0, 0, 0, 0, 0, 0, 9001, 0, 9002, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12436, 0, 0, 12364, 0, 0, 12366, 0, 0, 12368, 0, 0, 12370, 0, 0, 12372, 0, 0, 12374, 0, 0, 12376, 0, 0, 12378, 0, 0, 12380, 0, 0, 12382, 0, 0, 12384, 0, 0, 12386, 0, 0, 12389, 0, 0, 12391, 0, 0, 12393, 0, 0, 12400, 0, 0, 12401, 0, 0, 12403, 0, 0, 12404, 0, 0, 12406, 0, 0, 12407, 0, 0, 12409, 0, 0, 12410, 0, 0, 12412, 0, 0, 12413, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12446, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12460, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12462, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12464, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12466, 0, 0, 0, 0, 0, 0, 0, 0, 12468, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12470, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12472, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12474, 0, 0, 0, 0, 12476, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12478, 0, 0, 0, 0, 12480, 0, 0, 0, 0, 0, 0, 0, 0, 12482, 0, 0, 0, 0, 0, 0, 12485, 0, 0, 0, 0, 12487, 0, 0, 0, 0, 0, 0, 0, 12489, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12496, 0, 0, 12497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12499, 0, 0, 12500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12502, 0, 0, 12503, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12505, 0, 0, 12506, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12508, 0, 0, 12509, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12535, 0, 0, 0, 0, 0, 0, 0, 0, 12536, 0, 0, 0, 0, 12537, 0, 0, 0, 0, 12538, 0, 0, 0, 0, 0, 0, 0, 0, 12542, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64210, 0, 64211, 0, 64212, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63847, 0, 0, 0, 64112, 0, 0, 0, 0, 0, 63749, 0, 0, 0, 63838, 0, 0, 0, 0, 0, 0, 0, 63771, 0, 0, 0, 63930, 0, 0, 0, 0, 0, 0, 0, 63863, 0, 0, 0, 63997, 0, 63912, 0, 0, 0, 0, 0, 64115, 0, 63789, 0, 63925, 0, 64048, 0, 63845, 0, 63956, 0, 63931, 0, 64049, 0, 0, 0, 0, 0, 64012, 0, 64116, 0, 64050, 0, 0, 0, 64114, 0, 63864, 0, 0, 0, 63953, 0, 64117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64113, 0, 63790, 0, 63865, 0, 63829, 0, 63828, 0, 64021, 0, 0, 0, 0, 0, 0, 0, 64000, 0, 63900, 0, 63965, 0, 63999, 0, 63943, 0, 63882, 0, 63901, 0, 0, 0, 64118, 0, 64051, 0, 63826, 0, 63791, 0, 64052, 0, 63871, 0, 0, 0, 64119, 0, 0, 0, 63843, 0, 0, 0, 0, 0, 0, 0, 63979, 0, 0, 0, 0, 0, 0, 0, 64053, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63772, 0, 0, 0, 0, 0, 63851, 0, 0, 0, 0, 0, 63750, 0, 0, 0, 0, 0, 63966, 0, 63981, 0, 63872, 0, 63902, 0, 64121, 0, 63755, 0, 64122, 0, 64054, 0, 64013, 0, 64123, 0, 64055, 0, 64056, 0, 0, 0, 0, 0, 63913, 0, 0, 0, 0, 0, 64057, 0, 64124, 0, 63852, 0, 64058, 0, 64125, 0, 63818, 0, 63810, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64126, 0, 63756, 0, 63753, 0, 64127, 0, 63873, 0, 64128, 0, 64129, 0, 0, 0, 0, 0, 0, 0, 64004, 0, 0, 0, 63914, 0, 63932, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63933, 0, 63819, 0, 64059, 0, 63967, 0, 64060, 0, 0, 0, 63957, 0, 63777, 0, 63915, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63886, 0, 0, 0, 0, 0, 64001, 0, 63906, 0, 63784, 0, 64130, 0, 64011, 0, 64131, 0, 63874, 0, 0, 0, 0, 0, 63811, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64132, 0, 0, 0, 63960, 0, 63846, 0, 64133, 0, 0, 0, 63907, 0, 63840, 0, 63916, 0, 64061, 0, 64134, 0, 63929, 0, 64136, 0, 63961, 0, 64135, 0, 64138, 0, 64062, 0, 64063, 0, 63887, 0, 64139, 0, 63757, 0, 63888, 0, 0, 0, 63954, 0, 64140, 0, 0, 0, 0, 0, 63781, 0, 63835, 0, 64002, 0, 63859, 0, 63908, 0, 63861, 0, 64141, 0, 64142, 0, 64143, 0, 63889, 0, 63792, 0, 0, 0, 0, 0, 64065, 0, 64144, 0, 63849, 0, 0, 0, 0, 0, 63934, 0, 0, 0, 0, 0, 63875, 0, 0, 0, 64066, 0, 0, 0, 0, 0, 0, 63968, 0, 0, 0, 0, 64018, 0, 63941, 0, 64067, 0, 64006, 0, 63883, 0, 0, 0, 63745, 0, 0, 0, 0, 0, 64146, 0, 64147, 0, 0, 0, 63969, 0, 64148, 0, 63944, 0, 63988, 0, 63945, 0, 63962, 0, 0, 0, 0, 0, 0, 0, 0, 63866, 0, 64068, 0, 63970, 0, 63764, 0, 63820, 0, 63793, 0, 63773, 0, 0, 0, 0, 0, 0, 0, 63884, 0, 64149, 0, 63909, 0, 0, 0, 64150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63858, 0, 63848, 0, 63971, 0, 0, 0, 63765, 0, 64005, 0, 64151, 0, 63786, 0, 64069, 0, 63989, 0, 63821, 0, 63958, 0, 64070, 0, 63947, 0, 63980, 0, 64153, 0, 63748, 0, 64152, 0, 63822, 0, 64071, 0, 63890, 0, 63778, 0, 63876, 0, 64155, 0, 0, 0, 63995, 0, 63903, 0, 63766, 0, 63891, 0, 64072, 0, 63936, 0, 63982, 0, 63794, 0, 63774, 0, 0, 0, 64073, 0, 64158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63814, 0, 0, 0, 0, 0, 64159, 0, 63994, 0, 63787, 0, 64022, 0, 63911, 0, 0, 0, 63963, 0, 0, 0, 63917, 0, 63767, 0, 63972, 0, 63948, 0, 64074, 0, 63918, 0, 64161, 0, 63892, 0, 63983, 0, 0, 0, 0, 0, 64162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64163, 0, 63949, 0, 63862, 0, 63842, 0, 0, 0, 0, 0, 63973, 0, 64164, 0, 64165, 0, 63937, 0, 63758, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64166, 0, 64167, 0, 0, 0, 63795, 0, 0, 0, 64168, 0, 63853, 0, 64170, 0, 64169, 0, 64157, 0, 0, 0, 0, 0, 0, 0, 63950, 0, 63803, 0, 64075, 0, 63815, 0, 64171, 0, 63844, 0, 63877, 0, 0, 0, 64024, 0, 64076, 0, 64078, 0, 64077, 0, 64079, 0, 64080, 0, 64081, 0, 64025, 0, 64026, 0, 63804, 0, 64082, 0, 64083, 0, 64027, 0, 63926, 0, 0, 0, 0, 0, 63893, 0, 0, 0, 63830, 0, 64084, 0, 0, 0, 64085, 0, 64172, 0, 63991, 0, 0, 0, 63992, 0, 64086, 0, 63910, 0, 63812, 0, 0, 0, 64174, 0, 63993, 0, 64029, 0, 64003, 0, 63867, 0, 0, 0, 63951, 0, 63850, 0, 63823, 0, 64175, 0, 63805, 0, 63831, 0, 64087, 0, 64088, 0, 63824, 0, 64089, 0, 0, 0, 64177, 0, 0, 0, 64090, 0, 63974, 0, 63759, 0, 0, 0, 63919, 0, 64030, 0, 63796, 0, 64178, 0, 0, 0, 0, 0, 0, 0, 63920, 0, 63895, 0, 63813, 0, 0, 0, 0, 0, 63827, 0, 63782, 0, 0, 0, 63990, 0, 0, 0, 64092, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63868, 0, 0, 0, 0, 0, 64093, 0, 63860, 0, 63998, 0, 64179, 0, 63806, 0, 64180, 0, 63832, 0, 63768, 0, 63854, 0, 64095, 0, 63897, 0, 63938, 0, 63779, 0, 63984, 0, 63797, 0, 64032, 0, 63775, 0, 63760, 0, 0, 0, 63798, 0, 0, 0, 64181, 0, 63761, 0, 63783, 0, 0, 0, 64008, 0, 0, 0, 63904, 0, 63975, 0, 63976, 0, 63762, 0, 64096, 0, 64182, 0, 63780, 0, 0, 0, 64183, 0, 64010, 0, 64097, 0, 0, 0, 0, 0, 63905, 0, 64185, 0, 64187, 0, 63869, 0, 63809, 0, 64190, 0, 64034, 0, 64189, 0, 64188, 0, 64099, 0, 63996, 0, 63834, 0, 64192, 0, 0, 0, 0, 0, 63744, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63816, 0, 0, 0, 63747, 0, 64100, 0, 64101, 0, 0, 0, 0, 0, 0, 0, 63799, 0, 0, 0, 63746, 0, 63896, 0, 63959, 0, 64194, 0, 64007, 0, 63885, 0, 0, 0, 63857, 0, 0, 0, 64102, 0, 63898, 0, 64037, 0, 0, 0, 64195, 0, 63939, 0, 63763, 0, 0, 0, 63788, 0, 64038, 0, 0, 0, 63769, 0, 64196, 0, 63927, 0, 0, 0, 63977, 0, 63870, 0, 63754, 0, 63921, 0, 64197, 0, 63807, 0, 63899, 0, 0, 0, 0, 0, 63878, 0, 0, 0, 63942, 0, 63825, 0, 64009, 0, 63833, 0, 63955, 0, 64198, 0, 63964, 0, 63985, 0, 0, 0, 63928, 0, 0, 0, 63978, 0, 64199, 0, 0, 0, 63922, 0, 63817, 0, 63800, 0, 63923, 0, 0, 0, 64028, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64201, 0, 0, 0, 0, 0, 64202, 0, 0, 0, 0, 0, 64203, 0, 63924, 0, 64204, 0, 63952, 0, 0, 0, 0, 0, 0, 0, 64042, 0, 64043, 0, 64044, 0, 0, 0, 0, 0, 0, 0, 63770, 0, 63879, 0, 0, 0, 0, 0, 0, 0, 64205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63801, 0, 63986, 0, 0, 0, 64045, 0, 63802, 0, 63776, 0, 0, 0, 63808, 0, 63880, 0, 63987, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63881, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64216, 0, 0, 0, 0, 0, 63940, 0, 64217, 0, 63752, 0, 0, 0, 0, 0, 0, 0, 64300, 0, 0, 64301, 0, 0, 64208, 0, 64207, 0, 64209, 0, 64213, 0, 64214, 0, 64215, 0, 0, 0, 0, 0, 0, 0 }; static const uint8_t combiningClass[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 232, 220, 220, 220, 220, 232, 216, 220, 220, 220, 220, 220, 202, 202, 220, 220, 220, 220, 202, 202, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 1, 1, 1, 1, 1, 220, 220, 220, 220, 230, 230, 230, 230, 230, 230, 230, 230, 240, 230, 220, 220, 220, 230, 230, 230, 220, 220, 0, 230, 230, 230, 220, 220, 220, 220, 230, 232, 220, 220, 230, 233, 234, 234, 233, 0, 0, 0, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 230, 230, 230, 230, 220, 230, 230, 230, 222, 220, 230, 230, 230, 230, 230, 230, 220, 220, 220, 220, 220, 220, 230, 230, 220, 230, 230, 222, 228, 230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 0, 23, 0, 24, 25, 0, 230, 220, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 230, 230, 30, 31, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 28, 29, 30, 31, 32, 33, 34, 230, 230, 220, 220, 230, 230, 230, 230, 230, 220, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 230, 230, 230, 230, 220, 230, 0, 0, 230, 230, 0, 220, 230, 230, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 230, 230, 220, 230, 230, 220, 220, 220, 230, 220, 220, 230, 220, 230, 230, 230, 220, 230, 220, 230, 220, 230, 220, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 230, 220, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 84, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 103, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 122, 122, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 220, 0, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 130, 0, 132, 0, 0, 0, 0, 0, 130, 130, 130, 130, 0, 0, 130, 0, 230, 230, 9, 0, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 230, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 0, 0, 0, 0, 0, 0, 0, 230, 230, 220, 230, 230, 230, 230, 230, 230, 230, 220, 230, 230, 234, 214, 220, 230, 230, 1, 1, 230, 230, 230, 230, 1, 1, 1, 230, 230, 0, 0, 0, 0, 230, 0, 0, 0, 1, 1, 230, 220, 230, 1, 1, 220, 220, 220, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 228, 232, 222, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; ================================================ FILE: unity_decoder/libil2cpp/number-formatter.h ================================================ #ifndef _MONO_METADATA_NUMBER_FORMATTER_H_ #define _MONO_METADATA_NUMBER_FORMATTER_H_ 1 #include static const uint64_t Formatter_MantissaBitsTable[] = { 4556951262222748432ULL, 9113902524445496865ULL, 1822780504889099373ULL, 3645561009778198746ULL, 7291122019556397492ULL, 14582244039112794984ULL, 2916448807822558996ULL, 5832897615645117993ULL, 11665795231290235987ULL, 2333159046258047197ULL, 4666318092516094394ULL, 9332636185032188789ULL, 1866527237006437757ULL, 3733054474012875515ULL, 7466108948025751031ULL, 14932217896051502063ULL, 2986443579210300412ULL, 5972887158420600825ULL, 11945774316841201651ULL, 2389154863368240330ULL, 4778309726736480660ULL, 9556619453472961320ULL, 1911323890694592264ULL, 3822647781389184528ULL, 7645295562778369056ULL, 15290591125556738113ULL, 3058118225111347622ULL, 6116236450222695245ULL, 12232472900445390490ULL, 2446494580089078098ULL, 4892989160178156196ULL, 9785978320356312392ULL, 1957195664071262478ULL, 3914391328142524957ULL, 7828782656285049914ULL, 15657565312570099828ULL, 3131513062514019965ULL, 6263026125028039931ULL, 12526052250056079862ULL, 2505210450011215972ULL, 5010420900022431944ULL, 10020841800044863889ULL, 2004168360008972777ULL, 4008336720017945555ULL, 8016673440035891111ULL, 16033346880071782223ULL, 3206669376014356444ULL, 6413338752028712889ULL, 12826677504057425779ULL, 2565335500811485155ULL, 5130671001622970311ULL, 10261342003245940623ULL, 2052268400649188124ULL, 4104536801298376249ULL, 8209073602596752498ULL, 16418147205193504997ULL, 3283629441038700999ULL, 6567258882077401998ULL, 13134517764154803997ULL, 2626903552830960799ULL, 5253807105661921599ULL, 10507614211323843198ULL, 2101522842264768639ULL, 4203045684529537279ULL, 8406091369059074558ULL, 16812182738118149117ULL, 3362436547623629823ULL, 6724873095247259646ULL, 13449746190494519293ULL, 2689949238098903858ULL, 5379898476197807717ULL, 10759796952395615435ULL, 2151959390479123087ULL, 4303918780958246174ULL, 8607837561916492348ULL, 17215675123832984696ULL, 3443135024766596939ULL, 6886270049533193878ULL, 13772540099066387756ULL, 2754508019813277551ULL, 5509016039626555102ULL, 11018032079253110205ULL, 2203606415850622041ULL, 4407212831701244082ULL, 8814425663402488164ULL, 17628851326804976328ULL, 3525770265360995265ULL, 7051540530721990531ULL, 14103081061443981063ULL, 2820616212288796212ULL, 5641232424577592425ULL, 11282464849155184850ULL, 2256492969831036970ULL, 4512985939662073940ULL, 9025971879324147880ULL, 18051943758648295760ULL, 3610388751729659152ULL, 7220777503459318304ULL, 14441555006918636608ULL, 2888311001383727321ULL, 5776622002767454643ULL, 11553244005534909286ULL, 2310648801106981857ULL, 4621297602213963714ULL, 9242595204427927429ULL, 1848519040885585485ULL, 3697038081771170971ULL, 7394076163542341943ULL, 14788152327084683887ULL, 2957630465416936777ULL, 5915260930833873554ULL, 11830521861667747109ULL, 2366104372333549421ULL, 4732208744667098843ULL, 9464417489334197687ULL, 1892883497866839537ULL, 3785766995733679075ULL, 7571533991467358150ULL, 15143067982934716300ULL, 3028613596586943260ULL, 6057227193173886520ULL, 12114454386347773040ULL, 2422890877269554608ULL, 4845781754539109216ULL, 9691563509078218432ULL, 1938312701815643686ULL, 3876625403631287372ULL, 7753250807262574745ULL, 15506501614525149491ULL, 3101300322905029898ULL, 6202600645810059796ULL, 12405201291620119593ULL, 2481040258324023918ULL, 4962080516648047837ULL, 9924161033296095674ULL, 1984832206659219134ULL, 3969664413318438269ULL, 7939328826636876539ULL, 15878657653273753079ULL, 3175731530654750615ULL, 6351463061309501231ULL, 12702926122619002463ULL, 2540585224523800492ULL, 5081170449047600985ULL, 10162340898095201970ULL, 2032468179619040394ULL, 4064936359238080788ULL, 8129872718476161576ULL, 16259745436952323153ULL, 3251949087390464630ULL, 6503898174780929261ULL, 13007796349561858522ULL, 2601559269912371704ULL, 5203118539824743409ULL, 10406237079649486818ULL, 2081247415929897363ULL, 4162494831859794727ULL, 8324989663719589454ULL, 16649979327439178909ULL, 3329995865487835781ULL, 6659991730975671563ULL, 13319983461951343127ULL, 2663996692390268625ULL, 5327993384780537250ULL, 10655986769561074501ULL, 2131197353912214900ULL, 4262394707824429800ULL, 8524789415648859601ULL, 17049578831297719202ULL, 3409915766259543840ULL, 6819831532519087681ULL, 13639663065038175362ULL, 2727932613007635072ULL, 5455865226015270144ULL, 10911730452030540289ULL, 2182346090406108057ULL, 4364692180812216115ULL, 8729384361624432231ULL, 17458768723248864463ULL, 3491753744649772892ULL, 6983507489299545785ULL, 13967014978599091570ULL, 2793402995719818314ULL, 5586805991439636628ULL, 11173611982879273256ULL, 2234722396575854651ULL, 4469444793151709302ULL, 8938889586303418605ULL, 17877779172606837210ULL, 3575555834521367442ULL, 7151111669042734884ULL, 14302223338085469768ULL, 2860444667617093953ULL, 5720889335234187907ULL, 11441778670468375814ULL, 2288355734093675162ULL, 4576711468187350325ULL, 9153422936374700651ULL, 1830684587274940130ULL, 3661369174549880260ULL, 7322738349099760521ULL, 14645476698199521043ULL, 2929095339639904208ULL, 5858190679279808417ULL, 11716381358559616834ULL, 2343276271711923366ULL, 4686552543423846733ULL, 9373105086847693467ULL, 1874621017369538693ULL, 3749242034739077387ULL, 7498484069478154774ULL, 14996968138956309548ULL, 2999393627791261909ULL, 5998787255582523819ULL, 11997574511165047638ULL, 2399514902233009527ULL, 4799029804466019055ULL, 9598059608932038110ULL, 1919611921786407622ULL, 3839223843572815244ULL, 7678447687145630488ULL, 15356895374291260977ULL, 3071379074858252195ULL, 6142758149716504390ULL, 12285516299433008781ULL, 2457103259886601756ULL, 4914206519773203512ULL, 9828413039546407025ULL, 1965682607909281405ULL, 3931365215818562810ULL, 7862730431637125620ULL, 15725460863274251240ULL, 3145092172654850248ULL, 6290184345309700496ULL, 12580368690619400992ULL, 2516073738123880198ULL, 5032147476247760397ULL, 10064294952495520794ULL, 2012858990499104158ULL, 4025717980998208317ULL, 8051435961996416635ULL, 16102871923992833270ULL, 3220574384798566654ULL, 6441148769597133308ULL, 12882297539194266616ULL, 2576459507838853323ULL, 5152919015677706646ULL, 10305838031355413293ULL, 2061167606271082658ULL, 4122335212542165317ULL, 8244670425084330634ULL, 16489340850168661269ULL, 3297868170033732253ULL, 6595736340067464507ULL, 13191472680134929015ULL, 2638294536026985803ULL, 5276589072053971606ULL, 10553178144107943212ULL, 2110635628821588642ULL, 4221271257643177284ULL, 8442542515286354569ULL, 16885085030572709139ULL, 3377017006114541827ULL, 6754034012229083655ULL, 13508068024458167311ULL, 2701613604891633462ULL, 5403227209783266924ULL, 10806454419566533849ULL, 2161290883913306769ULL, 4322581767826613539ULL, 8645163535653227079ULL, 17290327071306454158ULL, 3458065414261290831ULL, 6916130828522581663ULL, 13832261657045163327ULL, 2766452331409032665ULL, 5532904662818065330ULL, 11065809325636130661ULL, 2213161865127226132ULL, 4426323730254452264ULL, 8852647460508904529ULL, 17705294921017809058ULL, 3541058984203561811ULL, 7082117968407123623ULL, 14164235936814247246ULL, 2832847187362849449ULL, 5665694374725698898ULL, 11331388749451397797ULL, 2266277749890279559ULL, 4532555499780559119ULL, 9065110999561118238ULL, 1813022199912223647ULL, 3626044399824447295ULL, 7252088799648894590ULL, 14504177599297789180ULL, 2900835519859557836ULL, 5801671039719115672ULL, 11603342079438231344ULL, 2320668415887646268ULL, 4641336831775292537ULL, 9282673663550585075ULL, 1856534732710117015ULL, 3713069465420234030ULL, 7426138930840468060ULL, 14852277861680936121ULL, 2970455572336187224ULL, 5940911144672374448ULL, 11881822289344748896ULL, 2376364457868949779ULL, 4752728915737899558ULL, 9505457831475799117ULL, 1901091566295159823ULL, 3802183132590319647ULL, 7604366265180639294ULL, 15208732530361278588ULL, 3041746506072255717ULL, 6083493012144511435ULL, 12166986024289022870ULL, 2433397204857804574ULL, 4866794409715609148ULL, 9733588819431218296ULL, 1946717763886243659ULL, 3893435527772487318ULL, 7786871055544974637ULL, 15573742111089949274ULL, 3114748422217989854ULL, 6229496844435979709ULL, 12458993688871959419ULL, 2491798737774391883ULL, 4983597475548783767ULL, 9967194951097567535ULL, 1993438990219513507ULL, 3986877980439027014ULL, 7973755960878054028ULL, 15947511921756108056ULL, 3189502384351221611ULL, 6379004768702443222ULL, 12758009537404886445ULL, 2551601907480977289ULL, 5103203814961954578ULL, 10206407629923909156ULL, 2041281525984781831ULL, 4082563051969563662ULL, 8165126103939127325ULL, 16330252207878254650ULL, 3266050441575650930ULL, 6532100883151301860ULL, 13064201766302603720ULL, 2612840353260520744ULL, 5225680706521041488ULL, 10451361413042082976ULL, 2090272282608416595ULL, 4180544565216833190ULL, 8361089130433666380ULL, 16722178260867332761ULL, 3344435652173466552ULL, 6688871304346933104ULL, 13377742608693866209ULL, 2675548521738773241ULL, 5351097043477546483ULL, 10702194086955092967ULL, 2140438817391018593ULL, 4280877634782037187ULL, 8561755269564074374ULL, 17123510539128148748ULL, 3424702107825629749ULL, 6849404215651259499ULL, 13698808431302518998ULL, 2739761686260503799ULL, 5479523372521007599ULL, 10959046745042015198ULL, 2191809349008403039ULL, 4383618698016806079ULL, 8767237396033612159ULL, 17534474792067224318ULL, 3506894958413444863ULL, 7013789916826889727ULL, 14027579833653779454ULL, 2805515966730755890ULL, 5611031933461511781ULL, 11222063866923023563ULL, 2244412773384604712ULL, 4488825546769209425ULL, 8977651093538418850ULL, 17955302187076837701ULL, 3591060437415367540ULL, 7182120874830735080ULL, 14364241749661470161ULL, 2872848349932294032ULL, 5745696699864588064ULL, 11491393399729176129ULL, 2298278679945835225ULL, 4596557359891670451ULL, 9193114719783340903ULL, 1838622943956668180ULL, 3677245887913336361ULL, 7354491775826672722ULL, 14708983551653345445ULL, 2941796710330669089ULL, 5883593420661338178ULL, 11767186841322676356ULL, 2353437368264535271ULL, 4706874736529070542ULL, 9413749473058141084ULL, 1882749894611628216ULL, 3765499789223256433ULL, 7530999578446512867ULL, 15061999156893025735ULL, 3012399831378605147ULL, 6024799662757210294ULL, 12049599325514420588ULL, 2409919865102884117ULL, 4819839730205768235ULL, 9639679460411536470ULL, 1927935892082307294ULL, 3855871784164614588ULL, 7711743568329229176ULL, 15423487136658458353ULL, 3084697427331691670ULL, 6169394854663383341ULL, 12338789709326766682ULL, 2467757941865353336ULL, 4935515883730706673ULL, 9871031767461413346ULL, 1974206353492282669ULL, 3948412706984565338ULL, 7896825413969130677ULL, 15793650827938261354ULL, 3158730165587652270ULL, 6317460331175304541ULL, 12634920662350609083ULL, 2526984132470121816ULL, 5053968264940243633ULL, 10107936529880487266ULL, 2021587305976097453ULL, 4043174611952194906ULL, 8086349223904389813ULL, 16172698447808779626ULL, 3234539689561755925ULL, 6469079379123511850ULL, 12938158758247023701ULL, 2587631751649404740ULL, 5175263503298809480ULL, 10350527006597618960ULL, 2070105401319523792ULL, 4140210802639047584ULL, 8280421605278095168ULL, 16560843210556190337ULL, 3312168642111238067ULL, 6624337284222476135ULL, 13248674568444952270ULL, 2649734913688990454ULL, 5299469827377980908ULL, 10598939654755961816ULL, 2119787930951192363ULL, 4239575861902384726ULL, 8479151723804769452ULL, 16958303447609538905ULL, 3391660689521907781ULL, 6783321379043815562ULL, 13566642758087631124ULL, 2713328551617526224ULL, 5426657103235052449ULL, 10853314206470104899ULL, 2170662841294020979ULL, 4341325682588041959ULL, 8682651365176083919ULL, 17365302730352167839ULL, 3473060546070433567ULL, 6946121092140867135ULL, 13892242184281734271ULL, 2778448436856346854ULL, 5556896873712693708ULL, 11113793747425387417ULL, 2222758749485077483ULL, 4445517498970154966ULL, 8891034997940309933ULL, 17782069995880619867ULL, 3556413999176123973ULL, 7112827998352247947ULL, 14225655996704495894ULL, 2845131199340899178ULL, 5690262398681798357ULL, 11380524797363596715ULL, 2276104959472719343ULL, 4552209918945438686ULL, 9104419837890877372ULL, 1820883967578175474ULL, 3641767935156350948ULL, 7283535870312701897ULL, 14567071740625403795ULL, 2913414348125080759ULL, 5826828696250161518ULL, 11653657392500323036ULL, 2330731478500064607ULL, 4661462957000129214ULL, 9322925914000258429ULL, 1864585182800051685ULL, 3729170365600103371ULL, 7458340731200206743ULL, 14916681462400413486ULL, 2983336292480082697ULL, 5966672584960165394ULL, 11933345169920330789ULL, 2386669033984066157ULL, 4773338067968132315ULL, 9546676135936264631ULL, 1909335227187252926ULL, 3818670454374505852ULL, 7637340908749011705ULL, 15274681817498023410ULL, 3054936363499604682ULL, 6109872726999209364ULL, 12219745453998418728ULL, 2443949090799683745ULL, 4887898181599367491ULL, 9775796363198734982ULL, 1955159272639746996ULL, 3910318545279493993ULL, 7820637090558987986ULL, 15641274181117975972ULL, 3128254836223595194ULL, 6256509672447190388ULL, 12513019344894380777ULL, 2502603868978876155ULL, 5005207737957752311ULL, 10010415475915504622ULL, 2002083095183100924ULL, 4004166190366201848ULL, 8008332380732403697ULL, 16016664761464807395ULL, 3203332952292961479ULL, 6406665904585922958ULL, 12813331809171845916ULL, 2562666361834369183ULL, 5125332723668738366ULL, 10250665447337476733ULL, 2050133089467495346ULL, 4100266178934990693ULL, 8200532357869981386ULL, 16401064715739962772ULL, 3280212943147992554ULL, 6560425886295985109ULL, 13120851772591970218ULL, 2624170354518394043ULL, 5248340709036788087ULL, 10496681418073576174ULL, 2099336283614715234ULL, 4198672567229430469ULL, 8397345134458860939ULL, 16794690268917721879ULL, 3358938053783544375ULL, 6717876107567088751ULL, 13435752215134177503ULL, 2687150443026835500ULL, 5374300886053671001ULL, 10748601772107342002ULL, 2149720354421468400ULL, 4299440708842936801ULL, 8598881417685873602ULL, 17197762835371747204ULL, 3439552567074349440ULL, 6879105134148698881ULL, 13758210268297397763ULL, 2751642053659479552ULL, 5503284107318959105ULL, 11006568214637918210ULL, 2201313642927583642ULL, 4402627285855167284ULL, 8805254571710334568ULL, 17610509143420669137ULL, 3522101828684133827ULL, 7044203657368267654ULL, 14088407314736535309ULL, 2817681462947307061ULL, 5635362925894614123ULL, 11270725851789228247ULL, 2254145170357845649ULL, 4508290340715691299ULL, 9016580681431382598ULL, 18033161362862765196ULL, 3606632272572553039ULL, 7213264545145106078ULL, 14426529090290212157ULL, 2885305818058042431ULL, 5770611636116084862ULL, 11541223272232169725ULL, 2308244654446433945ULL, 4616489308892867890ULL, 9232978617785735780ULL, 1846595723557147156ULL, 3693191447114294312ULL, 7386382894228588624ULL, 14772765788457177249ULL, 2954553157691435449ULL, 5909106315382870899ULL, 11818212630765741799ULL, 2363642526153148359ULL, 4727285052306296719ULL, 9454570104612593439ULL, 1890914020922518687ULL, 3781828041845037375ULL, 7563656083690074751ULL, 15127312167380149503ULL, 3025462433476029900ULL, 6050924866952059801ULL, 12101849733904119602ULL, 2420369946780823920ULL, 4840739893561647841ULL, 9681479787123295682ULL, 1936295957424659136ULL, 3872591914849318272ULL, 7745183829698636545ULL, 15490367659397273091ULL, 3098073531879454618ULL, 6196147063758909236ULL, 12392294127517818473ULL, 2478458825503563694ULL, 4956917651007127389ULL, 9913835302014254778ULL, 1982767060402850955ULL, 3965534120805701911ULL, 7931068241611403822ULL, 15862136483222807645ULL, 3172427296644561529ULL, 6344854593289123058ULL, 12689709186578246116ULL, 2537941837315649223ULL, 5075883674631298446ULL, 10151767349262596893ULL, 2030353469852519378ULL, 4060706939705038757ULL, 8121413879410077514ULL, 16242827758820155028ULL, 3248565551764031005ULL, 6497131103528062011ULL, 12994262207056124023ULL, 2598852441411224804ULL, 5197704882822449609ULL, 10395409765644899218ULL, 2079081953128979843ULL, 4158163906257959687ULL, 8316327812515919374ULL, 16632655625031838749ULL, 3326531125006367749ULL, 6653062250012735499ULL, 13306124500025470999ULL, 2661224900005094199ULL, 5322449800010188399ULL, 10644899600020376799ULL, 2128979920004075359ULL, 4257959840008150719ULL, 8515919680016301439ULL, 17031839360032602879ULL, 3406367872006520575ULL, 6812735744013041151ULL, 13625471488026082303ULL, 2725094297605216460ULL, 5450188595210432921ULL, 10900377190420865842ULL, 2180075438084173168ULL, 4360150876168346337ULL, 8720301752336692674ULL, 17440603504673385348ULL, 3488120700934677069ULL, 6976241401869354139ULL, 13952482803738708279ULL, 2790496560747741655ULL, 5580993121495483311ULL, 11161986242990966623ULL, 2232397248598193324ULL, 4464794497196386649ULL, 8929588994392773298ULL, 17859177988785546597ULL, 3571835597757109319ULL, 7143671195514218638ULL, 14287342391028437277ULL, 2857468478205687455ULL, 5714936956411374911ULL, 11429873912822749822ULL, 2285974782564549964ULL, 4571949565129099928ULL, 9143899130258199857ULL, 1828779826051639971ULL, 3657559652103279943ULL, 7315119304206559886ULL, 14630238608413119772ULL, 2926047721682623954ULL, 5852095443365247908ULL, 11704190886730495817ULL, 2340838177346099163ULL, 4681676354692198327ULL, 9363352709384396654ULL, 1872670541876879330ULL, 3745341083753758661ULL, 7490682167507517323ULL, 14981364335015034646ULL, 2996272867003006929ULL, 5992545734006013858ULL, 11985091468012027717ULL, 2397018293602405543ULL, 4794036587204811087ULL, 9588073174409622174ULL, 1917614634881924434ULL, 3835229269763848869ULL, 7670458539527697739ULL, 15340917079055395478ULL, 3068183415811079095ULL, 6136366831622158191ULL, 12272733663244316382ULL, 2454546732648863276ULL, 4909093465297726553ULL, 9818186930595453106ULL, 1963637386119090621ULL, 3927274772238181242ULL, 7854549544476362484ULL, 15709099088952724969ULL, 3141819817790544993ULL, 6283639635581089987ULL, 12567279271162179975ULL, 2513455854232435995ULL, 5026911708464871990ULL, 10053823416929743980ULL, 2010764683385948796ULL, 4021529366771897592ULL, 8043058733543795184ULL, 16086117467087590369ULL, 3217223493417518073ULL, 6434446986835036147ULL, 12868893973670072295ULL, 2573778794734014459ULL, 5147557589468028918ULL, 10295115178936057836ULL, 2059023035787211567ULL, 4118046071574423134ULL, 8236092143148846269ULL, 16472184286297692538ULL, 3294436857259538507ULL, 6588873714519077015ULL, 13177747429038154030ULL, 2635549485807630806ULL, 5271098971615261612ULL, 10542197943230523224ULL, 2108439588646104644ULL, 4216879177292209289ULL, 8433758354584418579ULL, 16867516709168837158ULL, 3373503341833767431ULL, 6747006683667534863ULL, 13494013367335069727ULL, 2698802673467013945ULL, 5397605346934027890ULL, 10795210693868055781ULL, 2159042138773611156ULL, 4318084277547222312ULL, 8636168555094444625ULL, 17272337110188889250ULL, 3454467422037777850ULL, 6908934844075555700ULL, 13817869688151111400ULL, 2763573937630222280ULL, 5527147875260444560ULL, 11054295750520889120ULL, 2210859150104177824ULL, 4421718300208355648ULL, 8843436600416711296ULL, 17686873200833422592ULL, 3537374640166684518ULL, 7074749280333369037ULL, 14149498560666738074ULL, 2829899712133347614ULL, 5659799424266695229ULL, 11319598848533390459ULL, 2263919769706678091ULL, 4527839539413356183ULL, 9055679078826712367ULL, 1811135815765342473ULL, 3622271631530684947ULL, 7244543263061369894ULL, 14489086526122739788ULL, 2897817305224547957ULL, 5795634610449095915ULL, 11591269220898191830ULL, 2318253844179638366ULL, 4636507688359276732ULL, 9273015376718553464ULL, 1854603075343710692ULL, 3709206150687421385ULL, 7418412301374842771ULL, 14836824602749685542ULL, 2967364920549937108ULL, 5934729841099874217ULL, 11869459682199748434ULL, 2373891936439949686ULL, 4747783872879899373ULL, 9495567745759798747ULL, 1899113549151959749ULL, 3798227098303919498ULL, 7596454196607838997ULL, 15192908393215677995ULL, 3038581678643135599ULL, 6077163357286271198ULL, 12154326714572542396ULL, 2430865342914508479ULL, 4861730685829016958ULL, 9723461371658033917ULL, 1944692274331606783ULL, 3889384548663213566ULL, 7778769097326427133ULL, 15557538194652854267ULL, 3111507638930570853ULL, 6223015277861141707ULL, 12446030555722283414ULL, 2489206111144456682ULL, 4978412222288913365ULL, 9956824444577826731ULL, 1991364888915565346ULL, 3982729777831130692ULL, 7965459555662261385ULL, 15930919111324522770ULL, 3186183822264904554ULL, 6372367644529809108ULL, 12744735289059618216ULL, 2548947057811923643ULL, 5097894115623847286ULL, 10195788231247694572ULL, 2039157646249538914ULL, 4078315292499077829ULL, 8156630584998155658ULL, 16313261169996311316ULL, 3262652233999262263ULL, 6525304467998524526ULL, 13050608935997049053ULL, 2610121787199409810ULL, 5220243574398819621ULL, 10440487148797639242ULL, 2088097429759527848ULL, 4176194859519055697ULL, 8352389719038111394ULL, 16704779438076222788ULL, 3340955887615244557ULL, 6681911775230489115ULL, 13363823550460978230ULL, 2672764710092195646ULL, 5345529420184391292ULL, 10691058840368782584ULL, 2138211768073756516ULL, 4276423536147513033ULL, 8552847072295026067ULL, 17105694144590052135ULL, 3421138828918010427ULL, 6842277657836020854ULL, 13684555315672041708ULL, 2736911063134408341ULL, 5473822126268816683ULL, 10947644252537633366ULL, 2189528850507526673ULL, 4379057701015053346ULL, 8758115402030106693ULL, 17516230804060213386ULL, 3503246160812042677ULL, 7006492321624085354ULL, 14012984643248170709ULL, 2802596928649634141ULL, 5605193857299268283ULL, 11210387714598536567ULL, 2242077542919707313ULL, 4484155085839414626ULL, 8968310171678829253ULL, 17936620343357658507ULL, 3587324068671531701ULL, 7174648137343063403ULL, 14349296274686126806ULL, 2869859254937225361ULL, 5739718509874450722ULL, 11479437019748901445ULL, 2295887403949780289ULL, 4591774807899560578ULL, 9183549615799121156ULL, 1836709923159824231ULL, 3673419846319648462ULL, 7346839692639296924ULL, 14693679385278593849ULL, 2938735877055718769ULL, 5877471754111437539ULL, 11754943508222875079ULL, 2350988701644575015ULL, 4701977403289150031ULL, 9403954806578300063ULL, 1880790961315660012ULL, 3761581922631320025ULL, 7523163845262640050ULL, 15046327690525280101ULL, 3009265538105056020ULL, 6018531076210112040ULL, 12037062152420224081ULL, 2407412430484044816ULL, 4814824860968089632ULL, 9629649721936179265ULL, 1925929944387235853ULL, 3851859888774471706ULL, 7703719777548943412ULL, 15407439555097886824ULL, 3081487911019577364ULL, 6162975822039154729ULL, 12325951644078309459ULL, 2465190328815661891ULL, 4930380657631323783ULL, 9860761315262647567ULL, 1972152263052529513ULL, 3944304526105059027ULL, 7888609052210118054ULL, 15777218104420236108ULL, 3155443620884047221ULL, 6310887241768094443ULL, 12621774483536188886ULL, 2524354896707237777ULL, 5048709793414475554ULL, 10097419586828951109ULL, 2019483917365790221ULL, 4038967834731580443ULL, 8077935669463160887ULL, 16155871338926321774ULL, 3231174267785264354ULL, 6462348535570528709ULL, 12924697071141057419ULL, 2584939414228211483ULL, 5169878828456422967ULL, 10339757656912845935ULL, 2067951531382569187ULL, 4135903062765138374ULL, 8271806125530276748ULL, 16543612251060553497ULL, 3308722450212110699ULL, 6617444900424221398ULL, 13234889800848442797ULL, 2646977960169688559ULL, 5293955920339377119ULL, 10587911840678754238ULL, 2117582368135750847ULL, 4235164736271501695ULL, 8470329472543003390ULL, 16940658945086006781ULL, 3388131789017201356ULL, 6776263578034402712ULL, 13552527156068805425ULL, 2710505431213761085ULL, 5421010862427522170ULL, 10842021724855044340ULL, 2168404344971008868ULL, 4336808689942017736ULL, 8673617379884035472ULL, 17347234759768070944ULL, 3469446951953614188ULL, 6938893903907228377ULL, 13877787807814456755ULL, 2775557561562891351ULL, 5551115123125782702ULL, 11102230246251565404ULL, 2220446049250313080ULL, 4440892098500626161ULL, 8881784197001252323ULL, 17763568394002504646ULL, 3552713678800500929ULL, 7105427357601001858ULL, 14210854715202003717ULL, 2842170943040400743ULL, 5684341886080801486ULL, 11368683772161602973ULL, 2273736754432320594ULL, 4547473508864641189ULL, 9094947017729282379ULL, 1818989403545856475ULL, 3637978807091712951ULL, 7275957614183425903ULL, 14551915228366851806ULL, 2910383045673370361ULL, 5820766091346740722ULL, 11641532182693481445ULL, 2328306436538696289ULL, 4656612873077392578ULL, 9313225746154785156ULL, 1862645149230957031ULL, 3725290298461914062ULL, 7450580596923828125ULL, 14901161193847656250ULL, 2980232238769531250ULL, 5960464477539062500ULL, 11920928955078125000ULL, 2384185791015625000ULL, 4768371582031250000ULL, 9536743164062500000ULL, 1907348632812500000ULL, 3814697265625000000ULL, 7629394531250000000ULL, 15258789062500000000ULL, 3051757812500000000ULL, 6103515625000000000ULL, 12207031250000000000ULL, 2441406250000000000ULL, 4882812500000000000ULL, 9765625000000000000ULL, 1953125000000000000ULL, 3906250000000000000ULL, 7812500000000000000ULL, 15625000000000000000ULL, 3125000000000000000ULL, 6250000000000000000ULL, 12500000000000000000ULL, 2500000000000000000ULL, 5000000000000000000ULL, 10000000000000000000ULL, 2000000000000000000ULL, 4000000000000000000ULL, 8000000000000000000ULL, 16000000000000000000ULL, 3200000000000000000ULL, 6400000000000000000ULL, 12800000000000000000ULL, 2560000000000000000ULL, 5120000000000000000ULL, 10240000000000000000ULL, 2048000000000000000ULL, 4096000000000000000ULL, 8192000000000000000ULL, 16384000000000000000ULL, 3276800000000000000ULL, 6553600000000000000ULL, 13107200000000000000ULL, 2621440000000000000ULL, 5242880000000000000ULL, 10485760000000000000ULL, 2097152000000000000ULL, 4194304000000000000ULL, 8388608000000000000ULL, 16777216000000000000ULL, 3355443200000000000ULL, 6710886400000000000ULL, 13421772800000000000ULL, 2684354560000000000ULL, 5368709120000000000ULL, 10737418240000000000ULL, 2147483648000000000ULL, 4294967296000000000ULL, 8589934592000000000ULL, 17179869184000000000ULL, 3435973836800000000ULL, 6871947673600000000ULL, 13743895347200000000ULL, 2748779069440000000ULL, 5497558138880000000ULL, 10995116277760000000ULL, 2199023255552000000ULL, 4398046511104000000ULL, 8796093022208000000ULL, 17592186044416000000ULL, 3518437208883200000ULL, 7036874417766400000ULL, 14073748835532800000ULL, 2814749767106560000ULL, 5629499534213120000ULL, 11258999068426240000ULL, 2251799813685248000ULL, 4503599627370496000ULL, 9007199254740992000ULL, 18014398509481984000ULL, 3602879701896396800ULL, 7205759403792793600ULL, 14411518807585587200ULL, 2882303761517117440ULL, 5764607523034234880ULL, 11529215046068469760ULL, 2305843009213693952ULL, 4611686018427387904ULL, 9223372036854775808ULL, 1844674407370955161ULL, 3689348814741910323ULL, 7378697629483820646ULL, 14757395258967641292ULL, 2951479051793528258ULL, 5902958103587056517ULL, 11805916207174113034ULL, 2361183241434822606ULL, 4722366482869645213ULL, 9444732965739290427ULL, 1888946593147858085ULL, 3777893186295716170ULL, 7555786372591432341ULL, 15111572745182864683ULL, 3022314549036572936ULL, 6044629098073145873ULL, 12089258196146291747ULL, 2417851639229258349ULL, 4835703278458516698ULL, 9671406556917033397ULL, 1934281311383406679ULL, 3868562622766813359ULL, 7737125245533626718ULL, 15474250491067253436ULL, 3094850098213450687ULL, 6189700196426901374ULL, 12379400392853802748ULL, 2475880078570760549ULL, 4951760157141521099ULL, 9903520314283042199ULL, 1980704062856608439ULL, 3961408125713216879ULL, 7922816251426433759ULL, 15845632502852867518ULL, 3169126500570573503ULL, 6338253001141147007ULL, 12676506002282294014ULL, 2535301200456458802ULL, 5070602400912917605ULL, 10141204801825835211ULL, 2028240960365167042ULL, 4056481920730334084ULL, 8112963841460668169ULL, 16225927682921336339ULL, 3245185536584267267ULL, 6490371073168534535ULL, 12980742146337069071ULL, 2596148429267413814ULL, 5192296858534827628ULL, 10384593717069655257ULL, 2076918743413931051ULL, 4153837486827862102ULL, 8307674973655724205ULL, 16615349947311448411ULL, 3323069989462289682ULL, 6646139978924579364ULL, 13292279957849158729ULL, 2658455991569831745ULL, 5316911983139663491ULL, 10633823966279326983ULL, 2126764793255865396ULL, 4253529586511730793ULL, 8507059173023461586ULL, 17014118346046923173ULL, 3402823669209384634ULL, 6805647338418769269ULL, 13611294676837538538ULL, 2722258935367507707ULL, 5444517870735015415ULL, 10889035741470030830ULL, 2177807148294006166ULL, 4355614296588012332ULL, 8711228593176024664ULL, 17422457186352049329ULL, 3484491437270409865ULL, 6968982874540819731ULL, 13937965749081639463ULL, 2787593149816327892ULL, 5575186299632655785ULL, 11150372599265311570ULL, 2230074519853062314ULL, 4460149039706124628ULL, 8920298079412249256ULL, 17840596158824498513ULL, 3568119231764899702ULL, 7136238463529799405ULL, 14272476927059598810ULL, 2854495385411919762ULL, 5708990770823839524ULL, 11417981541647679048ULL, 2283596308329535809ULL, 4567192616659071619ULL, 9134385233318143238ULL, 1826877046663628647ULL, 3653754093327257295ULL, 7307508186654514591ULL, 14615016373309029182ULL, 2923003274661805836ULL, 5846006549323611672ULL, 11692013098647223345ULL, 2338402619729444669ULL, 4676805239458889338ULL, 9353610478917778676ULL, 1870722095783555735ULL, 3741444191567111470ULL, 7482888383134222941ULL, 14965776766268445882ULL, 2993155353253689176ULL, 5986310706507378352ULL, 11972621413014756705ULL, 2394524282602951341ULL, 4789048565205902682ULL, 9578097130411805364ULL, 1915619426082361072ULL, 3831238852164722145ULL, 7662477704329444291ULL, 15324955408658888583ULL, 3064991081731777716ULL, 6129982163463555433ULL, 12259964326927110866ULL, 2451992865385422173ULL, 4903985730770844346ULL, 9807971461541688693ULL, 1961594292308337738ULL, 3923188584616675477ULL, 7846377169233350954ULL, 15692754338466701909ULL, 3138550867693340381ULL, 6277101735386680763ULL, 12554203470773361527ULL, 2510840694154672305ULL, 5021681388309344611ULL, 10043362776618689222ULL, 2008672555323737844ULL, 4017345110647475688ULL, 8034690221294951377ULL, 16069380442589902755ULL, 3213876088517980551ULL, 6427752177035961102ULL, 12855504354071922204ULL, 2571100870814384440ULL, 5142201741628768881ULL, 10284403483257537763ULL, 2056880696651507552ULL, 4113761393303015105ULL, 8227522786606030210ULL, 16455045573212060421ULL, 3291009114642412084ULL, 6582018229284824168ULL, 13164036458569648337ULL, 2632807291713929667ULL, 5265614583427859334ULL, 10531229166855718669ULL, 2106245833371143733ULL, 4212491666742287467ULL, 8424983333484574935ULL, 16849966666969149871ULL, 3369993333393829974ULL, 6739986666787659948ULL, 13479973333575319897ULL, 2695994666715063979ULL, 5391989333430127958ULL, 10783978666860255917ULL, 2156795733372051183ULL, 4313591466744102367ULL, 8627182933488204734ULL, 17254365866976409468ULL, 3450873173395281893ULL, 6901746346790563787ULL, 13803492693581127574ULL, 2760698538716225514ULL, 5521397077432451029ULL, 11042794154864902059ULL, 2208558830972980411ULL, 4417117661945960823ULL, 8834235323891921647ULL, 17668470647783843295ULL, 3533694129556768659ULL, 7067388259113537318ULL, 14134776518227074636ULL, 2826955303645414927ULL, 5653910607290829854ULL, 11307821214581659709ULL, 2261564242916331941ULL, 4523128485832663883ULL, 9046256971665327767ULL, 18092513943330655534ULL, 3618502788666131106ULL, 7237005577332262213ULL, 14474011154664524427ULL, 2894802230932904885ULL, 5789604461865809771ULL, 11579208923731619542ULL, 2315841784746323908ULL, 4631683569492647816ULL, 9263367138985295633ULL, 1852673427797059126ULL, 3705346855594118253ULL, 7410693711188236507ULL, 14821387422376473014ULL, 2964277484475294602ULL, 5928554968950589205ULL, 11857109937901178411ULL, 2371421987580235682ULL, 4742843975160471364ULL, 9485687950320942729ULL, 1897137590064188545ULL, 3794275180128377091ULL, 7588550360256754183ULL, 15177100720513508366ULL, 3035420144102701673ULL, 6070840288205403346ULL, 12141680576410806693ULL, 2428336115282161338ULL, 4856672230564322677ULL, 9713344461128645354ULL, 1942668892225729070ULL, 3885337784451458141ULL, 7770675568902916283ULL, 15541351137805832567ULL, 3108270227561166513ULL, 6216540455122333026ULL, 12433080910244666053ULL, 2486616182048933210ULL, 4973232364097866421ULL, 9946464728195732843ULL, 1989292945639146568ULL, 3978585891278293137ULL, 7957171782556586274ULL, 15914343565113172548ULL, 3182868713022634509ULL, 6365737426045269019ULL, 12731474852090538039ULL, 2546294970418107607ULL, 5092589940836215215ULL, 10185179881672430431ULL, 2037035976334486086ULL, 4074071952668972172ULL, 8148143905337944345ULL, 16296287810675888690ULL, 3259257562135177738ULL, 6518515124270355476ULL, 13037030248540710952ULL, 2607406049708142190ULL, 5214812099416284380ULL, 10429624198832568761ULL, 2085924839766513752ULL, 4171849679533027504ULL, 8343699359066055009ULL, 16687398718132110018ULL, 3337479743626422003ULL, 6674959487252844007ULL, 13349918974505688014ULL, 2669983794901137602ULL, 5339967589802275205ULL, 10679935179604550411ULL, 2135987035920910082ULL, 4271974071841820164ULL, 8543948143683640329ULL, 17087896287367280659ULL, 3417579257473456131ULL, 6835158514946912263ULL, 13670317029893824527ULL, 2734063405978764905ULL, 5468126811957529810ULL, 10936253623915059621ULL, 2187250724783011924ULL, 4374501449566023848ULL, 8749002899132047697ULL, 17498005798264095394ULL, 3499601159652819078ULL, 6999202319305638157ULL, 13998404638611276315ULL, 2799680927722255263ULL, 5599361855444510526ULL, 11198723710889021052ULL, 2239744742177804210ULL, 4479489484355608421ULL, 8958978968711216842ULL, 17917957937422433684ULL, 3583591587484486736ULL, 7167183174968973473ULL, 14334366349937946947ULL, 2866873269987589389ULL, 5733746539975178779ULL, 11467493079950357558ULL, 2293498615990071511ULL, 4586997231980143023ULL, 9173994463960286046ULL, 1834798892792057209ULL, 3669597785584114418ULL, 7339195571168228837ULL, 14678391142336457674ULL, 2935678228467291534ULL, 5871356456934583069ULL, 11742712913869166139ULL, 2348542582773833227ULL, 4697085165547666455ULL, 9394170331095332911ULL, 1878834066219066582ULL, 3757668132438133164ULL, 7515336264876266329ULL, 15030672529752532658ULL, 3006134505950506531ULL, 6012269011901013063ULL, 12024538023802026126ULL, 2404907604760405225ULL, 4809815209520810450ULL, 9619630419041620901ULL, 1923926083808324180ULL, 3847852167616648360ULL, 7695704335233296721ULL, 15391408670466593442ULL, 3078281734093318688ULL, 6156563468186637376ULL, 12313126936373274753ULL, 2462625387274654950ULL, 4925250774549309901ULL, 9850501549098619803ULL, 1970100309819723960ULL, 3940200619639447921ULL, 7880401239278895842ULL, 15760802478557791684ULL, 3152160495711558336ULL, 6304320991423116673ULL, 12608641982846233347ULL, 2521728396569246669ULL, 5043456793138493339ULL, 10086913586276986678ULL, 2017382717255397335ULL, 4034765434510794671ULL, 8069530869021589342ULL, 16139061738043178685ULL, 3227812347608635737ULL, 6455624695217271474ULL, 12911249390434542948ULL, 2582249878086908589ULL, 5164499756173817179ULL, 10328999512347634358ULL, 2065799902469526871ULL, 4131599804939053743ULL, 8263199609878107486ULL, 16526399219756214973ULL, 3305279843951242994ULL, 6610559687902485989ULL, 13221119375804971979ULL, 2644223875160994395ULL, 5288447750321988791ULL, 10576895500643977583ULL, 2115379100128795516ULL, 4230758200257591033ULL, 8461516400515182066ULL, 16923032801030364133ULL, 3384606560206072826ULL, 6769213120412145653ULL, 13538426240824291306ULL, 2707685248164858261ULL, 5415370496329716522ULL, 10830740992659433045ULL, 2166148198531886609ULL, 4332296397063773218ULL, 8664592794127546436ULL, 17329185588255092872ULL, 3465837117651018574ULL, 6931674235302037148ULL, 13863348470604074297ULL, 2772669694120814859ULL, 5545339388241629719ULL, 11090678776483259438ULL, 2218135755296651887ULL, 4436271510593303775ULL, 8872543021186607550ULL, 17745086042373215101ULL, 3549017208474643020ULL, 7098034416949286040ULL, 14196068833898572081ULL, 2839213766779714416ULL, 5678427533559428832ULL, 11356855067118857664ULL, 2271371013423771532ULL, 4542742026847543065ULL, 9085484053695086131ULL, 1817096810739017226ULL, 3634193621478034452ULL, 7268387242956068905ULL, 14536774485912137810ULL, 2907354897182427562ULL, 5814709794364855124ULL, 11629419588729710248ULL, 2325883917745942049ULL, 4651767835491884099ULL, 9303535670983768199ULL, 1860707134196753639ULL, 3721414268393507279ULL, 7442828536787014559ULL, 14885657073574029118ULL, 2977131414714805823ULL, 5954262829429611647ULL, 11908525658859223294ULL, 2381705131771844658ULL, 4763410263543689317ULL, 9526820527087378635ULL, 1905364105417475727ULL, 3810728210834951454ULL, 7621456421669902908ULL, 15242912843339805817ULL, 3048582568667961163ULL, 6097165137335922326ULL, 12194330274671844653ULL, 2438866054934368930ULL, 4877732109868737861ULL, 9755464219737475723ULL, 1951092843947495144ULL, 3902185687894990289ULL, 7804371375789980578ULL, 15608742751579961156ULL, 3121748550315992231ULL, 6243497100631984462ULL, 12486994201263968925ULL, 2497398840252793785ULL, 4994797680505587570ULL, 9989595361011175140ULL, 1997919072202235028ULL, 3995838144404470056ULL, 7991676288808940112ULL, 15983352577617880224ULL, 3196670515523576044ULL, 6393341031047152089ULL, 12786682062094304179ULL, 2557336412418860835ULL, 5114672824837721671ULL, 10229345649675443343ULL, 2045869129935088668ULL, 4091738259870177337ULL, 8183476519740354675ULL, 16366953039480709350ULL, 3273390607896141870ULL, 6546781215792283740ULL, 13093562431584567480ULL, 2618712486316913496ULL, 5237424972633826992ULL, 10474849945267653984ULL, 2094969989053530796ULL, 4189939978107061593ULL, 8379879956214123187ULL, 16759759912428246374ULL, 3351951982485649274ULL, 6703903964971298549ULL, 13407807929942597099ULL, 2681561585988519419ULL, 5363123171977038839ULL, 10726246343954077679ULL, 2145249268790815535ULL, 4290498537581631071ULL, 8580997075163262143ULL, 17161994150326524287ULL, 3432398830065304857ULL, 6864797660130609714ULL, 13729595320261219429ULL, 2745919064052243885ULL, 5491838128104487771ULL, 10983676256208975543ULL, 2196735251241795108ULL, 4393470502483590217ULL, 8786941004967180435ULL, 17573882009934360870ULL, 3514776401986872174ULL, 7029552803973744348ULL, 14059105607947488696ULL, 2811821121589497739ULL, 5623642243178995478ULL, 11247284486357990957ULL, 2249456897271598191ULL, 4498913794543196382ULL, 8997827589086392765ULL, 17995655178172785531ULL, 3599131035634557106ULL, 7198262071269114212ULL, 14396524142538228424ULL, 2879304828507645684ULL, 5758609657015291369ULL, 11517219314030582739ULL, 2303443862806116547ULL, 4606887725612233095ULL, 9213775451224466191ULL, 1842755090244893238ULL, 3685510180489786476ULL, 7371020360979572953ULL, 14742040721959145907ULL, 2948408144391829181ULL, 5896816288783658362ULL, 11793632577567316725ULL, 2358726515513463345ULL, 4717453031026926690ULL, 9434906062053853380ULL, 1886981212410770676ULL, 3773962424821541352ULL, 7547924849643082704ULL, 15095849699286165408ULL, 3019169939857233081ULL, 6038339879714466163ULL, 12076679759428932327ULL, 2415335951885786465ULL, 4830671903771572930ULL, 9661343807543145861ULL, 1932268761508629172ULL, 3864537523017258344ULL, 7729075046034516689ULL, 15458150092069033378ULL, 3091630018413806675ULL, 6183260036827613351ULL, 12366520073655226703ULL, 2473304014731045340ULL, 4946608029462090681ULL, 9893216058924181362ULL, 1978643211784836272ULL, 3957286423569672544ULL, 7914572847139345089ULL, 15829145694278690179ULL, 3165829138855738035ULL, 6331658277711476071ULL, 12663316555422952143ULL, 2532663311084590428ULL, 5065326622169180857ULL, 10130653244338361715ULL, 2026130648867672343ULL, 4052261297735344686ULL, 8104522595470689372ULL, 16209045190941378744ULL, 3241809038188275748ULL, 6483618076376551497ULL, 12967236152753102995ULL, 2593447230550620599ULL, 5186894461101241198ULL, 10373788922202482396ULL, 2074757784440496479ULL, 4149515568880992958ULL, 8299031137761985917ULL, 16598062275523971834ULL, 3319612455104794366ULL, 6639224910209588733ULL, 13278449820419177467ULL, 2655689964083835493ULL, 5311379928167670986ULL, 10622759856335341973ULL, 2124551971267068394ULL, 4249103942534136789ULL, 8498207885068273579ULL, 16996415770136547158ULL, 3399283154027309431ULL, 6798566308054618863ULL, 13597132616109237726ULL, 2719426523221847545ULL, 5438853046443695090ULL, 10877706092887390181ULL, 2175541218577478036ULL, 4351082437154956072ULL, 8702164874309912144ULL, 17404329748619824289ULL, 3480865949723964857ULL, 6961731899447929715ULL, 13923463798895859431ULL, 2784692759779171886ULL, 5569385519558343772ULL, 11138771039116687545ULL, 2227754207823337509ULL, 4455508415646675018ULL, 8911016831293350036ULL, 17822033662586700072ULL, 3564406732517340014ULL, 7128813465034680029ULL, 14257626930069360058ULL, 2851525386013872011ULL, 5703050772027744023ULL, 11406101544055488046ULL, 2281220308811097609ULL, 4562440617622195218ULL, 9124881235244390437ULL, 1824976247048878087ULL, 3649952494097756174ULL, 7299904988195512349ULL, 14599809976391024699ULL, 2919961995278204939ULL, 5839923990556409879ULL, 11679847981112819759ULL, 2335969596222563951ULL, 4671939192445127903ULL, 9343878384890255807ULL, 1868775676978051161ULL, 3737551353956102323ULL, 7475102707912204646ULL, 14950205415824409292ULL, 2990041083164881858ULL, 5980082166329763716ULL, 11960164332659527433ULL, 2392032866531905486ULL, 4784065733063810973ULL, 9568131466127621947ULL, 1913626293225524389ULL, 3827252586451048778ULL, 7654505172902097557ULL, 15309010345804195115ULL, 3061802069160839023ULL, 6123604138321678046ULL, 12247208276643356092ULL, 2449441655328671218ULL, 4898883310657342436ULL, 9797766621314684873ULL, 1959553324262936974ULL, 3919106648525873949ULL, 7838213297051747899ULL, 15676426594103495798ULL, 3135285318820699159ULL, 6270570637641398319ULL, 12541141275282796638ULL, 2508228255056559327ULL, 5016456510113118655ULL, 10032913020226237310ULL, 2006582604045247462ULL, 4013165208090494924ULL, 8026330416180989848ULL, 16052660832361979697ULL, 3210532166472395939ULL, 6421064332944791878ULL, 12842128665889583757ULL, 2568425733177916751ULL, 5136851466355833503ULL, 10273702932711667006ULL, 2054740586542333401ULL, 4109481173084666802ULL, 8218962346169333605ULL, 16437924692338667210ULL, 3287584938467733442ULL, 6575169876935466884ULL, 13150339753870933768ULL, 2630067950774186753ULL, 5260135901548373507ULL, 10520271803096747014ULL, 2104054360619349402ULL, 4208108721238698805ULL, 8416217442477397611ULL, 16832434884954795223ULL, 3366486976990959044ULL, 6732973953981918089ULL, 13465947907963836178ULL, 2693189581592767235ULL, 5386379163185534471ULL, 10772758326371068942ULL, 2154551665274213788ULL, 4309103330548427577ULL, 8618206661096855154ULL, 17236413322193710308ULL, 3447282664438742061ULL, 6894565328877484123ULL, 13789130657754968246ULL, 2757826131550993649ULL, 5515652263101987298ULL, 11031304526203974597ULL, 2206260905240794919ULL, 4412521810481589838ULL, 8825043620963179677ULL, 17650087241926359355ULL, 3530017448385271871ULL, 7060034896770543742ULL, 14120069793541087484ULL, 2824013958708217496ULL, 5648027917416434993ULL, 11296055834832869987ULL, 2259211166966573997ULL, 4518422333933147995ULL, 9036844667866295990ULL, 18073689335732591980ULL, 3614737867146518396ULL, 7229475734293036792ULL, 14458951468586073584ULL, 2891790293717214716ULL, 5783580587434429433ULL, 11567161174868858867ULL, 2313432234973771773ULL, 4626864469947543547ULL, 9253728939895087094ULL, 1850745787979017418ULL, 3701491575958034837ULL, 7402983151916069675ULL, 14805966303832139350ULL, 2961193260766427870ULL, 5922386521532855740ULL, 11844773043065711480ULL, 2368954608613142296ULL, 4737909217226284592ULL, 9475818434452569184ULL, 1895163686890513836ULL, 3790327373781027673ULL, 7580654747562055347ULL, 15161309495124110694ULL, 3032261899024822138ULL, 6064523798049644277ULL, 12129047596099288555ULL, 2425809519219857711ULL, 4851619038439715422ULL, 9703238076879430844ULL, 1940647615375886168ULL, 3881295230751772337ULL, 7762590461503544675ULL, 15525180923007089351ULL, 3105036184601417870ULL, 6210072369202835740ULL, 12420144738405671481ULL, 2484028947681134296ULL, 4968057895362268592ULL, 9936115790724537184ULL, 1987223158144907436ULL, 3974446316289814873ULL, 7948892632579629747ULL, 15897785265159259495ULL, 3179557053031851899ULL, 6359114106063703798ULL, 12718228212127407596ULL, 2543645642425481519ULL, 5087291284850963038ULL, 10174582569701926077ULL, 2034916513940385215ULL, 4069833027880770430ULL, 8139666055761540861ULL, 16279332111523081723ULL, 3255866422304616344ULL, 6511732844609232689ULL, 13023465689218465379ULL, 2604693137843693075ULL, 5209386275687386151ULL, 10418772551374772303ULL, 2083754510274954460ULL, 4167509020549908921ULL, 8335018041099817842ULL, 16670036082199635685ULL, 3334007216439927137ULL, 6668014432879854274ULL, 13336028865759708548ULL, 2667205773151941709ULL, 5334411546303883419ULL, 10668823092607766838ULL, 2133764618521553367ULL, 4267529237043106735ULL, 8535058474086213470ULL, 17070116948172426941ULL, 3414023389634485388ULL, 6828046779268970776ULL, 13656093558537941553ULL, 2731218711707588310ULL, 5462437423415176621ULL, 10924874846830353242ULL, 2184974969366070648ULL, 4369949938732141297ULL, 8739899877464282594ULL, 17479799754928565188ULL, 3495959950985713037ULL, 6991919901971426075ULL, 13983839803942852150ULL, 2796767960788570430ULL, 5593535921577140860ULL, 11187071843154281720ULL, 2237414368630856344ULL, 4474828737261712688ULL, 8949657474523425376ULL, 17899314949046850752ULL, 3579862989809370150ULL, 7159725979618740301ULL, 14319451959237480602ULL, 2863890391847496120ULL, 5727780783694992240ULL, 11455561567389984481ULL, 2291112313477996896ULL, 4582224626955993792ULL, 9164449253911987585ULL, 1832889850782397517ULL, 3665779701564795034ULL, 7331559403129590068ULL, 14663118806259180136ULL, 2932623761251836027ULL, 5865247522503672054ULL, 11730495045007344109ULL, 2346099009001468821ULL, 4692198018002937643ULL, 9384396036005875287ULL, 1876879207201175057ULL, 3753758414402350114ULL, 7507516828804700229ULL, 15015033657609400459ULL, 3003006731521880091ULL, 6006013463043760183ULL, 12012026926087520367ULL, 2402405385217504073ULL, 4804810770435008147ULL, 9609621540870016294ULL, 1921924308174003258ULL, 3843848616348006517ULL, 7687697232696013035ULL, 15375394465392026070ULL, 3075078893078405214ULL, 6150157786156810428ULL, 12300315572313620856ULL, 2460063114462724171ULL, 4920126228925448342ULL, 9840252457850896685ULL, 1968050491570179337ULL, 3936100983140358674ULL, 7872201966280717348ULL, 15744403932561434696ULL, 3148880786512286939ULL, 6297761573024573878ULL, 12595523146049147757ULL, 2519104629209829551ULL, 5038209258419659102ULL, 10076418516839318205ULL, 2015283703367863641ULL, 4030567406735727282ULL, 8061134813471454564ULL, 16122269626942909129ULL, 3224453925388581825ULL, 6448907850777163651ULL, 12897815701554327303ULL, 2579563140310865460ULL, 5159126280621730921ULL, 10318252561243461842ULL, 2063650512248692368ULL, 4127301024497384737ULL, 8254602048994769474ULL, 16509204097989538948ULL, 3301840819597907789ULL, 6603681639195815579ULL, 13207363278391631158ULL, 2641472655678326231ULL, 5282945311356652463ULL, 10565890622713304927ULL, 2113178124542660985ULL, 4226356249085321970ULL, 8452712498170643941ULL, 16905424996341287883ULL, 3381084999268257576ULL, 6762169998536515153ULL, 13524339997073030306ULL, 2704867999414606061ULL, 5409735998829212122ULL, 10819471997658424245ULL, 2163894399531684849ULL, 4327788799063369698ULL, 8655577598126739396ULL, 17311155196253478792ULL, 3462231039250695758ULL, 6924462078501391516ULL, 13848924157002783033ULL, 2769784831400556606ULL, 5539569662801113213ULL, 11079139325602226427ULL, 2215827865120445285ULL, 4431655730240890570ULL, 8863311460481781141ULL, 17726622920963562283ULL, 3545324584192712456ULL, 7090649168385424913ULL, 14181298336770849826ULL, 2836259667354169965ULL, 5672519334708339930ULL, 11345038669416679861ULL, 2269007733883335972ULL, 4538015467766671944ULL, 9076030935533343889ULL, 18152061871066687778ULL, 3630412374213337555ULL, 7260824748426675111ULL, 14521649496853350222ULL, 2904329899370670044ULL, 5808659798741340089ULL, 11617319597482680178ULL, 2323463919496536035ULL, 4646927838993072071ULL, 9293855677986144142ULL, 1858771135597228828ULL, 3717542271194457656ULL, 7435084542388915313ULL, 14870169084777830627ULL, 2974033816955566125ULL, 5948067633911132251ULL, 11896135267822264502ULL, 2379227053564452900ULL, 4758454107128905800ULL, 9516908214257811601ULL, 1903381642851562320ULL, 3806763285703124640ULL, 7613526571406249281ULL, 15227053142812498563ULL, 3045410628562499712ULL, 6090821257124999425ULL, 12181642514249998850ULL, 2436328502849999770ULL, 4872657005699999540ULL, 9745314011399999080ULL, 1949062802279999816ULL, 3898125604559999632ULL, 7796251209119999264ULL, 15592502418239998528ULL, 3118500483647999705ULL, 6237000967295999411ULL, 12474001934591998822ULL, 2494800386918399764ULL, 4989600773836799529ULL, 9979201547673599058ULL, 1995840309534719811ULL, 3991680619069439623ULL, 7983361238138879246ULL, 15966722476277758493ULL, 3193344495255551698ULL, 6386688990511103397ULL, 12773377981022206794ULL, 2554675596204441358ULL, 5109351192408882717ULL, 10218702384817765435ULL, 2043740476963553087ULL, 4087480953927106174ULL, 8174961907854212348ULL, 16349923815708424697ULL, 3269984763141684939ULL, 6539969526283369878ULL, 13079939052566739757ULL, 2615987810513347951ULL, 5231975621026695903ULL, 10463951242053391806ULL, 2092790248410678361ULL, 4185580496821356722ULL, 8371160993642713444ULL, 16742321987285426889ULL, 3348464397457085377ULL, 6696928794914170755ULL, 13393857589828341511ULL, 2678771517965668302ULL, 5357543035931336604ULL, 10715086071862673209ULL, 2143017214372534641ULL, 4286034428745069283ULL, 8572068857490138567ULL, 17144137714980277135ULL, 3428827542996055427ULL, 6857655085992110854ULL, 13715310171984221708ULL, 2743062034396844341ULL, 5486124068793688683ULL, 10972248137587377366ULL, 2194449627517475473ULL, 4388899255034950946ULL, 8777798510069901893ULL, 17555597020139803786ULL, 3511119404027960757ULL, 7022238808055921514ULL, 14044477616111843029ULL, 2808895523222368605ULL, 5617791046444737211ULL, 11235582092889474423ULL, 2247116418577894884ULL, 4494232837155789769ULL, 8988465674311579538ULL, 17976931348623159077ULL, 3595386269724631815ULL, 7190772539449263630ULL, 14381545078898527261ULL, 2876309015779705452ULL, 5752618031559410904ULL, 11505236063118821809ULL, 2301047212623764361ULL, 4602094425247528723ULL, 9204188850495057447ULL, 1840837770099011489ULL, 3681675540198022979ULL, 7363351080396045958ULL, }; static const int32_t Formatter_TensExponentTable[] = { -323, -323, -322, -322, -322, -322, -321, -321, -321, -320, -320, -320, -319, -319, -319, -319, -318, -318, -318, -317, -317, -317, -316, -316, -316, -316, -315, -315, -315, -314, -314, -314, -313, -313, -313, -313, -312, -312, -312, -311, -311, -311, -310, -310, -310, -310, -309, -309, -309, -308, -308, -308, -307, -307, -307, -307, -306, -306, -306, -305, -305, -305, -304, -304, -304, -304, -303, -303, -303, -302, -302, -302, -301, -301, -301, -301, -300, -300, -300, -299, -299, -299, -298, -298, -298, -298, -297, -297, -297, -296, -296, -296, -295, -295, -295, -295, -294, -294, -294, -293, -293, -293, -292, -292, -292, -291, -291, -291, -291, -290, -290, -290, -289, -289, -289, -288, -288, -288, -288, -287, -287, -287, -286, -286, -286, -285, -285, -285, -285, -284, -284, -284, -283, -283, -283, -282, -282, -282, -282, -281, -281, -281, -280, -280, -280, -279, -279, -279, -279, -278, -278, -278, -277, -277, -277, -276, -276, -276, -276, -275, -275, -275, -274, -274, -274, -273, -273, -273, -273, -272, -272, -272, -271, -271, -271, -270, -270, -270, -270, -269, -269, -269, -268, -268, -268, -267, -267, -267, -267, -266, -266, -266, -265, -265, -265, -264, -264, -264, -263, -263, -263, -263, -262, -262, -262, -261, -261, -261, -260, -260, -260, -260, -259, -259, -259, -258, -258, -258, -257, -257, -257, -257, -256, -256, -256, -255, -255, -255, -254, -254, -254, -254, -253, -253, -253, -252, -252, -252, -251, -251, -251, -251, -250, -250, -250, -249, -249, -249, -248, -248, -248, -248, -247, -247, -247, -246, -246, -246, -245, -245, -245, -245, -244, -244, -244, -243, -243, -243, -242, -242, -242, -242, -241, -241, -241, -240, -240, -240, -239, -239, -239, -239, -238, -238, -238, -237, -237, -237, -236, -236, -236, -235, -235, -235, -235, -234, -234, -234, -233, -233, -233, -232, -232, -232, -232, -231, -231, -231, -230, -230, -230, -229, -229, -229, -229, -228, -228, -228, -227, -227, -227, -226, -226, -226, -226, -225, -225, -225, -224, -224, -224, -223, -223, -223, -223, -222, -222, -222, -221, -221, -221, -220, -220, -220, -220, -219, -219, -219, -218, -218, -218, -217, -217, -217, -217, -216, -216, -216, -215, -215, -215, -214, -214, -214, -214, -213, -213, -213, -212, -212, -212, -211, -211, -211, -211, -210, -210, -210, -209, -209, -209, -208, -208, -208, -208, -207, -207, -207, -206, -206, -206, -205, -205, -205, -204, -204, -204, -204, -203, -203, -203, -202, -202, -202, -201, -201, -201, -201, -200, -200, -200, -199, -199, -199, -198, -198, -198, -198, -197, -197, -197, -196, -196, -196, -195, -195, -195, -195, -194, -194, -194, -193, -193, -193, -192, -192, -192, -192, -191, -191, -191, -190, -190, -190, -189, -189, -189, -189, -188, -188, -188, -187, -187, -187, -186, -186, -186, -186, -185, -185, -185, -184, -184, -184, -183, -183, -183, -183, -182, -182, -182, -181, -181, -181, -180, -180, -180, -180, -179, -179, -179, -178, -178, -178, -177, -177, -177, -176, -176, -176, -176, -175, -175, -175, -174, -174, -174, -173, -173, -173, -173, -172, -172, -172, -171, -171, -171, -170, -170, -170, -170, -169, -169, -169, -168, -168, -168, -167, -167, -167, -167, -166, -166, -166, -165, -165, -165, -164, -164, -164, -164, -163, -163, -163, -162, -162, -162, -161, -161, -161, -161, -160, -160, -160, -159, -159, -159, -158, -158, -158, -158, -157, -157, -157, -156, -156, -156, -155, -155, -155, -155, -154, -154, -154, -153, -153, -153, -152, -152, -152, -152, -151, -151, -151, -150, -150, -150, -149, -149, -149, -149, -148, -148, -148, -147, -147, -147, -146, -146, -146, -145, -145, -145, -145, -144, -144, -144, -143, -143, -143, -142, -142, -142, -142, -141, -141, -141, -140, -140, -140, -139, -139, -139, -139, -138, -138, -138, -137, -137, -137, -136, -136, -136, -136, -135, -135, -135, -134, -134, -134, -133, -133, -133, -133, -132, -132, -132, -131, -131, -131, -130, -130, -130, -130, -129, -129, -129, -128, -128, -128, -127, -127, -127, -127, -126, -126, -126, -125, -125, -125, -124, -124, -124, -124, -123, -123, -123, -122, -122, -122, -121, -121, -121, -121, -120, -120, -120, -119, -119, -119, -118, -118, -118, -117, -117, -117, -117, -116, -116, -116, -115, -115, -115, -114, -114, -114, -114, -113, -113, -113, -112, -112, -112, -111, -111, -111, -111, -110, -110, -110, -109, -109, -109, -108, -108, -108, -108, -107, -107, -107, -106, -106, -106, -105, -105, -105, -105, -104, -104, -104, -103, -103, -103, -102, -102, -102, -102, -101, -101, -101, -100, -100, -100, -99, -99, -99, -99, -98, -98, -98, -97, -97, -97, -96, -96, -96, -96, -95, -95, -95, -94, -94, -94, -93, -93, -93, -93, -92, -92, -92, -91, -91, -91, -90, -90, -90, -89, -89, -89, -89, -88, -88, -88, -87, -87, -87, -86, -86, -86, -86, -85, -85, -85, -84, -84, -84, -83, -83, -83, -83, -82, -82, -82, -81, -81, -81, -80, -80, -80, -80, -79, -79, -79, -78, -78, -78, -77, -77, -77, -77, -76, -76, -76, -75, -75, -75, -74, -74, -74, -74, -73, -73, -73, -72, -72, -72, -71, -71, -71, -71, -70, -70, -70, -69, -69, -69, -68, -68, -68, -68, -67, -67, -67, -66, -66, -66, -65, -65, -65, -65, -64, -64, -64, -63, -63, -63, -62, -62, -62, -62, -61, -61, -61, -60, -60, -60, -59, -59, -59, -58, -58, -58, -58, -57, -57, -57, -56, -56, -56, -55, -55, -55, -55, -54, -54, -54, -53, -53, -53, -52, -52, -52, -52, -51, -51, -51, -50, -50, -50, -49, -49, -49, -49, -48, -48, -48, -47, -47, -47, -46, -46, -46, -46, -45, -45, -45, -44, -44, -44, -43, -43, -43, -43, -42, -42, -42, -41, -41, -41, -40, -40, -40, -40, -39, -39, -39, -38, -38, -38, -37, -37, -37, -37, -36, -36, -36, -35, -35, -35, -34, -34, -34, -34, -33, -33, -33, -32, -32, -32, -31, -31, -31, -30, -30, -30, -30, -29, -29, -29, -28, -28, -28, -27, -27, -27, -27, -26, -26, -26, -25, -25, -25, -24, -24, -24, -24, -23, -23, -23, -22, -22, -22, -21, -21, -21, -21, -20, -20, -20, -19, -19, -19, -18, -18, -18, -18, -17, -17, -17, -16, -16, -16, -15, -15, -15, -15, -14, -14, -14, -13, -13, -13, -12, -12, -12, -12, -11, -11, -11, -10, -10, -10, -9, -9, -9, -9, -8, -8, -8, -7, -7, -7, -6, -6, -6, -6, -5, -5, -5, -4, -4, -4, -3, -3, -3, -3, -2, -2, -2, -1, -1, -1, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 27, 27, 27, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 35, 36, 36, 36, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44, 44, 45, 45, 45, 46, 46, 46, 47, 47, 47, 47, 48, 48, 48, 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, 52, 52, 52, 53, 53, 53, 53, 54, 54, 54, 55, 55, 55, 56, 56, 56, 56, 57, 57, 57, 58, 58, 58, 59, 59, 59, 60, 60, 60, 60, 61, 61, 61, 62, 62, 62, 63, 63, 63, 63, 64, 64, 64, 65, 65, 65, 66, 66, 66, 66, 67, 67, 67, 68, 68, 68, 69, 69, 69, 69, 70, 70, 70, 71, 71, 71, 72, 72, 72, 72, 73, 73, 73, 74, 74, 74, 75, 75, 75, 75, 76, 76, 76, 77, 77, 77, 78, 78, 78, 78, 79, 79, 79, 80, 80, 80, 81, 81, 81, 81, 82, 82, 82, 83, 83, 83, 84, 84, 84, 84, 85, 85, 85, 86, 86, 86, 87, 87, 87, 88, 88, 88, 88, 89, 89, 89, 90, 90, 90, 91, 91, 91, 91, 92, 92, 92, 93, 93, 93, 94, 94, 94, 94, 95, 95, 95, 96, 96, 96, 97, 97, 97, 97, 98, 98, 98, 99, 99, 99, 100, 100, 100, 100, 101, 101, 101, 102, 102, 102, 103, 103, 103, 103, 104, 104, 104, 105, 105, 105, 106, 106, 106, 106, 107, 107, 107, 108, 108, 108, 109, 109, 109, 109, 110, 110, 110, 111, 111, 111, 112, 112, 112, 112, 113, 113, 113, 114, 114, 114, 115, 115, 115, 116, 116, 116, 116, 117, 117, 117, 118, 118, 118, 119, 119, 119, 119, 120, 120, 120, 121, 121, 121, 122, 122, 122, 122, 123, 123, 123, 124, 124, 124, 125, 125, 125, 125, 126, 126, 126, 127, 127, 127, 128, 128, 128, 128, 129, 129, 129, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 133, 133, 133, 134, 134, 134, 134, 135, 135, 135, 136, 136, 136, 137, 137, 137, 137, 138, 138, 138, 139, 139, 139, 140, 140, 140, 140, 141, 141, 141, 142, 142, 142, 143, 143, 143, 143, 144, 144, 144, 145, 145, 145, 146, 146, 146, 147, 147, 147, 147, 148, 148, 148, 149, 149, 149, 150, 150, 150, 150, 151, 151, 151, 152, 152, 152, 153, 153, 153, 153, 154, 154, 154, 155, 155, 155, 156, 156, 156, 156, 157, 157, 157, 158, 158, 158, 159, 159, 159, 159, 160, 160, 160, 161, 161, 161, 162, 162, 162, 162, 163, 163, 163, 164, 164, 164, 165, 165, 165, 165, 166, 166, 166, 167, 167, 167, 168, 168, 168, 168, 169, 169, 169, 170, 170, 170, 171, 171, 171, 171, 172, 172, 172, 173, 173, 173, 174, 174, 174, 175, 175, 175, 175, 176, 176, 176, 177, 177, 177, 178, 178, 178, 178, 179, 179, 179, 180, 180, 180, 181, 181, 181, 181, 182, 182, 182, 183, 183, 183, 184, 184, 184, 184, 185, 185, 185, 186, 186, 186, 187, 187, 187, 187, 188, 188, 188, 189, 189, 189, 190, 190, 190, 190, 191, 191, 191, 192, 192, 192, 193, 193, 193, 193, 194, 194, 194, 195, 195, 195, 196, 196, 196, 196, 197, 197, 197, 198, 198, 198, 199, 199, 199, 199, 200, 200, 200, 201, 201, 201, 202, 202, 202, 202, 203, 203, 203, 204, 204, 204, 205, 205, 205, 206, 206, 206, 206, 207, 207, 207, 208, 208, 208, 209, 209, 209, 209, 210, 210, 210, 211, 211, 211, 212, 212, 212, 212, 213, 213, 213, 214, 214, 214, 215, 215, 215, 215, 216, 216, 216, 217, 217, 217, 218, 218, 218, 218, 219, 219, 219, 220, 220, 220, 221, 221, 221, 221, 222, 222, 222, 223, 223, 223, 224, 224, 224, 224, 225, 225, 225, 226, 226, 226, 227, 227, 227, 227, 228, 228, 228, 229, 229, 229, 230, 230, 230, 230, 231, 231, 231, 232, 232, 232, 233, 233, 233, 234, 234, 234, 234, 235, 235, 235, 236, 236, 236, 237, 237, 237, 237, 238, 238, 238, 239, 239, 239, 240, 240, 240, 240, 241, 241, 241, 242, 242, 242, 243, 243, 243, 243, 244, 244, 244, 245, 245, 245, 246, 246, 246, 246, 247, 247, 247, 248, 248, 248, 249, 249, 249, 249, 250, 250, 250, 251, 251, 251, 252, 252, 252, 252, 253, 253, 253, 254, 254, 254, 255, 255, 255, 255, 256, 256, 256, 257, 257, 257, 258, 258, 258, 258, 259, 259, 259, 260, 260, 260, 261, 261, 261, 261, 262, 262, 262, 263, 263, 263, 264, 264, 264, 265, 265, 265, 265, 266, 266, 266, 267, 267, 267, 268, 268, 268, 268, 269, 269, 269, 270, 270, 270, 271, 271, 271, 271, 272, 272, 272, 273, 273, 273, 274, 274, 274, 274, 275, 275, 275, 276, 276, 276, 277, 277, 277, 277, 278, 278, 278, 279, 279, 279, 280, 280, 280, 280, 281, 281, 281, 282, 282, 282, 283, 283, 283, 283, 284, 284, 284, 285, 285, 285, 286, 286, 286, 286, 287, 287, 287, 288, 288, 288, 289, 289, 289, 289, 290, 290, 290, 291, 291, 291, 292, 292, 292, 293, 293, 293, }; static const int16_t Formatter_DigitLowerTable[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; static const int16_t Formatter_DigitUpperTable[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; static const int64_t Formatter_TenPowersList[] = { 1LL, 10LL, 100LL, 1000LL, 10000LL, 100000LL, 1000000LL, 10000000LL, 100000000LL, 1000000000LL, 10000000000LL, 100000000000LL, 1000000000000LL, 10000000000000LL, 100000000000000LL, 1000000000000000LL, 10000000000000000LL, 100000000000000000LL, 1000000000000000000LL, }; // DecHexDigits s a translation table from a decimal number to its // digits hexadecimal representation (e.g. DecHexDigits [34] = 0x34). static const int32_t Formatter_DecHexDigits[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, }; #endif ================================================ FILE: unity_decoder/libil2cpp/object-internals.h ================================================ #pragma once #include "il2cpp-config.h" #include #include #include "class-internals.h" struct Il2CppClass; struct MethodInfo; struct PropertyInfo; struct FieldInfo; struct EventInfo; struct Il2CppType; struct Il2CppAssembly; struct Il2CppException; struct Il2CppImage; struct Il2CppDomain; struct Il2CppString; struct Il2CppReflectionMethod; struct Il2CppAsyncCall; struct Il2CppIUnknown; struct Il2CppWaitHandle; struct MonitorData; namespace il2cpp { namespace os { class FastMutex; class Thread; } } struct Il2CppReflectionAssembly; struct Il2CppObject { Il2CppClass *klass; MonitorData *monitor; }; typedef int32_t il2cpp_array_lower_bound_t; #define IL2CPP_ARRAY_MAX_INDEX ((int32_t) 0x7fffffff) #define IL2CPP_ARRAY_MAX_SIZE ((uint32_t) 0xffffffff) struct Il2CppArrayBounds { il2cpp_array_size_t length; il2cpp_array_lower_bound_t lower_bound; }; #if IL2CPP_COMPILER_MSVC #pragma warning( push ) #pragma warning( disable : 4200 ) #elif defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Winvalid-offsetof" #endif struct Il2CppArray : public Il2CppObject { /* bounds is NULL for szarrays */ Il2CppArrayBounds *bounds; /* total number of elements of the array */ il2cpp_array_size_t max_length; }; struct Il2CppArraySize : public Il2CppArray { ALIGN_TYPE(8) void* vector; }; const size_t kIl2CppSizeOfArray = (offsetof(Il2CppArraySize, vector)); const size_t kIl2CppOffsetOfArrayBounds = (offsetof(Il2CppArray, bounds)); const size_t kIl2CppOffsetOfArrayLength = (offsetof(Il2CppArray, max_length)); // System.String struct Il2CppString { Il2CppObject object; int32_t length; ///< Length of string *excluding* the trailing null (which is included in 'chars'). Il2CppChar chars[IL2CPP_ZERO_LEN_ARRAY]; }; #if IL2CPP_COMPILER_MSVC #pragma warning( pop ) #elif defined(__clang__) #pragma clang diagnostic pop #endif #define IL2CPP_OBJECT_SETREF(obj, fieldname, value) do {\ /* mono_gc_wbarrier_set_field ((MonoObject*)(obj), &((obj)->fieldname), (MonoObject*)value); */ \ (obj)->fieldname = (value); \ } while (0) /* This should be used if 's' can reside on the heap */ #define IL2CPP_STRUCT_SETREF(s, field, value) do {\ /* mono_gc_wbarrier_generic_store (&((s)->field), (MonoObject*)(value)); */ \ (s)->field = (value); \ } while (0) struct Il2CppReflectionType { Il2CppObject object; const Il2CppType *type; }; // IMPORTANT: All managed types corresponding to the objects below must be blacklisted in mscorlib.xml #if NET_4_0 // System.RuntimeType struct Il2CppReflectionRuntimeType { Il2CppReflectionType type; Il2CppObject *type_info; Il2CppObject* genericCache; Il2CppObject* serializationCtor; }; #endif // System.MonoType struct Il2CppReflectionMonoType { #if !NET_4_0 Il2CppReflectionType type; Il2CppObject *type_info; #else Il2CppReflectionRuntimeType type; #endif const Il2CppType* GetIl2CppType() const { #if !NET_4_0 return type.type; #else return type.type.type; #endif } }; // System.Reflection.EventInfo struct Il2CppReflectionEvent { Il2CppObject object; Il2CppObject *cached_add_event; }; // System.Reflection.MonoEvent struct Il2CppReflectionMonoEvent { Il2CppReflectionEvent event; Il2CppReflectionType* reflectedType; const EventInfo* eventInfo; }; // System.Reflection.MonoEventInfo struct Il2CppReflectionMonoEventInfo { Il2CppReflectionType* declaringType; Il2CppReflectionType* reflectedType; Il2CppString* name; Il2CppReflectionMethod* addMethod; Il2CppReflectionMethod* removeMethod; Il2CppReflectionMethod* raiseMethod; uint32_t eventAttributes; Il2CppArray* otherMethods; }; #if !NET_4_0 // System.MonoEnumInfo struct Il2CppEnumInfo { Il2CppReflectionType *utype; Il2CppArray *values; Il2CppArray *names; void* name_hash; }; #endif // System.Reflection.MonoField struct Il2CppReflectionField { Il2CppObject object; Il2CppClass *klass; FieldInfo *field; Il2CppString *name; Il2CppReflectionType *type; uint32_t attrs; }; // System.Reflection.MonoProperty struct Il2CppReflectionProperty { Il2CppObject object; Il2CppClass *klass; const PropertyInfo *property; }; // System.Reflection.MonoMethod struct Il2CppReflectionMethod { Il2CppObject object; const MethodInfo *method; Il2CppString *name; Il2CppReflectionType *reftype; }; // System.Reflection.MonoGenericMethod struct Il2CppReflectionGenericMethod { Il2CppReflectionMethod base; }; // System.Reflection.MonoMethodInfo struct Il2CppMethodInfo { Il2CppReflectionType *parent; Il2CppReflectionType *ret; uint32_t attrs; uint32_t implattrs; uint32_t callconv; }; // System.Reflection.MonoPropertyInfo struct Il2CppPropertyInfo { Il2CppReflectionType* parent; #if NET_4_0 Il2CppReflectionType* declaringType; #endif Il2CppString *name; Il2CppReflectionMethod *get; Il2CppReflectionMethod *set; uint32_t attrs; }; // System.Reflection.ParameterInfo struct Il2CppReflectionParameter { Il2CppObject object; Il2CppReflectionType *ClassImpl; Il2CppObject *DefaultValueImpl; Il2CppObject *MemberImpl; Il2CppString *NameImpl; int32_t PositionImpl; uint32_t AttrsImpl; Il2CppObject *MarshalAsImpl; }; // System.Reflection.Module struct Il2CppReflectionModule { Il2CppObject obj; const Il2CppImage* image; Il2CppReflectionAssembly* assembly; Il2CppString* fqname; Il2CppString* name; Il2CppString* scopename; bool is_resource; uint32_t token; }; // System.Reflection.AssemblyName struct Il2CppReflectionAssemblyName { Il2CppObject obj; Il2CppString *name; Il2CppString *codebase; int32_t major, minor, build, revision; Il2CppObject *cultureInfo; uint32_t flags; uint32_t hashalg; Il2CppObject *keypair; Il2CppArray *publicKey; Il2CppArray *keyToken; uint32_t versioncompat; Il2CppObject *version; uint32_t processor_architecture; #if NET_4_0 uint32_t contentType; #endif }; // System.Reflection.Assembly struct Il2CppReflectionAssembly { Il2CppObject object; const Il2CppAssembly *assembly; Il2CppObject *resolve_event_holder; /* CAS related */ Il2CppObject *evidence; /* Evidence */ Il2CppObject *minimum; /* PermissionSet - for SecurityAction.RequestMinimum */ Il2CppObject *optional; /* PermissionSet - for SecurityAction.RequestOptional */ Il2CppObject *refuse; /* PermissionSet - for SecurityAction.RequestRefuse */ Il2CppObject *granted; /* PermissionSet - for the resolved assembly granted permissions */ Il2CppObject *denied; /* PermissionSet - for the resolved assembly denied permissions */ /* */ bool from_byte_array; Il2CppString *name; }; // System.Reflection.Emit.UnmanagedMarshal struct Il2CppReflectionMarshal { Il2CppObject object; int32_t count; int32_t type; int32_t eltype; Il2CppString* guid; Il2CppString* mcookie; Il2CppString* marshaltype; Il2CppObject* marshaltyperef; int32_t param_num; bool has_size; }; // System.Reflection.Pointer struct Il2CppReflectionPointer { Il2CppObject object; void* data; Il2CppReflectionType* type; }; // System.IntPtr // Just in case there is a platform where we cannot replace struct {void* val;} with void* struct Il2CppIntPtr { void* m_value; static Il2CppIntPtr Zero; }; #if NET_4_0 // System.Threading.InternalThread struct Il2CppInternalThread { Il2CppObject obj; int lock_thread_id; il2cpp::os::Thread* handle; Il2CppArray* cached_culture_info; Il2CppChar* name; int name_len; uint32_t state; Il2CppObject* abort_exc; int abort_state_handle; uint64_t tid; void* stack_ptr; void** static_data; void* runtime_thread_info; Il2CppObject* current_appcontext; Il2CppObject* root_domain_thread; Il2CppArray* _serialized_principal; int _serialized_principal_version; void* appdomain_refs; int32_t interruption_requested; il2cpp::os::FastMutex* synch_cs; bool threadpool_thread; bool thread_interrupt_requested; int stack_size; uint8_t apartment_state; int critical_region_level; int managed_id; uint32_t small_id; void* manage_callback; void* interrupt_on_stop; void* flags; void* thread_pinning_ref; void* abort_protected_block_count; void* unused1; void* unused2; void* last; }; /* Keep in sync with System.IOSelectorJob in mcs/class/System/System/IOSelectorJob.cs */ struct Il2CppIOSelectorJob { Il2CppObject object; int32_t operation; Il2CppObject *callback; Il2CppObject *state; }; /* This is a copy of System.Runtime.Remoting.Messaging.CallType */ typedef enum { CallType_Sync = 0, CallType_BeginInvoke = 1, CallType_EndInvoke = 2, CallType_OneWay = 3 } Il2CppCallType; struct Il2CppMethodMessage { Il2CppObject obj; Il2CppReflectionMethod *method; Il2CppArray *args; Il2CppArray *names; Il2CppArray *arg_types; Il2CppObject *ctx; Il2CppObject *rval; Il2CppObject *exc; Il2CppAsyncResult *async_result; uint32_t call_type; }; #endif /* This is a copy of System.AppDomainSetup */ struct Il2CppAppDomainSetup { Il2CppObject object; Il2CppString* application_base; Il2CppString* application_name; Il2CppString* cache_path; Il2CppString* configuration_file; Il2CppString* dynamic_base; Il2CppString* license_file; Il2CppString* private_bin_path; Il2CppString* private_bin_path_probe; Il2CppString* shadow_copy_directories; Il2CppString* shadow_copy_files; uint8_t publisher_policy; uint8_t path_changed; int loader_optimization; uint8_t disallow_binding_redirects; uint8_t disallow_code_downloads; Il2CppObject* activation_arguments; /* it is System.Object in 1.x, ActivationArguments in 2.0 */ Il2CppObject* domain_initializer; Il2CppObject* application_trust; /* it is System.Object in 1.x, ApplicationTrust in 2.0 */ Il2CppArray* domain_initializer_args; uint8_t disallow_appbase_probe; Il2CppArray* configuration_bytes; #if NET_4_0 Il2CppArray* serialized_non_primitives; #endif }; // System.Threading.Thread struct Il2CppThread { Il2CppObject obj; #if !NET_4_0 int lock_thread_id; /* to be used as the pre-shifted thread id in thin locks */ il2cpp::os::Thread* handle; Il2CppArray *cached_culture_info; void* unused1; bool threadpool_thread;//bool threadpool_thread; Il2CppChar* name; uint32_t name_len; uint32_t state; Il2CppObject* abort_exc;//MonoException *abort_exc; int abort_state_handle; uint64_t tid; /* This is accessed as a gsize in the code (so it can hold a 64bit pointer on systems that need it), but needs to reserve 64 bits of space on all machines as it corresponds to a field in managed code */ void* start_notify; void* stack_ptr; void* *static_data; void* jit_data; void* lock_data; Il2CppObject* current_appcontext;//MonoAppContext *current_appcontext; int stack_size; Il2CppObject* start_obj;//MonoObject *start_obj; void* appdomain_refs;//GSList *appdomain_refs; ///* This is modified using atomic ops, so keep it a int32_t */ int32_t interruption_requested; void* suspend_event; void* suspended_event; void* resume_event; il2cpp::os::FastMutex* synch_cs; uint8_t* serialized_culture_info; uint32_t serialized_culture_info_len; uint8_t* serialized_ui_culture_info; uint32_t serialized_ui_culture_info_len; bool thread_dump_requested;//bool thread_dump_requested; void* end_stack; /* This is only used when running in the debugger. */ bool thread_interrupt_requested;//bool thread_interrupt_requested; uint8_t apartment_state; int32_t critical_region_level; uint32_t small_id; /* A small, unique id, used for the hazard pointer table. */ void* manage_callback; Il2CppException *pending_exception; Il2CppObject *ec_to_set; ///* // * These fields are used to avoid having to increment corlib versions // * when a new field is added to the unmanaged MonoThread structure. // */ void* interrupt_on_stop; uintptr_t flags; void* unused4; void* unused5; void* unused6; Il2CppObject* threadstart; int managed_id; Il2CppObject* principal; bool in_currentculture; #else Il2CppInternalThread* internal_thread; Il2CppObject* start_obj; Il2CppObject* pending_exception; int32_t priority; Il2CppObject* principal; int32_t principal_version; Il2CppDelegate* delegate; Il2CppObject* executionContext; bool executionContextBelongsToOuterScope; #endif #if !NET_4_0 Il2CppThread* GetInternalThread() { return this; } #else Il2CppInternalThread* GetInternalThread() const { return internal_thread; } #endif }; // System.Exception struct Il2CppException : public Il2CppObject { #if !NET_4_0 /* Stores the IPs and the generic sharing infos (vtable/MRGCTX) of the frames. */ Il2CppArray *trace_ips; Il2CppException *inner_ex; Il2CppString *message; Il2CppString *help_link; Il2CppString *class_name; Il2CppString *stack_trace; Il2CppString *remote_stack_trace; int32_t remote_stack_index; il2cpp_hresult_t hresult; Il2CppString *source; Il2CppObject *_data; #else Il2CppString* className; Il2CppString* message; Il2CppObject* _data; Il2CppException* inner_ex; Il2CppString* _helpURL; Il2CppArray* trace_ips; Il2CppString* stack_trace; Il2CppString* remote_stack_trace; int remote_stack_index; Il2CppObject* _dynamicMethods; il2cpp_hresult_t hresult; Il2CppString* source; Il2CppObject* safeSerializationManager; Il2CppArray* captured_traces; Il2CppArray* native_trace_ips; #endif }; // System.SystemException struct Il2CppSystemException { Il2CppException base; }; // System.ArgumentException struct Il2CppArgumentException { Il2CppException base; Il2CppString *argName; }; // System.TypedReference struct Il2CppTypedRef { Il2CppType *type; void* value; Il2CppClass *klass; }; // System.Delegate struct Il2CppDelegate { Il2CppObject object; /* The compiled code of the target method */ Il2CppMethodPointer method_ptr; /* The invoke code */ InvokerMethod invoke_impl; Il2CppObject *target; #if RUNTIME_MONO const MonoMethod *method; #else const MethodInfo *method; #endif void* delegate_trampoline; #if NET_4_0 Il2CppIntPtr extraArg; #endif /* * If non-NULL, this points to a memory location which stores the address of * the compiled code of the method, or NULL if it is not yet compiled. */ uint8_t **method_code; Il2CppReflectionMethod *method_info; Il2CppReflectionMethod *original_method_info; Il2CppObject *data; #if NET_4_0 bool method_is_virtual; #endif }; #if NET_4_0 struct Il2CppMulticastDelegate { Il2CppDelegate delegate; Il2CppArray *delegates; }; #endif // System.MarshalByRefObject struct Il2CppMarshalByRefObject { Il2CppObject obj; Il2CppObject *identity; }; // System.__Il2CppComObject (dummy type that replaces System.__ComObject) struct Il2CppComObject : Il2CppObject { Il2CppIUnknown* identity; }; // System.AppDomain struct Il2CppAppDomain { Il2CppMarshalByRefObject mbr; Il2CppDomain *data; }; // System.Diagnostics.StackFrame struct Il2CppStackFrame { Il2CppObject obj; int32_t il_offset; int32_t native_offset; #if NET_4_0 uint64_t methodAddress; uint32_t methodIndex; #endif Il2CppReflectionMethod *method; Il2CppString *filename; int32_t line; int32_t column; Il2CppString *internal_method_name; }; // System.Globalization.DateTimeFormatInfo struct Il2CppDateTimeFormatInfo { Il2CppObject obj; #if !NET_4_0 bool readOnly; Il2CppString* AMDesignator; Il2CppString* PMDesignator; Il2CppString* DateSeparator; Il2CppString* TimeSeparator; Il2CppString* ShortDatePattern; Il2CppString* LongDatePattern; Il2CppString* ShortTimePattern; Il2CppString* LongTimePattern; Il2CppString* MonthDayPattern; Il2CppString* YearMonthPattern; Il2CppString* FullDateTimePattern; Il2CppString* RFC1123Pattern; Il2CppString* SortableDateTimePattern; Il2CppString* UniversalSortableDateTimePattern; uint32_t FirstDayOfWeek; Il2CppObject* Calendar; uint32_t CalendarWeekRule; Il2CppArray* AbbreviatedDayNames; Il2CppArray* DayNames; Il2CppArray* MonthNames; Il2CppArray* AbbreviatedMonthNames; Il2CppArray* ShortDatePatterns; Il2CppArray* LongDatePatterns; Il2CppArray* ShortTimePatterns; Il2CppArray* LongTimePatterns; Il2CppArray* MonthDayPatterns; Il2CppArray* YearMonthPatterns; Il2CppArray* ShortDayNames; #else Il2CppObject* CultureData; Il2CppString* Name; Il2CppString* LangName; Il2CppObject* CompareInfo; Il2CppObject* CultureInfo; Il2CppString* AMDesignator; Il2CppString* PMDesignator; Il2CppString* DateSeparator; Il2CppString* GeneralShortTimePattern; Il2CppString* GeneralLongTimePattern; Il2CppString* TimeSeparator; Il2CppString* MonthDayPattern; Il2CppString* DateTimeOffsetPattern; Il2CppObject* Calendar; uint32_t FirstDayOfWeek; uint32_t CalendarWeekRule; Il2CppString* FullDateTimePattern; Il2CppArray* AbbreviatedDayNames; Il2CppArray* ShortDayNames; Il2CppArray* DayNames; Il2CppArray* AbbreviatedMonthNames; Il2CppArray* MonthNames; Il2CppArray* GenitiveMonthNames; Il2CppArray* GenitiveAbbreviatedMonthNames; Il2CppArray* LeapYearMonthNames; Il2CppString* LongDatePattern; Il2CppString* ShortDatePattern; Il2CppString* YearMonthPattern; Il2CppString* LongTimePattern; Il2CppString* ShortTimePattern; Il2CppArray* YearMonthPatterns; Il2CppArray* ShortDatePatterns; Il2CppArray* LongDatePatterns; Il2CppArray* ShortTimePatterns; Il2CppArray* LongTimePatterns; Il2CppArray* EraNames; Il2CppArray* AbbrevEraNames; Il2CppArray* AbbrevEnglishEraNames; Il2CppArray* OptionalCalendars; bool readOnly; int32_t FormatFlags; int32_t CultureID; bool UseUserOverride; bool UseCalendarInfo; int32_t DataItem; bool IsDefaultCalendar; Il2CppArray* DateWords; Il2CppString* FullTimeSpanPositivePattern; Il2CppString* FullTimeSpanNegativePattern; Il2CppArray* dtfiTokenHash; #endif }; // System.Globalization.NumberFormatInfo struct Il2CppNumberFormatInfo { Il2CppObject obj; #if !NET_4_0 bool readOnly; Il2CppString* decimalFormats; Il2CppString* currencyFormats; Il2CppString* percentFormats; Il2CppString* digitPattern; Il2CppString* zeroPattern; int32_t currencyDecimalDigits; Il2CppString* currencyDecimalSeparator; Il2CppString* currencyGroupSeparator; Il2CppArray* currencyGroupSizes; int32_t currencyNegativePattern; int32_t currencyPositivePattern; Il2CppString* currencySymbol; Il2CppString* naNSymbol; Il2CppString* negativeInfinitySymbol; Il2CppString* negativeSign; uint32_t numberDecimalDigits; Il2CppString* numberDecimalSeparator; Il2CppString* numberGroupSeparator; Il2CppArray* numberGroupSizes; int32_t numberNegativePattern; int32_t percentDecimalDigits; Il2CppString* percentDecimalSeparator; Il2CppString* percentGroupSeparator; Il2CppArray* percentGroupSizes; int32_t percentNegativePattern; int32_t percentPositivePattern; Il2CppString* percentSymbol; Il2CppString* perMilleSymbol; Il2CppString* positiveInfinitySymbol; Il2CppString* positiveSign; #else Il2CppArray* numberGroupSizes; Il2CppArray* currencyGroupSizes; Il2CppArray* percentGroupSizes; Il2CppString* positiveSign; Il2CppString* negativeSign; Il2CppString* numberDecimalSeparator; Il2CppString* numberGroupSeparator; Il2CppString* currencyGroupSeparator; Il2CppString* currencyDecimalSeparator; Il2CppString* currencySymbol; Il2CppString* ansiCurrencySymbol; Il2CppString* naNSymbol; Il2CppString* positiveInfinitySymbol; Il2CppString* negativeInfinitySymbol; Il2CppString* percentDecimalSeparator; Il2CppString* percentGroupSeparator; Il2CppString* percentSymbol; Il2CppString* perMilleSymbol; Il2CppArray* nativeDigits; int dataItem; int numberDecimalDigits; int currencyDecimalDigits; int currencyPositivePattern; int currencyNegativePattern; int numberNegativePattern; int percentPositivePattern; int percentNegativePattern; int percentDecimalDigits; int digitSubstitution; bool readOnly; bool useUserOverride; bool isInvariant; bool validForParseAsNumber; bool validForParseAsCurrency; #endif }; #if NET_4_0 struct Il2CppCultureData { Il2CppObject obj; Il2CppString *AMDesignator; Il2CppString *PMDesignator; Il2CppString *TimeSeparator; Il2CppArray *LongTimePatterns; Il2CppArray *ShortTimePatterns; uint32_t FirstDayOfWeek; uint32_t CalendarWeekRule; }; struct Il2CppCalendarData { Il2CppObject obj; Il2CppString *NativeName; Il2CppArray *ShortDatePatterns; Il2CppArray *YearMonthPatterns; Il2CppArray *LongDatePatterns; Il2CppString *MonthDayPattern; Il2CppArray *EraNames; Il2CppArray *AbbreviatedEraNames; Il2CppArray *AbbreviatedEnglishEraNames; Il2CppArray *DayNames; Il2CppArray *AbbreviatedDayNames; Il2CppArray *SuperShortDayNames; Il2CppArray *MonthNames; Il2CppArray *AbbreviatedMonthNames; Il2CppArray *GenitiveMonthNames; Il2CppArray *GenitiveAbbreviatedMonthNames; }; #endif // System.Globalization.CultureInfo struct Il2CppCultureInfo { Il2CppObject obj; bool is_read_only; int32_t lcid; int32_t parent_lcid; #if !NET_4_0 int32_t specific_lcid; #endif int32_t datetime_index; int32_t number_index; #if NET_4_0 int32_t default_calendar_type; #endif bool use_user_override; Il2CppNumberFormatInfo* number_format; Il2CppDateTimeFormatInfo* datetime_format; Il2CppObject* textinfo; Il2CppString* name; #if !NET_4_0 Il2CppString* displayname; #endif Il2CppString* englishname; Il2CppString* nativename; Il2CppString* iso3lang; Il2CppString* iso2lang; #if !NET_4_0 Il2CppString* icu_name; #endif Il2CppString* win3lang; Il2CppString* territory; #if NET_4_0 Il2CppArray* native_calendar_names; #endif Il2CppString* compareinfo; #if !NET_4_0 const int32_t* calendar_data; #endif const void* text_info_data; #if NET_4_0 int dataItem; Il2CppObject* calendar; Il2CppObject* parent_culture; bool constructed; Il2CppArray* cached_serialized_form; Il2CppObject* cultureData; bool isInherited; #endif }; // System.Globalization.RegionInfo struct Il2CppRegionInfo { Il2CppObject obj; #if NET_4_0 int32_t geo_id; #else int32_t lcid; int32_t region_id; #endif Il2CppString* iso2name; Il2CppString* iso3name; Il2CppString* win3name; Il2CppString* english_name; Il2CppString* currency_symbol; Il2CppString* iso_currency_symbol; Il2CppString* currency_english_name; }; // System.Runtime.InteropServices.SafeHandle // Inherited by Microsoft.Win32.SafeHandles.SafeWaitHandle struct Il2CppSafeHandle { Il2CppObject base; void* handle; #if !NET_4_0 void* invalid_handle_value; int refcount; bool owns_handle; #else int state; bool owns_handle; bool fullyInitialized; #endif }; // System.Text.StringBuilder struct Il2CppStringBuilder { Il2CppObject object; #if !NET_4_0 int32_t length; Il2CppString *str; Il2CppString *cached_str; int32_t max_capacity; #else Il2CppArray* chunkChars; Il2CppStringBuilder* chunkPrevious; int chunkLength; int chunkOffset; int maxCapacity; #endif }; // System.Net.SocketAddress struct Il2CppSocketAddress { Il2CppObject base; #if !NET_4_0 Il2CppArray* data; #else int m_Size; Il2CppArray* data; bool m_changed; int m_hash; #endif }; // System.Globalization.SortKey struct Il2CppSortKey { Il2CppObject base; Il2CppString *str; #if !NET_4_0 int32_t options; Il2CppArray *key; #else Il2CppArray *key; int32_t options; #endif int32_t lcid; }; // System.Runtime.InteropServices.ErrorWrapper struct Il2CppErrorWrapper { Il2CppObject base; int32_t errorCode; }; // System.Runtime.Remoting.Messaging.AsyncResult struct Il2CppAsyncResult { Il2CppObject base; Il2CppObject *async_state; Il2CppWaitHandle *handle; Il2CppDelegate *async_delegate; void* data; // We pass delegate arguments here. This is repurposed. Depends on Mono C# code not using the field. Il2CppAsyncCall *object_data; bool sync_completed; bool completed; bool endinvoke_called; Il2CppObject *async_callback; Il2CppObject *execution_context; Il2CppObject *original_context; }; // System.MonoAsyncCall struct Il2CppAsyncCall { Il2CppObject base; #if !NET_4_0 void *msg; // We pass exceptions through here for now. #else Il2CppMethodMessage *msg; #endif MethodInfo *cb_method; // We don't set this. Il2CppDelegate *cb_target; // We pass the actual delegate here. Il2CppObject *state; Il2CppObject *res; Il2CppArray *out_args; #if !NET_4_0 /* This is a HANDLE, we use guint64 so the managed object layout remains constant */ uint64_t wait_event; #endif }; struct Il2CppExceptionWrapper { #if RUNTIME_MONO MonoException* ex; Il2CppExceptionWrapper(MonoException* ex) : ex(ex) {} #else Il2CppException* ex; Il2CppExceptionWrapper(Il2CppException* ex) : ex(ex) {} #endif }; #if NET_4_0 struct Il2CppIOAsyncResult { Il2CppObject base; Il2CppDelegate* callback; Il2CppObject* state; Il2CppWaitHandle* wait_handle; bool completed_synchronously; bool completed; }; #endif /// Corresponds to Mono's internal System.Net.Sockets.Socket.SocketAsyncResult /// class. Has no relation to Il2CppAsyncResult. struct Il2CppSocketAsyncResult { #if !NET_4_0 Il2CppObject base; Il2CppObject *socket; Il2CppIntPtr handle; Il2CppObject *state; Il2CppDelegate *callback; Il2CppWaitHandle *wait_handle; Il2CppException *delayedException; Il2CppObject *ep; Il2CppArray *buffer; int32_t offset; int32_t size; int32_t socket_flags; Il2CppObject *accept_reuse_socket; Il2CppArray *addresses; int32_t port; Il2CppObject *buffers; bool reusesocket; Il2CppObject *acceptSocket; int32_t total; bool completed_synchronously; bool completed; bool blocking; int32_t error; int32_t operation; Il2CppAsyncResult *ares; #else Il2CppIOAsyncResult base; Il2CppObject* socket; int32_t operation; Il2CppException* delayedException; Il2CppObject* endPoint; Il2CppArray* buffer; int32_t offset; int32_t size; int32_t socket_flags; Il2CppObject* acceptSocket; Il2CppArray* addresses; int32_t port; Il2CppObject* buffers; bool reuseSocket; int32_t currentAddress; Il2CppObject* acceptedSocket; int32_t total; int32_t error; int32_t endCalled; #endif }; enum Il2CppResourceLocation { RESOURCE_LOCATION_EMBEDDED = 1, RESOURCE_LOCATION_ANOTHER_ASSEMBLY = 2, RESOURCE_LOCATION_IN_MANIFEST = 4 }; // System.Reflection.ManifestResourceInfo struct Il2CppManifestResourceInfo { Il2CppObject object; Il2CppReflectionAssembly* assembly; Il2CppString* filename; uint32_t location; }; #define IL2CPP_CHECK_ARG_NULL(arg) do { \ if (arg == NULL) \ { \ il2cpp::vm::Exception::Raise (il2cpp::vm::Exception::GetArgumentNullException (#arg)); \ }; } while (0) // System.Runtime.Remoting.Contexts.Context struct Il2CppAppContext { Il2CppObject obj; int32_t domain_id; int32_t context_id; void* static_data; }; #if !NET_4_0 // System.Decimal typedef struct { //Note that we are not taking care of endianess. union { uint32_t ss32; struct signscale { unsigned int reserved1 : 16; unsigned int scale : 8; unsigned int reserved2 : 7; unsigned int sign : 1; } signscale; } u; uint32_t hi32; uint32_t lo32; uint32_t mid32; } il2cpp_decimal_repr; #else struct Il2CppDecimal { // Decimal.cs treats the first two shorts as one long // And they seriable the data so we need to little endian // seriliazation // The wReserved overlaps with Variant's vt member #if IL2CPP_BYTE_ORDER == IL2CPP_BIG_ENDIAN union { struct { uint8_t sign; uint8_t scale; } u; uint16_t signscale; } u; uint16_t reserved; #else uint16_t reserved; union { struct { uint8_t scale; uint8_t sign; } u; uint16_t signscale; } u; #endif uint32_t Hi32; union { struct { uint32_t Lo32; uint32_t Mid32; } v; uint64_t Lo64; } v; }; // Structure to access an encoded double floating point struct Il2CppDouble { #if IL2CPP_BYTE_ORDER == IL2CPP_BIG_ENDIAN uint32_t sign : 1; uint32_t exp : 11; uint32_t mantHi : 20; uint32_t mantLo : 32; #else // BIGENDIAN uint32_t mantLo : 32; uint32_t mantHi : 20; uint32_t exp : 11; uint32_t sign : 1; #endif }; typedef union { Il2CppDouble s; double d; } Il2CppDouble_double; typedef enum { IL2CPP_DECIMAL_CMP_LT = -1, IL2CPP_DECIMAL_CMP_EQ, IL2CPP_DECIMAL_CMP_GT } Il2CppDecimalCompareResult; // Structure to access an encoded single floating point struct Il2CppSingle { #if IL2CPP_BYTE_ORDER == IL2CPP_BIG_ENDIAN uint32_t sign : 1; uint32_t exp : 8; uint32_t mant : 23; #else uint32_t mant : 23; uint32_t exp : 8; uint32_t sign : 1; #endif }; typedef union { Il2CppSingle s; float f; } Il2CppSingle_float; #endif // System.Guid struct Il2CppGuid { uint32_t data1; uint16_t data2; uint16_t data3; uint8_t data4[8]; }; struct Il2CppSafeArrayBound { uint32_t element_count; int32_t lower_bound; }; struct Il2CppSafeArray { uint16_t dimention_count; uint16_t features; uint32_t element_size; uint32_t lock_count; void* data; Il2CppSafeArrayBound bounds[1]; }; struct Il2CppWin32Decimal { uint16_t reserved; union { struct { uint8_t scale; uint8_t sign; } s; uint16_t signscale; } u; uint32_t hi32; union { struct { uint32_t lo32; uint32_t mid32; } s2; uint64_t lo64; } u2; }; typedef int16_t IL2CPP_VARIANT_BOOL; #define IL2CPP_VARIANT_TRUE ((IL2CPP_VARIANT_BOOL)-1) #define IL2CPP_VARIANT_FALSE ((IL2CPP_VARIANT_BOOL)0) enum Il2CppVarType { IL2CPP_VT_EMPTY = 0, IL2CPP_VT_NULL = 1, IL2CPP_VT_I2 = 2, IL2CPP_VT_I4 = 3, IL2CPP_VT_R4 = 4, IL2CPP_VT_R8 = 5, IL2CPP_VT_CY = 6, IL2CPP_VT_DATE = 7, IL2CPP_VT_BSTR = 8, IL2CPP_VT_DISPATCH = 9, IL2CPP_VT_ERROR = 10, IL2CPP_VT_BOOL = 11, IL2CPP_VT_VARIANT = 12, IL2CPP_VT_UNKNOWN = 13, IL2CPP_VT_DECIMAL = 14, IL2CPP_VT_I1 = 16, IL2CPP_VT_UI1 = 17, IL2CPP_VT_UI2 = 18, IL2CPP_VT_UI4 = 19, IL2CPP_VT_I8 = 20, IL2CPP_VT_UI8 = 21, IL2CPP_VT_INT = 22, IL2CPP_VT_UINT = 23, IL2CPP_VT_VOID = 24, IL2CPP_VT_HRESULT = 25, IL2CPP_VT_PTR = 26, IL2CPP_VT_SAFEARRAY = 27, IL2CPP_VT_CARRAY = 28, IL2CPP_VT_USERDEFINED = 29, IL2CPP_VT_LPSTR = 30, IL2CPP_VT_LPWSTR = 31, IL2CPP_VT_RECORD = 36, IL2CPP_VT_INT_PTR = 37, IL2CPP_VT_UINT_PTR = 38, IL2CPP_VT_FILETIME = 64, IL2CPP_VT_BLOB = 65, IL2CPP_VT_STREAM = 66, IL2CPP_VT_STORAGE = 67, IL2CPP_VT_STREAMED_OBJECT = 68, IL2CPP_VT_STORED_OBJECT = 69, IL2CPP_VT_BLOB_OBJECT = 70, IL2CPP_VT_CF = 71, IL2CPP_VT_CLSID = 72, IL2CPP_VT_VERSIONED_STREAM = 73, IL2CPP_VT_BSTR_BLOB = 0xfff, IL2CPP_VT_VECTOR = 0x1000, IL2CPP_VT_ARRAY = 0x2000, IL2CPP_VT_BYREF = 0x4000, IL2CPP_VT_RESERVED = 0x8000, IL2CPP_VT_ILLEGAL = 0xffff, IL2CPP_VT_ILLEGALMASKED = 0xfff, IL2CPP_VT_TYPEMASK = 0xfff, }; struct Il2CppVariant { union { struct __tagVARIANT { uint16_t type; uint16_t reserved1; uint16_t reserved2; uint16_t reserved3; union { int64_t llVal; int32_t lVal; uint8_t bVal; int16_t iVal; float fltVal; double dblVal; IL2CPP_VARIANT_BOOL boolVal; int32_t scode; int64_t cyVal; double date; Il2CppChar* bstrVal; Il2CppIUnknown* punkVal; void* pdispVal; Il2CppSafeArray* parray; uint8_t* pbVal; int16_t* piVal; int32_t* plVal; int64_t* pllVal; float* pfltVal; double* pdblVal; IL2CPP_VARIANT_BOOL* pboolVal; int32_t* pscode; int64_t* pcyVal; double* pdate; Il2CppChar* pbstrVal; Il2CppIUnknown** ppunkVal; void** ppdispVal; Il2CppSafeArray** pparray; Il2CppVariant* pvarVal; void* byref; char cVal; uint16_t uiVal; uint32_t ulVal; uint64_t ullVal; int intVal; unsigned int uintVal; Il2CppWin32Decimal* pdecVal; char* pcVal; uint16_t* puiVal; uint32_t* pulVal; uint64_t* pullVal; int* pintVal; unsigned int* puintVal; struct __tagBRECORD { void* pvRecord; void* pRecInfo; } n4; } n3; } n2; Il2CppWin32Decimal decVal; } n1; }; struct Il2CppFileTime { uint32_t low; uint32_t high; }; struct Il2CppStatStg { Il2CppChar* name; uint32_t type; uint64_t size; Il2CppFileTime mtime; Il2CppFileTime ctime; Il2CppFileTime atime; uint32_t mode; uint32_t locks; Il2CppGuid clsid; uint32_t state; uint32_t reserved; }; struct Il2CppHString__ { int unused; }; typedef Il2CppHString__* Il2CppHString; struct Il2CppHStringHeader { union { void* Reserved1; #if IL2CPP_SIZEOF_VOID_P == 8 char Reserved2[24]; #else char Reserved2[20]; #endif } Reserved; }; struct LIBIL2CPP_CODEGEN_API NOVTABLE Il2CppIUnknown { static const Il2CppGuid IID; virtual il2cpp_hresult_t STDCALL QueryInterface(const Il2CppGuid& iid, void** object) = 0; virtual uint32_t STDCALL AddRef() = 0; virtual uint32_t STDCALL Release() = 0; }; struct NOVTABLE Il2CppISequentialStream : Il2CppIUnknown { static const LIBIL2CPP_CODEGEN_API Il2CppGuid IID; virtual il2cpp_hresult_t STDCALL Read(void* buffer, uint32_t size, uint32_t* read) = 0; virtual il2cpp_hresult_t STDCALL Write(const void* buffer, uint32_t size, uint32_t* written) = 0; }; struct NOVTABLE Il2CppIStream : Il2CppISequentialStream { static const LIBIL2CPP_CODEGEN_API Il2CppGuid IID; virtual il2cpp_hresult_t STDCALL Seek(int64_t move, uint32_t origin, uint64_t* position) = 0; virtual il2cpp_hresult_t STDCALL SetSize(uint64_t size) = 0; virtual il2cpp_hresult_t STDCALL CopyTo(Il2CppIStream* stream, uint64_t size, uint64_t* read, uint64_t* written) = 0; virtual il2cpp_hresult_t STDCALL Commit(uint32_t flags) = 0; virtual il2cpp_hresult_t STDCALL Revert() = 0; virtual il2cpp_hresult_t STDCALL LockRegion(uint64_t offset, uint64_t size, uint32_t type) = 0; virtual il2cpp_hresult_t STDCALL UnlockRegion(uint64_t offset, uint64_t size, uint32_t type) = 0; virtual il2cpp_hresult_t STDCALL Stat(Il2CppStatStg* data, uint32_t flags) = 0; virtual il2cpp_hresult_t STDCALL Clone(Il2CppIStream** stream) = 0; }; struct LIBIL2CPP_CODEGEN_API NOVTABLE Il2CppIMarshal : Il2CppIUnknown { static const Il2CppGuid IID; virtual il2cpp_hresult_t STDCALL GetUnmarshalClass(const Il2CppGuid& iid, void* object, uint32_t context, void* reserved, uint32_t flags, Il2CppGuid* clsid) = 0; virtual il2cpp_hresult_t STDCALL GetMarshalSizeMax(const Il2CppGuid& iid, void* object, uint32_t context, void* reserved, uint32_t flags, uint32_t* size) = 0; virtual il2cpp_hresult_t STDCALL MarshalInterface(Il2CppIStream* stream, const Il2CppGuid& iid, void* object, uint32_t context, void* reserved, uint32_t flags) = 0; virtual il2cpp_hresult_t STDCALL UnmarshalInterface(Il2CppIStream* stream, const Il2CppGuid& iid, void** object) = 0; virtual il2cpp_hresult_t STDCALL ReleaseMarshalData(Il2CppIStream* stream) = 0; virtual il2cpp_hresult_t STDCALL DisconnectObject(uint32_t reserved) = 0; }; struct NOVTABLE Il2CppIManagedObject : Il2CppIUnknown { static const LIBIL2CPP_CODEGEN_API Il2CppGuid IID; virtual il2cpp_hresult_t STDCALL GetSerializedBuffer(Il2CppChar** bstr) = 0; virtual il2cpp_hresult_t STDCALL GetObjectIdentity(Il2CppChar** bstr_guid, int32_t* app_domain_id, intptr_t* ccw) = 0; }; struct LIBIL2CPP_CODEGEN_API NOVTABLE Il2CppIManagedObjectHolder : Il2CppIUnknown { static const Il2CppGuid IID; virtual Il2CppObject* STDCALL GetManagedObject() = 0; virtual void STDCALL Destroy() = 0; }; struct LIBIL2CPP_CODEGEN_API NOVTABLE Il2CppIInspectable : Il2CppIUnknown { static const Il2CppGuid IID; virtual il2cpp_hresult_t STDCALL GetIids(uint32_t* iidCount, Il2CppGuid** iids) = 0; virtual il2cpp_hresult_t STDCALL GetRuntimeClassName(Il2CppHString* className) = 0; virtual il2cpp_hresult_t STDCALL GetTrustLevel(int32_t* trustLevel) = 0; }; struct NOVTABLE Il2CppIActivationFactory : Il2CppIInspectable { static const LIBIL2CPP_CODEGEN_API Il2CppGuid IID; virtual il2cpp_hresult_t STDCALL ActivateInstance(Il2CppIInspectable** instance) = 0; }; struct NOVTABLE Il2CppIRestrictedErrorInfo : Il2CppIUnknown { static const LIBIL2CPP_CODEGEN_API Il2CppGuid IID; virtual il2cpp_hresult_t STDCALL GetErrorDetails(Il2CppChar** bstrDescription, il2cpp_hresult_t* error, Il2CppChar** bstrRestrictedDescription, Il2CppChar** bstrCapabilitySid) = 0; virtual il2cpp_hresult_t STDCALL GetReference(Il2CppChar** bstrReference) = 0; }; struct NOVTABLE Il2CppILanguageExceptionErrorInfo : Il2CppIUnknown { static const LIBIL2CPP_CODEGEN_API Il2CppGuid IID; virtual il2cpp_hresult_t STDCALL GetLanguageException(Il2CppIUnknown** languageException) = 0; }; struct NOVTABLE Il2CppIAgileObject : Il2CppIUnknown { static const LIBIL2CPP_CODEGEN_API Il2CppGuid IID; virtual il2cpp_hresult_t STDCALL GetLanguageException(Il2CppIUnknown** languageException) = 0; }; ================================================ FILE: unity_decoder/libil2cpp/os/Android/StackTrace.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_ANDROID #include "os/StackTrace.h" #include "os/Image.h" #include #include #include #include namespace il2cpp { namespace os { const int kMaxStackFrames = 128; namespace { extern "C" char end; uintptr_t s_BaseAddress; uintptr_t s_EndAddress; pthread_once_t s_InitKnownSymbolInfoOnceFlag = PTHREAD_ONCE_INIT; static void InitKnownSymbolInfo() { s_BaseAddress = reinterpret_cast(os::Image::GetImageBase()); s_EndAddress = reinterpret_cast(&end); } static bool KnownSymbol(const uintptr_t addr) { pthread_once(&s_InitKnownSymbolInfoOnceFlag, &InitKnownSymbolInfo); if (addr >= s_BaseAddress && addr <= s_EndAddress) return true; Dl_info info; if (!dladdr(reinterpret_cast(addr), &info)) return false; const char* const slash = strrchr(info.dli_fname, '/'); return slash && strcmp(slash + 1, "libunity.so") == 0; } struct AndroidStackTrace { size_t size; Il2CppMethodPointer addrs[kMaxStackFrames]; bool PushStackFrameAddress(const uintptr_t addr) { if (size >= kMaxStackFrames) return false; addrs[size++] = reinterpret_cast(addr); return true; } static _Unwind_Reason_Code Callback(struct _Unwind_Context* context, void* self) { const uintptr_t addr = _Unwind_GetIP(context); // Workaround to avoid crash when generating stack trace in some third-party libraries if (!KnownSymbol(addr)) return _URC_END_OF_STACK; if (static_cast(self)->PushStackFrameAddress(addr)) return _URC_NO_REASON; else return _URC_END_OF_STACK; } }; } void StackTrace::WalkStack(WalkStackCallback callback, void* context, WalkOrder walkOrder) { AndroidStackTrace callstack = {}; _Unwind_Backtrace(AndroidStackTrace::Callback, &callstack); for (size_t i = 0; i < callstack.size; ++i) { const size_t index = (walkOrder == kFirstCalledToLastCalled) ? (callstack.size - i - 1) : i; if (!callback(callstack.addrs[index], context)) break; } } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Atomic.h ================================================ #pragma once #include #include "utils/NonCopyable.h" namespace il2cpp { namespace os { // On Windows, MemoryBarrier is defined as a macro on x64. Conflicts with MemoryBarrier in Atomic.h. #undef MemoryBarrier class Atomic : public il2cpp::utils::NonCopyable { public: // All 32bit atomics must be performed on 4-byte aligned addresses. All 64bit atomics must be // performed on 8-byte aligned addresses. // Add and Add64 return the *result* of the addition, not the old value! (i.e. they work like // InterlockedAdd and __sync_add_and_fetch). static inline int32_t Add(volatile int32_t* location1, int32_t value); static inline int64_t Add64(volatile int64_t* location1, int64_t value); static inline int32_t Increment(volatile int32_t* value); static inline int64_t Increment64(volatile int64_t* value); static inline int32_t Decrement(volatile int32_t* value); static inline int64_t Decrement64(volatile int64_t* value); static inline int32_t CompareExchange(volatile int32_t* dest, int32_t exchange, int32_t comparand); static inline int64_t CompareExchange64(volatile int64_t* dest, int64_t exchange, int64_t comparand); static inline void* CompareExchangePointer(void* volatile* dest, void* exchange, void* comparand); static inline int32_t Exchange(volatile int32_t* dest, int32_t exchange); static inline int64_t Exchange64(volatile int64_t* dest, int64_t exchange); static inline void* ExchangePointer(void* volatile* dest, void* exchange); static inline int64_t Read64(volatile int64_t* addr); static inline void MemoryBarrier(); static inline uint32_t Add(volatile uint32_t* location1, uint32_t value) { return static_cast(Add((volatile int32_t*)location1, (int32_t)value)); } template static inline T* CompareExchangePointer(T* volatile* dest, T* newValue, T* oldValue) { return static_cast(CompareExchangePointer((void*volatile*)dest, newValue, oldValue)); } template static inline T* ExchangePointer(T* volatile* dest, T* newValue) { return static_cast(ExchangePointer((void*volatile*)dest, newValue)); } static inline uint64_t Read64(volatile uint64_t* addr) { return static_cast(Read64((volatile int64_t*)addr)); } template static inline T* ReadPointer(T* volatile* pointer) { #if IL2CPP_SIZEOF_VOID_P == 4 return reinterpret_cast(Add(reinterpret_cast(pointer), 0)); #else return reinterpret_cast(Add64(reinterpret_cast(pointer), 0)); #endif } static inline uint32_t Increment(volatile uint32_t* value) { return static_cast(Increment(reinterpret_cast(value))); } static inline uint64_t Increment64(volatile uint64_t* value) { return static_cast(Increment64(reinterpret_cast(value))); } static inline uint32_t Decrement(volatile uint32_t* value) { return static_cast(Decrement(reinterpret_cast(value))); } static inline uint64_t Decrement64(volatile uint64_t* value) { return static_cast(Decrement64(reinterpret_cast(value))); } static inline uint32_t CompareExchange(volatile uint32_t* value, uint32_t newValue, uint32_t oldValue) { return static_cast(CompareExchange(reinterpret_cast(value), newValue, oldValue)); } static inline uint64_t CompareExchange64(volatile uint64_t* value, uint64_t newValue, uint64_t oldValue) { return static_cast(CompareExchange64(reinterpret_cast(value), newValue, oldValue)); } static inline uint32_t Exchange(volatile uint32_t* value, uint32_t newValue) { return static_cast(Exchange(reinterpret_cast(value), newValue)); } static inline uint64_t Exchange64(volatile uint64_t* value, uint64_t newValue) { return static_cast(Exchange64(reinterpret_cast(value), newValue)); } }; } } #if !IL2CPP_SUPPORT_THREADS namespace il2cpp { namespace os { inline int32_t Atomic::Add(volatile int32_t* location1, int32_t value) { return *location1 += value; } inline int64_t Atomic::Add64(volatile int64_t* location1, int64_t value) { return *location1 += value; } inline int32_t Atomic::Increment(volatile int32_t* value) { return ++(*value); } inline int64_t Atomic::Increment64(volatile int64_t* value) { return ++(*value); } inline int32_t Atomic::Decrement(volatile int32_t* value) { return --(*value); } inline int64_t Atomic::Decrement64(volatile int64_t* value) { return --(*value); } inline int32_t Atomic::CompareExchange(volatile int32_t* dest, int32_t exchange, int32_t comparand) { int32_t orig = *dest; if (*dest == comparand) *dest = exchange; return orig; } inline int64_t Atomic::CompareExchange64(volatile int64_t* dest, int64_t exchange, int64_t comparand) { int64_t orig = *dest; if (*dest == comparand) *dest = exchange; return orig; } inline void* Atomic::CompareExchangePointer(void* volatile* dest, void* exchange, void* comparand) { void* orig = *dest; if (*dest == comparand) *dest = exchange; return orig; } inline int64_t Atomic::Exchange64(volatile int64_t* dest, int64_t exchange) { int64_t orig = *dest; *dest = exchange; return orig; } inline int32_t Atomic::Exchange(volatile int32_t* dest, int32_t exchange) { int32_t orig = *dest; *dest = exchange; return orig; } inline void* Atomic::ExchangePointer(void* volatile* dest, void* exchange) { void* orig = *dest; *dest = exchange; return orig; } int64_t Atomic::Read64(volatile int64_t* addr) { return *addr; } inline void Atomic::MemoryBarrier() { // Do nothing. } } } #elif IL2CPP_TARGET_WINDOWS #include "os/Win32/AtomicImpl.h" #elif IL2CPP_TARGET_PS4 #include "os/AtomicImpl.h" // has to come earlier than posix #elif IL2CPP_TARGET_PSP2 #include "os/PSP2/AtomicImpl.h" #elif IL2CPP_TARGET_POSIX #include "os/Posix/AtomicImpl.h" #else #include "os/AtomicImpl.h" #endif ================================================ FILE: unity_decoder/libil2cpp/os/COM.h ================================================ #pragma once namespace il2cpp { namespace os { class COM { public: static il2cpp_hresult_t CreateInstance(const Il2CppGuid& clsid, Il2CppIUnknown** object); static il2cpp_hresult_t CreateFreeThreadedMarshaler(Il2CppIUnknown* outer, Il2CppIUnknown** marshal); // variant static void VariantInit(Il2CppVariant* variant); static il2cpp_hresult_t VariantClear(Il2CppVariant* variant); // safe array static Il2CppSafeArray* SafeArrayCreate(uint16_t type, uint32_t dimention_count, Il2CppSafeArrayBound* bounds); static il2cpp_hresult_t SafeArrayDestroy(Il2CppSafeArray* safeArray); static il2cpp_hresult_t SafeArrayAccessData(Il2CppSafeArray* safeArray, void** data); static il2cpp_hresult_t SafeArrayUnaccessData(Il2CppSafeArray* safeArray); static il2cpp_hresult_t SafeArrayGetVartype(Il2CppSafeArray* safeArray, uint16_t* type); static uint32_t SafeArrayGetDim(Il2CppSafeArray* safeArray); static il2cpp_hresult_t SafeArrayGetLBound(Il2CppSafeArray* safeArray, uint32_t dimention, int32_t* bound); static il2cpp_hresult_t SafeArrayGetUBound(Il2CppSafeArray* safeArray, uint32_t dimention, int32_t* bound); }; } /* namespace os */ } /* namespace il2cpp*/ #pragma once ================================================ FILE: unity_decoder/libil2cpp/os/ConditionVariable.cpp ================================================ #if NET_4_0 #include "il2cpp-config.h" #include "os/Mutex.h" #include "os/ConditionVariable.h" #if IL2CPP_THREADS_WIN32 #include "os/Win32/ConditionVariableImpl.h" #else #include "os/Posix/ConditionVariableImpl.h" #endif namespace il2cpp { namespace os { ConditionVariable::ConditionVariable() : m_ConditionVariable(new ConditionVariableImpl()) { } ConditionVariable::~ConditionVariable() { delete m_ConditionVariable; } int ConditionVariable::Wait(FastMutex* lock) { return m_ConditionVariable->Wait(lock->GetImpl()); } int ConditionVariable::TimedWait(FastMutex* lock, uint32_t timeout_ms) { return m_ConditionVariable->TimedWait(lock->GetImpl(), timeout_ms); } void ConditionVariable::Broadcast() { m_ConditionVariable->Broadcast(); } void ConditionVariable::Signal() { m_ConditionVariable->Signal(); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/ConditionVariable.h ================================================ #pragma once #if NET_4_0 #include "utils/NonCopyable.h" namespace il2cpp { namespace os { class FastMutex; class ConditionVariableImpl; class ConditionVariable : public il2cpp::utils::NonCopyable { public: ConditionVariable(); ~ConditionVariable(); int Wait(FastMutex* lock); int TimedWait(FastMutex* lock, uint32_t timeout_ms); void Broadcast(); void Signal(); private: ConditionVariableImpl* m_ConditionVariable; }; } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Console.h ================================================ #pragma once #include struct FileHandle; struct Il2CppArray; namespace il2cpp { namespace os { namespace Console { // Isatty is in File class int32_t InternalKeyAvailable(int32_t ms_timeout); bool SetBreak(bool wantBreak); bool SetEcho(bool wantEcho); bool TtySetup(const std::string& keypadXmit, const std::string& teardown, uint8_t* control_characters, int32_t** size); } } } ================================================ FILE: unity_decoder/libil2cpp/os/CpuInfo.h ================================================ #pragma once #if NET_4_0 #if IL2CPP_ENABLE_CPU_INFO #include namespace il2cpp { namespace os { class CpuInfo { public: static void* Create(); /* * This function returns the cpu usage in percentage, * normalized on the number of cores. * * Warning : the percentage returned can be > 100%. This * might happens on systems like Android which, for * battery and performance reasons, shut down cores and * lie about the number of active cores. */ static int32_t Usage(void* previous); }; } } #endif #endif ================================================ FILE: unity_decoder/libil2cpp/os/Cryptography.h ================================================ #pragma once namespace il2cpp { namespace os { class Cryptography { public: /* Returns a handle the cryptography provider to use in other calls on this API. */ static void* GetCryptographyProvider(); /* Open the cryptogrpahy provider. */ static bool OpenCryptographyProvider(); /* Indicate that the cyrptography provider is no longer in use. */ static void ReleaseCryptographyProvider(void* provider); /* Use the provider to fill the buffer with cryptographically random bytes. */ static bool FillBufferWithRandomBytes(void* provider, uint32_t length, unsigned char* data); }; } } ================================================ FILE: unity_decoder/libil2cpp/os/Debug.cpp ================================================ #include "il2cpp-config.h" // Generic implementation for platforms that don't have this implemented #if !IL2CPP_ISDEBUGGERPRESENT_IMPLEMENTED #include "os/Debug.h" namespace il2cpp { namespace os { bool Debug::IsDebuggerPresent() { return false; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Debug.h ================================================ #pragma once namespace il2cpp { namespace os { class Debug { public: static bool IsDebuggerPresent(); }; } } ================================================ FILE: unity_decoder/libil2cpp/os/Directory.h ================================================ #pragma once #include #include #include #include "il2cpp-string-types.h" #include "os/ErrorCodes.h" #include "utils/StringView.h" namespace il2cpp { namespace os { class Directory { public: static std::string GetCurrent(int* error); static bool SetCurrent(const std::string& path, int* error); static bool Create(const std::string& path, int *error); static bool Remove(const std::string& path, int *error); static std::set GetFileSystemEntries(const std::string& path, const std::string& pathWithPattern, int32_t attrs, int32_t mask, int* error); struct FindHandle { void* osHandle; Il2CppNativeString directoryPath; Il2CppNativeString pattern; FindHandle(const utils::StringView& searchPathWithPattern); ~FindHandle(); inline void SetOSHandle(void* osHandle) { this->osHandle = osHandle; } int32_t CloseOSHandle(); }; static os::ErrorCode FindFirstFile(FindHandle* findHandle, const utils::StringView& searchPathWithPattern, Il2CppNativeString* resultFileName, int32_t* resultAttributes); static os::ErrorCode FindNextFile(FindHandle* findHandle, Il2CppNativeString* resultFileName, int32_t* resultAttributes); }; } } ================================================ FILE: unity_decoder/libil2cpp/os/Encoding.h ================================================ #pragma once #include namespace il2cpp { namespace os { namespace Encoding { std::string GetCharSet(); } } } ================================================ FILE: unity_decoder/libil2cpp/os/Environment.h ================================================ #pragma once #include #include #include struct Il2CppArray; namespace il2cpp { namespace os { class Environment { public: static std::string GetMachineName(); static int32_t GetProcessorCount(); static std::string GetOsVersionString(); static std::string GetOsUserName(); static std::string GetEnvironmentVariable(const std::string& name); static void SetEnvironmentVariable(const std::string& name, const std::string& value); static std::vector GetEnvironmentVariableNames(); static std::string GetHomeDirectory(); static std::vector GetLogicalDrives(); static void Exit(int result); static NORETURN void Abort(); static std::string GetWindowsFolderPath(int32_t folder); #if NET_4_0 static bool Is64BitOs(); #endif }; } } ================================================ FILE: unity_decoder/libil2cpp/os/Error.cpp ================================================ #include "il2cpp-config.h" #include "os/Error.h" #include "os/ThreadLocalValue.h" // Note: for now the implementation is not platform depentent. namespace il2cpp { namespace os { static ThreadLocalValue s_LastError; ErrorCode Error::GetLastError() { void* value = 0; s_LastError.GetValue(&value); return (ErrorCode)(int64_t)value; } void Error::SetLastError(ErrorCode code) { s_LastError.SetValue((void*)((int64_t)code)); } } } ================================================ FILE: unity_decoder/libil2cpp/os/Error.h ================================================ #pragma once #include "os/ErrorCodes.h" namespace il2cpp { namespace os { class Error { public: static ErrorCode GetLastError(); static void SetLastError(ErrorCode code); }; } } ================================================ FILE: unity_decoder/libil2cpp/os/ErrorCodes.h ================================================ #pragma once #include #include namespace il2cpp { namespace os { enum ErrorCode { kErrorCodeSuccess = 0, kErrorInvalidFunction = 1, kErrorCodeFileNotFound = 2, kErrorCodePathNotFound = 3, kErrorCodeTooManyOpenFiles = 4, kErrorCodeAccessDenied = 5, kErrorCodeInvalidHandle = 6, kErrorArenaTrashed = 7, kErrorNotEnoughMemory = 8, kErrorInvalidBlock = 9, kErrorBadEnvironment = 10, kErrorBadFormat = 11, kErrorInvalidAccess = 12, kErrorInvalidData = 13, kErrorOutofmemory = 14, kErrorCodeInvalidDrive = 15, kErrorCurrentDirectory = 16, kErrorCodeNotSameDevice = 17, kErrorCodeNoMoreFiles = 18, kErrorWriteProtect = 19, kErrorBadUnit = 20, kErrorNotReady = 21, kErrorBadCommand = 22, kErrorCrc = 23, kErrorBadLength = 24, kErrorSeek = 25, kErrorNotDosDisk = 26, kErrorSectorNotFound = 27, kErrorOutOfPaper = 28, kErrorCodeWriteFault = 29, kErrorCodeReadFault = 30, kErrorCodeGenFailure = 31, kErrorCodeSharingViolation = 32, kErrorCodeLockViolation = 33, kErrorWrongDisk = 34, kErrorSharingBufferExceeded = 36, kErrorHandleEof = 38, kErrorCodeHandleDiskFull = 39, kErrorNotSupported = 50, kErrorRemNotList = 51, kErrorDupName = 52, kErrorBadNetpath = 53, kErrorNetworkBusy = 54, kErrorDevNotExist = 55, kErrorTooManyCmds = 56, kErrorAdapHdwErr = 57, kErrorBadNetResp = 58, kErrorUnexpNetErr = 59, kErrorBadRemAdap = 60, kErrorPrintqFull = 61, kErrorNoSpoolSpace = 62, kErrorPrintCancelled = 63, kErrorNetnameDeleted = 64, kErrorNetworkAccessDenied = 65, kErrorBadDevType = 66, kErrorBadNetName = 67, kErrorTooManyNames = 68, kErrorTooManySess = 69, kErrorSharingPaused = 70, kErrorReqNotAccep = 71, kErrorRedirPaused = 72, kErrorCodeFileExists = 80, kErrorCodeCannotMake = 82, kErrorFailI24 = 83, kErrorOutOfStructures = 84, kErrorAlreadyAssigned = 85, kErrorInvalidPassword = 86, kErrorCodeInvalidParameter = 87, kErrorNetWriteFault = 88, kErrorNoProcSlots = 89, kErrorTooManySemaphores = 100, kErrorExclSemAlreadyOwned = 101, kErrorSemIsSet = 102, kErrorTooManySemRequests = 103, kErrorInvalidAtInterruptTime = 104, kErrorSemOwnerDied = 105, kErrorSemUserLimit = 106, kErrorDiskChange = 107, kErrorDriveLocked = 108, kErrorCodeBrokenPipe = 109, kErrorOpenFailed = 110, kErrorBufferOverflow = 111, kErrorDiskFull = 112, kErrorNoMoreSearchHandles = 113, kErrorInvalidTargetHandle = 114, kErrorInvalidCategory = 117, kErrorInvalidVerifySwitch = 118, kErrorBadDriverLevel = 119, kErrorCallNotImplemented = 120, kErrorSemTimeout = 121, kErrorInsufficientBuffer = 122, kErrorCodeInvalidName = 123, kErrorInvalidLevel = 124, kErrorNoVolumeLabel = 125, kErrorModNotFound = 126, kErrorProcNotFound = 127, kErrorWaitNoChildren = 128, kErrorChildNotComplete = 129, kErrorDirectAccessHandle = 130, kErrorNegativeSeek = 131, kErrorSeekOnDevice = 132, kErrorIsJoinTarget = 133, kErrorIsJoined = 134, kErrorIsSubsted = 135, kErrorNotJoined = 136, kErrorNotSubsted = 137, kErrorJoinToJoin = 138, kErrorSubstToSubst = 139, kErrorJoinToSubst = 140, kErrorSubstToJoin = 141, kErrorBusyDrive = 142, kErrorSameDrive = 143, kErrorDirNotRoot = 144, kErrorCodeDirNotEmpty = 145, kErrorIsSubstPath = 146, kErrorIsJoinPath = 147, kErrorPathBusy = 148, kErrorIsSubstTarget = 149, kErrorSystemTrace = 150, kErrorInvalidEventCount = 151, kErrorTooManyMuxwaiters = 152, kErrorInvalidListFormat = 153, kErrorLabelTooLong = 154, kErrorTooManyTcbs = 155, kErrorSignalRefused = 156, kErrorDiscarded = 157, kErrorNotLocked = 158, kErrorBadThreadidAddr = 159, kErrorBadArguments = 160, kErrorBadPathname = 161, kErrorSignalPending = 162, kErrorMaxThrdsReached = 164, kErrorLockFailed = 167, kErrorBusy = 170, kErrorCancelViolation = 173, kErrorAtomicLocksNotSupported = 174, kErrorInvalidSegmentNumber = 180, kErrorInvalidOrdinal = 182, kErrorCodeAlreadyExists = 183, kErrorInvalidFlagNumber = 186, kErrorSemNotFound = 187, kErrorInvalidStartingCodeseg = 188, kErrorInvalidStackseg = 189, kErrorInvalidModuletype = 190, kErrorInvalidExeSignature = 191, kErrorExeMarkedInvalid = 192, kErrorBadExeFormat = 193, kErrorIteratedDataExceeds64k = 194, kErrorInvalidMinallocsize = 195, kErrorDynlinkFromInvalidRing = 196, kErrorIoplNotEnabled = 197, kErrorInvalidSegdpl = 198, kErrorAutodatasegExceeds64k = 199, kErrorRing2segMustBeMovable = 200, kErrorRelocChainXeedsSeglim = 201, kErrorInfloopInRelocChain = 202, kErrorEnvvarNotFound = 203, kErrorNoSignalSent = 205, kErrorCodeFileNameExcedRange = 206, kErrorRing2StackInUse = 207, kErrorMetaExpansionTooLong = 208, kErrorInvalidSignalNumber = 209, kErrorThread1Inactive = 210, kErrorLocked = 212, kErrorTooManyModules = 214, kErrorNestingNotAllowed = 215, kErrorExeMachineTypeMismatch = 216, kErrorBadPipe = 230, kErrorPipeBusy = 231, kErrorNoData = 232, kErrorPipeNotConnected = 233, kErrorMoreData = 234, kErrorVcDisconnected = 240, kErrorInvalidEaName = 254, kErrorEaListInconsistent = 255, kWaitTimeout = 258, kErrorNoMoreItems = 259, kErrorCannotCopy = 266, kErrorDirectory = 267, kErrorEasDidntFit = 275, kErrorEaFileCorrupt = 276, kErrorEaTableFull = 277, kErrorInvalidEaHandle = 278, kErrorEasNotSupported = 282, kErrorNotOwner = 288, kErrorTooManyPosts = 298, kErrorPartialCopy = 299, kErrorOplockNotGranted = 300, kErrorInvalidOplockProtocol = 301, kErrorDiskTooFragmented = 302, kErrorDeletePending = 303, kErrorMrMidNotFound = 317, kErrorInvalidAddress = 487, kErrorArithmeticOverflow = 534, kErrorPipeConnected = 535, kErrorPipeListening = 536, kErrorEaAccessDenied = 994, kErrorOperationAborted = 995, kErrorIoIncomplete = 996, kErrorIoPending = 997, kErrorNoaccess = 998, kErrorSwaperror = 999, kErrorStackOverflow = 1001, kErrorInvalidMessage = 1002, kErrorCanNotComplete = 1003, kErrorInvalidFlags = 1004, kErrorUnrecognizedVolume = 1005, kErrorFileInvalid = 1006, kErrorFullscreenMode = 1007, kErrorNoToken = 1008, kErrorBaddb = 1009, kErrorBadkey = 1010, kErrorCantopen = 1011, kErrorCantread = 1012, kErrorCantwrite = 1013, kErrorRegistryRecovered = 1014, kErrorRegistryCorrupt = 1015, kErrorRegistryIoFailed = 1016, kErrorNotRegistryFile = 1017, kErrorKeyDeleted = 1018, kErrorNoLogSpace = 1019, kErrorKeyHasChildren = 1020, kErrorChildMustBeVolatile = 1021, kErrorNotifyEnumDir = 1022, kErrorDependentServicesRunning = 1051, kErrorInvalidServiceControl = 1052, kErrorServiceRequestTimeout = 1053, kErrorServiceNoThread = 1054, kErrorServiceDatabaseLocked = 1055, kErrorServiceAlreadyRunning = 1056, kErrorInvalidServiceAccount = 1057, kErrorServiceDisabled = 1058, kErrorCircularDependency = 1059, kErrorServiceDoesNotExist = 1060, kErrorServiceCannotAcceptCtrl = 1061, kErrorServiceNotActive = 1062, kErrorFailedServiceControllerConnect = 1063, kErrorExceptionInService = 1064, kErrorDatabaseDoesNotExist = 1065, kErrorServiceSpecificError = 1066, kErrorProcessAborted = 1067, kErrorServiceDependencyFail = 1068, kErrorServiceLogonFailed = 1069, kErrorServiceStartHang = 1070, kErrorInvalidServiceLock = 1071, kErrorServiceMarkedForDelete = 1072, kErrorServiceExists = 1073, kErrorAlreadyRunningLkg = 1074, kErrorServiceDependencyDeleted = 1075, kErrorBootAlreadyAccepted = 1076, kErrorServiceNeverStarted = 1077, kErrorDuplicateServiceName = 1078, kErrorDifferentServiceAccount = 1079, kErrorCannotDetectDriverFailure = 1080, kErrorCannotDetectProcessAbort = 1081, kErrorNoRecoveryProgram = 1082, kErrorServiceNotInExe = 1083, kErrorNotSafebootService = 1084, kErrorEndOfMedia = 1100, kErrorFilemarkDetected = 1101, kErrorBeginningOfMedia = 1102, kErrorSetmarkDetected = 1103, kErrorNoDataDetected = 1104, kErrorPartitionFailure = 1105, kErrorInvalidBlockLength = 1106, kErrorDeviceNotPartitioned = 1107, kErrorUnableToLockMedia = 1108, kErrorUnableToUnloadMedia = 1109, kErrorMediaChanged = 1110, kErrorBusReset = 1111, kErrorNoMediaInDrive = 1112, kErrorNoUnicodeTranslation = 1113, kErrorDllInitFailed = 1114, kErrorShutdownInProgress = 1115, kErrorNoShutdownInProgress = 1116, kErrorIoDevice = 1117, kErrorSerialNoDevice = 1118, kErrorIrqBusy = 1119, kErrorMoreWrites = 1120, kErrorCounterTimeout = 1121, kErrorFloppyIdMarkNotFound = 1122, kErrorFloppyWrongCylinder = 1123, kErrorFloppyUnknownError = 1124, kErrorFloppyBadRegisters = 1125, kErrorDiskRecalibrateFailed = 1126, kErrorDiskOperationFailed = 1127, kErrorDiskResetFailed = 1128, kErrorEomOverflow = 1129, kErrorNotEnoughServerMemory = 1130, kErrorPossibleDeadlock = 1131, kErrorMappedAlignment = 1132, kErrorSetPowerStateVetoed = 1140, kErrorSetPowerStateFailed = 1141, kErrorTooManyLinks = 1142, kErrorOldWinVersion = 1150, kErrorAppWrongOs = 1151, kErrorSingleInstanceApp = 1152, kErrorRmodeApp = 1153, kErrorInvalidDll = 1154, kErrorNoAssociation = 1155, kErrorDdeFail = 1156, kErrorDllNotFound = 1157, kErrorNoMoreUserHandles = 1158, kErrorMessageSyncOnly = 1159, kErrorSourceElementEmpty = 1160, kErrorDestinationElementFull = 1161, kErrorIllegalElementAddress = 1162, kErrorMagazineNotPresent = 1163, kErrorDeviceReinitializationNeeded = 1164, kErrorDeviceRequiresCleaning = 1165, kErrorDeviceDoorOpen = 1166, kErrorDeviceNotConnected = 1167, kErrorNotFound = 1168, kErrorNoMatch = 1169, kErrorSetNotFound = 1170, kErrorPointNotFound = 1171, kErrorNoTrackingService = 1172, kErrorNoVolumeId = 1173, kErrorUnableToRemoveReplaced = 1175, kErrorUnableToMoveReplacement = 1176, kErrorUnableToMoveReplacement2 = 1177, kErrorJournalDeleteInProgress = 1178, kErrorJournalNotActive = 1179, kErrorPotentialFileFound = 1180, kErrorJournalEntryDeleted = 1181, kErrorBadDevice = 1200, kErrorConnectionUnavail = 1201, kErrorDeviceAlreadyRemembered = 1202, kErrorNoNetOrBadPath = 1203, kErrorBadProvider = 1204, kErrorCannotOpenProfile = 1205, kErrorBadProfile = 1206, kErrorNotContainer = 1207, kErrorExtendedError = 1208, kErrorInvalidGroupname = 1209, kErrorInvalidComputername = 1210, kErrorInvalidEventname = 1211, kErrorInvalidDomainname = 1212, kErrorInvalidServicename = 1213, kErrorInvalidNetname = 1214, kErrorInvalidSharename = 1215, kErrorInvalidPasswordname = 1216, kErrorInvalidMessagename = 1217, kErrorInvalidMessagedest = 1218, kErrorSessionCredentialConflict = 1219, kErrorRemoteSessionLimitExceeded = 1220, kErrorDupDomainname = 1221, kErrorNoNetwork = 1222, kErrorCancelled = 1223, kErrorUserMappedFile = 1224, kErrorConnectionRefused = 1225, kErrorGracefulDisconnect = 1226, kErrorAddressAlreadyAssociated = 1227, kErrorAddressNotAssociated = 1228, kErrorConnectionInvalid = 1229, kErrorConnectionActive = 1230, kErrorNetworkUnreachable = 1231, kErrorHostUnreachable = 1232, kErrorProtocolUnreachable = 1233, kErrorPortUnreachable = 1234, kErrorRequestAborted = 1235, kErrorConnectionAborted = 1236, kErrorRetry = 1237, kErrorConnectionCountLimit = 1238, kErrorLoginTimeRestriction = 1239, kErrorLoginWkstaRestriction = 1240, kErrorIncorrectAddress = 1241, kErrorAlreadyRegistered = 1242, kErrorServiceNotFound = 1243, kErrorNotAuthenticated = 1244, kErrorNotLoggedOn = 1245, kErrorContinue = 1246, kErrorAlreadyInitialized = 1247, kErrorNoMoreDevices = 1248, kErrorNoSuchSite = 1249, kErrorDomainControllerExists = 1250, kErrorOnlyIfConnected = 1251, kErrorOverrideNochanges = 1252, kErrorBadUserProfile = 1253, kErrorNotSupportedOnSbs = 1254, kErrorServerShutdownInProgress = 1255, kErrorHostDown = 1256, kErrorNonAccountSid = 1257, kErrorNonDomainSid = 1258, kErrorApphelpBlock = 1259, kErrorAccessDisabledByPolicy = 1260, kErrorRegNatConsumption = 1261, kErrorCscshareOffline = 1262, kErrorPkinitFailure = 1263, kErrorSmartcardSubsystemFailure = 1264, kErrorDowngradeDetected = 1265, kSecESmartcardCertRevoked = 1266, kSecEIssuingCaUntrusted = 1267, kSecERevocationOfflineC = 1268, kSecEPkinitClientFailur = 1269, kSecESmartcardCertExpired = 1270, kErrorMachineLocked = 1271, kErrorCallbackSuppliedInvalidData = 1273, kErrorSyncForegroundRefreshRequired = 1274, kErrorDriverBlocked = 1275, kErrorInvalidImportOfNonDll = 1276, kErrorNotAllAssigned = 1300, kErrorSomeNotMapped = 1301, kErrorNoQuotasForAccount = 1302, kErrorLocalUserSessionKey = 1303, kErrorNullLmPassword = 1304, kErrorUnknownRevision = 1305, kErrorRevisionMismatch = 1306, kErrorInvalidOwner = 1307, kErrorInvalidPrimaryGroup = 1308, kErrorNoImpersonationToken = 1309, kErrorCantDisableMandatory = 1310, kErrorNoLogonServers = 1311, kErrorNoSuchLogonSession = 1312, kErrorNoSuchPrivilege = 1313, kErrorPrivilegeNotHeld = 1314, kErrorInvalidAccountName = 1315, kErrorUserExists = 1316, kErrorNoSuchUser = 1317, kErrorGroupExists = 1318, kErrorNoSuchGroup = 1319, kErrorMemberInGroup = 1320, kErrorMemberNotInGroup = 1321, kErrorLastAdmin = 1322, kErrorWrongPassword = 1323, kErrorIllFormedPassword = 1324, kErrorPasswordRestriction = 1325, kErrorLogonFailure = 1326, kErrorAccountRestriction = 1327, kErrorInvalidLogonHours = 1328, kErrorInvalidWorkstation = 1329, kErrorPasswordExpired = 1330, kErrorAccountDisabled = 1331, kErrorNoneMapped = 1332, kErrorTooManyLuidsRequested = 1333, kErrorLuidsExhausted = 1334, kErrorInvalidSubAuthority = 1335, kErrorInvalidAcl = 1336, kErrorInvalidSid = 1337, kErrorInvalidSecurityDescr = 1338, kErrorBadInheritanceAcl = 1340, kErrorServerDisabled = 1341, kErrorServerNotDisabled = 1342, kErrorInvalidIdAuthority = 1343, kErrorAllottedSpaceExceeded = 1344, kErrorInvalidGroupAttributes = 1345, kErrorBadImpersonationLevel = 1346, kErrorCantOpenAnonymous = 1347, kErrorBadValidationClass = 1348, kErrorBadTokenType = 1349, kErrorNoSecurityOnObject = 1350, kErrorCantAccessDomainInfo = 1351, kErrorInvalidServerState = 1352, kErrorInvalidDomainState = 1353, kErrorInvalidDomainRole = 1354, kErrorNoSuchDomain = 1355, kErrorDomainExists = 1356, kErrorDomainLimitExceeded = 1357, kErrorInternalDbCorruption = 1358, kErrorInternalError = 1359, kErrorGenericNotMapped = 1360, kErrorBadDescriptorFormat = 1361, kErrorNotLogonProcess = 1362, kErrorLogonSessionExists = 1363, kErrorNoSuchPackage = 1364, kErrorBadLogonSessionState = 1365, kErrorLogonSessionCollision = 1366, kErrorInvalidLogonType = 1367, kErrorCannotImpersonate = 1368, kErrorRxactInvalidState = 1369, kErrorRxactCommitFailure = 1370, kErrorSpecialAccount = 1371, kErrorSpecialGroup = 1372, kErrorSpecialUser = 1373, kErrorMembersPrimaryGroup = 1374, kErrorTokenAlreadyInUse = 1375, kErrorNoSuchAlias = 1376, kErrorMemberNotInAlias = 1377, kErrorMemberInAlias = 1378, kErrorAliasExists = 1379, kErrorLogonNotGranted = 1380, kErrorTooManySecrets = 1381, kErrorSecretTooLong = 1382, kErrorInternalDbError = 1383, kErrorTooManyContextIds = 1384, kErrorLogonTypeNotGranted = 1385, kErrorNtCrossEncryptionRequired = 1386, kErrorNoSuchMember = 1387, kErrorInvalidMember = 1388, kErrorTooManySids = 1389, kErrorLmCrossEncryptionRequired = 1390, kErrorNoInheritance = 1391, kErrorFileCorrupt = 1392, kErrorDiskCorrupt = 1393, kErrorNoUserSessionKey = 1394, kErrorLicenseQuotaExceeded = 1395, kErrorWrongTargetName = 1396, kErrorMutualAuthFailed = 1397, kErrorTimeSkew = 1398, kErrorCurrentDomainNotAllowed = 1399, kErrorInvalidWindowHandle = 1400, kErrorInvalidMenuHandle = 1401, kErrorInvalidCursorHandle = 1402, kErrorInvalidAccelHandle = 1403, kErrorInvalidHookHandle = 1404, kErrorInvalidDwpHandle = 1405, kErrorTlwWithWschild = 1406, kErrorCannotFindWndClass = 1407, kErrorWindowOfOtherThread = 1408, kErrorHotkeyAlreadyRegistered = 1409, kErrorClassAlreadyExists = 1410, kErrorClassDoesNotExist = 1411, kErrorClassHasWindows = 1412, kErrorInvalidIndex = 1413, kErrorInvalidIconHandle = 1414, kErrorPrivateDialogIndex = 1415, kErrorListboxIdNotFound = 1416, kErrorNoWildcardCharacters = 1417, kErrorClipboardNotOpen = 1418, kErrorHotkeyNotRegistered = 1419, kErrorWindowNotDialog = 1420, kErrorControlIdNotFound = 1421, kErrorInvalidComboboxMessage = 1422, kErrorWindowNotCombobox = 1423, kErrorInvalidEditHeight = 1424, kErrorDcNotFound = 1425, kErrorInvalidHookFilter = 1426, kErrorInvalidFilterProc = 1427, kErrorHookNeedsHmod = 1428, kErrorGlobalOnlyHook = 1429, kErrorJournalHookSet = 1430, kErrorHookNotInstalled = 1431, kErrorInvalidLbMessage = 1432, kErrorSetcountOnBadLb = 1433, kErrorLbWithoutTabstops = 1434, kErrorDestroyObjectOfOtherThread = 1435, kErrorChildWindowMenu = 1436, kErrorNoSystemMenu = 1437, kErrorInvalidMsgboxStyle = 1438, kErrorInvalidSpiValue = 1439, kErrorScreenAlreadyLocked = 1440, kErrorHwndsHaveDiffParent = 1441, kErrorNotChildWindow = 1442, kErrorInvalidGwCommand = 1443, kErrorInvalidThreadId = 1444, kErrorNonMdichildWindow = 1445, kErrorPopupAlreadyActive = 1446, kErrorNoScrollbars = 1447, kErrorInvalidScrollbarRange = 1448, kErrorInvalidShowwinCommand = 1449, kErrorNoSystemResources = 1450, kErrorNonpagedSystemResources = 1451, kErrorPagedSystemResources = 1452, kErrorWorkingSetQuota = 1453, kErrorPagefileQuota = 1454, kErrorCommitmentLimit = 1455, kErrorMenuItemNotFound = 1456, kErrorInvalidKeyboardHandle = 1457, kErrorHookTypeNotAllowed = 1458, kErrorRequiresInteractiveWindowstation = 1459, kErrorTimeout = 1460, kErrorInvalidMonitorHandle = 1461, kErrorEventlogFileCorrupt = 1500, kErrorEventlogCantStart = 1501, kErrorLogFileFull = 1502, kErrorEventlogFileChanged = 1503, kErrorInstallServiceFailure = 1601, kErrorInstallUserexit = 1602, kErrorInstallFailure = 1603, kErrorInstallSuspend = 1604, kErrorUnknownProduct = 1605, kErrorUnknownFeature = 1606, kErrorUnknownComponent = 1607, kErrorUnknownProperty = 1608, kErrorInvalidHandleState = 1609, kErrorBadConfiguration = 1610, kErrorIndexAbsent = 1611, kErrorInstallSourceAbsent = 1612, kErrorInstallPackageVersion = 1613, kErrorProductUninstalled = 1614, kErrorBadQuerySyntax = 1615, kErrorInvalidField = 1616, kErrorDeviceRemoved = 1617, kErrorInstallAlreadyRunning = 1618, kErrorInstallPackageOpenFailed = 1619, kErrorInstallPackageInvalid = 1620, kErrorInstallUiFailure = 1621, kErrorInstallLogFailure = 1622, kErrorInstallLanguageUnsupported = 1623, kErrorInstallTransformFailure = 1624, kErrorInstallPackageRejected = 1625, kErrorFunctionNotCalled = 1626, kErrorFunctionFailed = 1627, kErrorInvalidTable = 1628, kErrorDatatypeMismatch = 1629, kErrorUnsupportedType = 1630, kErrorCreateFailed = 1631, kErrorInstallTempUnwritable = 1632, kErrorInstallPlatformUnsupported = 1633, kErrorInstallNotused = 1634, kErrorPatchPackageOpenFailed = 1635, kErrorPatchPackageInvalid = 1636, kErrorPatchPackageUnsupported = 1637, kErrorProductVersion = 1638, kErrorInvalidCommandLine = 1639, kErrorInstallRemoteDisallowed = 1640, kErrorSuccessRebootInitiated = 1641, kErrorPatchTargetNotFound = 1642, kErrorPatchPackageRejected = 1643, kErrorInstallTransformRejected = 1644, kRpcSInvalidStringBinding = 1700, kRpcSWrongKindOfBinding = 1701, kRpcSInvalidBinding = 1702, kRpcSProtseqNotSupported = 1703, kRpcSInvalidRpcProtseq = 1704, kRpcSInvalidStringUuid = 1705, kRpcSInvalidEndpointFormat = 1706, kRpcSInvalidNetAddr = 1707, kRpcSNoEndpointFound = 1708, kRpcSInvalidTimeout = 1709, kRpcSObjectNotFound = 1710, kRpcSAlreadyRegistered = 1711, kRpcSTypeAlreadyRegistered = 1712, kRpcSAlreadyListening = 1713, kRpcSNoProtseqsRegistered = 1714, kRpcSNotListening = 1715, kRpcSUnknownMgrType = 1716, kRpcSUnknownIf = 1717, kRpcSNoBindings = 1718, kRpcSNoProtseqs = 1719, kRpcSCantCreateEndpoint = 1720, kRpcSOutOfResources = 1721, kRpcSServerUnavailable = 1722, kRpcSServerTooBusy = 1723, kRpcSInvalidNetworkOptions = 1724, kRpcSNoCallActive = 1725, kRpcSCallFailed = 1726, kRpcSCallFailedDne = 1727, kRpcSProtocolError = 1728, kRpcSUnsupportedTransSyn = 1730, kRpcSUnsupportedType = 1732, kRpcSInvalidTag = 1733, kRpcSInvalidBound = 1734, kRpcSNoEntryName = 1735, kRpcSInvalidNameSyntax = 1736, kRpcSUnsupportedNameSyntax = 1737, kRpcSUuidNoAddress = 1739, kRpcSDuplicateEndpoint = 1740, kRpcSUnknownAuthnType = 1741, kRpcSMaxCallsTooSmall = 1742, kRpcSStringTooLong = 1743, kRpcSProtseqNotFound = 1744, kRpcSProcnumOutOfRange = 1745, kRpcSBindingHasNoAuth = 1746, kRpcSUnknownAuthnService = 1747, kRpcSUnknownAuthnLevel = 1748, kRpcSInvalidAuthIdentity = 1749, kRpcSUnknownAuthzService = 1750, kEptSInvalidEntry = 1751, kEptSCantPerformOp = 1752, kEptSNotRegistered = 1753, kRpcSNothingToExport = 1754, kRpcSIncompleteName = 1755, kRpcSInvalidVersOption = 1756, kRpcSNoMoreMembers = 1757, kRpcSNotAllObjsUnexported = 1758, kRpcSInterfaceNotFound = 1759, kRpcSEntryAlreadyExists = 1760, kRpcSEntryNotFound = 1761, kRpcSNameServiceUnavailable = 1762, kRpcSInvalidNafId = 1763, kRpcSCannotSupport = 1764, kRpcSNoContextAvailable = 1765, kRpcSInternalError = 1766, kRpcSZeroDivide = 1767, kRpcSAddressError = 1768, kRpcSFpDivZero = 1769, kRpcSFpUnderflow = 1770, kRpcSFpOverflow = 1771, kRpcXNoMoreEntries = 1772, kRpcXSsCharTransOpenFail = 1773, kRpcXSsCharTransShortFile = 1774, kRpcXSsInNullContext = 1775, kRpcXSsContextDamaged = 1777, kRpcXSsHandlesMismatch = 1778, kRpcXSsCannotGetCallHandle = 1779, kRpcXNullRefPointer = 1780, kRpcXEnumValueOutOfRange = 1781, kRpcXByteCountTooSmall = 1782, kRpcXBadStubData = 1783, kErrorInvalidUserBuffer = 1784, kErrorUnrecognizedMedia = 1785, kErrorNoTrustLsaSecret = 1786, kErrorNoTrustSamAccount = 1787, kErrorTrustedDomainFailure = 1788, kErrorTrustedRelationshipFailure = 1789, kErrorTrustFailure = 1790, kRpcSCallInProgress = 1791, kErrorNetlogonNotStarted = 1792, kErrorAccountExpired = 1793, kErrorRedirectorHasOpenHandles = 1794, kErrorPrinterDriverAlreadyInstalled = 1795, kErrorUnknownPort = 1796, kErrorUnknownPrinterDriver = 1797, kErrorUnknownPrintprocessor = 1798, kErrorInvalidSeparatorFile = 1799, kErrorInvalidPriority = 1800, kErrorInvalidPrinterName = 1801, kErrorPrinterAlreadyExists = 1802, kErrorInvalidPrinterCommand = 1803, kErrorInvalidDatatype = 1804, kErrorInvalidEnvironment = 1805, kRpcSNoMoreBindings = 1806, kErrorNologonInterdomainTrustAccount = 1807, kErrorNologonWorkstationTrustAccount = 1808, kErrorNologonServerTrustAccount = 1809, kErrorDomainTrustInconsistent = 1810, kErrorServerHasOpenHandles = 1811, kErrorResourceDataNotFound = 1812, kErrorResourceTypeNotFound = 1813, kErrorResourceNameNotFound = 1814, kErrorResourceLangNotFound = 1815, kErrorNotEnoughQuota = 1816, kRpcSNoInterfaces = 1817, kRpcSCallCancelled = 1818, kRpcSBindingIncomplete = 1819, kRpcSCommFailure = 1820, kRpcSUnsupportedAuthnLevel = 1821, kRpcSNoPrincName = 1822, kRpcSNotRpcError = 1823, kRpcSUuidLocalOnly = 1824, kRpcSSecPkgError = 1825, kRpcSNotCancelled = 1826, kRpcXInvalidEsAction = 1827, kRpcXWrongEsVersion = 1828, kRpcXWrongStubVersion = 1829, kRpcXInvalidPipeObject = 1830, kRpcXWrongPipeOrder = 1831, kRpcXWrongPipeVersion = 1832, kRpcSGroupMemberNotFound = 1898, kEptSCantCreate = 1899, kRpcSInvalidObject = 1900, kErrorInvalidTime = 1901, kErrorInvalidFormName = 1902, kErrorInvalidFormSize = 1903, kErrorAlreadyWaiting = 1904, kErrorPrinterDeleted = 1905, kErrorInvalidPrinterState = 1906, kErrorPasswordMustChange = 1907, kErrorDomainControllerNotFound = 1908, kErrorAccountLockedOut = 1909, kOrInvalidOxid = 1910, kOrInvalidOid = 1911, kOrInvalidSet = 1912, kRpcSSendIncomplete = 1913, kRpcSInvalidAsyncHandle = 1914, kRpcSInvalidAsyncCall = 1915, kRpcXPipeClosed = 1916, kRpcXPipeDisciplineError = 1917, kRpcXPipeEmpty = 1918, kErrorNoSitename = 1919, kErrorCantAccessFile = 1920, kErrorCantResolveFilename = 1921, kRpcSEntryTypeMismatch = 1922, kRpcSNotAllObjsExported = 1923, kRpcSInterfaceNotExported = 1924, kRpcSProfileNotAdded = 1925, kRpcSPrfEltNotAdded = 1926, kRpcSPrfEltNotRemoved = 1927, kRpcSGrpEltNotAdded = 1928, kRpcSGrpEltNotRemoved = 1929, kErrorKmDriverBlocked = 1930, kErrorContextExpired = 1931, kErrorInvalidPixelFormat = 2000, kErrorBadDriver = 2001, kErrorInvalidWindowStyle = 2002, kErrorMetafileNotSupported = 2003, kErrorTransformNotSupported = 2004, kErrorClippingNotSupported = 2005, kErrorInvalidCmm = 2010, kErrorInvalidProfile = 2011, kErrorTagNotFound = 2012, kErrorTagNotPresent = 2013, kErrorDuplicateTag = 2014, kErrorProfileNotAssociatedWithDevice = 2015, kErrorProfileNotFound = 2016, kErrorInvalidColorspace = 2017, kErrorIcmNotEnabled = 2018, kErrorDeletingIcmXform = 2019, kErrorInvalidTransform = 2020, kErrorColorspaceMismatch = 2021, kErrorInvalidColorindex = 2022, kErrorConnectedOtherPassword = 2108, kErrorConnectedOtherPasswordDefault = 2109, kErrorBadUsername = 2202, kErrorNotConnected = 2250, kErrorOpenFiles = 2401, kErrorActiveConnections = 2402, kErrorDeviceInUse = 2404, kErrorUnknownPrintMonitor = 3000, kErrorPrinterDriverInUse = 3001, kErrorSpoolFileNotFound = 3002, kErrorSplNoStartdoc = 3003, kErrorSplNoAddjob = 3004, kErrorPrintProcessorAlreadyInstalled = 3005, kErrorPrintMonitorAlreadyInstalled = 3006, kErrorInvalidPrintMonitor = 3007, kErrorPrintMonitorInUse = 3008, kErrorPrinterHasJobsQueued = 3009, kErrorSuccessRebootRequired = 3010, kErrorSuccessRestartRequired = 3011, kErrorPrinterNotFound = 3012, kErrorPrinterDriverWarned = 3013, kErrorPrinterDriverBlocked = 3014, kErrorWinsInternal = 4000, kErrorCanNotDelLocalWins = 4001, kErrorStaticInit = 4002, kErrorIncBackup = 4003, kErrorFullBackup = 4004, kErrorRecNonExistent = 4005, kErrorRplNotAllowed = 4006, kErrorDhcpAddressConflict = 4100, kErrorWmiGuidNotFound = 4200, kErrorWmiInstanceNotFound = 4201, kErrorWmiItemidNotFound = 4202, kErrorWmiTryAgain = 4203, kErrorWmiDpNotFound = 4204, kErrorWmiUnresolvedInstanceRef = 4205, kErrorWmiAlreadyEnabled = 4206, kErrorWmiGuidDisconnected = 4207, kErrorWmiServerUnavailable = 4208, kErrorWmiDpFailed = 4209, kErrorWmiInvalidMof = 4210, kErrorWmiInvalidReginfo = 4211, kErrorWmiAlreadyDisabled = 4212, kErrorWmiReadOnly = 4213, kErrorWmiSetFailure = 4214, kErrorInvalidMedia = 4300, kErrorInvalidLibrary = 4301, kErrorInvalidMediaPool = 4302, kErrorDriveMediaMismatch = 4303, kErrorMediaOffline = 4304, kErrorLibraryOffline = 4305, kErrorEmpty = 4306, kErrorNotEmpty = 4307, kErrorMediaUnavailable = 4308, kErrorResourceDisabled = 4309, kErrorInvalidCleaner = 4310, kErrorUnableToClean = 4311, kErrorObjectNotFound = 4312, kErrorDatabaseFailure = 4313, kErrorDatabaseFull = 4314, kErrorMediaIncompatible = 4315, kErrorResourceNotPresent = 4316, kErrorInvalidOperation = 4317, kErrorMediaNotAvailable = 4318, kErrorDeviceNotAvailable = 4319, kErrorRequestRefused = 4320, kErrorInvalidDriveObject = 4321, kErrorLibraryFull = 4322, kErrorMediumNotAccessible = 4323, kErrorUnableToLoadMedium = 4324, kErrorUnableToInventoryDrive = 4325, kErrorUnableToInventorySlot = 4326, kErrorUnableToInventoryTransport = 4327, kErrorTransportFull = 4328, kErrorControllingIeport = 4329, kErrorUnableToEjectMountedMedia = 4330, kErrorCleanerSlotSet = 4331, kErrorCleanerSlotNotSet = 4332, kErrorCleanerCartridgeSpent = 4333, kErrorUnexpectedOmid = 4334, kErrorCantDeleteLastItem = 4335, kErrorMessageExceedsMaxSize = 4336, kErrorVolumeContainsSysFiles = 4337, kErrorIndigenousType = 4338, kErrorNoSupportingDrives = 4339, kErrorCleanerCartridgeInstalled = 4340, kErrorFileOffline = 4350, kErrorRemoteStorageNotActive = 4351, kErrorRemoteStorageMediaError = 4352, kErrorNotAReparsePoint = 4390, kErrorReparseAttributeConflict = 4391, kErrorInvalidReparseData = 4392, kErrorReparseTagInvalid = 4393, kErrorReparseTagMismatch = 4394, kErrorVolumeNotSisEnabled = 4500, kErrorDependentResourceExists = 5001, kErrorDependencyNotFound = 5002, kErrorDependencyAlreadyExists = 5003, kErrorResourceNotOnline = 5004, kErrorHostNodeNotAvailable = 5005, kErrorResourceNotAvailable = 5006, kErrorResourceNotFound = 5007, kErrorShutdownCluster = 5008, kErrorCantEvictActiveNode = 5009, kErrorObjectAlreadyExists = 5010, kErrorObjectInList = 5011, kErrorGroupNotAvailable = 5012, kErrorGroupNotFound = 5013, kErrorGroupNotOnline = 5014, kErrorHostNodeNotResourceOwner = 5015, kErrorHostNodeNotGroupOwner = 5016, kErrorResmonCreateFailed = 5017, kErrorResmonOnlineFailed = 5018, kErrorResourceOnline = 5019, kErrorQuorumResource = 5020, kErrorNotQuorumCapable = 5021, kErrorClusterShuttingDown = 5022, kErrorInvalidState = 5023, kErrorResourcePropertiesStored = 5024, kErrorNotQuorumClass = 5025, kErrorCoreResource = 5026, kErrorQuorumResourceOnlineFailed = 5027, kErrorQuorumlogOpenFailed = 5028, kErrorClusterlogCorrupt = 5029, kErrorClusterlogRecordExceedsMaxsize = 5030, kErrorClusterlogExceedsMaxsize = 5031, kErrorClusterlogChkpointNotFound = 5032, kErrorClusterlogNotEnoughSpace = 5033, kErrorQuorumOwnerAlive = 5034, kErrorNetworkNotAvailable = 5035, kErrorNodeNotAvailable = 5036, kErrorAllNodesNotAvailable = 5037, kErrorResourceFailed = 5038, kErrorClusterInvalidNode = 5039, kErrorClusterNodeExists = 5040, kErrorClusterJoinInProgress = 5041, kErrorClusterNodeNotFound = 5042, kErrorClusterLocalNodeNotFound = 5043, kErrorClusterNetworkExists = 5044, kErrorClusterNetworkNotFound = 5045, kErrorClusterNetinterfaceExists = 5046, kErrorClusterNetinterfaceNotFound = 5047, kErrorClusterInvalidRequest = 5048, kErrorClusterInvalidNetworkProvider = 5049, kErrorClusterNodeDown = 5050, kErrorClusterNodeUnreachable = 5051, kErrorClusterNodeNotMember = 5052, kErrorClusterJoinNotInProgress = 5053, kErrorClusterInvalidNetwork = 5054, kErrorClusterNodeUp = 5056, kErrorClusterIpaddrInUse = 5057, kErrorClusterNodeNotPaused = 5058, kErrorClusterNoSecurityContext = 5059, kErrorClusterNetworkNotInternal = 5060, kErrorClusterNodeAlreadyUp = 5061, kErrorClusterNodeAlreadyDown = 5062, kErrorClusterNetworkAlreadyOnline = 5063, kErrorClusterNetworkAlreadyOffline = 5064, kErrorClusterNodeAlreadyMember = 5065, kErrorClusterLastInternalNetwork = 5066, kErrorClusterNetworkHasDependents = 5067, kErrorInvalidOperationOnQuorum = 5068, kErrorDependencyNotAllowed = 5069, kErrorClusterNodePaused = 5070, kErrorNodeCantHostResource = 5071, kErrorClusterNodeNotReady = 5072, kErrorClusterNodeShuttingDown = 5073, kErrorClusterJoinAborted = 5074, kErrorClusterIncompatibleVersions = 5075, kErrorClusterMaxnumOfResourcesExceeded = 5076, kErrorClusterSystemConfigChanged = 5077, kErrorClusterResourceTypeNotFound = 5078, kErrorClusterRestypeNotSupported = 5079, kErrorClusterResnameNotFound = 5080, kErrorClusterNoRpcPackagesRegistered = 5081, kErrorClusterOwnerNotInPreflist = 5082, kErrorClusterDatabaseSeqmismatch = 5083, kErrorResmonInvalidState = 5084, kErrorClusterGumNotLocker = 5085, kErrorQuorumDiskNotFound = 5086, kErrorDatabaseBackupCorrupt = 5087, kErrorClusterNodeAlreadyHasDfsRoot = 5088, kErrorResourcePropertyUnchangeable = 5089, kErrorClusterMembershipInvalidState = 5890, kErrorClusterQuorumlogNotFound = 5891, kErrorClusterMembershipHalt = 5892, kErrorClusterInstanceIdMismatch = 5893, kErrorClusterNetworkNotFoundForIp = 5894, kErrorClusterPropertyDataTypeMismatch = 5895, kErrorClusterEvictWithoutCleanup = 5896, kErrorClusterParameterMismatch = 5897, kErrorNodeCannotBeClustered = 5898, kErrorClusterWrongOsVersion = 5899, kErrorClusterCantCreateDupClusterName = 5900, kErrorCodeEncryptionFailed = 6000, kErrorDecryptionFailed = 6001, kErrorFileEncrypted = 6002, kErrorNoRecoveryPolicy = 6003, kErrorNoEfs = 6004, kErrorWrongEfs = 6005, kErrorNoUserKeys = 6006, kErrorFileNotEncrypted = 6007, kErrorNotExportFormat = 6008, kErrorFileReadOnly = 6009, kErrorDirEfsDisallowed = 6010, kErrorEfsServerNotTrusted = 6011, kErrorBadRecoveryPolicy = 6012, kErrorEfsAlgBlobTooBig = 6013, kErrorVolumeNotSupportEfs = 6014, kErrorEfsDisabled = 6015, kErrorEfsVersionNotSupport = 6016, kErrorNoBrowserServersFound = 6118, kSchedEServiceNotLocalsystem = 6200, kErrorCtxWinstationNameInvalid = 7001, kErrorCtxInvalidPd = 7002, kErrorCtxPdNotFound = 7003, kErrorCtxWdNotFound = 7004, kErrorCtxCannotMakeEventlogEntry = 7005, kErrorCtxServiceNameCollision = 7006, kErrorCtxClosePending = 7007, kErrorCtxNoOutbuf = 7008, kErrorCtxModemInfNotFound = 7009, kErrorCtxInvalidModemname = 7010, kErrorCtxModemResponseError = 7011, kErrorCtxModemResponseTimeout = 7012, kErrorCtxModemResponseNoCarrier = 7013, kErrorCtxModemResponseNoDialtone = 7014, kErrorCtxModemResponseBusy = 7015, kErrorCtxModemResponseVoice = 7016, kErrorCtxTdError = 7017, kErrorCtxWinstationNotFound = 7022, kErrorCtxWinstationAlreadyExists = 7023, kErrorCtxWinstationBusy = 7024, kErrorCtxBadVideoMode = 7025, kErrorCtxGraphicsInvalid = 7035, kErrorCtxLogonDisabled = 7037, kErrorCtxNotConsole = 7038, kErrorCtxClientQueryTimeout = 7040, kErrorCtxConsoleDisconnect = 7041, kErrorCtxConsoleConnect = 7042, kErrorCtxShadowDenied = 7044, kErrorCtxWinstationAccessDenied = 7045, kErrorCtxInvalidWd = 7049, kErrorCtxShadowInvalid = 7050, kErrorCtxShadowDisabled = 7051, kErrorCtxClientLicenseInUse = 7052, kErrorCtxClientLicenseNotSet = 7053, kErrorCtxLicenseNotAvailable = 7054, kErrorCtxLicenseClientInvalid = 7055, kErrorCtxLicenseExpired = 7056, kErrorCtxShadowNotRunning = 7057, kErrorCtxShadowEndedByModeChange = 7058, kFrsErrInvalidApiSequence = 8001, kFrsErrStartingService = 8002, kFrsErrStoppingService = 8003, kFrsErrInternalApi = 8004, kFrsErrInternal = 8005, kFrsErrServiceComm = 8006, kFrsErrInsufficientPriv = 8007, kFrsErrAuthentication = 8008, kFrsErrParentInsufficientPriv = 8009, kFrsErrParentAuthentication = 8010, kFrsErrChildToParentComm = 8011, kFrsErrParentToChildComm = 8012, kFrsErrSysvolPopulate = 8013, kFrsErrSysvolPopulateTimeout = 8014, kFrsErrSysvolIsBusy = 8015, kFrsErrSysvolDemote = 8016, kFrsErrInvalidServiceParameter = 8017, kErrorDsNotInstalled = 8200, kErrorDsMembershipEvaluatedLocally = 8201, kErrorDsNoAttributeOrValue = 8202, kErrorDsInvalidAttributeSyntax = 8203, kErrorDsAttributeTypeUndefined = 8204, kErrorDsAttributeOrValueExists = 8205, kErrorDsBusy = 8206, kErrorDsUnavailable = 8207, kErrorDsNoRidsAllocated = 8208, kErrorDsNoMoreRids = 8209, kErrorDsIncorrectRoleOwner = 8210, kErrorDsRidmgrInitError = 8211, kErrorDsObjClassViolation = 8212, kErrorDsCantOnNonLeaf = 8213, kErrorDsCantOnRdn = 8214, kErrorDsCantModObjClass = 8215, kErrorDsCrossDomMoveError = 8216, kErrorDsGcNotAvailable = 8217, kErrorSharedPolicy = 8218, kErrorPolicyObjectNotFound = 8219, kErrorPolicyOnlyInDs = 8220, kErrorPromotionActive = 8221, kErrorNoPromotionActive = 8222, kErrorDsOperationsError = 8224, kErrorDsProtocolError = 8225, kErrorDsTimelimitExceeded = 8226, kErrorDsSizelimitExceeded = 8227, kErrorDsAdminLimitExceeded = 8228, kErrorDsCompareFalse = 8229, kErrorDsCompareTrue = 8230, kErrorDsAuthMethodNotSupported = 8231, kErrorDsStrongAuthRequired = 8232, kErrorDsInappropriateAuth = 8233, kErrorDsAuthUnknown = 8234, kErrorDsReferral = 8235, kErrorDsUnavailableCritExtension = 8236, kErrorDsConfidentialityRequired = 8237, kErrorDsInappropriateMatching = 8238, kErrorDsConstraintViolation = 8239, kErrorDsNoSuchObject = 8240, kErrorDsAliasProblem = 8241, kErrorDsInvalidDnSyntax = 8242, kErrorDsIsLeaf = 8243, kErrorDsAliasDerefProblem = 8244, kErrorDsUnwillingToPerform = 8245, kErrorDsLoopDetect = 8246, kErrorDsNamingViolation = 8247, kErrorDsObjectResultsTooLarge = 8248, kErrorDsAffectsMultipleDsas = 8249, kErrorDsServerDown = 8250, kErrorDsLocalError = 8251, kErrorDsEncodingError = 8252, kErrorDsDecodingError = 8253, kErrorDsFilterUnknown = 8254, kErrorDsParamError = 8255, kErrorDsNotSupported = 8256, kErrorDsNoResultsReturned = 8257, kErrorDsControlNotFound = 8258, kErrorDsClientLoop = 8259, kErrorDsReferralLimitExceeded = 8260, kErrorDsSortControlMissing = 8261, kErrorDsOffsetRangeError = 8262, kErrorDsRootMustBeNc = 8301, kErrorDsAddReplicaInhibited = 8302, kErrorDsAttNotDefInSchema = 8303, kErrorDsMaxObjSizeExceeded = 8304, kErrorDsObjStringNameExists = 8305, kErrorDsNoRdnDefinedInSchema = 8306, kErrorDsRdnDoesntMatchSchema = 8307, kErrorDsNoRequestedAttsFound = 8308, kErrorDsUserBufferToSmall = 8309, kErrorDsAttIsNotOnObj = 8310, kErrorDsIllegalModOperation = 8311, kErrorDsObjTooLarge = 8312, kErrorDsBadInstanceType = 8313, kErrorDsMasterdsaRequired = 8314, kErrorDsObjectClassRequired = 8315, kErrorDsMissingRequiredAtt = 8316, kErrorDsAttNotDefForClass = 8317, kErrorDsAttAlreadyExists = 8318, kErrorDsCantAddAttValues = 8320, kErrorDsSingleValueConstraint = 8321, kErrorDsRangeConstraint = 8322, kErrorDsAttValAlreadyExists = 8323, kErrorDsCantRemMissingAtt = 8324, kErrorDsCantRemMissingAttVal = 8325, kErrorDsRootCantBeSubref = 8326, kErrorDsNoChaining = 8327, kErrorDsNoChainedEval = 8328, kErrorDsNoParentObject = 8329, kErrorDsParentIsAnAlias = 8330, kErrorDsCantMixMasterAndReps = 8331, kErrorDsChildrenExist = 8332, kErrorDsObjNotFound = 8333, kErrorDsAliasedObjMissing = 8334, kErrorDsBadNameSyntax = 8335, kErrorDsAliasPointsToAlias = 8336, kErrorDsCantDerefAlias = 8337, kErrorDsOutOfScope = 8338, kErrorDsObjectBeingRemoved = 8339, kErrorDsCantDeleteDsaObj = 8340, kErrorDsGenericError = 8341, kErrorDsDsaMustBeIntMaster = 8342, kErrorDsClassNotDsa = 8343, kErrorDsInsuffAccessRights = 8344, kErrorDsIllegalSuperior = 8345, kErrorDsAttributeOwnedBySam = 8346, kErrorDsNameTooManyParts = 8347, kErrorDsNameTooLong = 8348, kErrorDsNameValueTooLong = 8349, kErrorDsNameUnparseable = 8350, kErrorDsNameTypeUnknown = 8351, kErrorDsNotAnObject = 8352, kErrorDsSecDescTooShort = 8353, kErrorDsSecDescInvalid = 8354, kErrorDsNoDeletedName = 8355, kErrorDsSubrefMustHaveParent = 8356, kErrorDsNcnameMustBeNc = 8357, kErrorDsCantAddSystemOnly = 8358, kErrorDsClassMustBeConcrete = 8359, kErrorDsInvalidDmd = 8360, kErrorDsObjGuidExists = 8361, kErrorDsNotOnBacklink = 8362, kErrorDsNoCrossrefForNc = 8363, kErrorDsShuttingDown = 8364, kErrorDsUnknownOperation = 8365, kErrorDsInvalidRoleOwner = 8366, kErrorDsCouldntContactFsmo = 8367, kErrorDsCrossNcDnRename = 8368, kErrorDsCantModSystemOnly = 8369, kErrorDsReplicatorOnly = 8370, kErrorDsObjClassNotDefined = 8371, kErrorDsObjClassNotSubclass = 8372, kErrorDsNameReferenceInvalid = 8373, kErrorDsCrossRefExists = 8374, kErrorDsCantDelMasterCrossref = 8375, kErrorDsSubtreeNotifyNotNcHead = 8376, kErrorDsNotifyFilterTooComplex = 8377, kErrorDsDupRdn = 8378, kErrorDsDupOid = 8379, kErrorDsDupMapiId = 8380, kErrorDsDupSchemaIdGuid = 8381, kErrorDsDupLdapDisplayName = 8382, kErrorDsSemanticAttTest = 8383, kErrorDsSyntaxMismatch = 8384, kErrorDsExistsInMustHave = 8385, kErrorDsExistsInMayHave = 8386, kErrorDsNonexistentMayHave = 8387, kErrorDsNonexistentMustHave = 8388, kErrorDsAuxClsTestFail = 8389, kErrorDsNonexistentPossSup = 8390, kErrorDsSubClsTestFail = 8391, kErrorDsBadRdnAttIdSyntax = 8392, kErrorDsExistsInAuxCls = 8393, kErrorDsExistsInSubCls = 8394, kErrorDsExistsInPossSup = 8395, kErrorDsRecalcschemaFailed = 8396, kErrorDsTreeDeleteNotFinished = 8397, kErrorDsCantDelete = 8398, kErrorDsAttSchemaReqId = 8399, kErrorDsBadAttSchemaSyntax = 8400, kErrorDsCantCacheAtt = 8401, kErrorDsCantCacheClass = 8402, kErrorDsCantRemoveAttCache = 8403, kErrorDsCantRemoveClassCache = 8404, kErrorDsCantRetrieveDn = 8405, kErrorDsMissingSupref = 8406, kErrorDsCantRetrieveInstance = 8407, kErrorDsCodeInconsistency = 8408, kErrorDsDatabaseError = 8409, kErrorDsGovernsidMissing = 8410, kErrorDsMissingExpectedAtt = 8411, kErrorDsNcnameMissingCrRef = 8412, kErrorDsSecurityCheckingError = 8413, kErrorDsSchemaNotLoaded = 8414, kErrorDsSchemaAllocFailed = 8415, kErrorDsAttSchemaReqSyntax = 8416, kErrorDsGcverifyError = 8417, kErrorDsDraSchemaMismatch = 8418, kErrorDsCantFindDsaObj = 8419, kErrorDsCantFindExpectedNc = 8420, kErrorDsCantFindNcInCache = 8421, kErrorDsCantRetrieveChild = 8422, kErrorDsSecurityIllegalModify = 8423, kErrorDsCantReplaceHiddenRec = 8424, kErrorDsBadHierarchyFile = 8425, kErrorDsBuildHierarchyTableFailed = 8426, kErrorDsConfigParamMissing = 8427, kErrorDsCountingAbIndicesFailed = 8428, kErrorDsHierarchyTableMallocFailed = 8429, kErrorDsInternalFailure = 8430, kErrorDsUnknownError = 8431, kErrorDsRootRequiresClassTop = 8432, kErrorDsRefusingFsmoRoles = 8433, kErrorDsMissingFsmoSettings = 8434, kErrorDsUnableToSurrenderRoles = 8435, kErrorDsDraGeneric = 8436, kErrorDsDraInvalidParameter = 8437, kErrorDsDraBusy = 8438, kErrorDsDraBadDn = 8439, kErrorDsDraBadNc = 8440, kErrorDsDraDnExists = 8441, kErrorDsDraInternalError = 8442, kErrorDsDraInconsistentDit = 8443, kErrorDsDraConnectionFailed = 8444, kErrorDsDraBadInstanceType = 8445, kErrorDsDraOutOfMem = 8446, kErrorDsDraMailProblem = 8447, kErrorDsDraRefAlreadyExists = 8448, kErrorDsDraRefNotFound = 8449, kErrorDsDraObjIsRepSource = 8450, kErrorDsDraDbError = 8451, kErrorDsDraNoReplica = 8452, kErrorDsDraAccessDenied = 8453, kErrorDsDraNotSupported = 8454, kErrorDsDraRpcCancelled = 8455, kErrorDsDraSourceDisabled = 8456, kErrorDsDraSinkDisabled = 8457, kErrorDsDraNameCollision = 8458, kErrorDsDraSourceReinstalled = 8459, kErrorDsDraMissingParent = 8460, kErrorDsDraPreempted = 8461, kErrorDsDraAbandonSync = 8462, kErrorDsDraShutdown = 8463, kErrorDsDraIncompatiblePartialSet = 8464, kErrorDsDraSourceIsPartialReplica = 8465, kErrorDsDraExtnConnectionFailed = 8466, kErrorDsInstallSchemaMismatch = 8467, kErrorDsDupLinkId = 8468, kErrorDsNameErrorResolving = 8469, kErrorDsNameErrorNotFound = 8470, kErrorDsNameErrorNotUnique = 8471, kErrorDsNameErrorNoMapping = 8472, kErrorDsNameErrorDomainOnly = 8473, kErrorDsNameErrorNoSyntacticalMapping = 8474, kErrorDsConstructedAttMod = 8475, kErrorDsWrongOmObjClass = 8476, kErrorDsDraReplPending = 8477, kErrorDsDsRequired = 8478, kErrorDsInvalidLdapDisplayName = 8479, kErrorDsNonBaseSearch = 8480, kErrorDsCantRetrieveAtts = 8481, kErrorDsBacklinkWithoutLink = 8482, kErrorDsEpochMismatch = 8483, kErrorDsSrcNameMismatch = 8484, kErrorDsSrcAndDstNcIdentical = 8485, kErrorDsDstNcMismatch = 8486, kErrorDsNotAuthoritiveForDstNc = 8487, kErrorDsSrcGuidMismatch = 8488, kErrorDsCantMoveDeletedObject = 8489, kErrorDsPdcOperationInProgress = 8490, kErrorDsCrossDomainCleanupReqd = 8491, kErrorDsIllegalXdomMoveOperation = 8492, kErrorDsCantWithAcctGroupMembershps = 8493, kErrorDsNcMustHaveNcParent = 8494, kErrorDsDstDomainNotNative = 8496, kErrorDsMissingInfrastructureContainer = 8497, kErrorDsCantMoveAccountGroup = 8498, kErrorDsCantMoveResourceGroup = 8499, kErrorDsInvalidSearchFlag = 8500, kErrorDsNoTreeDeleteAboveNc = 8501, kErrorDsCouldntLockTreeForDelete = 8502, kErrorDsCouldntIdentifyObjectsForTreeDelete = 8503, kErrorDsSamInitFailure = 8504, kErrorDsSensitiveGroupViolation = 8505, kErrorDsCantModPrimarygroupid = 8506, kErrorDsIllegalBaseSchemaMod = 8507, kErrorDsNonsafeSchemaChange = 8508, kErrorDsSchemaUpdateDisallowed = 8509, kErrorDsCantCreateUnderSchema = 8510, kErrorDsInstallNoSrcSchVersion = 8511, kErrorDsInstallNoSchVersionInInifile = 8512, kErrorDsInvalidGroupType = 8513, kErrorDsNoNestGlobalgroupInMixeddomain = 8514, kErrorDsNoNestLocalgroupInMixeddomain = 8515, kErrorDsGlobalCantHaveLocalMember = 8516, kErrorDsGlobalCantHaveUniversalMember = 8517, kErrorDsUniversalCantHaveLocalMember = 8518, kErrorDsGlobalCantHaveCrossdomainMember = 8519, kErrorDsLocalCantHaveCrossdomainLocalMember = 8520, kErrorDsHavePrimaryMembers = 8521, kErrorDsStringSdConversionFailed = 8522, kErrorDsNamingMasterGc = 8523, kErrorDsLookupFailure = 8524, kErrorDsCouldntUpdateSpns = 8525, kErrorDsCantRetrieveSd = 8526, kErrorDsKeyNotUnique = 8527, kErrorDsWrongLinkedAttSyntax = 8528, kErrorDsSamNeedBootkeyPassword = 8529, kErrorDsSamNeedBootkeyFloppy = 8530, kErrorDsCantStart = 8531, kErrorDsInitFailure = 8532, kErrorDsNoPktPrivacyOnConnection = 8533, kErrorDsSourceDomainInForest = 8534, kErrorDsDestinationDomainNotInForest = 8535, kErrorDsDestinationAuditingNotEnabled = 8536, kErrorDsCantFindDcForSrcDomain = 8537, kErrorDsSrcObjNotGroupOrUser = 8538, kErrorDsSrcSidExistsInForest = 8539, kErrorDsSrcAndDstObjectClassMismatch = 8540, kErrorSamInitFailure = 8541, kErrorDsDraSchemaInfoShip = 8542, kErrorDsDraSchemaConflict = 8543, kErrorDsDraEarlierSchemaConlict = 8544, kErrorDsDraObjNcMismatch = 8545, kErrorDsNcStillHasDsas = 8546, kErrorDsGcRequired = 8547, kErrorDsLocalMemberOfLocalOnly = 8548, kErrorDsNoFpoInUniversalGroups = 8549, kErrorDsCantAddToGc = 8550, kErrorDsNoCheckpointWithPdc = 8551, kErrorDsSourceAuditingNotEnabled = 8552, kErrorDsCantCreateInNondomainNc = 8553, kErrorDsInvalidNameForSpn = 8554, kErrorDsFilterUsesContructedAttrs = 8555, kErrorDsUnicodepwdNotInQuotes = 8556, kErrorDsMachineAccountQuotaExceeded = 8557, kErrorDsMustBeRunOnDstDc = 8558, kErrorDsSrcDcMustBeSp4OrGreater = 8559, kErrorDsCantTreeDeleteCriticalObj = 8560, kErrorDsInitFailureConsole = 8561, kErrorDsSamInitFailureConsole = 8562, kErrorDsForestVersionTooHigh = 8563, kErrorDsDomainVersionTooHigh = 8564, kErrorDsForestVersionTooLow = 8565, kErrorDsDomainVersionTooLow = 8566, kErrorDsIncompatibleVersion = 8567, kErrorDsLowDsaVersion = 8568, kErrorDsNoBehaviorVersionInMixeddomain = 8569, kErrorDsNotSupportedSortOrder = 8570, kErrorDsNameNotUnique = 8571, kErrorDsMachineAccountCreatedPrent4 = 8572, kErrorDsOutOfVersionStore = 8573, kErrorDsIncompatibleControlsUsed = 8574, kErrorDsNoRefDomain = 8575, kErrorDsReservedLinkId = 8576, kErrorDsLinkIdNotAvailable = 8577, kErrorDsAgCantHaveUniversalMember = 8578, kErrorDsModifydnDisallowedByInstanceType = 8579, kErrorDsNoObjectMoveInSchemaNc = 8580, kErrorDsModifydnDisallowedByFlag = 8581, kErrorDsModifydnWrongGrandparent = 8582, kErrorDsNameErrorTrustReferral = 8583, kErrorNotSupportedOnStandardServer = 8584, kErrorDsCantAccessRemotePartOfAd = 8585, kErrorDsCrImpossibleToValidate = 8586, kErrorDsThreadLimitExceeded = 8587, kErrorDsNotClosest = 8588, kErrorDsCantDeriveSpnWithoutServerRef = 8589, kErrorDsSingleUserModeFailed = 8590, kErrorDsNtdscriptSyntaxError = 8591, kErrorDsNtdscriptProcessError = 8592, kErrorDsDifferentReplEpochs = 8593, kErrorDsDrsExtensionsChanged = 8594, kErrorDsReplicaSetChangeNotAllowedOnDisabledCr = 8595, kErrorDsNoMsdsIntid = 8596, kErrorDsDupMsdsIntid = 8597, kErrorDsExistsInRdnattid = 8598, kErrorDsAuthorizationFailed = 8599, kErrorDsInvalidScript = 8600, kErrorDsRemoteCrossrefOpFailed = 8601, kDnsErrorRcodeFormatError = 9001, kDnsErrorRcodeServerFailure = 9002, kDnsErrorRcodeNameError = 9003, kDnsErrorRcodeNotImplemented = 9004, kDnsErrorRcodeRefused = 9005, kDnsErrorRcodeYxdomain = 9006, kDnsErrorRcodeYxrrset = 9007, kDnsErrorRcodeNxrrset = 9008, kDnsErrorRcodeNotauth = 9009, kDnsErrorRcodeNotzone = 9010, kDnsErrorRcodeBadsig = 9016, kDnsErrorRcodeBadkey = 9017, kDnsErrorRcodeBadtime = 9018, kDnsInfoNoRecords = 9501, kDnsErrorBadPacket = 9502, kDnsErrorNoPacket = 9503, kDnsErrorRcode = 9504, kDnsErrorUnsecurePacket = 9505, kDnsErrorInvalidType = 9551, kDnsErrorInvalidIpAddress = 9552, kDnsErrorInvalidProperty = 9553, kDnsErrorTryAgainLater = 9554, kDnsErrorNotUnique = 9555, kDnsErrorNonRfcName = 9556, kDnsStatusFqdn = 9557, kDnsStatusDottedName = 9558, kDnsStatusSinglePartName = 9559, kDnsErrorInvalidNameChar = 9560, kDnsErrorNumericName = 9561, kDnsErrorNotAllowedOnRootServer = 9562, kDnsErrorZoneDoesNotExist = 9601, kDnsErrorNoZoneInfo = 9602, kDnsErrorInvalidZoneOperation = 9603, kDnsErrorZoneConfigurationError = 9604, kDnsErrorZoneHasNoSoaRecord = 9605, kDnsErrorZoneHasNoNsRecords = 9606, kDnsErrorZoneLocked = 9607, kDnsErrorZoneCreationFailed = 9608, kDnsErrorZoneAlreadyExists = 9609, kDnsErrorAutozoneAlreadyExists = 9610, kDnsErrorInvalidZoneType = 9611, kDnsErrorSecondaryRequiresMasterIp = 9612, kDnsErrorZoneNotSecondary = 9613, kDnsErrorNeedSecondaryAddresses = 9614, kDnsErrorWinsInitFailed = 9615, kDnsErrorNeedWinsServers = 9616, kDnsErrorNbstatInitFailed = 9617, kDnsErrorSoaDeleteInvalid = 9618, kDnsErrorForwarderAlreadyExists = 9619, kDnsErrorZoneRequiresMasterIp = 9620, kDnsErrorZoneIsShutdown = 9621, kDnsErrorPrimaryRequiresDatafile = 9651, kDnsErrorInvalidDatafileName = 9652, kDnsErrorDatafileOpenFailure = 9653, kDnsErrorFileWritebackFailed = 9654, kDnsErrorDatafileParsing = 9655, kDnsErrorRecordDoesNotExist = 9701, kDnsErrorRecordFormat = 9702, kDnsErrorNodeCreationFailed = 9703, kDnsErrorUnknownRecordType = 9704, kDnsErrorRecordTimedOut = 9705, kDnsErrorNameNotInZone = 9706, kDnsErrorCnameLoop = 9707, kDnsErrorNodeIsCname = 9708, kDnsErrorCnameCollision = 9709, kDnsErrorRecordOnlyAtZoneRoot = 9710, kDnsErrorRecordAlreadyExists = 9711, kDnsErrorSecondaryData = 9712, kDnsErrorNoCreateCacheData = 9713, kDnsErrorNameDoesNotExist = 9714, kDnsWarningPtrCreateFailed = 9715, kDnsWarningDomainUndeleted = 9716, kDnsErrorDsUnavailable = 9717, kDnsErrorDsZoneAlreadyExists = 9718, kDnsErrorNoBootfileIfDsZone = 9719, kDnsInfoAxfrComplete = 9751, kDnsErrorAxfr = 9752, kDnsInfoAddedLocalWins = 9753, kDnsStatusContinueNeeded = 9801, kDnsErrorNoTcpip = 9851, kDnsErrorNoDnsServers = 9852, kDnsErrorDpDoesNotExist = 9901, kDnsErrorDpAlreadyExists = 9902, kDnsErrorDpNotEnlisted = 9903, kDnsErrorDpAlreadyEnlisted = 9904, kWSAeintr = 10004, kWSAebadf = 10009, kWSAeacces = 10013, kWSAefault = 10014, kWSAeinval = 10022, kWSAemfile = 10024, kWSAewouldblock = 10035, kWSAeinprogress = 10036, kWSAealready = 10037, kWSAenotsock = 10038, kWSAedestaddrreq = 10039, kWSAemsgsize = 10040, kWSAeprototype = 10041, kWSAenoprotoopt = 10042, kWSAeprotonosupport = 10043, kWSAesocktnosupport = 10044, kWSAeopnotsupp = 10045, kWSAepfnosupport = 10046, kWSAeafnosupport = 10047, kWSAeaddrinuse = 10048, kWSAeaddrnotavail = 10049, kWSAenetdown = 10050, kWSAenetunreach = 10051, kWSAenetreset = 10052, kWSAeconnaborted = 10053, kWSAeconnreset = 10054, kWSAenobufs = 10055, kWSAeisconn = 10056, kWSAenotconn = 10057, kWSAeshutdown = 10058, kWSAetoomanyrefs = 10059, kWSAetimedout = 10060, kWSAeconnrefused = 10061, kWSAeloop = 10062, kWSAenametoolong = 10063, kWSAehostdown = 10064, kWSAehostunreach = 10065, kWSAenotempty = 10066, kWSAeproclim = 10067, kWSAeusers = 10068, kWSAedquot = 10069, kWSAestale = 10070, kWSAeremote = 10071, kWSAsysnotready = 10091, kWSAvernotsupported = 10092, kWSAnotinitialised = 10093, kWSAediscon = 10101, kWSAenomore = 10102, kWSAecancelled = 10103, kWSAeinvalidproctable = 10104, kWSAeinvalidprovider = 10105, kWSAeproviderfailedinit = 10106, kWSAsyscallfailure = 10107, kWSAserviceNotFound = 10108, kWSAtypeNotFound = 10109, kWSAENoMore = 10110, kWSAECancelled = 10111, kWSAerefused = 10112, kWSAhostNotFound = 11001, kWSAtryAgain = 11002, kWSAnoRecovery = 11003, kWSAnoData = 11004, kWSAQosReceivers = 11005, kWSAQosSenders = 11006, kWSAQosNoSenders = 11007, kWSAQosNoReceivers = 11008, kWSAQosRequestConfirmed = 11009, kWSAQosAdmissionFailure = 11010, kWSAQosPolicyFailure = 11011, kWSAQosBadStyle = 11012, kWSAQosBadObject = 11013, kWSAQosTrafficCtrlError = 11014, kWSAQosGenericError = 11015, kWSAQosEservicetype = 11016, kWSAQosEflowspec = 11017, kWSAQosEprovspecbuf = 11018, kWSAQosEfilterstyle = 11019, kWSAQosEfiltertype = 11020, kWSAQosEfiltercount = 11021, kWSAQosEobjlength = 11022, kWSAQosEflowcount = 11023, kWSAQosEunknownpsobj = 11024, kWSAQosEpolicyobj = 11025, kWSAQosEflowdesc = 11026, kWSAQosEpsflowspec = 11027, kWSAQosEpsfilterspec = 11028, kWSAQosEsdmodeobj = 11029, kWSAQosEshaperateobj = 11030, kWSAQosReservedPetype = 11031, kErrorIpsecQmPolicyExists = 13000, kErrorIpsecQmPolicyNotFound = 13001, kErrorIpsecQmPolicyInUse = 13002, kErrorIpsecMmPolicyExists = 13003, kErrorIpsecMmPolicyNotFound = 13004, kErrorIpsecMmPolicyInUse = 13005, kErrorIpsecMmFilterExists = 13006, kErrorIpsecMmFilterNotFound = 13007, kErrorIpsecTransportFilterExists = 13008, kErrorIpsecTransportFilterNotFound = 13009, kErrorIpsecMmAuthExists = 13010, kErrorIpsecMmAuthNotFound = 13011, kErrorIpsecMmAuthInUse = 13012, kErrorIpsecDefaultMmPolicyNotFound = 13013, kErrorIpsecDefaultMmAuthNotFound = 13014, kErrorIpsecDefaultQmPolicyNotFound = 13015, kErrorIpsecTunnelFilterExists = 13016, kErrorIpsecTunnelFilterNotFound = 13017, kErrorIpsecMmFilterPendingDeletion = 13018, kErrorIpsecTransportFilterPendingDeletion = 13019, kErrorIpsecTunnelFilterPendingDeletion = 13020, kErrorIpsecMmPolicyPendingDeletion = 13021, kErrorIpsecMmAuthPendingDeletion = 13022, kErrorIpsecQmPolicyPendingDeletion = 13023, kErrorIpsecIkeAuthFail = 13801, kErrorIpsecIkeAttribFail = 13802, kErrorIpsecIkeNegotiationPending = 13803, kErrorIpsecIkeGeneralProcessingError = 13804, kErrorIpsecIkeTimedOut = 13805, kErrorIpsecIkeNoCert = 13806, kErrorIpsecIkeSaDeleted = 13807, kErrorIpsecIkeSaReaped = 13808, kErrorIpsecIkeMmAcquireDrop = 13809, kErrorIpsecIkeQmAcquireDrop = 13810, kErrorIpsecIkeQueueDropMm = 13811, kErrorIpsecIkeQueueDropNoMm = 13812, kErrorIpsecIkeDropNoResponse = 13813, kErrorIpsecIkeMmDelayDrop = 13814, kErrorIpsecIkeQmDelayDrop = 13815, kErrorIpsecIkeError = 13816, kErrorIpsecIkeCrlFailed = 13817, kErrorIpsecIkeInvalidKeyUsage = 13818, kErrorIpsecIkeInvalidCertType = 13819, kErrorIpsecIkeNoPrivateKey = 13820, kErrorIpsecIkeDhFail = 13822, kErrorIpsecIkeInvalidHeader = 13824, kErrorIpsecIkeNoPolicy = 13825, kErrorIpsecIkeInvalidSignature = 13826, kErrorIpsecIkeKerberosError = 13827, kErrorIpsecIkeNoPublicKey = 13828, kErrorIpsecIkeProcessErr = 13829, kErrorIpsecIkeProcessErrSa = 13830, kErrorIpsecIkeProcessErrProp = 13831, kErrorIpsecIkeProcessErrTrans = 13832, kErrorIpsecIkeProcessErrKe = 13833, kErrorIpsecIkeProcessErrId = 13834, kErrorIpsecIkeProcessErrCert = 13835, kErrorIpsecIkeProcessErrCertReq = 13836, kErrorIpsecIkeProcessErrHash = 13837, kErrorIpsecIkeProcessErrSig = 13838, kErrorIpsecIkeProcessErrNonce = 13839, kErrorIpsecIkeProcessErrNotify = 13840, kErrorIpsecIkeProcessErrDelete = 13841, kErrorIpsecIkeProcessErrVendor = 13842, kErrorIpsecIkeInvalidPayload = 13843, kErrorIpsecIkeLoadSoftSa = 13844, kErrorIpsecIkeSoftSaTornDown = 13845, kErrorIpsecIkeInvalidCookie = 13846, kErrorIpsecIkeNoPeerCert = 13847, kErrorIpsecIkePeerCrlFailed = 13848, kErrorIpsecIkePolicyChange = 13849, kErrorIpsecIkeNoMmPolicy = 13850, kErrorIpsecIkeNotcbpriv = 13851, kErrorIpsecIkeSecloadfail = 13852, kErrorIpsecIkeFailsspinit = 13853, kErrorIpsecIkeFailqueryssp = 13854, kErrorIpsecIkeSrvacqfail = 13855, kErrorIpsecIkeSrvquerycred = 13856, kErrorIpsecIkeGetspifail = 13857, kErrorIpsecIkeInvalidFilter = 13858, kErrorIpsecIkeOutOfMemory = 13859, kErrorIpsecIkeAddUpdateKeyFailed = 13860, kErrorIpsecIkeInvalidPolicy = 13861, kErrorIpsecIkeUnknownDoi = 13862, kErrorIpsecIkeInvalidSituation = 13863, kErrorIpsecIkeDhFailure = 13864, kErrorIpsecIkeInvalidGroup = 13865, kErrorIpsecIkeEncrypt = 13866, kErrorIpsecIkeDecrypt = 13867, kErrorIpsecIkePolicyMatch = 13868, kErrorIpsecIkeUnsupportedId = 13869, kErrorIpsecIkeInvalidHash = 13870, kErrorIpsecIkeInvalidHashAlg = 13871, kErrorIpsecIkeInvalidHashSize = 13872, kErrorIpsecIkeInvalidEncryptAlg = 13873, kErrorIpsecIkeInvalidAuthAlg = 13874, kErrorIpsecIkeInvalidSig = 13875, kErrorIpsecIkeLoadFailed = 13876, kErrorIpsecIkeRpcDelete = 13877, kErrorIpsecIkeBenignReinit = 13878, kErrorIpsecIkeInvalidResponderLifetimeNotify = 13879, kErrorIpsecIkeInvalidCertKeylen = 13881, kErrorIpsecIkeMmLimit = 13882, kErrorIpsecIkeNegotiationDisabled = 13883, kErrorIpsecIkeNegStatusEnd = 13884, kErrorSxsSectionNotFound = 14000, kErrorSxsCantGenActctx = 14001, kErrorSxsInvalidActctxdataFormat = 14002, kErrorSxsAssemblyNotFound = 14003, kErrorSxsManifestFormatError = 14004, kErrorSxsManifestParseError = 14005, kErrorSxsActivationContextDisabled = 14006, kErrorSxsKeyNotFound = 14007, kErrorSxsVersionConflict = 14008, kErrorSxsWrongSectionType = 14009, kErrorSxsThreadQueriesDisabled = 14010, kErrorSxsProcessDefaultAlreadySet = 14011, kErrorSxsUnknownEncodingGroup = 14012, kErrorSxsUnknownEncoding = 14013, kErrorSxsInvalidXmlNamespaceUri = 14014, kErrorSxsRootManifestDependencyNotInstalled = 14015, kErrorSxsLeafManifestDependencyNotInstalled = 14016, kErrorSxsInvalidAssemblyIdentityAttribute = 14017, kErrorSxsManifestMissingRequiredDefaultNamespace = 14018, kErrorSxsManifestInvalidRequiredDefaultNamespace = 14019, kErrorSxsPrivateManifestCrossPathWithReparsePoint = 14020, kErrorSxsDuplicateDllName = 14021, kErrorSxsDuplicateWindowclassName = 14022, kErrorSxsDuplicateClsid = 14023, kErrorSxsDuplicateIid = 14024, kErrorSxsDuplicateTlbid = 14025, kErrorSxsDuplicateProgid = 14026, kErrorSxsDuplicateAssemblyName = 14027, kErrorSxsFileHashMismatch = 14028, kErrorSxsPolicyParseError = 14029, kErrorSxsXmlEMissingquote = 14030, kErrorSxsXmlECommentsyntax = 14031, kErrorSxsXmlEBadstartnamechar = 14032, kErrorSxsXmlEBadnamechar = 14033, kErrorSxsXmlEBadcharinstring = 14034, kErrorSxsXmlEXmldeclsyntax = 14035, kErrorSxsXmlEBadchardata = 14036, kErrorSxsXmlEMissingwhitespace = 14037, kErrorSxsXmlEExpectingtagend = 14038, kErrorSxsXmlEMissingsemicolon = 14039, kErrorSxsXmlEUnbalancedparen = 14040, kErrorSxsXmlEInternalerror = 14041, kErrorSxsXmlEUnexpectedWhitespace = 14042, kErrorSxsXmlEIncompleteEncoding = 14043, kErrorSxsXmlEMissingParen = 14044, kErrorSxsXmlEExpectingclosequote = 14045, kErrorSxsXmlEMultipleColons = 14046, kErrorSxsXmlEInvalidDecimal = 14047, kErrorSxsXmlEInvalidHexidecimal = 14048, kErrorSxsXmlEInvalidUnicode = 14049, kErrorSxsXmlEWhitespaceorquestionmark = 14050, kErrorSxsXmlEUnexpectedendtag = 14051, kErrorSxsXmlEUnclosedtag = 14052, kErrorSxsXmlEDuplicateattribute = 14053, kErrorSxsXmlEMultipleroots = 14054, kErrorSxsXmlEInvalidatrootlevel = 14055, kErrorSxsXmlEBadxmldecl = 14056, kErrorSxsXmlEMissingroot = 14057, kErrorSxsXmlEUnexpectedeof = 14058, kErrorSxsXmlEBadperefinsubset = 14059, kErrorSxsXmlEUnclosedstarttag = 14060, kErrorSxsXmlEUnclosedendtag = 14061, kErrorSxsXmlEUnclosedstring = 14062, kErrorSxsXmlEUnclosedcomment = 14063, kErrorSxsXmlEUncloseddecl = 14064, kErrorSxsXmlEUnclosedcdata = 14065, kErrorSxsXmlEReservednamespace = 14066, kErrorSxsXmlEInvalidencoding = 14067, kErrorSxsXmlEInvalidswitch = 14068, kErrorSxsXmlEBadxmlcase = 14069, kErrorSxsXmlEInvalidStandalone = 14070, kErrorSxsXmlEUnexpectedStandalone = 14071, kErrorSxsXmlEInvalidVersion = 14072, kErrorSxsXmlEMissingequals = 14073, kErrorSxsProtectionRecoveryFailed = 14074, kErrorSxsProtectionPublicKeyTooShort = 14075, kErrorSxsProtectionCatalogNotValid = 14076, kErrorSxsUntranslatableHresult = 14077, kErrorSxsProtectionCatalogFileMissing = 14078, kErrorSxsMissingAssemblyIdentityAttribute = 14079, kErrorSxsInvalidAssemblyIdentityAttributeName = 14080 }; } } ================================================ FILE: unity_decoder/libil2cpp/os/Event.cpp ================================================ #include "il2cpp-config.h" #include "os/Event.h" #if IL2CPP_THREADS_WIN32 #include "os/Win32/EventImpl.h" #elif IL2CPP_THREADS_PTHREAD #include "os/Posix/EventImpl.h" #else #include "os/EventImpl.h" #endif namespace il2cpp { namespace os { Event::Event(bool manualReset, bool signaled) : m_Event(new EventImpl(manualReset, signaled)) { } Event::~Event() { delete m_Event; } ErrorCode Event::Set() { return m_Event->Set(); } ErrorCode Event::Reset() { return m_Event->Reset(); } WaitStatus Event::Wait(bool interruptible) { return m_Event->Wait(interruptible); } WaitStatus Event::Wait(uint32_t ms, bool interruptible) { return m_Event->Wait(ms, interruptible); } } } ================================================ FILE: unity_decoder/libil2cpp/os/Event.h ================================================ #pragma once #include "os/ErrorCodes.h" #include "os/Handle.h" #include "os/WaitStatus.h" #include "utils/NonCopyable.h" namespace il2cpp { namespace os { class EventImpl; class Event : public il2cpp::utils::NonCopyable { public: Event(bool manualReset = false, bool signaled = false); ~Event(); ErrorCode Set(); ErrorCode Reset(); WaitStatus Wait(bool interruptible = false); WaitStatus Wait(uint32_t ms, bool interruptible = false); private: EventImpl* m_Event; }; class EventHandle : public Handle { public: EventHandle(Event* event) : m_Event(event) {} virtual ~EventHandle() { delete m_Event; } virtual bool Wait() { m_Event->Wait(true); return true; } virtual bool Wait(uint32_t ms) { return m_Event->Wait(ms, true) != kWaitStatusTimeout; } virtual void Signal() { m_Event->Set(); } Event& Get() { return *m_Event; } private: Event* m_Event; }; } } ================================================ FILE: unity_decoder/libil2cpp/os/File.h ================================================ #pragma once #include "il2cpp-config.h" #include #include #include "os/ErrorCodes.h" #include "os/OSGlobalEnums.h" namespace il2cpp { namespace os { // File enums and structs struct FileHandle; struct FileStat { std::string name; int32_t attributes; int64_t length; int64_t creation_time; int64_t last_access_time; int64_t last_write_time; }; class LIBIL2CPP_CODEGEN_API File { public: static bool Isatty(FileHandle* fileHandle); static FileHandle* GetStdInput(); static FileHandle* GetStdOutput(); static FileHandle* GetStdError(); static bool CreatePipe(FileHandle** read_handle, FileHandle** write_handle); static bool CreatePipe(FileHandle** read_handle, FileHandle** write_handle, int* error); static FileType GetFileType(FileHandle* handle); static UnityPalFileAttributes GetFileAttributes(const std::string& path, int* error); static bool SetFileAttributes(const std::string& path, UnityPalFileAttributes attributes, int* error); static bool GetFileStat(const std::string& path, FileStat * stat, int* error); static bool CopyFile(const std::string& src, const std::string& dest, bool overwrite, int* error); static bool MoveFile(const std::string& src, const std::string& dest, int* error); static bool DeleteFile(const std::string& path, int *error); static bool ReplaceFile(const std::string& sourceFileName, const std::string& destinationFileName, const std::string& destinationBackupFileName, bool ignoreMetadataErrors, int* error); static FileHandle* Open(const std::string& path, int openMode, int accessMode, int shareMode, int options, int *error); static bool Close(FileHandle* handle, int *error); static bool SetFileTime(FileHandle* handle, int64_t creation_time, int64_t last_access_time, int64_t last_write_time, int* error); static int64_t GetLength(FileHandle* handle, int *error); static bool SetLength(FileHandle* handle, int64_t length, int *error); static int64_t Seek(FileHandle* handle, int64_t offset, int origin, int *error); static int Read(FileHandle* handle, char *dest, int count, int *error); static int32_t Write(FileHandle* handle, const char* buffer, int count, int *error); static bool Flush(FileHandle* handle, int* error); static void Lock(FileHandle* handle, int64_t position, int64_t length, int* error); static void Unlock(FileHandle* handle, int64_t position, int64_t length, int* error); static bool DuplicateHandle(FileHandle* source_process_handle, FileHandle* source_handle, FileHandle* target_process_handle, FileHandle** target_handle, int access, int inherit, int options, int* error); }; } } ================================================ FILE: unity_decoder/libil2cpp/os/FileSystemWatcher.h ================================================ #pragma once namespace il2cpp { namespace os { namespace FileSystemWatcher { int IsSupported(); } } } ================================================ FILE: unity_decoder/libil2cpp/os/Generic/COM.cpp ================================================ #include "il2cpp-config.h" #include "object-internals.h" #include "os/COM.h" #if IL2CPP_USE_GENERIC_COM namespace il2cpp { namespace os { il2cpp_hresult_t COM::CreateInstance(const Il2CppGuid& clsid, Il2CppIUnknown** object) { NO_UNUSED_WARNING(clsid); IL2CPP_ASSERT(object); *object = NULL; return IL2CPP_REGDB_E_CLASSNOTREG; } il2cpp_hresult_t COM::CreateFreeThreadedMarshaler(Il2CppIUnknown* outer, Il2CppIUnknown** marshal) { NO_UNUSED_WARNING(outer); IL2CPP_ASSERT(marshal); *marshal = NULL; return IL2CPP_COR_E_PLATFORMNOTSUPPORTED; } } } #endif #if IL2CPP_USE_GENERIC_COM_SAFEARRAYS namespace il2cpp { namespace os { // variant void COM::VariantInit(Il2CppVariant* variant) { NO_UNUSED_WARNING(variant); } il2cpp_hresult_t COM::VariantClear(Il2CppVariant* variant) { NO_UNUSED_WARNING(variant); return IL2CPP_COR_E_PLATFORMNOTSUPPORTED; } // safe array Il2CppSafeArray* COM::SafeArrayCreate(uint16_t type, uint32_t dimention_count, Il2CppSafeArrayBound* bounds) { NO_UNUSED_WARNING(type); NO_UNUSED_WARNING(dimention_count); NO_UNUSED_WARNING(bounds); return NULL; } il2cpp_hresult_t COM::SafeArrayDestroy(Il2CppSafeArray* safeArray) { NO_UNUSED_WARNING(safeArray); return IL2CPP_COR_E_PLATFORMNOTSUPPORTED; } il2cpp_hresult_t COM::SafeArrayAccessData(Il2CppSafeArray* safeArray, void** data) { NO_UNUSED_WARNING(safeArray); IL2CPP_ASSERT(data); *data = NULL; return IL2CPP_COR_E_PLATFORMNOTSUPPORTED; } il2cpp_hresult_t COM::SafeArrayUnaccessData(Il2CppSafeArray* safeArray) { NO_UNUSED_WARNING(safeArray); return IL2CPP_COR_E_PLATFORMNOTSUPPORTED; } il2cpp_hresult_t COM::SafeArrayGetVartype(Il2CppSafeArray* safeArray, uint16_t* type) { NO_UNUSED_WARNING(safeArray); IL2CPP_ASSERT(type); *type = 0; return IL2CPP_COR_E_PLATFORMNOTSUPPORTED; } uint32_t COM::SafeArrayGetDim(Il2CppSafeArray* safeArray) { NO_UNUSED_WARNING(safeArray); return 0; } il2cpp_hresult_t COM::SafeArrayGetLBound(Il2CppSafeArray* safeArray, uint32_t dimention, int32_t* bound) { NO_UNUSED_WARNING(safeArray); NO_UNUSED_WARNING(dimention); IL2CPP_ASSERT(bound); *bound = 0; return IL2CPP_COR_E_PLATFORMNOTSUPPORTED; } il2cpp_hresult_t COM::SafeArrayGetUBound(Il2CppSafeArray* safeArray, uint32_t dimention, int32_t* bound) { NO_UNUSED_WARNING(safeArray); NO_UNUSED_WARNING(dimention); IL2CPP_ASSERT(bound); *bound = 0; return IL2CPP_COR_E_PLATFORMNOTSUPPORTED; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Generic/Environment.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_USE_GENERIC_ENVIRONMENT #include "os/Environment.h" #include namespace il2cpp { namespace os { std::string Environment::GetMachineName() { return "il2cpp"; } int32_t Environment::GetProcessorCount() { return 1; } std::string Environment::GetOsVersionString() { return "0.0.0.0"; } std::string Environment::GetOsUserName() { return "Unknown"; } std::string Environment::GetEnvironmentVariable(const std::string& name) { return std::string(""); } void Environment::SetEnvironmentVariable(const std::string& name, const std::string& value) { } std::vector Environment::GetEnvironmentVariableNames() { NOT_IMPLEMENTED_ICALL(Environment::GetEnvironmentVariableNames); return std::vector(); } std::string Environment::GetHomeDirectory() { NOT_IMPLEMENTED_ICALL(Environment::GetHomeDirectory); return std::string(); } std::vector Environment::GetLogicalDrives() { NOT_IMPLEMENTED_ICALL(Environment::GetLogicalDrives); return std::vector(); } void Environment::Exit(int result) { NOT_IMPLEMENTED_ICALL(Environment::Exit); } NORETURN void Environment::Abort() { abort(); } #if NET_4_0 bool Environment::Is64BitOs() { return false; } #endif } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Generic/Initialize.cpp ================================================ #include "il2cpp-config.h" #include "os/Initialize.h" #if !IL2CPP_TARGET_WINDOWS void il2cpp::os::Initialize() { } void il2cpp::os::Uninitialize() { } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Generic/MarshalStringAlloc.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_USE_GENERIC_COM #include "os/MarshalStringAlloc.h" namespace il2cpp { namespace os { il2cpp_hresult_t MarshalStringAlloc::AllocateBStringLength(const Il2CppChar* text, int32_t length, Il2CppChar** bstr) { NO_UNUSED_WARNING(text); NO_UNUSED_WARNING(length); IL2CPP_ASSERT(bstr); *bstr = NULL; return IL2CPP_COR_E_PLATFORMNOTSUPPORTED; } il2cpp_hresult_t MarshalStringAlloc::GetBStringLength(const Il2CppChar* bstr, int32_t* length) { NO_UNUSED_WARNING(bstr); IL2CPP_ASSERT(length); *length = 0; return IL2CPP_COR_E_PLATFORMNOTSUPPORTED; } il2cpp_hresult_t MarshalStringAlloc::FreeBString(Il2CppChar* bstr) { NO_UNUSED_WARNING(bstr); return IL2CPP_COR_E_PLATFORMNOTSUPPORTED; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Generic/MemoryMappedFile.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_USE_GENERIC_MEMORY_MAPPED_FILE #include "os/File.h" #include "os/MemoryMappedFile.h" #include "utils/Memory.h" namespace il2cpp { namespace os { void* MemoryMappedFile::Map(FileHandle* file, size_t length, size_t offset) { int error = 0; if (!length) { length = os::File::GetLength(file, &error); if (error != 0) { return NULL; } } void* buffer = IL2CPP_MALLOC(length); os::File::Seek(file, offset, 0, &error); if (error != 0) { IL2CPP_FREE(buffer); return NULL; } int bytesRead = File::Read(file, (char*)buffer, (int)length, &error); if (bytesRead != length || error != 0) { IL2CPP_FREE(buffer); return NULL; } return buffer; } void MemoryMappedFile::Unmap(void* address, size_t length) { IL2CPP_FREE(address); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Generic/SocketImpl.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_USE_GENERIC_SOCKET_IMPL #include "os/Generic/SocketImpl.h" #define SOCKET_NOT_IMPLEMENTED \ IL2CPP_ASSERT(0 && "The target platform does not support Sockets"); namespace il2cpp { namespace os { void SocketImpl::Startup() { } void SocketImpl::Cleanup() { } WaitStatus SocketImpl::GetHostName(std::string &name) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::GetHostByAddr(const std::string &address, std::string &name, std::vector &aliases, std::vector &addr_list) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::GetHostByName(const std::string &host, std::string &name, std::vector &aliases, std::vector &addr_list) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } SocketImpl::SocketImpl(ThreadStatusCallback thread_status_callback) { SOCKET_NOT_IMPLEMENTED } SocketImpl::~SocketImpl() { } WaitStatus SocketImpl::Create(AddressFamily family, SocketType type, ProtocolType protocol) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::Create(SocketDescriptor fd, int32_t family, int32_t type, int32_t protocol) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::Close() { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::SetBlocking(bool blocking) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } ErrorCode SocketImpl::GetLastError() const { SOCKET_NOT_IMPLEMENTED return (ErrorCode) - 1; } WaitStatus SocketImpl::Bind(const char *path) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::Bind(const char *address, uint16_t port) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::Bind(uint32_t address, uint16_t port) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::Bind(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::Connect(const char *path) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::Shutdown(int32_t how) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::Disconnect(bool reuse) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::Connect(uint32_t address, uint16_t port) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::Connect(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::GetLocalEndPointInfo(EndPointInfo &info) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::GetRemoteEndPointInfo(EndPointInfo &info) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::Listen(int32_t backlog) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::Accept(os::Socket **socket) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::Receive(const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::Send(const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::SendArray(WSABuf *wsabufs, int32_t count, int32_t *sent, SocketFlags c_flags) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::ReceiveArray(WSABuf *wsabufs, int32_t count, int32_t *len, SocketFlags flags) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::SendTo(uint32_t address, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::SendTo(const char *path, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::SendTo(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::RecvFrom(uint32_t address, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::RecvFrom(const char *path, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::RecvFrom(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::Available(int32_t *amount) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::Ioctl(int32_t command, const uint8_t *in_data, int32_t in_len, uint8_t *out_data, int32_t out_len, int32_t *written) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::GetSocketOption(SocketOptionLevel level, SocketOptionName name, uint8_t *buffer, int32_t *length) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::GetSocketOptionFull(SocketOptionLevel level, SocketOptionName name, int32_t *first, int32_t *second) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::Poll(std::vector &requests, int32_t count, int32_t timeout, int32_t *result, int32_t *error) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::Poll(std::vector &requests, int32_t timeout, int32_t *result, int32_t *error) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::Poll(PollRequest& request, int32_t timeout, int32_t *result, int32_t *error) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::SetSocketOption(SocketOptionLevel level, SocketOptionName name, int32_t value) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::SetSocketOptionLinger(SocketOptionLevel level, SocketOptionName name, bool enabled, int32_t seconds) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::SetSocketOptionArray(SocketOptionLevel level, SocketOptionName name, const uint8_t *buffer, int32_t length) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } WaitStatus SocketImpl::SetSocketOptionMembership(SocketOptionLevel level, SocketOptionName name, uint32_t group_address, uint32_t local_address) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } #if IL2CPP_SUPPORT_IPV6 WaitStatus SocketImpl::SetSocketOptionMembership(SocketOptionLevel level, SocketOptionName name, IPv6Address ipv6, uint64_t interfaceOffset) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } #endif WaitStatus SocketImpl::SendFile(const char *filename, TransmitFileBuffers *buffers, TransmitFileOptions options) { SOCKET_NOT_IMPLEMENTED return kWaitStatusFailure; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Generic/SocketImpl.h ================================================ #pragma once #if IL2CPP_USE_GENERIC_SOCKET_IMPL #include #include #include #include "os/Socket.h" #include "os/ErrorCodes.h" #include "os/WaitStatus.h" #include "utils/NonCopyable.h" namespace il2cpp { namespace os { class SocketImpl : public il2cpp::utils::NonCopyable { public: typedef int32_t SocketDescriptor; SocketImpl(ThreadStatusCallback thread_status_callback); ~SocketImpl(); inline SocketDescriptor GetDescriptor() { return -1; } ErrorCode GetLastError() const; WaitStatus Create(SocketDescriptor fd, int32_t family, int32_t type, int32_t protocol); WaitStatus Create(AddressFamily family, SocketType type, ProtocolType protocol); WaitStatus Close(); bool IsClosed() { return true; } WaitStatus SetBlocking(bool blocking); WaitStatus Listen(int32_t blacklog); WaitStatus Bind(const char *path); WaitStatus Bind(const char *address, uint16_t port); WaitStatus Bind(uint32_t address, uint16_t port); WaitStatus Bind(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port); WaitStatus Connect(const char *path); WaitStatus Connect(uint32_t address, uint16_t port); WaitStatus Connect(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port); WaitStatus Disconnect(bool reuse); WaitStatus Shutdown(int32_t how); WaitStatus GetLocalEndPointInfo(EndPointInfo &info); WaitStatus GetRemoteEndPointInfo(EndPointInfo &info); WaitStatus Receive(const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len); WaitStatus Send(const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len); WaitStatus SendArray(WSABuf *wsabufs, int32_t count, int32_t *sent, SocketFlags c_flags); WaitStatus ReceiveArray(WSABuf *wsabufs, int32_t count, int32_t *len, SocketFlags c_flags); WaitStatus SendTo(uint32_t address, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len); WaitStatus SendTo(const char *path, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len); WaitStatus SendTo(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len); WaitStatus RecvFrom(uint32_t address, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep); WaitStatus RecvFrom(const char *path, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep); WaitStatus RecvFrom(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep); WaitStatus Accept(os::Socket **socket); WaitStatus Available(int32_t *amount); WaitStatus Ioctl(int32_t command, const uint8_t *in_data, int32_t in_len, uint8_t *out_data, int32_t out_len, int32_t *written); WaitStatus GetSocketOption(SocketOptionLevel level, SocketOptionName name, uint8_t *buffer, int32_t *length); WaitStatus GetSocketOptionFull(SocketOptionLevel level, SocketOptionName name, int32_t *first, int32_t *second); WaitStatus SetSocketOption(SocketOptionLevel level, SocketOptionName name, int32_t value); WaitStatus SetSocketOptionLinger(SocketOptionLevel level, SocketOptionName name, bool enabled, int32_t seconds); WaitStatus SetSocketOptionArray(SocketOptionLevel level, SocketOptionName name, const uint8_t *buffer, int32_t length); WaitStatus SetSocketOptionMembership(SocketOptionLevel level, SocketOptionName name, uint32_t group_address, uint32_t local_address); #if IL2CPP_SUPPORT_IPV6 WaitStatus SetSocketOptionMembership(SocketOptionLevel level, SocketOptionName name, IPv6Address ipv6, uint64_t interfaceOffset); #endif WaitStatus SendFile(const char *filename, TransmitFileBuffers *buffers, TransmitFileOptions options); static WaitStatus Poll(std::vector &requests, int32_t count, int32_t timeout, int32_t *result, int32_t *error); static WaitStatus Poll(std::vector &requests, int32_t timeout, int32_t *result, int32_t *error); static WaitStatus Poll(PollRequest& request, int32_t timeout, int32_t *result, int32_t *error); static WaitStatus GetHostName(std::string &name); static WaitStatus GetHostByName(const std::string &host, std::string &name, std::vector &aliases, std::vector &addr_list); static WaitStatus GetHostByAddr(const std::string &address, std::string &name, std::vector &aliases, std::vector &addr_list); static void Startup(); static void Cleanup(); }; } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Generic/WindowsRuntime.cpp ================================================ #include "il2cpp-config.h" #include "il2cpp-vm-support.h" #include "os/WindowsRuntime.h" #include "vm/Exception.h" #if IL2CPP_USE_GENERIC_WINDOWSRUNTIME namespace il2cpp { namespace os { il2cpp_hresult_t WindowsRuntime::GetActivationFactory(Il2CppHString className, Il2CppIActivationFactory** activationFactory) { NO_UNUSED_WARNING(className); NO_UNUSED_WARNING(activationFactory); IL2CPP_ASSERT(className != NULL); IL2CPP_ASSERT(activationFactory != NULL); return IL2CPP_REGDB_E_CLASSNOTREG; } il2cpp_hresult_t WindowsRuntime::CreateHStringReference(const utils::StringView& str, Il2CppHStringHeader* header, Il2CppHString* hstring) { NO_UNUSED_WARNING(str); NO_UNUSED_WARNING(header); NO_UNUSED_WARNING(hstring); IL2CPP_ASSERT(header != NULL); IL2CPP_ASSERT(hstring != NULL); return IL2CPP_COR_E_PLATFORMNOTSUPPORTED; } il2cpp_hresult_t WindowsRuntime::CreateHString(const utils::StringView& str, Il2CppHString* hstring) { NO_UNUSED_WARNING(str); NO_UNUSED_WARNING(hstring); return IL2CPP_COR_E_PLATFORMNOTSUPPORTED; } il2cpp_hresult_t WindowsRuntime::DeleteHString(Il2CppHString hstring) { NO_UNUSED_WARNING(hstring); return IL2CPP_COR_E_PLATFORMNOTSUPPORTED; } const Il2CppChar* WindowsRuntime::GetHStringBuffer(Il2CppHString hstring, uint32_t* length) { NO_UNUSED_WARNING(hstring); NO_UNUSED_WARNING(length); IL2CPP_VM_RAISE_COM_EXCEPTION(IL2CPP_COR_E_PLATFORMNOTSUPPORTED, false); return NULL; } Il2CppString* WindowsRuntime::HStringToManagedString(Il2CppHString hstring) { NO_UNUSED_WARNING(hstring); IL2CPP_VM_RAISE_COM_EXCEPTION(IL2CPP_COR_E_PLATFORMNOTSUPPORTED, false); return NULL; } Il2CppIRestrictedErrorInfo* WindowsRuntime::GetRestrictedErrorInfo() { return NULL; } void WindowsRuntime::OriginateLanguageException(Il2CppException* ex, Il2CppString* exceptionString) { NO_UNUSED_WARNING(ex); NO_UNUSED_WARNING(exceptionString); } void WindowsRuntime::EnableErrorReporting() { } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Handle.h ================================================ #pragma once #include "utils/NonCopyable.h" namespace il2cpp { namespace os { class Handle : public il2cpp::utils::NonCopyable { public: virtual ~Handle() {} virtual bool Wait() = 0; virtual bool Wait(uint32_t ms) = 0; virtual void Signal() = 0; }; } } ================================================ FILE: unity_decoder/libil2cpp/os/Image.h ================================================ #pragma once namespace il2cpp { namespace os { namespace Image { void* GetImageBase(); } } } ================================================ FILE: unity_decoder/libil2cpp/os/Initialize.h ================================================ #pragma once namespace il2cpp { namespace os { void Initialize(); void Uninitialize(); } } ================================================ FILE: unity_decoder/libil2cpp/os/LastError.h ================================================ #pragma once namespace il2cpp { namespace os { class LastError { public: static uint32_t GetLastError(); }; } /* namespace os */ } /* namespace il2cpp*/ ================================================ FILE: unity_decoder/libil2cpp/os/LibraryLoader.h ================================================ #pragma once #include "il2cpp-config.h" #include "utils/StringView.h" #include struct PInvokeArguments; namespace il2cpp { namespace os { class LibraryLoader { public: static Il2CppMethodPointer GetHardcodedPInvokeDependencyFunctionPointer(const il2cpp::utils::StringView& nativeDynamicLibrary, const il2cpp::utils::StringView& entryPoint); static void* LoadDynamicLibrary(const utils::StringView& nativeDynamicLibrary); static Il2CppMethodPointer GetFunctionPointer(void* dynamicLibrary, const PInvokeArguments& pinvokeArgs); static Il2CppMethodPointer GetFunctionPointer(void* dynamicLibrary, const char* functionName); static void CleanupLoadedLibraries(); }; } /* namespace os */ } /* namespace il2cpp*/ ================================================ FILE: unity_decoder/libil2cpp/os/Locale.h ================================================ #pragma once #include #include namespace il2cpp { namespace os { class Locale { public: static void Initialize(); static void UnInitialize(); static std::string GetLocale(); #if IL2CPP_SUPPORT_LOCALE_INDEPENDENT_PARSING static double DoubleParseLocaleIndependentImpl(char *ptr, char** endptr); #endif }; } /* namespace os */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/os/MarshalAlloc.h ================================================ #pragma once namespace il2cpp { namespace os { class MarshalAlloc { public: static void* Allocate(size_t size); static void* ReAlloc(void* ptr, size_t size); static void Free(void* ptr); }; } /* namespace os */ } /* namespace il2cpp*/ ================================================ FILE: unity_decoder/libil2cpp/os/MarshalStringAlloc.h ================================================ #pragma once namespace il2cpp { namespace os { class MarshalStringAlloc { public: static il2cpp_hresult_t AllocateBStringLength(const Il2CppChar* text, int32_t length, Il2CppChar** bstr); static il2cpp_hresult_t GetBStringLength(const Il2CppChar* bstr, int32_t* length); static il2cpp_hresult_t FreeBString(Il2CppChar* bstr); }; } /* namespace os */ } /* namespace il2cpp*/ ================================================ FILE: unity_decoder/libil2cpp/os/Memory.h ================================================ #pragma once namespace il2cpp { namespace os { namespace Memory { void* AlignedAlloc(size_t size, size_t alignment); void* AlignedReAlloc(void* memory, size_t newSize, size_t alignment); void AlignedFree(void* memory); } } } ================================================ FILE: unity_decoder/libil2cpp/os/MemoryMappedFile.h ================================================ #pragma once #include #include "File.h" namespace il2cpp { namespace os { class MemoryMappedFile { public: static void* Map(FileHandle* file) { return Map(file, 0, 0); } static void Unmap(void* address) { Unmap(address, 0); } static void* Map(FileHandle* file, size_t length, size_t offset); static void Unmap(void* address, size_t length); }; } } ================================================ FILE: unity_decoder/libil2cpp/os/Messages.cpp ================================================ #include #include "il2cpp-config.h" #include "os/Messages.h" #define N_ELEMENTS(e) \ (sizeof (e) / sizeof ((e)[0])) namespace il2cpp { namespace os { ErrorDesc common_messages[] = { { kErrorCodeSuccess, "Success" }, { kErrorCodeFileNotFound, "Cannot find the specified file" }, { kErrorCodePathNotFound, "Cannot find the specified file" }, { kErrorCodeTooManyOpenFiles, "Too many open files" }, { kErrorCodeAccessDenied, "Access denied" }, { kErrorCodeInvalidHandle, "Invalid handle" }, { kErrorInvalidData, "Invalid data" }, { kErrorOutofmemory, "Out of memory" }, { kErrorCodeNotSameDevice, "Not same device" }, { kErrorCodeNoMoreFiles, "No more files" }, { kErrorBadLength, "Bad length" }, { kErrorCodeGenFailure, "General failure" }, { kErrorCodeSharingViolation, "Sharing violation" }, { kErrorCodeLockViolation, "Lock violation" }, { kErrorNotSupported, "Operation not supported" }, { kErrorCodeInvalidParameter, "Invalid parameter" }, { kErrorCallNotImplemented, "Call not implemented" }, { kErrorCodeInvalidName, "Invalid name" }, { kErrorProcNotFound, "Process not found" }, { kErrorCodeAlreadyExists, "Already exists" }, { kErrorDirectory, "Is a directory" }, { kErrorCodeEncryptionFailed, "Encryption failed" }, { kWSAeintr, "interrupted" }, { kWSAebadf, "Bad file number" }, { kWSAeacces, "Access denied" }, { kWSAefault, "Bad address" }, { kWSAeinval, "Invalid arguments" }, { kWSAemfile, "Too many open files" }, { kWSAewouldblock, "Operation on non-blocking socket would block" }, { kWSAeinprogress, "Operation in progress" }, { kWSAealready, "Operation already in progress" }, { kWSAenotsock, "The descriptor is not a socket" }, { kWSAedestaddrreq, "Destination address required" }, { kWSAemsgsize, "Message too long" }, { kWSAeprototype, "Protocol wrong type for socket" }, { kWSAenoprotoopt, "Protocol option not supported" }, { kWSAeprotonosupport, "Protocol not supported" }, { kWSAesocktnosupport, "Socket not supported" }, { kWSAeopnotsupp, "Operation not supported" }, { kWSAepfnosupport, "Protocol family not supported" }, { kWSAeafnosupport, "An address incompatible with the requested protocol was used" }, { kWSAeaddrinuse, "Address already in use" }, { kWSAeaddrnotavail, "The requested address is not valid in this context" }, { kWSAenetdown, "Network subsystem is down" }, { kWSAenetunreach, "Network is unreachable" }, { kWSAenetreset, "Connection broken, keep-alive detected a problem" }, { kWSAeconnaborted, "An established connection was aborted in your host machine." }, { kWSAeconnreset, "Connection reset by peer" }, { kWSAenobufs, "Not enough buffer space is available" }, { kWSAeisconn, "Socket is already connected" }, { kWSAenotconn, "The socket is not connected" }, { kWSAeshutdown, "The socket has been shut down" }, { kWSAetoomanyrefs, "Too many references: cannot splice" }, { kWSAetimedout, "Connection timed out" }, { kWSAeconnrefused, "Connection refused" }, { kWSAeloop, "Too many symbolic links encountered" }, { kWSAenametoolong, "File name too long" }, { kWSAehostdown, "Host is down" }, { kWSAehostunreach, "No route to host" }, { kWSAenotempty, "Directory not empty" }, { kWSAeproclim, "EPROCLIM" }, { kWSAeusers, "Too many users" }, { kWSAedquot, "Quota exceeded" }, { kWSAestale, "Stale NFS file handle" }, { kWSAeremote, "Object is remote" }, { kWSAsysnotready, "SYSNOTREADY" }, { kWSAvernotsupported, "VERNOTSUPPORTED" }, { kWSAnotinitialised, "Winsock not initialised" }, { kWSAediscon, "EDISCON" }, { kWSAenomore, "ENOMORE" }, { kWSAecancelled, "Operation canceled" }, { kWSAeinvalidproctable, "EINVALIDPROCTABLE" }, { kWSAeinvalidprovider, "EINVALIDPROVIDER" }, { kWSAeproviderfailedinit, "EPROVIDERFAILEDINIT" }, { kWSAsyscallfailure, "System call failed" }, { kWSAserviceNotFound, "SERVICE_NOT_FOUND" }, { kWSAtypeNotFound, "TYPE_NOT_FOUND" }, { kWSAENoMore, "E_NO_MORE" }, { kWSAECancelled, "E_CANCELLED" }, { kWSAerefused, "EREFUSED" }, { kWSAhostNotFound, "No such host is known" }, { kWSAtryAgain, "A temporary error occurred on an authoritative name server. Try again later." }, { kWSAnoRecovery, "No recovery" }, { kWSAnoData, "No data" }, }; #ifndef IL2CPP_DISABLE_FULL_MESSAGES ErrorDesc messages[] = { { kErrorInvalidFunction, "Invalid function" }, { kErrorArenaTrashed, "Arena trashed" }, { kErrorNotEnoughMemory, "Not enough memory" }, { kErrorInvalidBlock, "Invalid block" }, { kErrorBadEnvironment, "Bad environment" }, { kErrorBadFormat, "Bad format" }, { kErrorInvalidAccess, "Invalid access" }, { kErrorInvalidDrive, "Invalid drive" }, { kErrorCurrentDirectory, "Current directory" }, { kErrorWriteProtect, "Write protect" }, { kErrorBadUnit, "Bad unit" }, { kErrorNotReady, "Not ready" }, { kErrorBadCommand, "Bad command" }, { kErrorCrc, "CRC" }, { kErrorSeek, "Seek" }, { kErrorNotDosDisk, "Not DOS disk" }, { kErrorSectorNotFound, "Sector not found" }, { kErrorOutOfPaper, "Out of paper" }, { kErrorWriteFault, "Write fault" }, { kErrorReadFault, "Read fault" }, { kErrorWrongDisk, "Wrong disk" }, { kErrorSharingBufferExceeded, "Sharing buffer exceeded" }, { kErrorHandleEof, "Handle EOF" }, { kErrorHandleDiskFull, "Handle disk full" }, { kErrorRemNotList, "Rem not list" }, { kErrorDupName, "Duplicate name" }, { kErrorBadNetpath, "Bad netpath" }, { kErrorNetworkBusy, "Network busy" }, { kErrorDevNotExist, "Device does not exist" }, { kErrorTooManyCmds, "Too many commands" }, { kErrorAdapHdwErr, "ADAP HDW error" }, { kErrorBadNetResp, "Bad net response" }, { kErrorUnexpNetErr, "Unexpected net error" }, { kErrorBadRemAdap, "Bad rem adap" }, { kErrorPrintqFull, "Print queue full" }, { kErrorNoSpoolSpace, "No spool space" }, { kErrorPrintCancelled, "Print cancelled" }, { kErrorNetnameDeleted, "Netname deleted" }, { kErrorNetworkAccessDenied, "Network access denied" }, { kErrorBadDevType, "Bad device type" }, { kErrorBadNetName, "Bad net name" }, { kErrorTooManyNames, "Too many names" }, { kErrorTooManySess, "Too many sessions" }, { kErrorSharingPaused, "Sharing paused" }, { kErrorReqNotAccep, "Req not accep" }, { kErrorRedirPaused, "Redir paused" }, { kErrorFileExists, "File exists" }, { kErrorCannotMake, "Cannot make" }, { kErrorFailI24, "Fail i24" }, { kErrorOutOfStructures, "Out of structures" }, { kErrorAlreadyAssigned, "Already assigned" }, { kErrorInvalidPassword, "Invalid password" }, { kErrorNetWriteFault, "Net write fault" }, { kErrorNoProcSlots, "No proc slots" }, { kErrorTooManySemaphores, "Too many semaphores" }, { kErrorExclSemAlreadyOwned, "Exclusive semaphore already owned" }, { kErrorSemIsSet, "Semaphore is set" }, { kErrorTooManySemRequests, "Too many semaphore requests" }, { kErrorInvalidAtInterruptTime, "Invalid at interrupt time" }, { kErrorSemOwnerDied, "Semaphore owner died" }, { kErrorSemUserLimit, "Semaphore user limit" }, { kErrorDiskChange, "Disk change" }, { kErrorDriveLocked, "Drive locked" }, { kErrorBrokenPipe, "Broken pipe" }, { kErrorOpenFailed, "Open failed" }, { kErrorBufferOverflow, "Buffer overflow" }, { kErrorDiskFull, "Disk full" }, { kErrorNoMoreSearchHandles, "No more search handles" }, { kErrorInvalidTargetHandle, "Invalid target handle" }, { kErrorInvalidCategory, "Invalid category" }, { kErrorInvalidVerifySwitch, "Invalid verify switch" }, { kErrorBadDriverLevel, "Bad driver level" }, { kErrorSemTimeout, "Semaphore timeout" }, { kErrorInsufficientBuffer, "Insufficient buffer" }, { kErrorInvalidLevel, "Invalid level" }, { kErrorNoVolumeLabel, "No volume label" }, { kErrorModNotFound, "Module not found" }, { kErrorWaitNoChildren, "Wait no children" }, { kErrorChildNotComplete, "Child not complete" }, { kErrorDirectAccessHandle, "Direct access handle" }, { kErrorNegativeSeek, "Negative seek" }, { kErrorSeekOnDevice, "Seek on device" }, { kErrorIsJoinTarget, "Is join target" }, { kErrorIsJoined, "Is joined" }, { kErrorIsSubsted, "Is substed" }, { kErrorNotJoined, "Not joined" }, { kErrorNotSubsted, "Not substed" }, { kErrorJoinToJoin, "Join to join" }, { kErrorSubstToSubst, "Subst to subst" }, { kErrorJoinToSubst, "Join to subst" }, { kErrorSubstToJoin, "Subst to join" }, { kErrorBusyDrive, "Busy drive" }, { kErrorSameDrive, "Same drive" }, { kErrorDirNotRoot, "Directory not root" }, { kErrorDirNotEmpty, "Directory not empty" }, { kErrorIsSubstPath, "Is subst path" }, { kErrorIsJoinPath, "Is join path" }, { kErrorPathBusy, "Path busy" }, { kErrorIsSubstTarget, "Is subst target" }, { kErrorSystemTrace, "System trace" }, { kErrorInvalidEventCount, "Invalid event count" }, { kErrorTooManyMuxwaiters, "Too many muxwaiters" }, { kErrorInvalidListFormat, "Invalid list format" }, { kErrorLabelTooLong, "Label too long" }, { kErrorTooManyTcbs, "Too many TCBs" }, { kErrorSignalRefused, "Signal refused" }, { kErrorDiscarded, "Discarded" }, { kErrorNotLocked, "Not locked" }, { kErrorBadThreadidAddr, "Bad thread ID addr" }, { kErrorBadArguments, "Bad arguments" }, { kErrorBadPathname, "Bad pathname" }, { kErrorSignalPending, "Signal pending" }, { kErrorMaxThrdsReached, "Max thrds reached" }, { kErrorLockFailed, "Lock failed" }, { kErrorBusy, "Busy" }, { kErrorCancelViolation, "Cancel violation" }, { kErrorAtomicLocksNotSupported, "Atomic locks not supported" }, { kErrorInvalidSegmentNumber, "Invalid segment number" }, { kErrorInvalidOrdinal, "Invalid ordinal" }, { kErrorInvalidFlagNumber, "Invalid flag number" }, { kErrorSemNotFound, "Sem not found" }, { kErrorInvalidStartingCodeseg, "Invalid starting codeseg" }, { kErrorInvalidStackseg, "Invalid stackseg" }, { kErrorInvalidModuletype, "Invalid moduletype" }, { kErrorInvalidExeSignature, "Invalid exe signature" }, { kErrorExeMarkedInvalid, "Exe marked invalid" }, { kErrorBadExeFormat, "Bad exe format" }, { kErrorIteratedDataExceeds64k, "Iterated data exceeds 64k (and that should be enough for anybody!)" }, { kErrorInvalidMinallocsize, "Invalid minallocsize" }, { kErrorDynlinkFromInvalidRing, "Dynlink from invalid ring" }, { kErrorIoplNotEnabled, "IOPL not enabled" }, { kErrorInvalidSegdpl, "Invalid segdpl" }, { kErrorAutodatasegExceeds64k, "Autodataseg exceeds 64k" }, { kErrorRing2segMustBeMovable, "Ring2seg must be movable" }, { kErrorRelocChainXeedsSeglim, "Reloc chain exceeds seglim" }, { kErrorInfloopInRelocChain, "Infloop in reloc chain" }, { kErrorEnvvarNotFound, "Env var not found" }, { kErrorNoSignalSent, "No signal sent" }, { kErrorFilenameExcedRange, "Filename exceeds range" }, { kErrorRing2StackInUse, "Ring2 stack in use" }, { kErrorMetaExpansionTooLong, "Meta expansion too long" }, { kErrorInvalidSignalNumber, "Invalid signal number" }, { kErrorThread1Inactive, "Thread 1 inactive" }, { kErrorLocked, "Locked" }, { kErrorTooManyModules, "Too many modules" }, { kErrorNestingNotAllowed, "Nesting not allowed" }, { kErrorExeMachineTypeMismatch, "Exe machine type mismatch" }, { kErrorBadPipe, "Bad pipe" }, { kErrorPipeBusy, "Pipe busy" }, { kErrorNoData, "No data" }, { kErrorPipeNotConnected, "Pipe not connected" }, { kErrorMoreData, "More data" }, { kErrorVcDisconnected, "VC disconnected" }, { kErrorInvalidEaName, "Invalid EA name" }, { kErrorEaListInconsistent, "EA list inconsistent" }, { kWaitTimeout, "Wait timeout" }, { kErrorNoMoreItems, "No more items" }, { kErrorCannotCopy, "Cannot copy" }, { kErrorEasDidntFit, "EAS didnt fit" }, { kErrorEaFileCorrupt, "EA file corrupt" }, { kErrorEaTableFull, "EA table full" }, { kErrorInvalidEaHandle, "Invalid EA handle" }, { kErrorEasNotSupported, "EAs not supported" }, { kErrorNotOwner, "Not owner" }, { kErrorTooManyPosts, "Too many posts" }, { kErrorPartialCopy, "Partial copy" }, { kErrorOplockNotGranted, "Oplock not granted" }, { kErrorInvalidOplockProtocol, "Invalid oplock protocol" }, { kErrorDiskTooFragmented, "Disk too fragmented" }, { kErrorDeletePending, "Delete pending" }, { kErrorMrMidNotFound, "Mr Mid not found" }, { kErrorInvalidAddress, "Invalid address" }, { kErrorArithmeticOverflow, "Arithmetic overflow" }, { kErrorPipeConnected, "Pipe connected" }, { kErrorPipeListening, "Pipe listening" }, { kErrorEaAccessDenied, "EA access denied" }, { kErrorOperationAborted, "Operation aborted" }, { kErrorIoIncomplete, "IO incomplete" }, { kErrorIoPending, "IO pending" }, { kErrorNoaccess, "No access" }, { kErrorSwaperror, "Swap error" }, { kErrorStackOverflow, "Stack overflow" }, { kErrorInvalidMessage, "Invalid message" }, { kErrorCanNotComplete, "Can not complete" }, { kErrorInvalidFlags, "Invalid flags" }, { kErrorUnrecognizedVolume, "Unrecognised volume" }, { kErrorFileInvalid, "File invalid" }, { kErrorFullscreenMode, "Full screen mode" }, { kErrorNoToken, "No token" }, { kErrorBaddb, "Bad DB" }, { kErrorBadkey, "Bad key" }, { kErrorCantopen, "Can't open" }, { kErrorCantread, "Can't read" }, { kErrorCantwrite, "Can't write" }, { kErrorRegistryRecovered, "Registry recovered" }, { kErrorRegistryCorrupt, "Registry corrupt" }, { kErrorRegistryIoFailed, "Registry IO failed" }, { kErrorNotRegistryFile, "Not registry file" }, { kErrorKeyDeleted, "Key deleted" }, { kErrorNoLogSpace, "No log space" }, { kErrorKeyHasChildren, "Key has children" }, { kErrorChildMustBeVolatile, "Child must be volatile" }, { kErrorNotifyEnumDir, "Notify enum dir" }, { kErrorDependentServicesRunning, "Dependent services running" }, { kErrorInvalidServiceControl, "Invalid service control" }, { kErrorServiceRequestTimeout, "Service request timeout" }, { kErrorServiceNoThread, "Service no thread" }, { kErrorServiceDatabaseLocked, "Service database locked" }, { kErrorServiceAlreadyRunning, "Service already running" }, { kErrorInvalidServiceAccount, "Invalid service account" }, { kErrorServiceDisabled, "Service disabled" }, { kErrorCircularDependency, "Circular dependency" }, { kErrorServiceDoesNotExist, "Service does not exist" }, { kErrorServiceCannotAcceptCtrl, "Service cannot accept ctrl" }, { kErrorServiceNotActive, "Service not active" }, { kErrorFailedServiceControllerConnect, "Failed service controller connect" }, { kErrorExceptionInService, "Exception in service" }, { kErrorDatabaseDoesNotExist, "Database does not exist" }, { kErrorServiceSpecificError, "Service specific error" }, { kErrorProcessAborted, "Process aborted" }, { kErrorServiceDependencyFail, "Service dependency fail" }, { kErrorServiceLogonFailed, "Service logon failed" }, { kErrorServiceStartHang, "Service start hang" }, { kErrorInvalidServiceLock, "Invalid service lock" }, { kErrorServiceMarkedForDelete, "Service marked for delete" }, { kErrorServiceExists, "Service exists" }, { kErrorAlreadyRunningLkg, "Already running lkg" }, { kErrorServiceDependencyDeleted, "Service dependency deleted" }, { kErrorBootAlreadyAccepted, "Boot already accepted" }, { kErrorServiceNeverStarted, "Service never started" }, { kErrorDuplicateServiceName, "Duplicate service name" }, { kErrorDifferentServiceAccount, "Different service account" }, { kErrorCannotDetectDriverFailure, "Cannot detect driver failure" }, { kErrorCannotDetectProcessAbort, "Cannot detect process abort" }, { kErrorNoRecoveryProgram, "No recovery program" }, { kErrorServiceNotInExe, "Service not in exe" }, { kErrorNotSafebootService, "Not safeboot service" }, { kErrorEndOfMedia, "End of media" }, { kErrorFilemarkDetected, "Filemark detected" }, { kErrorBeginningOfMedia, "Beginning of media" }, { kErrorSetmarkDetected, "Setmark detected" }, { kErrorNoDataDetected, "No data detected" }, { kErrorPartitionFailure, "Partition failure" }, { kErrorInvalidBlockLength, "Invalid block length" }, { kErrorDeviceNotPartitioned, "Device not partitioned" }, { kErrorUnableToLockMedia, "Unable to lock media" }, { kErrorUnableToUnloadMedia, "Unable to unload media" }, { kErrorMediaChanged, "Media changed" }, { kErrorBusReset, "Bus reset" }, { kErrorNoMediaInDrive, "No media in drive" }, { kErrorNoUnicodeTranslation, "No unicode translation" }, { kErrorDllInitFailed, "DLL init failed" }, { kErrorShutdownInProgress, "Shutdown in progress" }, { kErrorNoShutdownInProgress, "No shutdown in progress" }, { kErrorIoDevice, "IO device" }, { kErrorSerialNoDevice, "Serial IO device" }, { kErrorIrqBusy, "IRQ busy" }, { kErrorMoreWrites, "More writes" }, { kErrorCounterTimeout, "Counter timeout" }, { kErrorFloppyIdMarkNotFound, "Floppy ID mark not found" }, { kErrorFloppyWrongCylinder, "Floppy wrong cylinder" }, { kErrorFloppyUnknownError, "Floppy unknown error" }, { kErrorFloppyBadRegisters, "Floppy bad registers" }, { kErrorDiskRecalibrateFailed, "Disk recalibrate failed" }, { kErrorDiskOperationFailed, "Disk operation failed" }, { kErrorDiskResetFailed, "Disk reset failed" }, { kErrorEomOverflow, "EOM overflow" }, { kErrorNotEnoughServerMemory, "Not enough server memory" }, { kErrorPossibleDeadlock, "Possible deadlock" }, { kErrorMappedAlignment, "Mapped alignment" }, { kErrorSetPowerStateVetoed, "Set power state vetoed" }, { kErrorSetPowerStateFailed, "Set power state failed" }, { kErrorTooManyLinks, "Too many links" }, { kErrorOldWinVersion, "Old win version" }, { kErrorAppWrongOs, "App wrong OS" }, { kErrorSingleInstanceApp, "Single instance app" }, { kErrorRmodeApp, "Rmode app" }, { kErrorInvalidDll, "Invalid DLL" }, { kErrorNoAssociation, "No association" }, { kErrorDdeFail, "DDE fail" }, { kErrorDllNotFound, "DLL not found" }, { kErrorNoMoreUserHandles, "No more user handles" }, { kErrorMessageSyncOnly, "Message sync only" }, { kErrorSourceElementEmpty, "Source element empty" }, { kErrorDestinationElementFull, "Destination element full" }, { kErrorIllegalElementAddress, "Illegal element address" }, { kErrorMagazineNotPresent, "Magazine not present" }, { kErrorDeviceReinitializationNeeded, "Device reinitialization needed" }, { kErrorDeviceRequiresCleaning, "Device requires cleaning" }, { kErrorDeviceDoorOpen, "Device door open" }, { kErrorDeviceNotConnected, "Device not connected" }, { kErrorNotFound, "Not found" }, { kErrorNoMatch, "No match" }, { kErrorSetNotFound, "Set not found" }, { kErrorPointNotFound, "Point not found" }, { kErrorNoTrackingService, "No tracking service" }, { kErrorNoVolumeId, "No volume ID" }, { kErrorUnableToRemoveReplaced, "Unable to remove replaced" }, { kErrorUnableToMoveReplacement, "Unable to move replacement" }, { kErrorUnableToMoveReplacement2, "Unable to move replacement 2" }, { kErrorJournalDeleteInProgress, "Journal delete in progress" }, { kErrorJournalNotActive, "Journal not active" }, { kErrorPotentialFileFound, "Potential file found" }, { kErrorJournalEntryDeleted, "Journal entry deleted" }, { kErrorBadDevice, "Bad device" }, { kErrorConnectionUnavail, "Connection unavail" }, { kErrorDeviceAlreadyRemembered, "Device already remembered" }, { kErrorNoNetOrBadPath, "No net or bad path" }, { kErrorBadProvider, "Bad provider" }, { kErrorCannotOpenProfile, "Cannot open profile" }, { kErrorBadProfile, "Bad profile" }, { kErrorNotContainer, "Not container" }, { kErrorExtendedError, "Extended error" }, { kErrorInvalidGroupname, "Invalid group name" }, { kErrorInvalidComputername, "Invalid computer name" }, { kErrorInvalidEventname, "Invalid event name" }, { kErrorInvalidDomainname, "Invalid domain name" }, { kErrorInvalidServicename, "Invalid service name" }, { kErrorInvalidNetname, "Invalid net name" }, { kErrorInvalidSharename, "Invalid share name" }, { kErrorInvalidPasswordname, "Invalid password name" }, { kErrorInvalidMessagename, "Invalid message name" }, { kErrorInvalidMessagedest, "Invalid message dest" }, { kErrorSessionCredentialConflict, "Session credential conflict" }, { kErrorRemoteSessionLimitExceeded, "Remote session limit exceeded" }, { kErrorDupDomainname, "Dup domain name" }, { kErrorNoNetwork, "No network" }, { kErrorCancelled, "Cancelled" }, { kErrorUserMappedFile, "User mapped file" }, { kErrorConnectionRefused, "Connection refused" }, { kErrorGracefulDisconnect, "Graceful disconnect" }, { kErrorAddressAlreadyAssociated, "Address already associated" }, { kErrorAddressNotAssociated, "Address not associated" }, { kErrorConnectionInvalid, "Connected invalid" }, { kErrorConnectionActive, "Connection active" }, { kErrorNetworkUnreachable, "Network unreachable" }, { kErrorHostUnreachable, "Host unreachable" }, { kErrorProtocolUnreachable, "Protocol unreachable" }, { kErrorPortUnreachable, "Port unreachable" }, { kErrorRequestAborted, "Request aborted" }, { kErrorConnectionAborted, "Connection aborted" }, { kErrorRetry, "Retry" }, { kErrorConnectionCountLimit, "Connection count limit" }, { kErrorLoginTimeRestriction, "Login time restriction" }, { kErrorLoginWkstaRestriction, "Login wksta restriction" }, { kErrorIncorrectAddress, "Incorrect address" }, { kErrorAlreadyRegistered, "Already registered" }, { kErrorServiceNotFound, "Service not found" }, { kErrorNotAuthenticated, "Not authenticated" }, { kErrorNotLoggedOn, "Not logged on" }, { kErrorContinue, "Continue" }, { kErrorAlreadyInitialized, "Already initialised" }, { kErrorNoMoreDevices, "No more devices" }, { kErrorNoSuchSite, "No such site" }, { kErrorDomainControllerExists, "Domain controller exists" }, { kErrorOnlyIfConnected, "Only if connected" }, { kErrorOverrideNochanges, "Override no changes" }, { kErrorBadUserProfile, "Bad user profile" }, { kErrorNotSupportedOnSbs, "Not supported on SBS" }, { kErrorServerShutdownInProgress, "Server shutdown in progress" }, { kErrorHostDown, "Host down" }, { kErrorNonAccountSid, "Non account sid" }, { kErrorNonDomainSid, "Non domain sid" }, { kErrorApphelpBlock, "Apphelp block" }, { kErrorAccessDisabledByPolicy, "Access disabled by policy" }, { kErrorRegNatConsumption, "Reg nat consumption" }, { kErrorCscshareOffline, "CSC share offline" }, { kErrorPkinitFailure, "PK init failure" }, { kErrorSmartcardSubsystemFailure, "Smartcard subsystem failure" }, { kErrorDowngradeDetected, "Downgrade detected" }, { kSecESmartcardCertRevoked, "Smartcard cert revoked" }, { kSecEIssuingCaUntrusted, "Issuing CA untrusted" }, { kSecERevocationOfflineC, "Revocation offline" }, { kSecEPkinitClientFailur, "PK init client failure" }, { kSecESmartcardCertExpired, "Smartcard cert expired" }, { kErrorMachineLocked, "Machine locked" }, { kErrorCallbackSuppliedInvalidData, "Callback supplied invalid data" }, { kErrorSyncForegroundRefreshRequired, "Sync foreground refresh required" }, { kErrorDriverBlocked, "Driver blocked" }, { kErrorInvalidImportOfNonDll, "Invalid import of non DLL" }, { kErrorNotAllAssigned, "Not all assigned" }, { kErrorSomeNotMapped, "Some not mapped" }, { kErrorNoQuotasForAccount, "No quotas for account" }, { kErrorLocalUserSessionKey, "Local user session key" }, { kErrorNullLmPassword, "Null LM password" }, { kErrorUnknownRevision, "Unknown revision" }, { kErrorRevisionMismatch, "Revision mismatch" }, { kErrorInvalidOwner, "Invalid owner" }, { kErrorInvalidPrimaryGroup, "Invalid primary group" }, { kErrorNoImpersonationToken, "No impersonation token" }, { kErrorCantDisableMandatory, "Can't disable mandatory" }, { kErrorNoLogonServers, "No logon servers" }, { kErrorNoSuchLogonSession, "No such logon session" }, { kErrorNoSuchPrivilege, "No such privilege" }, { kErrorPrivilegeNotHeld, "Privilege not held" }, { kErrorInvalidAccountName, "Invalid account name" }, { kErrorUserExists, "User exists" }, { kErrorNoSuchUser, "No such user" }, { kErrorGroupExists, "Group exists" }, { kErrorNoSuchGroup, "No such group" }, { kErrorMemberInGroup, "Member in group" }, { kErrorMemberNotInGroup, "Member not in group" }, { kErrorLastAdmin, "Last admin" }, { kErrorWrongPassword, "Wrong password" }, { kErrorIllFormedPassword, "Ill formed password" }, { kErrorPasswordRestriction, "Password restriction" }, { kErrorLogonFailure, "Logon failure" }, { kErrorAccountRestriction, "Account restriction" }, { kErrorInvalidLogonHours, "Invalid logon hours" }, { kErrorInvalidWorkstation, "Invalid workstation" }, { kErrorPasswordExpired, "Password expired" }, { kErrorAccountDisabled, "Account disabled" }, { kErrorNoneMapped, "None mapped" }, { kErrorTooManyLuidsRequested, "Too many LUIDs requested" }, { kErrorLuidsExhausted, "LUIDs exhausted" }, { kErrorInvalidSubAuthority, "Invalid sub authority" }, { kErrorInvalidAcl, "Invalid ACL" }, { kErrorInvalidSid, "Invalid SID" }, { kErrorInvalidSecurityDescr, "Invalid security descr" }, { kErrorBadInheritanceAcl, "Bad inheritance ACL" }, { kErrorServerDisabled, "Server disabled" }, { kErrorServerNotDisabled, "Server not disabled" }, { kErrorInvalidIdAuthority, "Invalid ID authority" }, { kErrorAllottedSpaceExceeded, "Allotted space exceeded" }, { kErrorInvalidGroupAttributes, "Invalid group attributes" }, { kErrorBadImpersonationLevel, "Bad impersonation level" }, { kErrorCantOpenAnonymous, "Can't open anonymous" }, { kErrorBadValidationClass, "Bad validation class" }, { kErrorBadTokenType, "Bad token type" }, { kErrorNoSecurityOnObject, "No security on object" }, { kErrorCantAccessDomainInfo, "Can't access domain info" }, { kErrorInvalidServerState, "Invalid server state" }, { kErrorInvalidDomainState, "Invalid domain state" }, { kErrorInvalidDomainRole, "Invalid domain role" }, { kErrorNoSuchDomain, "No such domain" }, { kErrorDomainExists, "Domain exists" }, { kErrorDomainLimitExceeded, "Domain limit exceeded" }, { kErrorInternalDbCorruption, "Internal DB corruption" }, { kErrorInternalError, "Internal error" }, { kErrorGenericNotMapped, "Generic not mapped" }, { kErrorBadDescriptorFormat, "Bad descriptor format" }, { kErrorNotLogonProcess, "Not logon process" }, { kErrorLogonSessionExists, "Logon session exists" }, { kErrorNoSuchPackage, "No such package" }, { kErrorBadLogonSessionState, "Bad logon session state" }, { kErrorLogonSessionCollision, "Logon session collision" }, { kErrorInvalidLogonType, "Invalid logon type" }, { kErrorCannotImpersonate, "Cannot impersonate" }, { kErrorRxactInvalidState, "Rxact invalid state" }, { kErrorRxactCommitFailure, "Rxact commit failure" }, { kErrorSpecialAccount, "Special account" }, { kErrorSpecialGroup, "Special group" }, { kErrorSpecialUser, "Special user" }, { kErrorMembersPrimaryGroup, "Members primary group" }, { kErrorTokenAlreadyInUse, "Token already in use" }, { kErrorNoSuchAlias, "No such alias" }, { kErrorMemberNotInAlias, "Member not in alias" }, { kErrorMemberInAlias, "Member in alias" }, { kErrorAliasExists, "Alias exists" }, { kErrorLogonNotGranted, "Logon not granted" }, { kErrorTooManySecrets, "Too many secrets" }, { kErrorSecretTooLong, "Secret too long" }, { kErrorInternalDbError, "Internal DB error" }, { kErrorTooManyContextIds, "Too many context IDs" }, { kErrorLogonTypeNotGranted, "Logon type not granted" }, { kErrorNtCrossEncryptionRequired, "NT cross encryption required" }, { kErrorNoSuchMember, "No such member" }, { kErrorInvalidMember, "Invalid member" }, { kErrorTooManySids, "Too many SIDs" }, { kErrorLmCrossEncryptionRequired, "LM cross encryption required" }, { kErrorNoInheritance, "No inheritance" }, { kErrorFileCorrupt, "File corrupt" }, { kErrorDiskCorrupt, "Disk corrupt" }, { kErrorNoUserSessionKey, "No user session key" }, { kErrorLicenseQuotaExceeded, "Licence quota exceeded" }, { kErrorWrongTargetName, "Wrong target name" }, { kErrorMutualAuthFailed, "Mutual auth failed" }, { kErrorTimeSkew, "Time skew" }, { kErrorCurrentDomainNotAllowed, "Current domain not allowed" }, { kErrorInvalidWindowHandle, "Invalid window handle" }, { kErrorInvalidMenuHandle, "Invalid menu handle" }, { kErrorInvalidCursorHandle, "Invalid cursor handle" }, { kErrorInvalidAccelHandle, "Invalid accel handle" }, { kErrorInvalidHookHandle, "Invalid hook handle" }, { kErrorInvalidDwpHandle, "Invalid DWP handle" }, { kErrorTlwWithWschild, "TLW with wschild" }, { kErrorCannotFindWndClass, "Cannot find WND class" }, { kErrorWindowOfOtherThread, "Window of other thread" }, { kErrorHotkeyAlreadyRegistered, "Hotkey already registered" }, { kErrorClassAlreadyExists, "Class already exists" }, { kErrorClassDoesNotExist, "Class does not exist" }, { kErrorClassHasWindows, "Class has windows" }, { kErrorInvalidIndex, "Invalid index" }, { kErrorInvalidIconHandle, "Invalid icon handle" }, { kErrorPrivateDialogIndex, "Private dialog index" }, { kErrorListboxIdNotFound, "Listbox ID not found" }, { kErrorNoWildcardCharacters, "No wildcard characters" }, { kErrorClipboardNotOpen, "Clipboard not open" }, { kErrorHotkeyNotRegistered, "Hotkey not registered" }, { kErrorWindowNotDialog, "Window not dialog" }, { kErrorControlIdNotFound, "Control ID not found" }, { kErrorInvalidComboboxMessage, "Invalid combobox message" }, { kErrorWindowNotCombobox, "Window not combobox" }, { kErrorInvalidEditHeight, "Invalid edit height" }, { kErrorDcNotFound, "DC not found" }, { kErrorInvalidHookFilter, "Invalid hook filter" }, { kErrorInvalidFilterProc, "Invalid filter proc" }, { kErrorHookNeedsHmod, "Hook needs HMOD" }, { kErrorGlobalOnlyHook, "Global only hook" }, { kErrorJournalHookSet, "Journal hook set" }, { kErrorHookNotInstalled, "Hook not installed" }, { kErrorInvalidLbMessage, "Invalid LB message" }, { kErrorSetcountOnBadLb, "Setcount on bad LB" }, { kErrorLbWithoutTabstops, "LB without tabstops" }, { kErrorDestroyObjectOfOtherThread, "Destroy object of other thread" }, { kErrorChildWindowMenu, "Child window menu" }, { kErrorNoSystemMenu, "No system menu" }, { kErrorInvalidMsgboxStyle, "Invalid msgbox style" }, { kErrorInvalidSpiValue, "Invalid SPI value" }, { kErrorScreenAlreadyLocked, "Screen already locked" }, { kErrorHwndsHaveDiffParent, "HWNDs have different parent" }, { kErrorNotChildWindow, "Not child window" }, { kErrorInvalidGwCommand, "Invalid GW command" }, { kErrorInvalidThreadId, "Invalid thread ID" }, { kErrorNonMdichildWindow, "Non MDI child window" }, { kErrorPopupAlreadyActive, "Popup already active" }, { kErrorNoScrollbars, "No scrollbars" }, { kErrorInvalidScrollbarRange, "Invalid scrollbar range" }, { kErrorInvalidShowwinCommand, "Invalid showwin command" }, { kErrorNoSystemResources, "No system resources" }, { kErrorNonpagedSystemResources, "Nonpaged system resources" }, { kErrorPagedSystemResources, "Paged system resources" }, { kErrorWorkingSetQuota, "Working set quota" }, { kErrorPagefileQuota, "Pagefile quota" }, { kErrorCommitmentLimit, "Commitment limit" }, { kErrorMenuItemNotFound, "Menu item not found" }, { kErrorInvalidKeyboardHandle, "Invalid keyboard handle" }, { kErrorHookTypeNotAllowed, "Hook type not allowed" }, { kErrorRequiresInteractiveWindowstation, "Requires interactive windowstation" }, { kErrorTimeout, "Timeout" }, { kErrorInvalidMonitorHandle, "Invalid monitor handle" }, { kErrorEventlogFileCorrupt, "Eventlog file corrupt" }, { kErrorEventlogCantStart, "Eventlog can't start" }, { kErrorLogFileFull, "Log file full" }, { kErrorEventlogFileChanged, "Eventlog file changed" }, { kErrorInstallServiceFailure, "Install service failure" }, { kErrorInstallUserexit, "Install userexit" }, { kErrorInstallFailure, "Install failure" }, { kErrorInstallSuspend, "Install suspend" }, { kErrorUnknownProduct, "Unknown product" }, { kErrorUnknownFeature, "Unknown feature" }, { kErrorUnknownComponent, "Unknown component" }, { kErrorUnknownProperty, "Unknown property" }, { kErrorInvalidHandleState, "Invalid handle state" }, { kErrorBadConfiguration, "Bad configuration" }, { kErrorIndexAbsent, "Index absent" }, { kErrorInstallSourceAbsent, "Install source absent" }, { kErrorInstallPackageVersion, "Install package version" }, { kErrorProductUninstalled, "Product uninstalled" }, { kErrorBadQuerySyntax, "Bad query syntax" }, { kErrorInvalidField, "Invalid field" }, { kErrorDeviceRemoved, "Device removed" }, { kErrorInstallAlreadyRunning, "Install already running" }, { kErrorInstallPackageOpenFailed, "Install package open failed" }, { kErrorInstallPackageInvalid, "Install package invalid" }, { kErrorInstallUiFailure, "Install UI failure" }, { kErrorInstallLogFailure, "Install log failure" }, { kErrorInstallLanguageUnsupported, "Install language unsupported" }, { kErrorInstallTransformFailure, "Install transform failure" }, { kErrorInstallPackageRejected, "Install package rejected" }, { kErrorFunctionNotCalled, "Function not called" }, { kErrorFunctionFailed, "Function failed" }, { kErrorInvalidTable, "Invalid table" }, { kErrorDatatypeMismatch, "Datatype mismatch" }, { kErrorUnsupportedType, "Unsupported type" }, { kErrorCreateFailed, "Create failed" }, { kErrorInstallTempUnwritable, "Install temp unwritable" }, { kErrorInstallPlatformUnsupported, "Install platform unsupported" }, { kErrorInstallNotused, "Install notused" }, { kErrorPatchPackageOpenFailed, "Patch package open failed" }, { kErrorPatchPackageInvalid, "Patch package invalid" }, { kErrorPatchPackageUnsupported, "Patch package unsupported" }, { kErrorProductVersion, "Product version" }, { kErrorInvalidCommandLine, "Invalid command line" }, { kErrorInstallRemoteDisallowed, "Install remote disallowed" }, { kErrorSuccessRebootInitiated, "Success reboot initiated" }, { kErrorPatchTargetNotFound, "Patch target not found" }, { kErrorPatchPackageRejected, "Patch package rejected" }, { kErrorInstallTransformRejected, "Install transform rejected" }, { kRpcSInvalidStringBinding, "RPC S Invalid string binding" }, { kRpcSWrongKindOfBinding, "RPC S Wrong kind of binding" }, { kRpcSInvalidBinding, "RPC S Invalid binding" }, { kRpcSProtseqNotSupported, "RPC S Protseq not supported" }, { kRpcSInvalidRpcProtseq, "RPC S Invalid RPC protseq" }, { kRpcSInvalidStringUuid, "RPC S Invalid string UUID" }, { kRpcSInvalidEndpointFormat, "RPC S Invalid endpoint format" }, { kRpcSInvalidNetAddr, "RPC S Invalid net addr" }, { kRpcSNoEndpointFound, "RPC S No endpoint found" }, { kRpcSInvalidTimeout, "RPC S Invalid timeout" }, { kRpcSObjectNotFound, "RPC S Object not found" }, { kRpcSAlreadyRegistered, "RPC S Already registered" }, { kRpcSTypeAlreadyRegistered, "RPC S Type already registered" }, { kRpcSAlreadyListening, "RPC S Already listening" }, { kRpcSNoProtseqsRegistered, "RPC S Not protseqs registered" }, { kRpcSNotListening, "RPC S Not listening" }, { kRpcSUnknownMgrType, "RPC S Unknown mgr type" }, { kRpcSUnknownIf, "RPC S Unknown IF" }, { kRpcSNoBindings, "RPC S No bindings" }, { kRpcSNoProtseqs, "RPC S Not protseqs" }, { kRpcSCantCreateEndpoint, "RPC S Can't create endpoint" }, { kRpcSOutOfResources, "RPC S Out of resources" }, { kRpcSServerUnavailable, "RPC S Server unavailable" }, { kRpcSServerTooBusy, "RPC S Server too busy" }, { kRpcSInvalidNetworkOptions, "RPC S Invalid network options" }, { kRpcSNoCallActive, "RPC S No call active" }, { kRpcSCallFailed, "RPC S Call failed" }, { kRpcSCallFailedDne, "RPC S Call failed DNE" }, { kRpcSProtocolError, "RPC S Protocol error" }, { kRpcSUnsupportedTransSyn, "RPC S Unsupported trans syn" }, { kRpcSUnsupportedType, "RPC S Unsupported type" }, { kRpcSInvalidTag, "RPC S Invalid tag" }, { kRpcSInvalidBound, "RPC S Invalid bound" }, { kRpcSNoEntryName, "RPC S No entry name" }, { kRpcSInvalidNameSyntax, "RPC S Invalid name syntax" }, { kRpcSUnsupportedNameSyntax, "RPC S Unsupported name syntax" }, { kRpcSUuidNoAddress, "RPC S UUID no address" }, { kRpcSDuplicateEndpoint, "RPC S Duplicate endpoint" }, { kRpcSUnknownAuthnType, "RPC S Unknown authn type" }, { kRpcSMaxCallsTooSmall, "RPC S Max calls too small" }, { kRpcSStringTooLong, "RPC S String too long" }, { kRpcSProtseqNotFound, "RPC S Protseq not found" }, { kRpcSProcnumOutOfRange, "RPC S Procnum out of range" }, { kRpcSBindingHasNoAuth, "RPC S Binding has no auth" }, { kRpcSUnknownAuthnService, "RPC S Unknown authn service" }, { kRpcSUnknownAuthnLevel, "RPC S Unknown authn level" }, { kRpcSInvalidAuthIdentity, "RPC S Invalid auth identity" }, { kRpcSUnknownAuthzService, "RPC S Unknown authz service" }, { kEptSInvalidEntry, "EPT S Invalid entry" }, { kEptSCantPerformOp, "EPT S Can't perform op" }, { kEptSNotRegistered, "EPT S Not registered" }, { kRpcSNothingToExport, "RPC S Nothing to export" }, { kRpcSIncompleteName, "RPC S Incomplete name" }, { kRpcSInvalidVersOption, "RPC S Invalid vers option" }, { kRpcSNoMoreMembers, "RPC S No more members" }, { kRpcSNotAllObjsUnexported, "RPC S Not all objs unexported" }, { kRpcSInterfaceNotFound, "RPC S Interface not found" }, { kRpcSEntryAlreadyExists, "RPC S Entry already exists" }, { kRpcSEntryNotFound, "RPC S Entry not found" }, { kRpcSNameServiceUnavailable, "RPC S Name service unavailable" }, { kRpcSInvalidNafId, "RPC S Invalid naf ID" }, { kRpcSCannotSupport, "RPC S Cannot support" }, { kRpcSNoContextAvailable, "RPC S No context available" }, { kRpcSInternalError, "RPC S Internal error" }, { kRpcSZeroDivide, "RPC S Zero divide" }, { kRpcSAddressError, "RPC S Address error" }, { kRpcSFpDivZero, "RPC S FP div zero" }, { kRpcSFpUnderflow, "RPC S FP Underflow" }, { kRpcSFpOverflow, "RPC S Overflow" }, { kRpcXNoMoreEntries, "RPC X No more entries" }, { kRpcXSsCharTransOpenFail, "RPC X SS char trans open fail" }, { kRpcXSsCharTransShortFile, "RPC X SS char trans short file" }, { kRpcXSsInNullContext, "RPC S SS in null context" }, { kRpcXSsContextDamaged, "RPC X SS context damaged" }, { kRpcXSsHandlesMismatch, "RPC X SS handles mismatch" }, { kRpcXSsCannotGetCallHandle, "RPC X SS cannot get call handle" }, { kRpcXNullRefPointer, "RPC X Null ref pointer" }, { kRpcXEnumValueOutOfRange, "RPC X enum value out of range" }, { kRpcXByteCountTooSmall, "RPC X byte count too small" }, { kRpcXBadStubData, "RPC X bad stub data" }, { kErrorInvalidUserBuffer, "Invalid user buffer" }, { kErrorUnrecognizedMedia, "Unrecognised media" }, { kErrorNoTrustLsaSecret, "No trust lsa secret" }, { kErrorNoTrustSamAccount, "No trust sam account" }, { kErrorTrustedDomainFailure, "Trusted domain failure" }, { kErrorTrustedRelationshipFailure, "Trusted relationship failure" }, { kErrorTrustFailure, "Trust failure" }, { kRpcSCallInProgress, "RPC S call in progress" }, { kErrorNetlogonNotStarted, "Error netlogon not started" }, { kErrorAccountExpired, "Account expired" }, { kErrorRedirectorHasOpenHandles, "Redirector has open handles" }, { kErrorPrinterDriverAlreadyInstalled, "Printer driver already installed" }, { kErrorUnknownPort, "Unknown port" }, { kErrorUnknownPrinterDriver, "Unknown printer driver" }, { kErrorUnknownPrintprocessor, "Unknown printprocessor" }, { kErrorInvalidSeparatorFile, "Invalid separator file" }, { kErrorInvalidPriority, "Invalid priority" }, { kErrorInvalidPrinterName, "Invalid printer name" }, { kErrorPrinterAlreadyExists, "Printer already exists" }, { kErrorInvalidPrinterCommand, "Invalid printer command" }, { kErrorInvalidDatatype, "Invalid datatype" }, { kErrorInvalidEnvironment, "Invalid environment" }, { kRpcSNoMoreBindings, "RPC S no more bindings" }, { kErrorNologonInterdomainTrustAccount, "Nologon interdomain trust account" }, { kErrorNologonWorkstationTrustAccount, "Nologon workstation trust account" }, { kErrorNologonServerTrustAccount, "Nologon server trust account" }, { kErrorDomainTrustInconsistent, "Domain trust inconsistent" }, { kErrorServerHasOpenHandles, "Server has open handles" }, { kErrorResourceDataNotFound, "Resource data not found" }, { kErrorResourceTypeNotFound, "Resource type not found" }, { kErrorResourceNameNotFound, "Resource name not found" }, { kErrorResourceLangNotFound, "Resource lang not found" }, { kErrorNotEnoughQuota, "Not enough quota" }, { kRpcSNoInterfaces, "RPC S no interfaces" }, { kRpcSCallCancelled, "RPC S Call cancelled" }, { kRpcSBindingIncomplete, "RPC S Binding incomplete" }, { kRpcSCommFailure, "RPC S Comm failure" }, { kRpcSUnsupportedAuthnLevel, "RPC S Unsupported authn level" }, { kRpcSNoPrincName, "RPC S No princ name" }, { kRpcSNotRpcError, "RPC S Not RPC error" }, { kRpcSUuidLocalOnly, "RPC U UUID local only" }, { kRpcSSecPkgError, "RPC S Sec pkg error" }, { kRpcSNotCancelled, "RPC S Not cancelled" }, { kRpcXInvalidEsAction, "RPC X Invalid ES action" }, { kRpcXWrongEsVersion, "RPC X Wrong ES version" }, { kRpcXWrongStubVersion, "RPC X Wrong stub version" }, { kRpcXInvalidPipeObject, "RPC X Invalid pipe object" }, { kRpcXWrongPipeOrder, "RPC X Wrong pipe order" }, { kRpcXWrongPipeVersion, "RPC X Wrong pipe version" }, { kRpcSGroupMemberNotFound, "RPC S group member not found" }, { kEptSCantCreate, "EPT S Can't create" }, { kRpcSInvalidObject, "RPC S Invalid object" }, { kErrorInvalidTime, "Invalid time" }, { kErrorInvalidFormName, "Invalid form name" }, { kErrorInvalidFormSize, "Invalid form size" }, { kErrorAlreadyWaiting, "Already waiting" }, { kErrorPrinterDeleted, "Printer deleted" }, { kErrorInvalidPrinterState, "Invalid printer state" }, { kErrorPasswordMustChange, "Password must change" }, { kErrorDomainControllerNotFound, "Domain controller not found" }, { kErrorAccountLockedOut, "Account locked out" }, { kOrInvalidOxid, "OR Invalid OXID" }, { kOrInvalidOid, "OR Invalid OID" }, { kOrInvalidSet, "OR Invalid set" }, { kRpcSSendIncomplete, "RPC S Send incomplete" }, { kRpcSInvalidAsyncHandle, "RPC S Invalid async handle" }, { kRpcSInvalidAsyncCall, "RPC S Invalid async call" }, { kRpcXPipeClosed, "RPC X Pipe closed" }, { kRpcXPipeDisciplineError, "RPC X Pipe discipline error" }, { kRpcXPipeEmpty, "RPC X Pipe empty" }, { kErrorNoSitename, "No sitename" }, { kErrorCantAccessFile, "Can't access file" }, { kErrorCantResolveFilename, "Can't resolve filename" }, { kRpcSEntryTypeMismatch, "RPC S Entry type mismatch" }, { kRpcSNotAllObjsExported, "RPC S Not all objs exported" }, { kRpcSInterfaceNotExported, "RPC S Interface not exported" }, { kRpcSProfileNotAdded, "RPC S Profile not added" }, { kRpcSPrfEltNotAdded, "RPC S PRF ELT not added" }, { kRpcSPrfEltNotRemoved, "RPC S PRF ELT not removed" }, { kRpcSGrpEltNotAdded, "RPC S GRP ELT not added" }, { kRpcSGrpEltNotRemoved, "RPC S GRP ELT not removed" }, { kErrorKmDriverBlocked, "KM driver blocked" }, { kErrorContextExpired, "Context expired" }, { kErrorInvalidPixelFormat, "Invalid pixel format" }, { kErrorBadDriver, "Bad driver" }, { kErrorInvalidWindowStyle, "Invalid window style" }, { kErrorMetafileNotSupported, "Metafile not supported" }, { kErrorTransformNotSupported, "Transform not supported" }, { kErrorClippingNotSupported, "Clipping not supported" }, { kErrorInvalidCmm, "Invalid CMM" }, { kErrorInvalidProfile, "Invalid profile" }, { kErrorTagNotFound, "Tag not found" }, { kErrorTagNotPresent, "Tag not present" }, { kErrorDuplicateTag, "Duplicate tag" }, { kErrorProfileNotAssociatedWithDevice, "Profile not associated with device" }, { kErrorProfileNotFound, "Profile not found" }, { kErrorInvalidColorspace, "Invalid colorspace" }, { kErrorIcmNotEnabled, "ICM not enabled" }, { kErrorDeletingIcmXform, "Deleting ICM xform" }, { kErrorInvalidTransform, "Invalid transform" }, { kErrorColorspaceMismatch, "Colorspace mismatch" }, { kErrorInvalidColorindex, "Invalid colorindex" }, { kErrorConnectedOtherPassword, "Connected other password" }, { kErrorConnectedOtherPasswordDefault, "Connected other password default" }, { kErrorBadUsername, "Bad username" }, { kErrorNotConnected, "Not connected" }, { kErrorOpenFiles, "Open files" }, { kErrorActiveConnections, "Active connections" }, { kErrorDeviceInUse, "Device in use" }, { kErrorUnknownPrintMonitor, "Unknown print monitor" }, { kErrorPrinterDriverInUse, "Printer driver in use" }, { kErrorSpoolFileNotFound, "Spool file not found" }, { kErrorSplNoStartdoc, "SPL no startdoc" }, { kErrorSplNoAddjob, "SPL no addjob" }, { kErrorPrintProcessorAlreadyInstalled, "Print processor already installed" }, { kErrorPrintMonitorAlreadyInstalled, "Print monitor already installed" }, { kErrorInvalidPrintMonitor, "Invalid print monitor" }, { kErrorPrintMonitorInUse, "Print monitor in use" }, { kErrorPrinterHasJobsQueued, "Printer has jobs queued" }, { kErrorSuccessRebootRequired, "Success reboot required" }, { kErrorSuccessRestartRequired, "Success restart required" }, { kErrorPrinterNotFound, "Printer not found" }, { kErrorPrinterDriverWarned, "Printer driver warned" }, { kErrorPrinterDriverBlocked, "Printer driver blocked" }, { kErrorWinsInternal, "Wins internal" }, { kErrorCanNotDelLocalWins, "Can not del local wins" }, { kErrorStaticInit, "Static init" }, { kErrorIncBackup, "Inc backup" }, { kErrorFullBackup, "Full backup" }, { kErrorRecNonExistent, "Rec not existent" }, { kErrorRplNotAllowed, "RPL not allowed" }, { kErrorDhcpAddressConflict, "DHCP address conflict" }, { kErrorWmiGuidNotFound, "WMU GUID not found" }, { kErrorWmiInstanceNotFound, "WMI instance not found" }, { kErrorWmiItemidNotFound, "WMI ItemID not found" }, { kErrorWmiTryAgain, "WMI try again" }, { kErrorWmiDpNotFound, "WMI DP not found" }, { kErrorWmiUnresolvedInstanceRef, "WMI unresolved instance ref" }, { kErrorWmiAlreadyEnabled, "WMU already enabled" }, { kErrorWmiGuidDisconnected, "WMU GUID disconnected" }, { kErrorWmiServerUnavailable, "WMI server unavailable" }, { kErrorWmiDpFailed, "WMI DP failed" }, { kErrorWmiInvalidMof, "WMI invalid MOF" }, { kErrorWmiInvalidReginfo, "WMI invalid reginfo" }, { kErrorWmiAlreadyDisabled, "WMI already disabled" }, { kErrorWmiReadOnly, "WMI read only" }, { kErrorWmiSetFailure, "WMI set failure" }, { kErrorInvalidMedia, "Invalid media" }, { kErrorInvalidLibrary, "Invalid library" }, { kErrorInvalidMediaPool, "Invalid media pool" }, { kErrorDriveMediaMismatch, "Drive media mismatch" }, { kErrorMediaOffline, "Media offline" }, { kErrorLibraryOffline, "Library offline" }, { kErrorEmpty, "Empty" }, { kErrorNotEmpty, "Not empty" }, { kErrorMediaUnavailable, "Media unavailable" }, { kErrorResourceDisabled, "Resource disabled" }, { kErrorInvalidCleaner, "Invalid cleaner" }, { kErrorUnableToClean, "Unable to clean" }, { kErrorObjectNotFound, "Object not found" }, { kErrorDatabaseFailure, "Database failure" }, { kErrorDatabaseFull, "Database full" }, { kErrorMediaIncompatible, "Media incompatible" }, { kErrorResourceNotPresent, "Resource not present" }, { kErrorInvalidOperation, "Invalid operation" }, { kErrorMediaNotAvailable, "Media not available" }, { kErrorDeviceNotAvailable, "Device not available" }, { kErrorRequestRefused, "Request refused" }, { kErrorInvalidDriveObject, "Invalid drive object" }, { kErrorLibraryFull, "Library full" }, { kErrorMediumNotAccessible, "Medium not accessible" }, { kErrorUnableToLoadMedium, "Unable to load medium" }, { kErrorUnableToInventoryDrive, "Unable to inventory drive" }, { kErrorUnableToInventorySlot, "Unable to inventory slot" }, { kErrorUnableToInventoryTransport, "Unable to inventory transport" }, { kErrorTransportFull, "Transport full" }, { kErrorControllingIeport, "Controlling ieport" }, { kErrorUnableToEjectMountedMedia, "Unable to eject mounted media" }, { kErrorCleanerSlotSet, "Cleaner slot set" }, { kErrorCleanerSlotNotSet, "Cleaner slot not set" }, { kErrorCleanerCartridgeSpent, "Cleaner cartridge spent" }, { kErrorUnexpectedOmid, "Unexpected omid" }, { kErrorCantDeleteLastItem, "Can't delete last item" }, { kErrorMessageExceedsMaxSize, "Message exceeds max size" }, { kErrorVolumeContainsSysFiles, "Volume contains sys files" }, { kErrorIndigenousType, "Indigenous type" }, { kErrorNoSupportingDrives, "No supporting drives" }, { kErrorCleanerCartridgeInstalled, "Cleaner cartridge installed" }, { kErrorFileOffline, "Fill offline" }, { kErrorRemoteStorageNotActive, "Remote storage not active" }, { kErrorRemoteStorageMediaError, "Remote storage media error" }, { kErrorNotAReparsePoint, "Not a reparse point" }, { kErrorReparseAttributeConflict, "Reparse attribute conflict" }, { kErrorInvalidReparseData, "Invalid reparse data" }, { kErrorReparseTagInvalid, "Reparse tag invalid" }, { kErrorReparseTagMismatch, "Reparse tag mismatch" }, { kErrorVolumeNotSisEnabled, "Volume not sis enabled" }, { kErrorDependentResourceExists, "Dependent resource exists" }, { kErrorDependencyNotFound, "Dependency not found" }, { kErrorDependencyAlreadyExists, "Dependency already exists" }, { kErrorResourceNotOnline, "Resource not online" }, { kErrorHostNodeNotAvailable, "Host node not available" }, { kErrorResourceNotAvailable, "Resource not available" }, { kErrorResourceNotFound, "Resource not found" }, { kErrorShutdownCluster, "Shutdown cluster" }, { kErrorCantEvictActiveNode, "Can't evict active node" }, { kErrorObjectAlreadyExists, "Object already exists" }, { kErrorObjectInList, "Object in list" }, { kErrorGroupNotAvailable, "Group not available" }, { kErrorGroupNotFound, "Group not found" }, { kErrorGroupNotOnline, "Group not online" }, { kErrorHostNodeNotResourceOwner, "Host node not resource owner" }, { kErrorHostNodeNotGroupOwner, "Host node not group owner" }, { kErrorResmonCreateFailed, "Resmon create failed" }, { kErrorResmonOnlineFailed, "Resmon online failed" }, { kErrorResourceOnline, "Resource online" }, { kErrorQuorumResource, "Quorum resource" }, { kErrorNotQuorumCapable, "Not quorum capable" }, { kErrorClusterShuttingDown, "Cluster shutting down" }, { kErrorInvalidState, "Invalid state" }, { kErrorResourcePropertiesStored, "Resource properties stored" }, { kErrorNotQuorumClass, "Not quorum class" }, { kErrorCoreResource, "Core resource" }, { kErrorQuorumResourceOnlineFailed, "Quorum resource online failed" }, { kErrorQuorumlogOpenFailed, "Quorumlog open failed" }, { kErrorClusterlogCorrupt, "Clusterlog corrupt" }, { kErrorClusterlogRecordExceedsMaxsize, "Clusterlog record exceeds maxsize" }, { kErrorClusterlogExceedsMaxsize, "Clusterlog exceeds maxsize" }, { kErrorClusterlogChkpointNotFound, "Clusterlog chkpoint not found" }, { kErrorClusterlogNotEnoughSpace, "Clusterlog not enough space" }, { kErrorQuorumOwnerAlive, "Quorum owner alive" }, { kErrorNetworkNotAvailable, "Network not available" }, { kErrorNodeNotAvailable, "Node not available" }, { kErrorAllNodesNotAvailable, "All nodes not available" }, { kErrorResourceFailed, "Resource failed" }, { kErrorClusterInvalidNode, "Cluster invalid node" }, { kErrorClusterNodeExists, "Cluster node exists" }, { kErrorClusterJoinInProgress, "Cluster join in progress" }, { kErrorClusterNodeNotFound, "Cluster node not found" }, { kErrorClusterLocalNodeNotFound, "Cluster local node not found" }, { kErrorClusterNetworkExists, "Cluster network exists" }, { kErrorClusterNetworkNotFound, "Cluster network not found" }, { kErrorClusterNetinterfaceExists, "Cluster netinterface exists" }, { kErrorClusterNetinterfaceNotFound, "Cluster netinterface not found" }, { kErrorClusterInvalidRequest, "Cluster invalid request" }, { kErrorClusterInvalidNetworkProvider, "Cluster invalid network provider" }, { kErrorClusterNodeDown, "Cluster node down" }, { kErrorClusterNodeUnreachable, "Cluster node unreachable" }, { kErrorClusterNodeNotMember, "Cluster node not member" }, { kErrorClusterJoinNotInProgress, "Cluster join not in progress" }, { kErrorClusterInvalidNetwork, "Cluster invalid network" }, { kErrorClusterNodeUp, "Cluster node up" }, { kErrorClusterIpaddrInUse, "Cluster ipaddr in use" }, { kErrorClusterNodeNotPaused, "Cluster node not paused" }, { kErrorClusterNoSecurityContext, "Cluster no security context" }, { kErrorClusterNetworkNotInternal, "Cluster network not internal" }, { kErrorClusterNodeAlreadyUp, "Cluster node already up" }, { kErrorClusterNodeAlreadyDown, "Cluster node already down" }, { kErrorClusterNetworkAlreadyOnline, "Cluster network already online" }, { kErrorClusterNetworkAlreadyOffline, "Cluster network already offline" }, { kErrorClusterNodeAlreadyMember, "Cluster node already member" }, { kErrorClusterLastInternalNetwork, "Cluster last internal network" }, { kErrorClusterNetworkHasDependents, "Cluster network has dependents" }, { kErrorInvalidOperationOnQuorum, "Invalid operation on quorum" }, { kErrorDependencyNotAllowed, "Dependency not allowed" }, { kErrorClusterNodePaused, "Cluster node paused" }, { kErrorNodeCantHostResource, "Node can't host resource" }, { kErrorClusterNodeNotReady, "Cluster node not ready" }, { kErrorClusterNodeShuttingDown, "Cluster node shutting down" }, { kErrorClusterJoinAborted, "Cluster join aborted" }, { kErrorClusterIncompatibleVersions, "Cluster incompatible versions" }, { kErrorClusterMaxnumOfResourcesExceeded, "Cluster maxnum of resources exceeded" }, { kErrorClusterSystemConfigChanged, "Cluster system config changed" }, { kErrorClusterResourceTypeNotFound, "Cluster resource type not found" }, { kErrorClusterRestypeNotSupported, "Cluster restype not supported" }, { kErrorClusterResnameNotFound, "Cluster resname not found" }, { kErrorClusterNoRpcPackagesRegistered, "Cluster no RPC packages registered" }, { kErrorClusterOwnerNotInPreflist, "Cluster owner not in preflist" }, { kErrorClusterDatabaseSeqmismatch, "Cluster database seqmismatch" }, { kErrorResmonInvalidState, "Resmon invalid state" }, { kErrorClusterGumNotLocker, "Cluster gum not locker" }, { kErrorQuorumDiskNotFound, "Quorum disk not found" }, { kErrorDatabaseBackupCorrupt, "Database backup corrupt" }, { kErrorClusterNodeAlreadyHasDfsRoot, "Cluster node already has DFS root" }, { kErrorResourcePropertyUnchangeable, "Resource property unchangeable" }, { kErrorClusterMembershipInvalidState, "Cluster membership invalid state" }, { kErrorClusterQuorumlogNotFound, "Cluster quorumlog not found" }, { kErrorClusterMembershipHalt, "Cluster membership halt" }, { kErrorClusterInstanceIdMismatch, "Cluster instance ID mismatch" }, { kErrorClusterNetworkNotFoundForIp, "Cluster network not found for IP" }, { kErrorClusterPropertyDataTypeMismatch, "Cluster property data type mismatch" }, { kErrorClusterEvictWithoutCleanup, "Cluster evict without cleanup" }, { kErrorClusterParameterMismatch, "Cluster parameter mismatch" }, { kErrorNodeCannotBeClustered, "Node cannot be clustered" }, { kErrorClusterWrongOsVersion, "Cluster wrong OS version" }, { kErrorClusterCantCreateDupClusterName, "Cluster can't create dup cluster name" }, { kErrorDecryptionFailed, "Decryption failed" }, { kErrorFileEncrypted, "File encrypted" }, { kErrorNoRecoveryPolicy, "No recovery policy" }, { kErrorNoEfs, "No EFS" }, { kErrorWrongEfs, "Wrong EFS" }, { kErrorNoUserKeys, "No user keys" }, { kErrorFileNotEncrypted, "File not encryped" }, { kErrorNotExportFormat, "Not export format" }, { kErrorFileReadOnly, "File read only" }, { kErrorDirEfsDisallowed, "Dir EFS disallowed" }, { kErrorEfsServerNotTrusted, "EFS server not trusted" }, { kErrorBadRecoveryPolicy, "Bad recovery policy" }, { kErrorEfsAlgBlobTooBig, "ETS alg blob too big" }, { kErrorVolumeNotSupportEfs, "Volume not support EFS" }, { kErrorEfsDisabled, "EFS disabled" }, { kErrorEfsVersionNotSupport, "EFS version not support" }, { kErrorNoBrowserServersFound, "No browser servers found" }, { kSchedEServiceNotLocalsystem, "Sched E service not localsystem" }, { kErrorCtxWinstationNameInvalid, "Ctx winstation name invalid" }, { kErrorCtxInvalidPd, "Ctx invalid PD" }, { kErrorCtxPdNotFound, "Ctx PD not found" }, { kErrorCtxWdNotFound, "Ctx WD not found" }, { kErrorCtxCannotMakeEventlogEntry, "Ctx cannot make eventlog entry" }, { kErrorCtxServiceNameCollision, "Ctx service name collision" }, { kErrorCtxClosePending, "Ctx close pending" }, { kErrorCtxNoOutbuf, "Ctx no outbuf" }, { kErrorCtxModemInfNotFound, "Ctx modem inf not found" }, { kErrorCtxInvalidModemname, "Ctx invalid modemname" }, { kErrorCtxModemResponseError, "Ctx modem response error" }, { kErrorCtxModemResponseTimeout, "Ctx modem response timeout" }, { kErrorCtxModemResponseNoCarrier, "Ctx modem response no carrier" }, { kErrorCtxModemResponseNoDialtone, "Ctx modem response no dial tone" }, { kErrorCtxModemResponseBusy, "Ctx modem response busy" }, { kErrorCtxModemResponseVoice, "Ctx modem response voice" }, { kErrorCtxTdError, "Ctx TD error" }, { kErrorCtxWinstationNotFound, "Ctx winstation not found" }, { kErrorCtxWinstationAlreadyExists, "Ctx winstation already exists" }, { kErrorCtxWinstationBusy, "Ctx winstation busy" }, { kErrorCtxBadVideoMode, "Ctx bad video mode" }, { kErrorCtxGraphicsInvalid, "Ctx graphics invalid" }, { kErrorCtxLogonDisabled, "Ctx logon disabled" }, { kErrorCtxNotConsole, "Ctx not console" }, { kErrorCtxClientQueryTimeout, "Ctx client query timeout" }, { kErrorCtxConsoleDisconnect, "Ctx console disconnect" }, { kErrorCtxConsoleConnect, "Ctx console connect" }, { kErrorCtxShadowDenied, "Ctx shadow denied" }, { kErrorCtxWinstationAccessDenied, "Ctx winstation access denied" }, { kErrorCtxInvalidWd, "Ctx invalid WD" }, { kErrorCtxShadowInvalid, "Ctx shadow invalid" }, { kErrorCtxShadowDisabled, "Ctx shadow disabled" }, { kErrorCtxClientLicenseInUse, "Ctx client licence in use" }, { kErrorCtxClientLicenseNotSet, "Ctx client licence not set" }, { kErrorCtxLicenseNotAvailable, "Ctx licence not available" }, { kErrorCtxLicenseClientInvalid, "Ctx licence client invalid" }, { kErrorCtxLicenseExpired, "Ctx licence expired" }, { kErrorCtxShadowNotRunning, "Ctx shadow not running" }, { kErrorCtxShadowEndedByModeChange, "Ctx shadow ended by mode change" }, { kFrsErrInvalidApiSequence, "FRS err invalid API sequence" }, { kFrsErrStartingService, "FRS err starting service" }, { kFrsErrStoppingService, "FRS err stopping service" }, { kFrsErrInternalApi, "FRS err internal API" }, { kFrsErrInternal, "FRS err internal" }, { kFrsErrServiceComm, "FRS err service comm" }, { kFrsErrInsufficientPriv, "FRS err insufficient priv" }, { kFrsErrAuthentication, "FRS err authentication" }, { kFrsErrParentInsufficientPriv, "FRS err parent insufficient priv" }, { kFrsErrParentAuthentication, "FRS err parent authentication" }, { kFrsErrChildToParentComm, "FRS err child to parent comm" }, { kFrsErrParentToChildComm, "FRS err parent to child comm" }, { kFrsErrSysvolPopulate, "FRS err sysvol populate" }, { kFrsErrSysvolPopulateTimeout, "FRS err sysvol populate timeout" }, { kFrsErrSysvolIsBusy, "FRS err sysvol is busy" }, { kFrsErrSysvolDemote, "FRS err sysvol demote" }, { kFrsErrInvalidServiceParameter, "FRS err invalid service parameter" }, { kErrorDsNotInstalled, "DS not installed" }, { kErrorDsMembershipEvaluatedLocally, "DS membership evaluated locally" }, { kErrorDsNoAttributeOrValue, "DS no attribute or value" }, { kErrorDsInvalidAttributeSyntax, "DS invalid attribute syntax" }, { kErrorDsAttributeTypeUndefined, "DS attribute type undefined" }, { kErrorDsAttributeOrValueExists, "DS attribute or value exists" }, { kErrorDsBusy, "DS busy" }, { kErrorDsUnavailable, "DS unavailable" }, { kErrorDsNoRidsAllocated, "DS no rids allocated" }, { kErrorDsNoMoreRids, "DS no more rids" }, { kErrorDsIncorrectRoleOwner, "DS incorrect role owner" }, { kErrorDsRidmgrInitError, "DS ridmgr init error" }, { kErrorDsObjClassViolation, "DS obj class violation" }, { kErrorDsCantOnNonLeaf, "DS can't on non leaf" }, { kErrorDsCantOnRdn, "DS can't on rnd" }, { kErrorDsCantModObjClass, "DS can't mod obj class" }, { kErrorDsCrossDomMoveError, "DS cross dom move error" }, { kErrorDsGcNotAvailable, "DS GC not available" }, { kErrorSharedPolicy, "Shared policy" }, { kErrorPolicyObjectNotFound, "Policy object not found" }, { kErrorPolicyOnlyInDs, "Policy only in DS" }, { kErrorPromotionActive, "Promotion active" }, { kErrorNoPromotionActive, "No promotion active" }, { kErrorDsOperationsError, "DS operations error" }, { kErrorDsProtocolError, "DS protocol error" }, { kErrorDsTimelimitExceeded, "DS timelimit exceeded" }, { kErrorDsSizelimitExceeded, "DS sizelimit exceeded" }, { kErrorDsAdminLimitExceeded, "DS admin limit exceeded" }, { kErrorDsCompareFalse, "DS compare false" }, { kErrorDsCompareTrue, "DS compare true" }, { kErrorDsAuthMethodNotSupported, "DS auth method not supported" }, { kErrorDsStrongAuthRequired, "DS strong auth required" }, { kErrorDsInappropriateAuth, "DS inappropriate auth" }, { kErrorDsAuthUnknown, "DS auth unknown" }, { kErrorDsReferral, "DS referral" }, { kErrorDsUnavailableCritExtension, "DS unavailable crit extension" }, { kErrorDsConfidentialityRequired, "DS confidentiality required" }, { kErrorDsInappropriateMatching, "DS inappropriate matching" }, { kErrorDsConstraintViolation, "DS constraint violation" }, { kErrorDsNoSuchObject, "DS no such object" }, { kErrorDsAliasProblem, "DS alias problem" }, { kErrorDsInvalidDnSyntax, "DS invalid dn syntax" }, { kErrorDsIsLeaf, "DS is leaf" }, { kErrorDsAliasDerefProblem, "DS alias deref problem" }, { kErrorDsUnwillingToPerform, "DS unwilling to perform" }, { kErrorDsLoopDetect, "DS loop detect" }, { kErrorDsNamingViolation, "DS naming violation" }, { kErrorDsObjectResultsTooLarge, "DS object results too large" }, { kErrorDsAffectsMultipleDsas, "DS affects multiple dsas" }, { kErrorDsServerDown, "DS server down" }, { kErrorDsLocalError, "DS local error" }, { kErrorDsEncodingError, "DS encoding error" }, { kErrorDsDecodingError, "DS decoding error" }, { kErrorDsFilterUnknown, "DS filter unknown" }, { kErrorDsParamError, "DS param error" }, { kErrorDsNotSupported, "DS not supported" }, { kErrorDsNoResultsReturned, "DS no results returned" }, { kErrorDsControlNotFound, "DS control not found" }, { kErrorDsClientLoop, "DS client loop" }, { kErrorDsReferralLimitExceeded, "DS referral limit exceeded" }, { kErrorDsSortControlMissing, "DS sort control missing" }, { kErrorDsOffsetRangeError, "DS offset range error" }, { kErrorDsRootMustBeNc, "DS root must be nc" }, { kErrorDsAddReplicaInhibited, "DS and replica inhibited" }, { kErrorDsAttNotDefInSchema, "DS att not def in schema" }, { kErrorDsMaxObjSizeExceeded, "DS max obj size exceeded" }, { kErrorDsObjStringNameExists, "DS obj string name exists" }, { kErrorDsNoRdnDefinedInSchema, "DS no rdn defined in schema" }, { kErrorDsRdnDoesntMatchSchema, "DS rdn doesn't match schema" }, { kErrorDsNoRequestedAttsFound, "DS no requested atts found" }, { kErrorDsUserBufferToSmall, "DS user buffer too small" }, { kErrorDsAttIsNotOnObj, "DS att is not on obj" }, { kErrorDsIllegalModOperation, "DS illegal mod operation" }, { kErrorDsObjTooLarge, "DS obj too large" }, { kErrorDsBadInstanceType, "DS bad instance type" }, { kErrorDsMasterdsaRequired, "DS masterdsa required" }, { kErrorDsObjectClassRequired, "DS object class required" }, { kErrorDsMissingRequiredAtt, "DS missing required att" }, { kErrorDsAttNotDefForClass, "DS att not def for class" }, { kErrorDsAttAlreadyExists, "DS att already exists" }, { kErrorDsCantAddAttValues, "DS can't add att values" }, { kErrorDsSingleValueConstraint, "DS single value constraint" }, { kErrorDsRangeConstraint, "DS range constraint" }, { kErrorDsAttValAlreadyExists, "DS att val already exists" }, { kErrorDsCantRemMissingAtt, "DS can't rem missing att" }, { kErrorDsCantRemMissingAttVal, "DS can't rem missing att val" }, { kErrorDsRootCantBeSubref, "DS root can't be subref" }, { kErrorDsNoChaining, "DS no chaining" }, { kErrorDsNoChainedEval, "DS no chained eval" }, { kErrorDsNoParentObject, "DS no parent object" }, { kErrorDsParentIsAnAlias, "DS parent is an alias" }, { kErrorDsCantMixMasterAndReps, "DS can't mix master and reps" }, { kErrorDsChildrenExist, "DS children exist" }, { kErrorDsObjNotFound, "DS obj not found" }, { kErrorDsAliasedObjMissing, "DS aliased obj missing" }, { kErrorDsBadNameSyntax, "DS bad name syntax" }, { kErrorDsAliasPointsToAlias, "DS alias points to alias" }, { kErrorDsCantDerefAlias, "DS can't redef alias" }, { kErrorDsOutOfScope, "DS out of scope" }, { kErrorDsObjectBeingRemoved, "DS object being removed" }, { kErrorDsCantDeleteDsaObj, "DS can't delete dsa obj" }, { kErrorDsGenericError, "DS generic error" }, { kErrorDsDsaMustBeIntMaster, "DS dsa must be int master" }, { kErrorDsClassNotDsa, "DS class not dsa" }, { kErrorDsInsuffAccessRights, "DS insuff access rights" }, { kErrorDsIllegalSuperior, "DS illegal superior" }, { kErrorDsAttributeOwnedBySam, "DS attribute owned by sam" }, { kErrorDsNameTooManyParts, "DS name too many parts" }, { kErrorDsNameTooLong, "DS name too long" }, { kErrorDsNameValueTooLong, "DS name value too long" }, { kErrorDsNameUnparseable, "DS name unparseable" }, { kErrorDsNameTypeUnknown, "DS name type unknown" }, { kErrorDsNotAnObject, "DS not an object" }, { kErrorDsSecDescTooShort, "DS sec desc too short" }, { kErrorDsSecDescInvalid, "DS sec desc invalid" }, { kErrorDsNoDeletedName, "DS no deleted name" }, { kErrorDsSubrefMustHaveParent, "DS subref must have parent" }, { kErrorDsNcnameMustBeNc, "DS ncname must be nc" }, { kErrorDsCantAddSystemOnly, "DS can't add system only" }, { kErrorDsClassMustBeConcrete, "DS class must be concrete" }, { kErrorDsInvalidDmd, "DS invalid dmd" }, { kErrorDsObjGuidExists, "DS obj GUID exists" }, { kErrorDsNotOnBacklink, "DS not on backlink" }, { kErrorDsNoCrossrefForNc, "DS no crossref for nc" }, { kErrorDsShuttingDown, "DS shutting down" }, { kErrorDsUnknownOperation, "DS unknown operation" }, { kErrorDsInvalidRoleOwner, "DS invalid role owner" }, { kErrorDsCouldntContactFsmo, "DS couldn't contact fsmo" }, { kErrorDsCrossNcDnRename, "DS cross nc dn rename" }, { kErrorDsCantModSystemOnly, "DS can't mod system only" }, { kErrorDsReplicatorOnly, "DS replicator only" }, { kErrorDsObjClassNotDefined, "DS obj class not defined" }, { kErrorDsObjClassNotSubclass, "DS obj class not subclass" }, { kErrorDsNameReferenceInvalid, "DS name reference invalid" }, { kErrorDsCrossRefExists, "DS cross ref exists" }, { kErrorDsCantDelMasterCrossref, "DS can't del master crossref" }, { kErrorDsSubtreeNotifyNotNcHead, "DS subtree notify not nc head" }, { kErrorDsNotifyFilterTooComplex, "DS notify filter too complex" }, { kErrorDsDupRdn, "DS dup rdn" }, { kErrorDsDupOid, "DS dup oid" }, { kErrorDsDupMapiId, "DS dup mapi ID" }, { kErrorDsDupSchemaIdGuid, "DS dup schema ID GUID" }, { kErrorDsDupLdapDisplayName, "DS dup LDAP display name" }, { kErrorDsSemanticAttTest, "DS semantic att test" }, { kErrorDsSyntaxMismatch, "DS syntax mismatch" }, { kErrorDsExistsInMustHave, "DS exists in must have" }, { kErrorDsExistsInMayHave, "DS exists in may have" }, { kErrorDsNonexistentMayHave, "DS nonexistent may have" }, { kErrorDsNonexistentMustHave, "DS nonexistent must have" }, { kErrorDsAuxClsTestFail, "DS aux cls test fail" }, { kErrorDsNonexistentPossSup, "DS nonexistent poss sup" }, { kErrorDsSubClsTestFail, "DS sub cls test fail" }, { kErrorDsBadRdnAttIdSyntax, "DS bad rdn att ID syntax" }, { kErrorDsExistsInAuxCls, "DS exists in aux cls" }, { kErrorDsExistsInSubCls, "DS exists in sub cls" }, { kErrorDsExistsInPossSup, "DS exists in poss sup" }, { kErrorDsRecalcschemaFailed, "DS recalcschema failed" }, { kErrorDsTreeDeleteNotFinished, "DS tree delete not finished" }, { kErrorDsCantDelete, "DS can't delete" }, { kErrorDsAttSchemaReqId, "DS att schema req ID" }, { kErrorDsBadAttSchemaSyntax, "DS bad att schema syntax" }, { kErrorDsCantCacheAtt, "DS can't cache att" }, { kErrorDsCantCacheClass, "DS can't cache class" }, { kErrorDsCantRemoveAttCache, "DS can't remove att cache" }, { kErrorDsCantRemoveClassCache, "DS can't remove class cache" }, { kErrorDsCantRetrieveDn, "DS can't retrieve DN" }, { kErrorDsMissingSupref, "DS missing supref" }, { kErrorDsCantRetrieveInstance, "DS can't retrieve instance" }, { kErrorDsCodeInconsistency, "DS code inconsistency" }, { kErrorDsDatabaseError, "DS database error" }, { kErrorDsGovernsidMissing, "DS governsid missing" }, { kErrorDsMissingExpectedAtt, "DS missing expected att" }, { kErrorDsNcnameMissingCrRef, "DS ncname missing cr ref" }, { kErrorDsSecurityCheckingError, "DS security checking error" }, { kErrorDsSchemaNotLoaded, "DS schema not loaded" }, { kErrorDsSchemaAllocFailed, "DS schema alloc failed" }, { kErrorDsAttSchemaReqSyntax, "DS att schema req syntax" }, { kErrorDsGcverifyError, "DS gcverify error" }, { kErrorDsDraSchemaMismatch, "DS dra schema mismatch" }, { kErrorDsCantFindDsaObj, "DS can't find dsa obj" }, { kErrorDsCantFindExpectedNc, "DS can't find expected nc" }, { kErrorDsCantFindNcInCache, "DS can't find nc in cache" }, { kErrorDsCantRetrieveChild, "DS can't retrieve child" }, { kErrorDsSecurityIllegalModify, "DS security illegal modify" }, { kErrorDsCantReplaceHiddenRec, "DS can't replace hidden rec" }, { kErrorDsBadHierarchyFile, "DS bad hierarchy file" }, { kErrorDsBuildHierarchyTableFailed, "DS build hierarchy table failed" }, { kErrorDsConfigParamMissing, "DS config param missing" }, { kErrorDsCountingAbIndicesFailed, "DS counting ab indices failed" }, { kErrorDsHierarchyTableMallocFailed, "DS hierarchy table malloc failed" }, { kErrorDsInternalFailure, "DS internal failure" }, { kErrorDsUnknownError, "DS unknown error" }, { kErrorDsRootRequiresClassTop, "DS root requires class top" }, { kErrorDsRefusingFsmoRoles, "DS refusing fmso roles" }, { kErrorDsMissingFsmoSettings, "DS missing fmso settings" }, { kErrorDsUnableToSurrenderRoles, "DS unable to surrender roles" }, { kErrorDsDraGeneric, "DS dra generic" }, { kErrorDsDraInvalidParameter, "DS dra invalid parameter" }, { kErrorDsDraBusy, "DS dra busy" }, { kErrorDsDraBadDn, "DS dra bad dn" }, { kErrorDsDraBadNc, "DS dra bad nc" }, { kErrorDsDraDnExists, "DS dra dn exists" }, { kErrorDsDraInternalError, "DS dra internal error" }, { kErrorDsDraInconsistentDit, "DS dra inconsistent dit" }, { kErrorDsDraConnectionFailed, "DS dra connection failed" }, { kErrorDsDraBadInstanceType, "DS dra bad instance type" }, { kErrorDsDraOutOfMem, "DS dra out of mem" }, { kErrorDsDraMailProblem, "DS dra mail problem" }, { kErrorDsDraRefAlreadyExists, "DS dra ref already exists" }, { kErrorDsDraRefNotFound, "DS dra ref not found" }, { kErrorDsDraObjIsRepSource, "DS dra obj is rep source" }, { kErrorDsDraDbError, "DS dra db error" }, { kErrorDsDraNoReplica, "DS dra no replica" }, { kErrorDsDraAccessDenied, "DS dra access denied" }, { kErrorDsDraNotSupported, "DS dra not supported" }, { kErrorDsDraRpcCancelled, "DS dra RPC cancelled" }, { kErrorDsDraSourceDisabled, "DS dra source disabled" }, { kErrorDsDraSinkDisabled, "DS dra sink disabled" }, { kErrorDsDraNameCollision, "DS dra name collision" }, { kErrorDsDraSourceReinstalled, "DS dra source reinstalled" }, { kErrorDsDraMissingParent, "DS dra missing parent" }, { kErrorDsDraPreempted, "DS dra preempted" }, { kErrorDsDraAbandonSync, "DS dra abandon sync" }, { kErrorDsDraShutdown, "DS dra shutdown" }, { kErrorDsDraIncompatiblePartialSet, "DS dra incompatible partial set" }, { kErrorDsDraSourceIsPartialReplica, "DS dra source is partial replica" }, { kErrorDsDraExtnConnectionFailed, "DS dra extn connection failed" }, { kErrorDsInstallSchemaMismatch, "DS install schema mismatch" }, { kErrorDsDupLinkId, "DS dup link ID" }, { kErrorDsNameErrorResolving, "DS name error resolving" }, { kErrorDsNameErrorNotFound, "DS name error not found" }, { kErrorDsNameErrorNotUnique, "DS name error not unique" }, { kErrorDsNameErrorNoMapping, "DS name error no mapping" }, { kErrorDsNameErrorDomainOnly, "DS name error domain only" }, { kErrorDsNameErrorNoSyntacticalMapping, "DS name error no syntactical mapping" }, { kErrorDsConstructedAttMod, "DS constructed att mod" }, { kErrorDsWrongOmObjClass, "DS wrong om obj class" }, { kErrorDsDraReplPending, "DS dra repl pending" }, { kErrorDsDsRequired, "DS ds required" }, { kErrorDsInvalidLdapDisplayName, "DS invalid LDAP display name" }, { kErrorDsNonBaseSearch, "DS non base search" }, { kErrorDsCantRetrieveAtts, "DS can't retrieve atts" }, { kErrorDsBacklinkWithoutLink, "DS backlink without link" }, { kErrorDsEpochMismatch, "DS epoch mismatch" }, { kErrorDsSrcNameMismatch, "DS src name mismatch" }, { kErrorDsSrcAndDstNcIdentical, "DS src and dst nc identical" }, { kErrorDsDstNcMismatch, "DS dst nc mismatch" }, { kErrorDsNotAuthoritiveForDstNc, "DS not authoritive for dst nc" }, { kErrorDsSrcGuidMismatch, "DS src GUID mismatch" }, { kErrorDsCantMoveDeletedObject, "DS can't move deleted object" }, { kErrorDsPdcOperationInProgress, "DS pdc operation in progress" }, { kErrorDsCrossDomainCleanupReqd, "DS cross domain cleanup reqd" }, { kErrorDsIllegalXdomMoveOperation, "DS illegal xdom move operation" }, { kErrorDsCantWithAcctGroupMembershps, "DS can't with acct group membershps" }, { kErrorDsNcMustHaveNcParent, "DS nc must have nc parent" }, { kErrorDsDstDomainNotNative, "DS dst domain not native" }, { kErrorDsMissingInfrastructureContainer, "DS missing infrastructure container" }, { kErrorDsCantMoveAccountGroup, "DS can't move account group" }, { kErrorDsCantMoveResourceGroup, "DS can't move resource group" }, { kErrorDsInvalidSearchFlag, "DS invalid search flag" }, { kErrorDsNoTreeDeleteAboveNc, "DS no tree delete above nc" }, { kErrorDsCouldntLockTreeForDelete, "DS couldn't lock tree for delete" }, { kErrorDsCouldntIdentifyObjectsForTreeDelete, "DS couldn't identify objects for tree delete" }, { kErrorDsSamInitFailure, "DS sam init failure" }, { kErrorDsSensitiveGroupViolation, "DS sensitive group violation" }, { kErrorDsCantModPrimarygroupid, "DS can't mod primarygroupid" }, { kErrorDsIllegalBaseSchemaMod, "DS illegal base schema mod" }, { kErrorDsNonsafeSchemaChange, "DS nonsafe schema change" }, { kErrorDsSchemaUpdateDisallowed, "DS schema update disallowed" }, { kErrorDsCantCreateUnderSchema, "DS can't create under schema" }, { kErrorDsInstallNoSrcSchVersion, "DS install no src sch version" }, { kErrorDsInstallNoSchVersionInInifile, "DS install no sch version in inifile" }, { kErrorDsInvalidGroupType, "DS invalid group type" }, { kErrorDsNoNestGlobalgroupInMixeddomain, "DS no nest globalgroup in mixeddomain" }, { kErrorDsNoNestLocalgroupInMixeddomain, "DS no nest localgroup in mixeddomain" }, { kErrorDsGlobalCantHaveLocalMember, "DS global can't have local member" }, { kErrorDsGlobalCantHaveUniversalMember, "DS global can't have universal member" }, { kErrorDsUniversalCantHaveLocalMember, "DS universal can't have local member" }, { kErrorDsGlobalCantHaveCrossdomainMember, "DS global can't have crossdomain member" }, { kErrorDsLocalCantHaveCrossdomainLocalMember, "DS local can't have crossdomain local member" }, { kErrorDsHavePrimaryMembers, "DS have primary members" }, { kErrorDsStringSdConversionFailed, "DS string sd conversion failed" }, { kErrorDsNamingMasterGc, "DS naming master gc" }, { kErrorDsLookupFailure, "DS lookup failure" }, { kErrorDsCouldntUpdateSpns, "DS couldn't update spns" }, { kErrorDsCantRetrieveSd, "DS can't retrieve sd" }, { kErrorDsKeyNotUnique, "DS key not unique" }, { kErrorDsWrongLinkedAttSyntax, "DS wrong linked att syntax" }, { kErrorDsSamNeedBootkeyPassword, "DS sam need bootkey password" }, { kErrorDsSamNeedBootkeyFloppy, "DS sam need bootkey floppy" }, { kErrorDsCantStart, "DS can't start" }, { kErrorDsInitFailure, "DS init failure" }, { kErrorDsNoPktPrivacyOnConnection, "DS no pkt privacy on connection" }, { kErrorDsSourceDomainInForest, "DS source domain in forest" }, { kErrorDsDestinationDomainNotInForest, "DS destination domain not in forest" }, { kErrorDsDestinationAuditingNotEnabled, "DS destination auditing not enabled" }, { kErrorDsCantFindDcForSrcDomain, "DS can't find dc for src domain" }, { kErrorDsSrcObjNotGroupOrUser, "DS src obj not group or user" }, { kErrorDsSrcSidExistsInForest, "DS src sid exists in forest" }, { kErrorDsSrcAndDstObjectClassMismatch, "DS src and dst object class mismatch" }, { kErrorSamInitFailure, "Sam init failure" }, { kErrorDsDraSchemaInfoShip, "DS dra schema info ship" }, { kErrorDsDraSchemaConflict, "DS dra schema conflict" }, { kErrorDsDraEarlierSchemaConlict, "DS dra earlier schema conflict" }, { kErrorDsDraObjNcMismatch, "DS dra obj nc mismatch" }, { kErrorDsNcStillHasDsas, "DS nc still has dsas" }, { kErrorDsGcRequired, "DS gc required" }, { kErrorDsLocalMemberOfLocalOnly, "DS local member of local only" }, { kErrorDsNoFpoInUniversalGroups, "DS no fpo in universal groups" }, { kErrorDsCantAddToGc, "DS can't add to gc" }, { kErrorDsNoCheckpointWithPdc, "DS no checkpoint with pdc" }, { kErrorDsSourceAuditingNotEnabled, "DS source auditing not enabled" }, { kErrorDsCantCreateInNondomainNc, "DS can't create in nondomain nc" }, { kErrorDsInvalidNameForSpn, "DS invalid name for spn" }, { kErrorDsFilterUsesContructedAttrs, "DS filter uses constructed attrs" }, { kErrorDsUnicodepwdNotInQuotes, "DS unicodepwd not in quotes" }, { kErrorDsMachineAccountQuotaExceeded, "DS machine account quota exceeded" }, { kErrorDsMustBeRunOnDstDc, "DS must be run on dst dc" }, { kErrorDsSrcDcMustBeSp4OrGreater, "DS src dc must be sp4 or greater" }, { kErrorDsCantTreeDeleteCriticalObj, "DS can't tree delete critical obj" }, { kErrorDsInitFailureConsole, "DS init failure console" }, { kErrorDsSamInitFailureConsole, "DS sam init failure console" }, { kErrorDsForestVersionTooHigh, "DS forest version too high" }, { kErrorDsDomainVersionTooHigh, "DS domain version too high" }, { kErrorDsForestVersionTooLow, "DS forest version too low" }, { kErrorDsDomainVersionTooLow, "DS domain version too low" }, { kErrorDsIncompatibleVersion, "DS incompatible version" }, { kErrorDsLowDsaVersion, "DS low dsa version" }, { kErrorDsNoBehaviorVersionInMixeddomain, "DS no behaviour version in mixeddomain" }, { kErrorDsNotSupportedSortOrder, "DS not supported sort order" }, { kErrorDsNameNotUnique, "DS name not unique" }, { kErrorDsMachineAccountCreatedPrent4, "DS machine account created prent4" }, { kErrorDsOutOfVersionStore, "DS out of version store" }, { kErrorDsIncompatibleControlsUsed, "DS incompatible controls used" }, { kErrorDsNoRefDomain, "DS no ref domain" }, { kErrorDsReservedLinkId, "DS reserved link ID" }, { kErrorDsLinkIdNotAvailable, "DS link ID not available" }, { kErrorDsAgCantHaveUniversalMember, "DS ag can't have universal member" }, { kErrorDsModifydnDisallowedByInstanceType, "DS modifydn disallowed by instance type" }, { kErrorDsNoObjectMoveInSchemaNc, "DS no object move in schema nc" }, { kErrorDsModifydnDisallowedByFlag, "DS modifydn disallowed by flag" }, { kErrorDsModifydnWrongGrandparent, "DS modifydn wrong grandparent" }, { kErrorDsNameErrorTrustReferral, "DS name error trust referral" }, { kErrorNotSupportedOnStandardServer, "Not supported on standard server" }, { kErrorDsCantAccessRemotePartOfAd, "DS can't access remote part of ad" }, { kErrorDsCrImpossibleToValidate, "DS cr impossible to validate" }, { kErrorDsThreadLimitExceeded, "DS thread limit exceeded" }, { kErrorDsNotClosest, "DS not closest" }, { kErrorDsCantDeriveSpnWithoutServerRef, "DS can't derive spn without server ref" }, { kErrorDsSingleUserModeFailed, "DS single user mode failed" }, { kErrorDsNtdscriptSyntaxError, "DS ntdscript syntax error" }, { kErrorDsNtdscriptProcessError, "DS ntdscript process error" }, { kErrorDsDifferentReplEpochs, "DS different repl epochs" }, { kErrorDsDrsExtensionsChanged, "DS drs extensions changed" }, { kErrorDsReplicaSetChangeNotAllowedOnDisabledCr, "DS replica set change not allowed on disabled cr" }, { kErrorDsNoMsdsIntid, "DS no msds intid" }, { kErrorDsDupMsdsIntid, "DS dup msds intid" }, { kErrorDsExistsInRdnattid, "DS exists in rdnattid" }, { kErrorDsAuthorizationFailed, "DS authorisation failed" }, { kErrorDsInvalidScript, "DS invalid script" }, { kErrorDsRemoteCrossrefOpFailed, "DS remote crossref op failed" }, { kDnsErrorRcodeFormatError, "DNS error rcode format error" }, { kDnsErrorRcodeServerFailure, "DNS error rcode server failure" }, { kDnsErrorRcodeNameError, "DNS error rcode name error" }, { kDnsErrorRcodeNotImplemented, "DNS error rcode not implemented" }, { kDnsErrorRcodeRefused, "DNS error rcode refused" }, { kDnsErrorRcodeYxdomain, "DNS error rcode yxdomain" }, { kDnsErrorRcodeYxrrset, "DNS error rcode yxrrset" }, { kDnsErrorRcodeNxrrset, "DNS error rcode nxrrset" }, { kDnsErrorRcodeNotauth, "DNS error rcode notauth" }, { kDnsErrorRcodeNotzone, "DNS error rcode notzone" }, { kDnsErrorRcodeBadsig, "DNS error rcode badsig" }, { kDnsErrorRcodeBadkey, "DNS error rcode badkey" }, { kDnsErrorRcodeBadtime, "DNS error rcode badtime" }, { kDnsInfoNoRecords, "DNS info no records" }, { kDnsErrorBadPacket, "DNS error bad packet" }, { kDnsErrorNoPacket, "DNS error no packet" }, { kDnsErrorRcode, "DNS error rcode" }, { kDnsErrorUnsecurePacket, "DNS error unsecure packet" }, { kDnsErrorInvalidType, "DNS error invalid type" }, { kDnsErrorInvalidIpAddress, "DNS error invalid IP address" }, { kDnsErrorInvalidProperty, "DNS error invalid property" }, { kDnsErrorTryAgainLater, "DNS error try again later" }, { kDnsErrorNotUnique, "DNS error not unique" }, { kDnsErrorNonRfcName, "DNS error non RFC name" }, { kDnsStatusFqdn, "DNS status FQDN" }, { kDnsStatusDottedName, "DNS status dotted name" }, { kDnsStatusSinglePartName, "DNS status single part name" }, { kDnsErrorInvalidNameChar, "DNS error invalid name char" }, { kDnsErrorNumericName, "DNS error numeric name" }, { kDnsErrorNotAllowedOnRootServer, "DNS error not allowed on root server" }, { kDnsErrorZoneDoesNotExist, "DNS error zone does not exist" }, { kDnsErrorNoZoneInfo, "DNS error not zone info" }, { kDnsErrorInvalidZoneOperation, "DNS error invalid zone operation" }, { kDnsErrorZoneConfigurationError, "DNS error zone configuration error" }, { kDnsErrorZoneHasNoSoaRecord, "DNS error zone has not SOA record" }, { kDnsErrorZoneHasNoNsRecords, "DNS error zone has no NS records" }, { kDnsErrorZoneLocked, "DNS error zone locked" }, { kDnsErrorZoneCreationFailed, "DNS error zone creation failed" }, { kDnsErrorZoneAlreadyExists, "DNS error zone already exists" }, { kDnsErrorAutozoneAlreadyExists, "DNS error autozone already exists" }, { kDnsErrorInvalidZoneType, "DNS error invalid zone type" }, { kDnsErrorSecondaryRequiresMasterIp, "DNS error secondary requires master IP" }, { kDnsErrorZoneNotSecondary, "DNS error zone not secondary" }, { kDnsErrorNeedSecondaryAddresses, "DNS error need secondary addresses" }, { kDnsErrorWinsInitFailed, "DNS error wins init failed" }, { kDnsErrorNeedWinsServers, "DNS error need wins servers" }, { kDnsErrorNbstatInitFailed, "DNS error nbstat init failed" }, { kDnsErrorSoaDeleteInvalid, "DNS error SOA delete invalid" }, { kDnsErrorForwarderAlreadyExists, "DNS error forwarder already exists" }, { kDnsErrorZoneRequiresMasterIp, "DNS error zone requires master IP" }, { kDnsErrorZoneIsShutdown, "DNS error zone is shutdown" }, { kDnsErrorPrimaryRequiresDatafile, "DNS error primary requires datafile" }, { kDnsErrorInvalidDatafileName, "DNS error invalid datafile name" }, { kDnsErrorDatafileOpenFailure, "DNS error datafile open failure" }, { kDnsErrorFileWritebackFailed, "DNS error file writeback failed" }, { kDnsErrorDatafileParsing, "DNS error datafile parsing" }, { kDnsErrorRecordDoesNotExist, "DNS error record does not exist" }, { kDnsErrorRecordFormat, "DNS error record format" }, { kDnsErrorNodeCreationFailed, "DNS error node creation failed" }, { kDnsErrorUnknownRecordType, "DNS error unknown record type" }, { kDnsErrorRecordTimedOut, "DNS error record timed out" }, { kDnsErrorNameNotInZone, "DNS error name not in zone" }, { kDnsErrorCnameLoop, "DNS error CNAME loop" }, { kDnsErrorNodeIsCname, "DNS error node is CNAME" }, { kDnsErrorCnameCollision, "DNS error CNAME collision" }, { kDnsErrorRecordOnlyAtZoneRoot, "DNS error record only at zone root" }, { kDnsErrorRecordAlreadyExists, "DNS error record already exists" }, { kDnsErrorSecondaryData, "DNS error secondary data" }, { kDnsErrorNoCreateCacheData, "DNS error no create cache data" }, { kDnsErrorNameDoesNotExist, "DNS error name does not exist" }, { kDnsWarningPtrCreateFailed, "DNS warning PTR create failed" }, { kDnsWarningDomainUndeleted, "DNS warning domain undeleted" }, { kDnsErrorDsUnavailable, "DNS error ds unavailable" }, { kDnsErrorDsZoneAlreadyExists, "DNS error ds zone already exists" }, { kDnsErrorNoBootfileIfDsZone, "DNS error no bootfile if ds zone" }, { kDnsInfoAxfrComplete, "DNS info AXFR complete" }, { kDnsErrorAxfr, "DNS error AXFR" }, { kDnsInfoAddedLocalWins, "DNS info added local wins" }, { kDnsStatusContinueNeeded, "DNS status continue needed" }, { kDnsErrorNoTcpip, "DNS error no TCPIP" }, { kDnsErrorNoDnsServers, "DNS error no DNS servers" }, { kDnsErrorDpDoesNotExist, "DNS error dp does not exist" }, { kDnsErrorDpAlreadyExists, "DNS error dp already exists" }, { kDnsErrorDpNotEnlisted, "DNS error dp not enlisted" }, { kDnsErrorDpAlreadyEnlisted, "DNS error dp already enlisted" }, { kWSAQosReceivers, "QOS receivers" }, { kWSAQosSenders, "QOS senders" }, { kWSAQosNoSenders, "QOS no senders" }, { kWSAQosNoReceivers, "QOS no receivers" }, { kWSAQosRequestConfirmed, "QOS request confirmed" }, { kWSAQosAdmissionFailure, "QOS admission failure" }, { kWSAQosPolicyFailure, "QOS policy failure" }, { kWSAQosBadStyle, "QOS bad style" }, { kWSAQosBadObject, "QOS bad object" }, { kWSAQosTrafficCtrlError, "QOS traffic ctrl error" }, { kWSAQosGenericError, "QOS generic error" }, { kWSAQosEservicetype, "QOS eservicetype" }, { kWSAQosEflowspec, "QOS eflowspec" }, { kWSAQosEprovspecbuf, "QOS eprovspecbuf" }, { kWSAQosEfilterstyle, "QOS efilterstyle" }, { kWSAQosEfiltertype, "QOS efiltertype" }, { kWSAQosEfiltercount, "QOS efiltercount" }, { kWSAQosEobjlength, "QOS eobjlength" }, { kWSAQosEflowcount, "QOS eflowcount" }, { kWSAQosEunknownpsobj, "QOS eunknownpsobj" }, { kWSAQosEpolicyobj, "QOS epolicyobj" }, { kWSAQosEflowdesc, "QOS eflowdesc" }, { kWSAQosEpsflowspec, "QOS epsflowspec" }, { kWSAQosEpsfilterspec, "QOS epsfilterspec" }, { kWSAQosEsdmodeobj, "QOS esdmodeobj" }, { kWSAQosEshaperateobj, "QOS eshaperateobj" }, { kWSAQosReservedPetype, "QOS reserved petype" }, { kErrorIpsecQmPolicyExists, "IPSEC qm policy exists" }, { kErrorIpsecQmPolicyNotFound, "IPSEC qm policy not found" }, { kErrorIpsecQmPolicyInUse, "IPSEC qm policy in use" }, { kErrorIpsecMmPolicyExists, "IPSEC mm policy exists" }, { kErrorIpsecMmPolicyNotFound, "IPSEC mm policy not found" }, { kErrorIpsecMmPolicyInUse, "IPSEC mm policy in use" }, { kErrorIpsecMmFilterExists, "IPSEC mm filter exists" }, { kErrorIpsecMmFilterNotFound, "IPSEC mm filter not found" }, { kErrorIpsecTransportFilterExists, "IPSEC transport filter exists" }, { kErrorIpsecTransportFilterNotFound, "IPSEC transport filter not found" }, { kErrorIpsecMmAuthExists, "IPSEC mm auth exists" }, { kErrorIpsecMmAuthNotFound, "IPSEC mm auth not found" }, { kErrorIpsecMmAuthInUse, "IPSEC mm auth in use" }, { kErrorIpsecDefaultMmPolicyNotFound, "IPSEC default mm policy not found" }, { kErrorIpsecDefaultMmAuthNotFound, "IPSEC default mm auth not found" }, { kErrorIpsecDefaultQmPolicyNotFound, "IPSEC default qm policy not found" }, { kErrorIpsecTunnelFilterExists, "IPSEC tunnel filter exists" }, { kErrorIpsecTunnelFilterNotFound, "IPSEC tunnel filter not found" }, { kErrorIpsecMmFilterPendingDeletion, "IPSEC mm filter pending deletion" }, { kErrorIpsecTransportFilterPendingDeletion, "IPSEC transport filter pending deletion" }, { kErrorIpsecTunnelFilterPendingDeletion, "IPSEC tunnel filter pending deletion" }, { kErrorIpsecMmPolicyPendingDeletion, "IPSEC mm policy pending deletion" }, { kErrorIpsecMmAuthPendingDeletion, "IPSEC mm auth pending deletion" }, { kErrorIpsecQmPolicyPendingDeletion, "IPSEC qm policy pending deletion" }, { kErrorIpsecIkeAuthFail, "IPSEC IKE auth fail" }, { kErrorIpsecIkeAttribFail, "IPSEC IKE attrib fail" }, { kErrorIpsecIkeNegotiationPending, "IPSEC IKE negotiation pending" }, { kErrorIpsecIkeGeneralProcessingError, "IPSEC IKE general processing error" }, { kErrorIpsecIkeTimedOut, "IPSEC IKE timed out" }, { kErrorIpsecIkeNoCert, "IPSEC IKE no cert" }, { kErrorIpsecIkeSaDeleted, "IPSEC IKE sa deleted" }, { kErrorIpsecIkeSaReaped, "IPSEC IKE sa reaped" }, { kErrorIpsecIkeMmAcquireDrop, "IPSEC IKE mm acquire drop" }, { kErrorIpsecIkeQmAcquireDrop, "IPSEC IKE qm acquire drop" }, { kErrorIpsecIkeQueueDropMm, "IPSEC IKE queue drop mm" }, { kErrorIpsecIkeQueueDropNoMm, "IPSEC IKE queue drop no mm" }, { kErrorIpsecIkeDropNoResponse, "IPSEC IKE drop no response" }, { kErrorIpsecIkeMmDelayDrop, "IPSEC IKE mm delay drop" }, { kErrorIpsecIkeQmDelayDrop, "IPSEC IKE qm delay drop" }, { kErrorIpsecIkeError, "IPSEC IKE error" }, { kErrorIpsecIkeCrlFailed, "IPSEC IKE crl failed" }, { kErrorIpsecIkeInvalidKeyUsage, "IPSEC IKE invalid key usage" }, { kErrorIpsecIkeInvalidCertType, "IPSEC IKE invalid cert type" }, { kErrorIpsecIkeNoPrivateKey, "IPSEC IKE no private key" }, { kErrorIpsecIkeDhFail, "IPSEC IKE dh fail" }, { kErrorIpsecIkeInvalidHeader, "IPSEC IKE invalid header" }, { kErrorIpsecIkeNoPolicy, "IPSEC IKE no policy" }, { kErrorIpsecIkeInvalidSignature, "IPSEC IKE invalid signature" }, { kErrorIpsecIkeKerberosError, "IPSEC IKE kerberos error" }, { kErrorIpsecIkeNoPublicKey, "IPSEC IKE no public key" }, { kErrorIpsecIkeProcessErr, "IPSEC IKE process err" }, { kErrorIpsecIkeProcessErrSa, "IPSEC IKE process err sa" }, { kErrorIpsecIkeProcessErrProp, "IPSEC IKE process err prop" }, { kErrorIpsecIkeProcessErrTrans, "IPSEC IKE process err trans" }, { kErrorIpsecIkeProcessErrKe, "IPSEC IKE process err ke" }, { kErrorIpsecIkeProcessErrId, "IPSEC IKE process err ID" }, { kErrorIpsecIkeProcessErrCert, "IPSEC IKE process err cert" }, { kErrorIpsecIkeProcessErrCertReq, "IPSEC IKE process err cert req" }, { kErrorIpsecIkeProcessErrHash, "IPSEC IKE process err hash" }, { kErrorIpsecIkeProcessErrSig, "IPSEC IKE process err sig" }, { kErrorIpsecIkeProcessErrNonce, "IPSEC IKE process err nonce" }, { kErrorIpsecIkeProcessErrNotify, "IPSEC IKE process err notify" }, { kErrorIpsecIkeProcessErrDelete, "IPSEC IKE process err delete" }, { kErrorIpsecIkeProcessErrVendor, "IPSEC IKE process err vendor" }, { kErrorIpsecIkeInvalidPayload, "IPSEC IKE invalid payload" }, { kErrorIpsecIkeLoadSoftSa, "IPSEC IKE load soft sa" }, { kErrorIpsecIkeSoftSaTornDown, "IPSEC IKE soft sa torn down" }, { kErrorIpsecIkeInvalidCookie, "IPSEC IKE invalid cookie" }, { kErrorIpsecIkeNoPeerCert, "IPSEC IKE no peer cert" }, { kErrorIpsecIkePeerCrlFailed, "IPSEC IKE peer CRL failed" }, { kErrorIpsecIkePolicyChange, "IPSEC IKE policy change" }, { kErrorIpsecIkeNoMmPolicy, "IPSEC IKE no mm policy" }, { kErrorIpsecIkeNotcbpriv, "IPSEC IKE notcbpriv" }, { kErrorIpsecIkeSecloadfail, "IPSEC IKE secloadfail" }, { kErrorIpsecIkeFailsspinit, "IPSEC IKE failsspinit" }, { kErrorIpsecIkeFailqueryssp, "IPSEC IKE failqueryssp" }, { kErrorIpsecIkeSrvacqfail, "IPSEC IKE srvacqfail" }, { kErrorIpsecIkeSrvquerycred, "IPSEC IKE srvquerycred" }, { kErrorIpsecIkeGetspifail, "IPSEC IKE getspifail" }, { kErrorIpsecIkeInvalidFilter, "IPSEC IKE invalid filter" }, { kErrorIpsecIkeOutOfMemory, "IPSEC IKE out of memory" }, { kErrorIpsecIkeAddUpdateKeyFailed, "IPSEC IKE add update key failed" }, { kErrorIpsecIkeInvalidPolicy, "IPSEC IKE invalid policy" }, { kErrorIpsecIkeUnknownDoi, "IPSEC IKE unknown doi" }, { kErrorIpsecIkeInvalidSituation, "IPSEC IKE invalid situation" }, { kErrorIpsecIkeDhFailure, "IPSEC IKE dh failure" }, { kErrorIpsecIkeInvalidGroup, "IPSEC IKE invalid group" }, { kErrorIpsecIkeEncrypt, "IPSEC IKE encrypt" }, { kErrorIpsecIkeDecrypt, "IPSEC IKE decrypt" }, { kErrorIpsecIkePolicyMatch, "IPSEC IKE policy match" }, { kErrorIpsecIkeUnsupportedId, "IPSEC IKE unsupported ID" }, { kErrorIpsecIkeInvalidHash, "IPSEC IKE invalid hash" }, { kErrorIpsecIkeInvalidHashAlg, "IPSEC IKE invalid hash alg" }, { kErrorIpsecIkeInvalidHashSize, "IPSEC IKE invalid hash size" }, { kErrorIpsecIkeInvalidEncryptAlg, "IPSEC IKE invalid encrypt alg" }, { kErrorIpsecIkeInvalidAuthAlg, "IPSEC IKE invalid auth alg" }, { kErrorIpsecIkeInvalidSig, "IPSEC IKE invalid sig" }, { kErrorIpsecIkeLoadFailed, "IPSEC IKE load failed" }, { kErrorIpsecIkeRpcDelete, "IPSEC IKE rpc delete" }, { kErrorIpsecIkeBenignReinit, "IPSEC IKE benign reinit" }, { kErrorIpsecIkeInvalidResponderLifetimeNotify, "IPSEC IKE invalid responder lifetime notify" }, { kErrorIpsecIkeInvalidCertKeylen, "IPSEC IKE invalid cert keylen" }, { kErrorIpsecIkeMmLimit, "IPSEC IKE mm limit" }, { kErrorIpsecIkeNegotiationDisabled, "IPSEC IKE negotiation disabled" }, { kErrorIpsecIkeNegStatusEnd, "IPSEC IKE neg status end" }, { kErrorSxsSectionNotFound, "Sxs section not found" }, { kErrorSxsCantGenActctx, "Sxs can't gen actctx" }, { kErrorSxsInvalidActctxdataFormat, "Sxs invalid actctxdata format" }, { kErrorSxsAssemblyNotFound, "Sxs assembly not found" }, { kErrorSxsManifestFormatError, "Sxs manifest format error" }, { kErrorSxsManifestParseError, "Sxs manifest parse error" }, { kErrorSxsActivationContextDisabled, "Sxs activation context disabled" }, { kErrorSxsKeyNotFound, "Sxs key not found" }, { kErrorSxsVersionConflict, "Sxs version conflict" }, { kErrorSxsWrongSectionType, "Sxs wrong section type" }, { kErrorSxsThreadQueriesDisabled, "Sxs thread queries disabled" }, { kErrorSxsProcessDefaultAlreadySet, "Sxs process default already set" }, { kErrorSxsUnknownEncodingGroup, "Sxs unknown encoding group" }, { kErrorSxsUnknownEncoding, "Sxs unknown encoding" }, { kErrorSxsInvalidXmlNamespaceUri, "Sxs invalid XML namespace URI" }, { kErrorSxsRootManifestDependencyNotInstalled, "Sxs root manifest dependency not installed" }, { kErrorSxsLeafManifestDependencyNotInstalled, "Sxs leaf manifest dependency not installed" }, { kErrorSxsInvalidAssemblyIdentityAttribute, "Sxs invalid assembly indentity attribute" }, { kErrorSxsManifestMissingRequiredDefaultNamespace, "Sxs manifest missing required default namespace" }, { kErrorSxsManifestInvalidRequiredDefaultNamespace, "Sxs manifest invalid required default namespace" }, { kErrorSxsPrivateManifestCrossPathWithReparsePoint, "Sxs private manifest cross path with reparse point" }, { kErrorSxsDuplicateDllName, "Sxs duplicate dll name" }, { kErrorSxsDuplicateWindowclassName, "Sxs duplicate windowclass name" }, { kErrorSxsDuplicateClsid, "Sxs duplicate clsid" }, { kErrorSxsDuplicateIid, "Sxs duplicate iid" }, { kErrorSxsDuplicateTlbid, "Sxs duplicate tlbid" }, { kErrorSxsDuplicateProgid, "Sxs duplicate progid" }, { kErrorSxsDuplicateAssemblyName, "Sxs duplicate assembly name" }, { kErrorSxsFileHashMismatch, "Sxs file hash mismatch" }, { kErrorSxsPolicyParseError, "Sxs policy parse error" }, { kErrorSxsXmlEMissingquote, "Sxs XML e missingquote" }, { kErrorSxsXmlECommentsyntax, "Sxs XML e commentsyntax" }, { kErrorSxsXmlEBadstartnamechar, "Sxs XML e badstartnamechar" }, { kErrorSxsXmlEBadnamechar, "Sxs XML e badnamechar" }, { kErrorSxsXmlEBadcharinstring, "Sxs XML e badcharinstring" }, { kErrorSxsXmlEXmldeclsyntax, "Sxs XML e xmldeclsyntax" }, { kErrorSxsXmlEBadchardata, "Sxs XML e badchardata" }, { kErrorSxsXmlEMissingwhitespace, "Sxs XML e missingwhitespace" }, { kErrorSxsXmlEExpectingtagend, "Sxs XML e expectingtagend" }, { kErrorSxsXmlEMissingsemicolon, "Sxs XML e missingsemicolon" }, { kErrorSxsXmlEUnbalancedparen, "Sxs XML e unbalancedparen" }, { kErrorSxsXmlEInternalerror, "Sxs XML e internalerror" }, { kErrorSxsXmlEUnexpectedWhitespace, "Sxs XML e unexpected whitespace" }, { kErrorSxsXmlEIncompleteEncoding, "Sxs XML e incomplete encoding" }, { kErrorSxsXmlEMissingParen, "Sxs XML e missing paren" }, { kErrorSxsXmlEExpectingclosequote, "Sxs XML e expectingclosequote" }, { kErrorSxsXmlEMultipleColons, "Sxs XML e multiple colons" }, { kErrorSxsXmlEInvalidDecimal, "Sxs XML e invalid decimal" }, { kErrorSxsXmlEInvalidHexidecimal, "Sxs XML e invalid hexidecimal" }, { kErrorSxsXmlEInvalidUnicode, "Sxs XML e invalid unicode" }, { kErrorSxsXmlEWhitespaceorquestionmark, "Sxs XML e whitespaceorquestionmark" }, { kErrorSxsXmlEUnexpectedendtag, "Sxs XML e unexpectedendtag" }, { kErrorSxsXmlEUnclosedtag, "Sxs XML e unclosedtag" }, { kErrorSxsXmlEDuplicateattribute, "Sxs XML e duplicateattribute" }, { kErrorSxsXmlEMultipleroots, "Sxs XML e multipleroots" }, { kErrorSxsXmlEInvalidatrootlevel, "Sxs XML e invalidatrootlevel" }, { kErrorSxsXmlEBadxmldecl, "Sxs XML e badxmldecl" }, { kErrorSxsXmlEMissingroot, "Sxs XML e missingroot" }, { kErrorSxsXmlEUnexpectedeof, "Sxs XML e unexpectedeof" }, { kErrorSxsXmlEBadperefinsubset, "Sxs XML e badperefinsubset" }, { kErrorSxsXmlEUnclosedstarttag, "Sxs XML e unclosedstarttag" }, { kErrorSxsXmlEUnclosedendtag, "Sxs XML e unclosedendtag" }, { kErrorSxsXmlEUnclosedstring, "Sxs XML e unclosedstring" }, { kErrorSxsXmlEUnclosedcomment, "Sxs XML e unclosedcomment" }, { kErrorSxsXmlEUncloseddecl, "Sxs XML e uncloseddecl" }, { kErrorSxsXmlEUnclosedcdata, "Sxs XML e unclosedcdata" }, { kErrorSxsXmlEReservednamespace, "Sxs XML e reservednamespace" }, { kErrorSxsXmlEInvalidencoding, "Sxs XML e invalidencoding" }, { kErrorSxsXmlEInvalidswitch, "Sxs XML e invalidswitch" }, { kErrorSxsXmlEBadxmlcase, "Sxs XML e badxmlcase" }, { kErrorSxsXmlEInvalidStandalone, "Sxs XML e invalid standalone" }, { kErrorSxsXmlEUnexpectedStandalone, "Sxs XML e unexpected standalone" }, { kErrorSxsXmlEInvalidVersion, "Sxs XML e invalid version" }, { kErrorSxsXmlEMissingequals, "Sxs XML e missingequals" }, { kErrorSxsProtectionRecoveryFailed, "Sxs protection recovery failed" }, { kErrorSxsProtectionPublicKeyTooShort, "Sxs protection public key too short" }, { kErrorSxsProtectionCatalogNotValid, "Sxs protection catalog not valid" }, { kErrorSxsUntranslatableHresult, "Sxs untranslatable hresult" }, { kErrorSxsProtectionCatalogFileMissing, "Sxs protection catalog file missing" }, { kErrorSxsMissingAssemblyIdentityAttribute, "Sxs missing assembly identity attribute" }, { kErrorSxsInvalidAssemblyIdentityAttributeName, "Sxs invalid assembly identity attribute name" }, }; #endif /* IL2CPP_DISABLE_FULL_MESSAGES */ static int32_t compare_message(const void *first, const void *second) { ErrorDesc *efirst = (ErrorDesc*)first; ErrorDesc *esecond = (ErrorDesc*)second; return (int32_t)efirst->code - (int32_t)esecond->code; } static const char *find_message(ErrorCode code, ErrorDesc *list, int32_t count) { ErrorDesc key = { code, "" }; ErrorDesc *result = (ErrorDesc*)bsearch(&key, list, count, sizeof(ErrorDesc), compare_message); return result ? result->message : NULL; } static const char *find_message_linear(ErrorCode code, ErrorDesc *list, int32_t count) { int32_t prev = -1; for (int32_t i = 0; i < count; ++i) { if (list[i].code > prev) prev = list[i].code; else { // static int error_shown; // if (!error_shown){ // error_shown = 1; // fprintf (stderr, "Mono: Incorrect message sorted in io-layer/messages.c at index %d (msg=%s)\n", i, list [i].txt); // } } if (list[i].code == code) { // static int error_shown; // if (!error_shown){ // error_shown = 1; // fprintf (stderr, "Mono: Error %d with text %s is improperly sorted in io-layer/messages.c\n", id, list [i].txt); // } return list[i].message; } } return NULL; } std::string Messages::FromCode(ErrorCode code) { const char *message = find_message(code, common_messages, N_ELEMENTS(common_messages)); if (message != NULL) return message; #ifndef IL2CPP_DISABLE_FULL_MESSAGES message = find_message(code, messages, N_ELEMENTS(messages)); if (message != NULL) return message; #endif // Linear search, in case someone adds an error message and does not add it // to the list in a sorted position, this will be catched during development. message = find_message_linear(code, common_messages, N_ELEMENTS(common_messages)); if (message != NULL) return message; #ifndef IL2CPP_DISABLE_FULL_MESSAGES message = find_message_linear(code, messages, N_ELEMENTS(messages)); if (message != NULL) return message; #endif return std::string(); } } } ================================================ FILE: unity_decoder/libil2cpp/os/Messages.h ================================================ #pragma once #include "il2cpp-config.h" #include #include #include "os/ErrorCodes.h" namespace il2cpp { namespace os { struct ErrorDesc { ErrorCode code; const char *message; }; extern ErrorDesc common_messages[]; #ifndef IL2CPP_DISABLE_FULL_MESSAGES extern ErrorDesc messages[]; #endif class Messages { public: static std::string FromCode(ErrorCode code); }; } } ================================================ FILE: unity_decoder/libil2cpp/os/Mutex.cpp ================================================ #include "il2cpp-config.h" #include "os/Mutex.h" #include "os/Atomic.h" #if IL2CPP_THREADS_WIN32 #include "os/Win32/MutexImpl.h" #elif IL2CPP_TARGET_PSP2 #include "os/PSP2/MutexImpl.h" #elif IL2CPP_THREADS_PTHREAD #include "os/Posix/MutexImpl.h" #else #include "os/MutexImpl.h" #endif namespace il2cpp { namespace os { Mutex::Mutex(bool initiallyOwned) : m_Mutex(new MutexImpl()) { if (initiallyOwned) Lock(); } Mutex::~Mutex() { delete m_Mutex; } void Mutex::Lock(bool interruptible) { m_Mutex->Lock(interruptible); } bool Mutex::TryLock(uint32_t milliseconds, bool interruptible) { return m_Mutex->TryLock(milliseconds, interruptible); } void Mutex::Unlock() { m_Mutex->Unlock(); } FastMutex::FastMutex() : m_Impl(new FastMutexImpl()) { } FastMutex::~FastMutex() { delete m_Impl; } void FastMutex::Lock() { m_Impl->Lock(); } void FastMutex::Unlock() { m_Impl->Unlock(); } FastMutexImpl* FastMutex::GetImpl() { return m_Impl; } } } ================================================ FILE: unity_decoder/libil2cpp/os/Mutex.h ================================================ #pragma once #include "os/ErrorCodes.h" #include "os/Handle.h" #include "os/WaitStatus.h" #include "utils/NonCopyable.h" namespace il2cpp { namespace os { class MutexImpl; class FastMutexImpl; class Mutex : public il2cpp::utils::NonCopyable { public: Mutex(bool initiallyOwned = false); ~Mutex(); void Lock(bool interruptible = false); bool TryLock(uint32_t milliseconds = 0, bool interruptible = false); void Unlock(); private: MutexImpl* m_Mutex; }; struct AutoLock : public il2cpp::utils::NonCopyable { AutoLock(Mutex* mutex) : m_Mutex(mutex) { m_Mutex->Lock(); } ~AutoLock() { m_Mutex->Unlock(); } private: Mutex* m_Mutex; }; class MutexHandle : public Handle { public: MutexHandle(Mutex* mutex) : m_Mutex(mutex) {} virtual ~MutexHandle() { delete m_Mutex; } virtual bool Wait() { m_Mutex->Lock(true); return true; } virtual bool Wait(uint32_t ms) { return m_Mutex->TryLock(ms, true); } virtual void Signal() { m_Mutex->Unlock(); } Mutex* Get() { return m_Mutex; } private: Mutex* m_Mutex; }; /// Lightweight mutex that has no support for interruption or timed waits. Meant for /// internal use only. class FastMutex { public: FastMutex(); ~FastMutex(); void Lock(); void Unlock(); FastMutexImpl* GetImpl(); private: FastMutexImpl* m_Impl; }; struct FastAutoLock : public il2cpp::utils::NonCopyable { FastAutoLock(FastMutex* mutex) : m_Mutex(mutex) { m_Mutex->Lock(); } ~FastAutoLock() { m_Mutex->Unlock(); } private: FastMutex* m_Mutex; }; struct FastAutoUnlock : public il2cpp::utils::NonCopyable { FastAutoUnlock(FastMutex* mutex) : m_Mutex(mutex) { m_Mutex->Unlock(); } ~FastAutoUnlock() { m_Mutex->Lock(); } private: FastMutex* m_Mutex; }; } } ================================================ FILE: unity_decoder/libil2cpp/os/NativeMethods.h ================================================ #pragma once #include #include "os/Process.h" #include #include namespace il2cpp { namespace os { class NativeMethods { public: static bool CloseProcess(ProcessHandle* handle); static bool GetExitCodeProcess(ProcessHandle* handle, int32_t* exitCode); static int32_t GetCurrentProcessId(); static ProcessHandle* GetCurrentProcess(); }; } } ================================================ FILE: unity_decoder/libil2cpp/os/OSGlobalEnums.h ================================================ #pragma once enum FileType { kFileTypeUnknown = 0x0000, kFileTypeDisk = 0x0001, kFileTypeChar = 0x0002, kFileTypePipe = 0x0003, kFileTypeRemote = 0x8000 }; enum UnityPalFileAttributes { kFileAttributeReadOnly = 0x00000001, kFileAttributeHidden = 0x00000002, kFileAttributeSystem = 0x00000004, kFileAttributeDirectory = 0x00000010, kFileAttributeArchive = 0x00000020, kFileAttributeDevice = 0x00000040, kFileAttributeNormal = 0x00000080, kFileAttributeTemporary = 0x00000100, kFileAttributeSparse_file = 0x00000200, kFileAttributeReparse_point = 0x00000400, kFileAttributeCompressed = 0x00000800, kFileAttributeOffline = 0x00001000, kFileAttributeNot_content_indexed = 0x00002000, kFileAttributeEncrypted = 0x00004000, kFileAttributeVirtual = 0x00010000, kFileAttributeInternalMonoExecutable = 0x80000000 // Only used internally by Mono }; enum FileAccess { kFileAccessRead = 0x01, kFileAccessWrite = 0x02, kFileAccessReadWrite = kFileAccessRead | kFileAccessWrite }; enum FileMode { kFileModeCreateNew = 1, kFileModeCreate = 2, kFileModeOpen = 3, kFileModeOpenOrCreate = 4, kFileModeTruncate = 5, kFileModeAppend = 6 }; enum FileShare { kFileShareNone = 0x0, kFileShareRead = 0x01, kFileShareWrite = 0x02, kFileShareReadWrite = kFileShareRead | kFileShareWrite, kFileShareDelete = 0x04 }; enum FileOptions { kFileOptionsNone = 0, kFileOptionsTemporary = 1, // Internal. See note in System.IO.FileOptions kFileOptionsEncrypted = 0x4000, kFileOptionsDeleteOnClose = 0x4000000, kFileOptionsSequentialScan = 0x8000000, kFileOptionsRandomAccess = 0x10000000, kFileOptionsAsynchronous = 0x40000000, kFileOptionsWriteThrough = 0x80000000 }; enum SeekOrigin { kFileSeekOriginBegin = 0, kFileSeekOriginCurrent = 1, kFileSeekOriginEnd = 2 }; ================================================ FILE: unity_decoder/libil2cpp/os/OSX/Image.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_DARWIN #include #include namespace il2cpp { namespace os { namespace Image { void* GetImageBase() { // OSX/iOS uses ASLR (address space layout randomization), so // find where the image is loaded. This is usually zero in the // debugger for an executable, but non-zero when a debugger is not // present. std::vector path; uint32_t size = 0; int error = _NSGetExecutablePath(NULL, &size); IL2CPP_ASSERT(error == -1); if (error != -1) return NULL; path.reserve(size); error = _NSGetExecutablePath(&path[0], &size); IL2CPP_ASSERT(error == 0); if (error != 0) return NULL; // Assume that we are either in an executable, or a dynamic // library named UserAssembly.dylib (for the OSX standalone player) int userAssemblyImageIndex = -1; int executableImageIndex = -1; int numberOfImages = _dyld_image_count(); for (uint32_t i = 0; i < numberOfImages; i++) { const char* imageName = _dyld_get_image_name(i); if (strstr(imageName, "UserAssembly.dylib") != NULL) userAssemblyImageIndex = i; else if (strcmp(imageName, &path[0]) == 0) executableImageIndex = i; } if (userAssemblyImageIndex != -1) return (void*)_dyld_get_image_vmaddr_slide(userAssemblyImageIndex); else if (executableImageIndex != -1) return (void*)_dyld_get_image_vmaddr_slide(executableImageIndex); return NULL; } } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/OSX/Process.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_DARWIN #include #if !IL2CPP_TARGET_IOS #include #endif #include #include #include "os/Process.h" #include "vm/Exception.h" struct ProcessHandle { pid_t pid; }; namespace il2cpp { namespace os { int Process::GetCurrentProcessId() { return getpid(); } ProcessHandle* Process::GetProcess(int processId) { // If/when we implement the CreateProcess_internal icall we will likely // need to so something smarter here to find the process if we did // not create it and return a known pseudo-handle. For now this // is sufficient though. return (ProcessHandle*)(intptr_t)processId; } void Process::FreeProcess(ProcessHandle* handle) { // We have nothing to do here. } std::string Process::GetProcessName(ProcessHandle* handle) { #if !IL2CPP_TARGET_IOS const size_t bufferLength = 256; char buf[bufferLength]; int length = proc_name((int)((intptr_t)handle), buf, bufferLength); if (length <= 0) return std::string(); return std::string(buf, length); #else NOT_SUPPORTED_IL2CPP(Process::GetProcessName, "GetProcessName is not supported for non-Windows/OSX desktop platforms"); return std::string(); #endif } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Path.cpp ================================================ #include "il2cpp-config.h" #include "os/Path.h" #include #if IL2CPP_USE_GENERIC_ENVIRONMENT #include "os/Path.h" #include namespace il2cpp { namespace os { std::string Path::GetExecutablePath() { return std::string(""); } std::string Path::GetTempPath() { return std::string(""); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Path.h ================================================ #pragma once #include #include namespace il2cpp { namespace os { class Path { public: static std::string GetExecutablePath(); static std::string GetTempPath(); }; } } ================================================ FILE: unity_decoder/libil2cpp/os/Posix/AtomicImpl.h ================================================ #pragma once #include #ifdef __EMSCRIPTEN__ #include #endif // Assumes clang or gcc as compiler. #if IL2CPP_TARGET_POSIX namespace il2cpp { namespace os { inline int32_t Atomic::Add(volatile int32_t* location1, int32_t value) { ASSERT_ALIGNMENT(location1, 4); return __sync_add_and_fetch(location1, value); } inline int64_t Atomic::Add64(volatile int64_t* location1, int64_t value) { ASSERT_ALIGNMENT(location1, 8); return __sync_add_and_fetch(location1, value); } inline int32_t Atomic::Increment(volatile int32_t* value) { ASSERT_ALIGNMENT(value, 4); return __sync_add_and_fetch(value, 1); } inline int64_t Atomic::Increment64(volatile int64_t* value) { ASSERT_ALIGNMENT(value, 8); return __sync_add_and_fetch(value, 1); } inline int32_t Atomic::Decrement(volatile int32_t* value) { ASSERT_ALIGNMENT(value, 4); return __sync_add_and_fetch(value, -1); } inline int64_t Atomic::Decrement64(volatile int64_t* value) { ASSERT_ALIGNMENT(value, 8); return __sync_add_and_fetch(value, -1); } inline int32_t Atomic::CompareExchange(volatile int32_t* dest, int32_t exchange, int32_t comparand) { ASSERT_ALIGNMENT(dest, 4); return __sync_val_compare_and_swap(dest, comparand, exchange); } inline int64_t Atomic::CompareExchange64(volatile int64_t* dest, int64_t exchange, int64_t comparand) { ASSERT_ALIGNMENT(dest, 8); #ifdef __EMSCRIPTEN__ return emscripten_atomic_cas_u64((void*)dest, comparand, exchange) == comparand ? comparand : *dest; #else return __sync_val_compare_and_swap(dest, comparand, exchange); #endif } inline void* Atomic::CompareExchangePointer(void* volatile* dest, void* exchange, void* comparand) { ASSERT_ALIGNMENT(dest, IL2CPP_SIZEOF_VOID_P); return __sync_val_compare_and_swap(dest, comparand, exchange); } inline int32_t Atomic::Exchange(volatile int32_t* dest, int32_t exchange) { ASSERT_ALIGNMENT(dest, 4); #ifdef __EMSCRIPTEN__ return emscripten_atomic_exchange_u32((void*)dest, exchange); #else int32_t prev; do { prev = *dest; } while (!__sync_bool_compare_and_swap(dest, prev, exchange)); return prev; #endif } inline int64_t Atomic::Exchange64(volatile int64_t* dest, int64_t exchange) { ASSERT_ALIGNMENT(dest, 8); #ifdef __EMSCRIPTEN__ return emscripten_atomic_exchange_u64((void*)dest, exchange); #else int64_t prev; do { prev = *dest; } while (!__sync_bool_compare_and_swap(dest, prev, exchange)); return prev; #endif } inline void* Atomic::ExchangePointer(void* volatile* dest, void* exchange) { ASSERT_ALIGNMENT(dest, IL2CPP_SIZEOF_VOID_P); #ifdef __EMSCRIPTEN__ return (void*)emscripten_atomic_exchange_u32((void*)dest, (uint32_t)exchange); #else void* prev; do { prev = *dest; } while (!__sync_bool_compare_and_swap(dest, prev, exchange)); return prev; #endif } inline int64_t Atomic::Read64(volatile int64_t* addr) { ASSERT_ALIGNMENT(addr, 8); return __sync_fetch_and_add(addr, 0); } inline void Atomic::MemoryBarrier() { __sync_synchronize(); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/ConditionVariableImpl.cpp ================================================ #include "il2cpp-config.h" #if NET_4_0 #if IL2CPP_THREADS_PTHREAD #include "MutexImpl.h" #include "ConditionVariableImpl.h" #include #include namespace il2cpp { namespace os { ConditionVariableImpl::ConditionVariableImpl() { pthread_cond_init(&m_ConditionVariable, NULL); } ConditionVariableImpl::~ConditionVariableImpl() { pthread_cond_destroy(&m_ConditionVariable); } int ConditionVariableImpl::Wait(FastMutexImpl* lock) { return pthread_cond_wait(&m_ConditionVariable, lock->GetOSHandle()); } int ConditionVariableImpl::TimedWait(FastMutexImpl* lock, uint32_t timeout_ms) { struct timeval tv; struct timespec ts; int64_t usecs; int res; if (timeout_ms == (uint32_t)0xFFFFFFFF) return pthread_cond_wait(&m_ConditionVariable, lock->GetOSHandle()); /* ms = 10^-3, us = 10^-6, ns = 10^-9 */ gettimeofday(&tv, NULL); tv.tv_sec += timeout_ms / 1000; usecs = tv.tv_usec + ((timeout_ms % 1000) * 1000); if (usecs >= 1000000) { usecs -= 1000000; tv.tv_sec++; } ts.tv_sec = tv.tv_sec; ts.tv_nsec = usecs * 1000; return pthread_cond_timedwait(&m_ConditionVariable, lock->GetOSHandle(), &ts); } void ConditionVariableImpl::Broadcast() { pthread_cond_broadcast(&m_ConditionVariable); } void ConditionVariableImpl::Signal() { pthread_cond_signal(&m_ConditionVariable); } } } #endif #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/ConditionVariableImpl.h ================================================ #pragma once #if NET_4_0 #if IL2CPP_THREADS_PTHREAD #include #include "utils/NonCopyable.h" class FastMutexImpl; namespace il2cpp { namespace os { class ConditionVariableImpl : public il2cpp::utils::NonCopyable { public: ConditionVariableImpl(); ~ConditionVariableImpl(); int Wait(FastMutexImpl* lock); int TimedWait(FastMutexImpl* lock, uint32_t timeout_ms); void Broadcast(); void Signal(); private: pthread_cond_t m_ConditionVariable; }; } } #endif #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/Console.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_POSIX #include "os/Console.h" #include "os/File.h" #include #include #include #include #include #include #include #include #include #include namespace il2cpp { namespace os { namespace Console { static bool setupComplete = false; static int32_t s_terminalSize; static struct termios s_initialAttr; static struct termios s_il2cppAttr; static std::string s_keypadXmit; static std::string s_teardown; static struct sigaction s_saveSigcont, s_saveSigint, s_saveSigwinch; static int32_t GetTerminalSize() { struct winsize ws; if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == 0) return (ws.ws_col << 16) | ws.ws_row; return -1; } static bool SetProperty(int32_t property, bool value) { struct termios attr; bool callset = false; bool check; if (tcgetattr(STDIN_FILENO, &attr) == -1) return false; check = (attr.c_lflag & property) != 0; if ((value || check) && !(value && check)) { callset = true; if (value) attr.c_lflag |= property; else attr.c_lflag &= ~property; } if (!callset) return true; if (tcsetattr(STDIN_FILENO, TCSANOW, &attr) == -1) return true; s_il2cppAttr = attr; return true; } static void SetControlChars(uint8_t* control_chars, const uint8_t *cc) { // The index into the array comes from corlib/System/ControlCharacters.cs #ifdef VINTR control_chars[0] = cc[VINTR]; #endif #ifdef VQUIT control_chars[1] = cc[VQUIT]; #endif #ifdef VERASE control_chars[2] = cc[VERASE]; #endif #ifdef VKILL control_chars[3] = cc[VKILL]; #endif #ifdef VEOF control_chars[4] = cc[VEOF]; #endif #ifdef VTIME control_chars[5] = cc[VTIME]; #endif #ifdef VMIN control_chars[6] = cc[VMIN]; #endif #ifdef VSWTC control_chars[7] = cc[VSWTC]; #endif #ifdef VSTART control_chars[8] = cc[VSTART]; #endif #ifdef VSTOP control_chars[9] = cc[VSTOP]; #endif #ifdef VSUSP control_chars[10] = cc[VSUSP]; #endif #ifdef VEOL control_chars[11] = cc[VEOL]; #endif #ifdef VREPRINT control_chars[12] = cc[VREPRINT]; #endif #ifdef VDISCARD control_chars[13] = cc[VDISCARD]; #endif #ifdef VWERASE control_chars[14] = cc[VWERASE]; #endif #ifdef VLNEXT control_chars[15] = cc[VLNEXT]; #endif #ifdef VEOL2 control_chars[16] = cc[VEOL2]; #endif } static void CallDoConsoleCancelEvent() { // TODO: Call Console.cancel_handler delegate from another thread. } static void SigintHandler(int signo) { static bool insideSigint = false; if (insideSigint) return; insideSigint = true; CallDoConsoleCancelEvent(); insideSigint = false; } static void SigcontHandler(int signo, siginfo_t *the_siginfo, void *data) { // Ignore error, there is not much we can do in the sigcont handler. tcsetattr(STDIN_FILENO, TCSANOW, &s_il2cppAttr); if (!s_keypadXmit.empty()) write(STDOUT_FILENO, s_keypadXmit.c_str(), s_keypadXmit.length()); // Call previous handler if (s_saveSigcont.sa_sigaction != NULL && s_saveSigcont.sa_sigaction != (void*)SIG_DFL && s_saveSigcont.sa_sigaction != (void*)SIG_IGN) (*s_saveSigcont.sa_sigaction)(signo, the_siginfo, data); } static void SigwinchHandler(int signo, siginfo_t *the_siginfo, void *data) { const int32_t size = GetTerminalSize(); if (size != -1) s_terminalSize = size; // Call previous handler if (s_saveSigwinch.sa_sigaction != NULL && s_saveSigwinch.sa_sigaction != (void*)SIG_DFL && s_saveSigwinch.sa_sigaction != (void*)SIG_IGN) (*s_saveSigwinch.sa_sigaction)(signo, the_siginfo, data); } static void ConsoleSetupSignalHandler() { struct sigaction sigcont, sigint, sigwinch; memset(&sigcont, 0, sizeof(struct sigaction)); memset(&sigint, 0, sizeof(struct sigaction)); memset(&sigwinch, 0, sizeof(struct sigaction)); // Continuing sigcont.sa_sigaction = SigcontHandler; sigcont.sa_flags = SA_SIGINFO; sigemptyset(&sigcont.sa_mask); sigaction(SIGCONT, &sigcont, &s_saveSigcont); // Interrupt handler sigint.sa_handler = SigintHandler; sigint.sa_flags = 0; sigemptyset(&sigint.sa_mask); sigaction(SIGINT, &sigint, &s_saveSigint); // Window size changed sigwinch.sa_sigaction = SigwinchHandler; sigwinch.sa_flags = SA_SIGINFO; sigemptyset(&sigwinch.sa_mask); sigaction(SIGWINCH, &sigwinch, &s_saveSigwinch); } // Exists in Mono, but is unused. static void ConsoleRestoreSignalHandlers() { sigaction(SIGCONT, &s_saveSigcont, NULL); sigaction(SIGINT, &s_saveSigint, NULL); sigaction(SIGWINCH, &s_saveSigwinch, NULL); } int32_t InternalKeyAvailable(int32_t ms_timeout) { fd_set rfds; struct timeval tv; struct timeval *tvptr; div_t divvy; int32_t ret, nbytes; do { FD_ZERO(&rfds); FD_SET(STDIN_FILENO, &rfds); if (ms_timeout >= 0) { divvy = div(ms_timeout, 1000); tv.tv_sec = divvy.quot; tv.tv_usec = divvy.rem; tvptr = &tv; } else { tvptr = NULL; } ret = select(STDIN_FILENO + 1, &rfds, NULL, NULL, tvptr); } while (ret == -1 && errno == EINTR); if (ret > 0) { nbytes = 0; ret = ioctl(STDIN_FILENO, FIONREAD, &nbytes); if (ret >= 0) ret = nbytes; } return (ret > 0) ? ret : 0; } bool SetBreak(bool wantBreak) { return SetProperty(IGNBRK, !wantBreak); } bool SetEcho(bool wantEcho) { return SetProperty(ECHO, wantEcho); } static void TtyShutdown() { if (!setupComplete) return; if (!s_teardown.empty()) write(STDOUT_FILENO, s_teardown.c_str(), s_teardown.length()); tcflush(STDIN_FILENO, TCIFLUSH); tcsetattr(STDIN_FILENO, TCSANOW, &s_initialAttr); SetProperty(ECHO, true); setupComplete = false; } bool TtySetup(const std::string& keypadXmit, const std::string& teardown, uint8_t* control_characters, int32_t** size) { s_terminalSize = GetTerminalSize(); if (s_terminalSize == -1) { int32_t cols = 0, rows = 0; const char *colsValue = getenv("COLUMNS"); if (colsValue != NULL) cols = atoi(colsValue); const char *linesValue = getenv("LINES"); if (linesValue != NULL) rows = atoi(linesValue); if (cols != 0 && rows != 0) s_terminalSize = (cols << 16) | rows; else s_terminalSize = -1; } *size = &s_terminalSize; if (tcgetattr(STDIN_FILENO, &s_initialAttr) == -1) return false; s_il2cppAttr = s_initialAttr; s_il2cppAttr.c_lflag &= ~(ICANON); s_il2cppAttr.c_iflag &= ~(IXON | IXOFF); s_il2cppAttr.c_cc[VMIN] = 1; s_il2cppAttr.c_cc[VTIME] = 0; if (tcsetattr(STDIN_FILENO, TCSANOW, &s_il2cppAttr) == -1) return false; s_keypadXmit = keypadXmit; SetControlChars(control_characters, s_il2cppAttr.c_cc); if (setupComplete) return true; ConsoleSetupSignalHandler(); setupComplete = true; s_teardown = teardown; atexit(TtyShutdown); return true; } } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/CpuInfo.cpp ================================================ #if NET_4_0 #if IL2CPP_ENABLE_CPU_INFO #include "il2cpp-config.h" #if IL2CPP_TARGET_POSIX #include "os/CpuInfo.h" #include #include #include "utils/Memory.h" #include "os/Time.h" #include "os/Environment.h" #include #if IL2CPP_TARGET_DARWIN #include #endif #include #include #if IL2CPP_TARGET_LINUX || IL2CPP_TARGET_TIZEN #include #endif struct Il2CppCpuUsageState { int64_t kernel_time; int64_t user_time; int64_t current_time; }; namespace il2cpp { namespace os { void* CpuInfo::Create() { return IL2CPP_MALLOC_ZERO(sizeof(Il2CppCpuUsageState)); } int32_t CpuInfo::Usage(void* previous) { Il2CppCpuUsageState* prev = (Il2CppCpuUsageState*)previous; int32_t cpu_usage = 0; int64_t cpu_total_time; int64_t cpu_busy_time; struct rusage resource_usage; int64_t current_time; int64_t kernel_time; int64_t user_time; if (getrusage(RUSAGE_SELF, &resource_usage) == -1) { return -1; } current_time = os::Time::GetTicks100NanosecondsMonotonic(); kernel_time = resource_usage.ru_stime.tv_sec * 1000 * 1000 * 10 + resource_usage.ru_stime.tv_usec * 10; user_time = resource_usage.ru_utime.tv_sec * 1000 * 1000 * 10 + resource_usage.ru_utime.tv_usec * 10; cpu_busy_time = (user_time - (prev ? prev->user_time : 0)) + (kernel_time - (prev ? prev->kernel_time : 0)); cpu_total_time = (current_time - (prev ? prev->current_time : 0)) * il2cpp::os::Environment::GetProcessorCount(); if (prev) { prev->kernel_time = kernel_time; prev->user_time = user_time; prev->current_time = current_time; } if (cpu_total_time > 0 && cpu_busy_time > 0) cpu_usage = (int32_t)(cpu_busy_time * 100 / cpu_total_time); return cpu_usage; } } } #endif #endif #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/Cryptography.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_POSIX #include "os/Cryptography.h" #include #include #include #ifndef NAME_DEV_URANDOM #define NAME_DEV_URANDOM "/dev/urandom" #endif static int64_t file = -1; namespace il2cpp { namespace os { void* Cryptography::GetCryptographyProvider() { return (file < 0) ? NULL : (void*)file; } bool Cryptography::OpenCryptographyProvider() { #ifdef NAME_DEV_URANDOM file = open(NAME_DEV_URANDOM, O_RDONLY); #endif #ifdef NAME_DEV_RANDOM if (file < 0) file = open(NAME_DEV_RANDOM, O_RDONLY); #endif return true; } void Cryptography::ReleaseCryptographyProvider(void* provider) { } bool Cryptography::FillBufferWithRandomBytes(void* provider, uint32_t length, unsigned char* data) { int count = 0; ssize_t err; // Make sure the provider is correct, or we may end up reading from the wrong file. // If provider happens to be 0 we will read from stdin and hang! if ((int64_t)provider != file) return false; do { err = read((int)(size_t)provider, data + count, length - count); if (err < 0) { if (errno == EINTR) continue; break; } count += err; } while (count < length); return err >= 0; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/Directory.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_POSIX #include "os/Directory.h" #include "os/ErrorCodes.h" #include "os/File.h" #include "os/Posix/Error.h" #include "utils/DirectoryUtils.h" #include "utils/Memory.h" #include "utils/PathUtils.h" #include "utils/StringUtils.h" #include #include #include #include #include #include #include #include #include namespace il2cpp { namespace os { std::string Directory::GetCurrent(int *error) { char buf[PATH_MAX + 1]; // Note: not all implementations would allocate a buffer when passing 0 to getcwd, as we used to do. // this does *not* seem to be part of the POSIX spec: // http://pubs.opengroup.org/onlinepubs/000095399/functions/getcwd.html char* cwd = getcwd(buf, PATH_MAX + 1); if (cwd == NULL) { *error = FileErrnoToErrorCode(errno); return std::string(); } std::string directory(cwd); *error = kErrorCodeSuccess; return directory; } bool Directory::SetCurrent(const std::string& path, int *error) { const int ret = chdir(path.c_str()); if (ret == -1) { *error = FileErrnoToErrorCode(errno); return false; } *error = kErrorCodeSuccess; return true; } bool Directory::Create(const std::string& path, int *error) { const int ret = mkdir(path.c_str(), 0777); if (ret == -1) { *error = PathErrnoToErrorCode(path, errno); return false; } *error = kErrorCodeSuccess; return true; } bool Directory::Remove(const std::string& path, int *error) { const int ret = rmdir(path.c_str()); if (ret == -1) { *error = PathErrnoToErrorCode(path, errno); return false; } *error = kErrorCodeSuccess; return true; } static void DirectoryGlob(DIR *dir, const std::string& pattern, std::set& result) { if (pattern.empty()) return; std::string matchPattern = il2cpp::utils::CollapseAdjacentStars(pattern); struct dirent *entry; while ((entry = readdir(dir)) != NULL) { const std::string filename(entry->d_name); if (!il2cpp::utils::Match(filename, matchPattern)) continue; result.insert(filename); } } static bool DirectoryGlob(const std::string& directoryPath, const std::string& pattern, std::set& result, int* error) { DIR* dir = opendir(directoryPath.c_str()); if (dir == NULL) { *error = PathErrnoToErrorCode(directoryPath, errno); return false; } DirectoryGlob(dir, pattern, result); closedir(dir); return true; } std::set Directory::GetFileSystemEntries(const std::string& path, const std::string& pathWithPattern, int32_t attributes, int32_t mask, int* error) { const std::string directoryPath(il2cpp::utils::PathUtils::DirectoryName(pathWithPattern)); const std::string pattern(il2cpp::utils::PathUtils::Basename(pathWithPattern)); std::set globResult; if (DirectoryGlob(directoryPath, pattern, globResult, error) == false) return std::set(); if (il2cpp::utils::StringUtils::EndsWith(pattern, ".*")) { /* Special-case the patterns ending in '.*', as * windows also matches entries with no extension with * this pattern. */ if (DirectoryGlob(directoryPath, pattern.substr(0, pattern.length() - 2), globResult, error) == false) return std::set(); } std::set result; for (std::set::const_iterator it = globResult.begin(), end = globResult.end(); it != end; ++it) { const std::string& filename = *it; if (filename == "." || filename == "..") continue; const std::string path(directoryPath + IL2CPP_DIR_SEPARATOR + filename); int attributeError; const int32_t pathAttributes = static_cast(File::GetFileAttributes(path, &attributeError)); if (attributeError != kErrorCodeSuccess) continue; if ((pathAttributes & mask) == attributes) result.insert(path); } *error = kErrorCodeSuccess; return result; } Directory::FindHandle::FindHandle(const utils::StringView& searchPathWithPattern) : osHandle(NULL) { directoryPath = il2cpp::utils::PathUtils::DirectoryName(searchPathWithPattern); pattern = il2cpp::utils::PathUtils::Basename(searchPathWithPattern); // Special-case the patterns ending in '.*', as windows also matches entries with no extension with this pattern. if (il2cpp::utils::StringUtils::EndsWith(pattern, ".*")) { pattern.erase(pattern.size() - 1, 1); *pattern.rbegin() = '*'; } pattern = il2cpp::utils::CollapseAdjacentStars(pattern); } Directory::FindHandle::~FindHandle() { IL2CPP_ASSERT(osHandle == NULL); } int32_t Directory::FindHandle::CloseOSHandle() { int32_t result = os::kErrorCodeSuccess; if (osHandle != NULL) { int32_t ret = closedir(static_cast(osHandle)); if (ret != 0) result = FileErrnoToErrorCode(errno); osHandle = NULL; } return result; } os::ErrorCode Directory::FindFirstFile(FindHandle* findHandle, const utils::StringView& searchPathWithPattern, Il2CppNativeString* resultFileName, int32_t* resultAttributes) { DIR* dir = opendir(findHandle->directoryPath.c_str()); if (dir == NULL) return PathErrnoToErrorCode(findHandle->directoryPath, errno); findHandle->SetOSHandle(dir); return FindNextFile(findHandle, resultFileName, resultAttributes); } os::ErrorCode Directory::FindNextFile(FindHandle* findHandle, Il2CppNativeString* resultFileName, int32_t* resultAttributes) { errno = 0; dirent* entry; while ((entry = readdir(static_cast(findHandle->osHandle))) != NULL) { const Il2CppNativeString filename(entry->d_name); if (il2cpp::utils::Match(filename, findHandle->pattern)) { const Il2CppNativeString path = utils::PathUtils::Combine(findHandle->directoryPath, filename); int attributeError; const int32_t pathAttributes = static_cast(File::GetFileAttributes(path, &attributeError)); if (attributeError == kErrorCodeSuccess) { *resultFileName = filename; *resultAttributes = pathAttributes; return os::kErrorCodeSuccess; } } } if (errno != 0) return FileErrnoToErrorCode(errno); return os::kErrorCodeNoMoreFiles; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/Encoding.cpp ================================================ #include "il2cpp-config.h" #if !IL2CPP_USE_GENERIC_ENVIRONMENT && IL2CPP_TARGET_POSIX #include "os/Encoding.h" #ifdef HAVE_LANGINFO_H #include #endif namespace il2cpp { namespace os { namespace Encoding { std::string GetCharSet() { #if HAVE_LANGINFO_H return nl_langinfo(CODESET); #else return "UTF-8"; #endif } } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/Environment.cpp ================================================ #include "il2cpp-config.h" #include "il2cpp-vm-support.h" #if !IL2CPP_USE_GENERIC_ENVIRONMENT && IL2CPP_TARGET_POSIX && !IL2CPP_TARGET_PS4 #include "class-internals.h" #include "os/Environment.h" #include "il2cpp-api.h" #include #include #include #if defined(__APPLE__) && !defined(__arm__) // Apple defines this in crt_externs.h but doesn't provide that header for // arm-apple-darwin9. We'll manually define the symbol on Apple as it does // in fact exist on all implementations (so far) extern "C" char*** _NSGetEnviron(void); #define environ (*_NSGetEnviron()) #else extern char **environ; // GNU C library #endif namespace il2cpp { namespace os { std::string Environment::GetMachineName() { char buf[256]; if (gethostname(buf, sizeof(buf)) != 0) return NULL; return buf; } int32_t Environment::GetProcessorCount() { int count = 1; #ifdef _SC_NPROCESSORS_ONLN count = (int)sysconf(_SC_NPROCESSORS_ONLN); if (count > 0) return count; #endif #ifdef USE_SYSCTL { int mib[2]; size_t len = sizeof(int); mib[0] = CTL_HW; mib[1] = HW_NCPU; if (sysctl(mib, 2, &count, &len, NULL, 0) == 0) return count; } #endif return count; } std::string Environment::GetOsVersionString() { struct utsname name; if (uname(&name) >= 0) return name.release; return "0.0.0.0"; } std::string Environment::GetOsUserName() { const std::string username(GetEnvironmentVariable("USER")); return username.empty() ? "Unknown" : username; } std::string Environment::GetEnvironmentVariable(const std::string& name) { const char* variable = getenv(name.c_str()); return variable ? std::string(variable) : std::string(); } void Environment::SetEnvironmentVariable(const std::string& name, const std::string& value) { if (value.empty()) { unsetenv(name.c_str()); } else { setenv(name.c_str(), value.c_str(), 1); // 1 means overwrite } } std::vector Environment::GetEnvironmentVariableNames() { std::vector result; for (char **envvar = environ; *envvar != NULL; ++envvar) { const char* equalAddress = strchr(*envvar, '='); if (equalAddress != NULL) result.push_back(std::string(*envvar, size_t(equalAddress - *envvar))); } return result; } std::string Environment::GetHomeDirectory() { static std::string homeDirectory; if (!homeDirectory.empty()) return homeDirectory; homeDirectory = GetEnvironmentVariable("HOME"); return homeDirectory.empty() ? "/" : homeDirectory; } std::vector Environment::GetLogicalDrives() { std::vector result; // This implementation is not correct according to the definition of this icall, but this is // the only "logical drive" that the Mono version in Unity returns for OSX. result.push_back("/"); // TODO: Implement additional logic for Linux return result; } void Environment::Exit(int result) { IL2CPP_VM_SHUTDOWN(); exit(result); } NORETURN void Environment::Abort() { abort(); } std::string Environment::GetWindowsFolderPath(int folder) { // This should only be called on Windows. return std::string(); } #if NET_4_0 bool Environment::Is64BitOs() { struct utsname name; if (uname(&name) >= 0) { return strcmp(name.machine, "x86_64") == 0 || strncmp(name.machine, "aarch64", 7) == 0 || strncmp(name.machine, "ppc64", 5) == 0; } return false; } #endif } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/Error.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_POSIX #include "Error.h" #include "utils/PathUtils.h" #include #include #include namespace il2cpp { namespace os { ErrorCode SocketErrnoToErrorCode(int32_t code) { ErrorCode result = (ErrorCode) - 1; switch (code) { case 0: result = kErrorCodeSuccess; break; case EACCES: result = kWSAeacces; break; #ifdef EADDRINUSE case EADDRINUSE: result = kWSAeaddrinuse; break; #endif #ifdef EAFNOSUPPORT case EAFNOSUPPORT: result = kWSAeafnosupport; break; #endif #if EAGAIN != EWOULDBLOCK case EAGAIN: result = kWSAewouldblock; break; #endif #ifdef EALREADY case EALREADY: result = kWSAealready; break; #endif case EBADF: result = kWSAenotsock; break; #ifdef ECONNABORTED case ECONNABORTED: result = kWSAenetdown; break; #endif #ifdef ECONNREFUSED case ECONNREFUSED: result = kWSAeconnrefused; break; #endif #ifdef ECONNRESET case ECONNRESET: result = kWSAeconnreset; break; #endif case EFAULT: result = kWSAefault; break; #ifdef EHOSTUNREACH case EHOSTUNREACH: result = kWSAehostunreach; break; #endif #ifdef EINPROGRESS case EINPROGRESS: result = kWSAeinprogress; break; #endif case EINTR: result = kWSAeintr; break; case EINVAL: result = kWSAeinval; break; // FIXME: case EIO: result = WSAE????; break; #ifdef EISCONN case EISCONN: result = kWSAeisconn; break; #endif // FIXME: case ELOOP: result = WSA????; break; case EMFILE: result = kWSAemfile; break; #ifdef EMSGSIZE case EMSGSIZE: result = kWSAemsgsize; break; #endif // FIXME: case ENAMETOOLONG: result = kWSAeacces; break; #ifdef ENETUNREACH case ENETUNREACH: result = kWSAenetunreach; break; #endif #ifdef ENOBUFS case ENOBUFS: result = kWSAenobufs; break; #endif // case ENOENT: result = WSAE????; break; case ENOMEM: result = kWSAenobufs; break; #ifdef ENOPROTOOPT case ENOPROTOOPT: result = kWSAenoprotoopt; break; #endif #ifdef ENOSR case ENOSR: result = kWSAenetdown; break; #endif #ifdef ENOTCONN case ENOTCONN: result = kWSAenotconn; break; #endif // FIXME: case ENOTDIR: result = WSAE????; break; #ifdef ENOTSOCK case ENOTSOCK: result = kWSAenotsock; break; #endif case ENOTTY: result = kWSAenotsock; break; #ifdef EOPNOTSUPP case EOPNOTSUPP: result = kWSAeopnotsupp; break; #endif case EPERM: result = kWSAeacces; break; case EPIPE: result = kWSAeshutdown; break; #ifdef EPROTONOSUPPORT case EPROTONOSUPPORT: result = kWSAeprotonosupport; break; #endif #if ERESTARTSYS case ERESTARTSYS: result = kWSAenetdown; break; #endif // FIXME: case EROFS: result = WSAE????; break; #ifdef ESOCKTNOSUPPORT case ESOCKTNOSUPPORT: result = kWSAesocktnosupport; break; #endif #ifdef ETIMEDOUT case ETIMEDOUT: result = kWSAetimedout; break; #endif #ifdef EWOULDBLOCK case EWOULDBLOCK: result = kWSAewouldblock; break; #endif #ifdef EADDRNOTAVAIL case EADDRNOTAVAIL: result = kWSAeaddrnotavail; break; #endif case ENOENT: result = kWSAeconnrefused; break; #ifdef EDESTADDRREQ case EDESTADDRREQ: result = kWSAedestaddrreq; break; #endif case ENODEV: result = kWSAenetdown; break; #ifdef EHOSTDOWN case EHOSTDOWN: result = kWSAehostdown; break; #endif #ifdef ENXIO case ENXIO: result = kWSAhostNotFound; break; #endif default: result = kWSAsyscallfailure; break; } return result; } ErrorCode FileErrnoToErrorCode(int32_t code) { ErrorCode ret; /* mapping ideas borrowed from wine. they may need some work */ switch (code) { case EACCES: case EPERM: case EROFS: ret = kErrorCodeAccessDenied; break; case EAGAIN: ret = kErrorCodeSharingViolation; break; case EBUSY: ret = kErrorCodeLockViolation; break; case EEXIST: ret = kErrorCodeFileExists; break; case EINVAL: case ESPIPE: ret = kErrorSeek; break; case EISDIR: ret = kErrorCodeCannotMake; break; case ENFILE: case EMFILE: ret = kErrorCodeTooManyOpenFiles; break; case ENOENT: case ENOTDIR: ret = kErrorCodeFileNotFound; break; case ENOSPC: ret = kErrorCodeHandleDiskFull; break; case ENOTEMPTY: ret = kErrorCodeDirNotEmpty; break; case ENOEXEC: ret = kErrorBadFormat; break; case ENAMETOOLONG: ret = kErrorCodeFileNameExcedRange; break; #ifdef EINPROGRESS case EINPROGRESS: ret = kErrorIoPending; break; #endif case ENOSYS: ret = kErrorNotSupported; break; case EBADF: ret = kErrorCodeInvalidHandle; break; case EIO: ret = kErrorCodeInvalidHandle; break; case EINTR: ret = kErrorIoPending; break; case EPIPE: ret = kErrorCodeWriteFault; break; default: ret = kErrorCodeGenFailure; break; } return ret; } ErrorCode PathErrnoToErrorCode(const std::string& path, int32_t code) { if (code == ENOENT) { const std::string dirname(il2cpp::utils::PathUtils::DirectoryName(path)); #if !IL2CPP_TARGET_PS4 && !IL2CPP_TARGET_PSP2 if (access(dirname.c_str(), F_OK) == 0) return kErrorCodeFileNotFound; else #endif return kErrorCodePathNotFound; } else return FileErrnoToErrorCode(code); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/Error.h ================================================ #pragma once #include #include #include "os/ErrorCodes.h" namespace il2cpp { namespace os { ErrorCode SocketErrnoToErrorCode(int32_t code); ErrorCode FileErrnoToErrorCode(int32_t code); ErrorCode PathErrnoToErrorCode(const std::string& path, int32_t code); } } ================================================ FILE: unity_decoder/libil2cpp/os/Posix/EventImpl.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_THREADS_PTHREAD #include "EventImpl.h" #include "PosixHelpers.h" #include namespace il2cpp { namespace os { EventImpl::EventImpl(bool manualReset, bool signaled) : posix::PosixWaitObject(manualReset ? kManualResetEvent : kAutoResetEvent) { if (signaled) m_Count = 1; } ErrorCode EventImpl::Set() { posix::PosixAutoLock lock(&m_Mutex); m_Count = 1; if (HaveWaitingThreads()) pthread_cond_broadcast(&m_Condition); return kErrorCodeSuccess; } ErrorCode EventImpl::Reset() { posix::PosixAutoLock lock(&m_Mutex); m_Count = 0; return kErrorCodeSuccess; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/EventImpl.h ================================================ #pragma once #if IL2CPP_THREADS_PTHREAD #include "os/ErrorCodes.h" #include "os/WaitStatus.h" #include "PosixWaitObject.h" #include namespace il2cpp { namespace os { class EventImpl : public posix::PosixWaitObject { public: EventImpl(bool manualReset = false, bool signaled = false); ErrorCode Set(); ErrorCode Reset(); }; } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/File.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_POSIX #include "FileHandle.h" #if IL2CPP_USE_POSIX_FILE_PLATFORM_CONFIG #include "FilePlatformConfig.h" #endif #include "os/ErrorCodes.h" #include "os/File.h" #include "os/Mutex.h" #include "os/Posix/Error.h" #include "utils/PathUtils.h" #include #include #include #include #include #include #include #include #define INVALID_FILE_HANDLE (FileHandle*)-1; #define INVALID_FILE_ATTRIBUTES (UnityPalFileAttributes)((uint32_t)-1); #define TIME_ZERO 116444736000000000ULL namespace il2cpp { namespace os { // Head and tail of linked list. static FileHandle* s_fileHandleHead = NULL; static FileHandle* s_fileHandleTail = NULL; static FastMutex s_fileHandleMutex; static void AddFileHandle(FileHandle *fileHandle) { FastAutoLock autoLock(&s_fileHandleMutex); if (s_fileHandleHead == NULL) { IL2CPP_ASSERT(s_fileHandleTail == NULL); s_fileHandleHead = fileHandle; s_fileHandleTail = fileHandle; } else { IL2CPP_ASSERT(s_fileHandleTail != NULL); IL2CPP_ASSERT(s_fileHandleTail->next == NULL); s_fileHandleTail->next = fileHandle; fileHandle->prev = s_fileHandleTail; s_fileHandleTail = fileHandle; } } static void RemoveFileHandle(il2cpp::os::FileHandle *fileHandle) { FastAutoLock autoLock(&s_fileHandleMutex); if (s_fileHandleHead == fileHandle) s_fileHandleHead = fileHandle->next; if (s_fileHandleTail == fileHandle) s_fileHandleTail = fileHandle->prev; if (fileHandle->prev) fileHandle->prev->next = fileHandle->next; if (fileHandle->next) fileHandle->next->prev = fileHandle->prev; } static const FileHandle* FindFileHandle(const struct stat& statBuf) { FastAutoLock autoLock(&s_fileHandleMutex); const dev_t device = statBuf.st_dev; const ino_t inode = statBuf.st_ino; for (FileHandle *handle = s_fileHandleHead; handle != NULL; handle = handle->next) { if (handle->device == device && handle->inode == inode) return handle; } return NULL; } // NOTE: // Checking for file sharing violations only works for the current process. // // Mono implements this feature across processes by storing the file handles as // a look up table in a shared file. static bool ShareAllowOpen(const struct stat& statBuf, int shareMode, int accessMode) { const FileHandle *fileHandle = FindFileHandle(statBuf); if (fileHandle == NULL) // File is not open return true; if (fileHandle->shareMode == kFileShareNone) return false; if (((fileHandle->shareMode == kFileShareRead) && (accessMode != kFileAccessRead)) || ((fileHandle->shareMode == kFileShareWrite) && (accessMode != kFileAccessWrite))) { return false; } if (((fileHandle->accessMode & kFileAccessRead) && !(shareMode & kFileShareRead)) || ((fileHandle->accessMode & kFileAccessWrite) && !(shareMode & kFileShareWrite))) { return false; } return true; } static UnityPalFileAttributes StatToFileAttribute(const std::string& path, struct stat& pathStat, struct stat* linkStat) { uint32_t fileAttributes = 0; if (S_ISSOCK(pathStat.st_mode)) pathStat.st_mode &= ~S_IFSOCK; // don't consider socket protection #if defined(__APPLE__) && defined(__MACH__) if ((pathStat.st_flags & UF_IMMUTABLE) || (pathStat.st_flags & SF_IMMUTABLE)) fileAttributes |= kFileAttributeReadOnly; #endif const std::string filename(il2cpp::utils::PathUtils::Basename(path)); if (S_ISDIR(pathStat.st_mode)) { fileAttributes = kFileAttributeDirectory; if (!(pathStat.st_mode & S_IWUSR) && !(pathStat.st_mode & S_IWGRP) && !(pathStat.st_mode & S_IWOTH)) fileAttributes |= kFileAttributeReadOnly; if (filename[0] == '.') fileAttributes |= kFileAttributeHidden; } else { if (!(pathStat.st_mode & S_IWUSR) && !(pathStat.st_mode & S_IWGRP) && !(pathStat.st_mode & S_IWOTH)) { fileAttributes = kFileAttributeReadOnly; if (filename[0] == '.') fileAttributes |= kFileAttributeHidden; } else if (filename[0] == '.') fileAttributes = kFileAttributeHidden; else fileAttributes = kFileAttributeNormal; } if (linkStat != NULL && S_ISLNK(linkStat->st_mode)) fileAttributes |= kFileAttributeReparse_point; return (UnityPalFileAttributes)fileAttributes; } static int GetStatAndLinkStat(const std::string& path, struct stat& pathStat, struct stat& linkStat) { const int statResult = stat(path.c_str(), &pathStat); if (statResult == -1 && errno == ENOENT && lstat(path.c_str(), &pathStat) != 0) // Might be a dangling symlink... return PathErrnoToErrorCode(path, errno); if (lstat(path.c_str(), &linkStat) != 0) return PathErrnoToErrorCode(path, errno); return kErrorCodeSuccess; } static uint64_t TimeToTicks(time_t timeval) { return ((uint64_t)timeval * 10000000) + TIME_ZERO; } static time_t TicksToTime(uint64_t ticks) { return (ticks - TIME_ZERO) / 10000000; } static bool InternalCopyFile(int srcFd, int destFd, const struct stat& srcStat, int *error) { const blksize_t preferedBlockSize = srcStat.st_blksize; const blksize_t bufferSize = preferedBlockSize < 8192 ? 8192 : (preferedBlockSize > 65536 ? 65536 : preferedBlockSize); char *buffer = new char[bufferSize]; ssize_t readBytes; while ((readBytes = read(srcFd, buffer, bufferSize)) > 0) { char* writeBuffer = buffer; ssize_t writeBytes = readBytes; while (writeBytes > 0) { const ssize_t writtenBytes = write(destFd, writeBuffer, writeBytes); if (writtenBytes < 0) { if (errno == EINTR) continue; delete[] buffer; *error = FileErrnoToErrorCode(errno); return false; } writeBytes -= writtenBytes; writeBuffer += writtenBytes; } } delete[] buffer; if (readBytes < 0) { *error = FileErrnoToErrorCode(errno); return false; } IL2CPP_ASSERT(readBytes == 0); return true; } bool File::Isatty(FileHandle* fileHandle) { return isatty(fileHandle->fd) == 1; } FileHandle* File::GetStdError() { static FileHandle* s_handle = NULL; if (s_handle) return s_handle; s_handle = new FileHandle(); s_handle->fd = 2; s_handle->type = kFileTypeChar; s_handle->options = 0; s_handle->accessMode = kFileAccessReadWrite; s_handle->shareMode = -1; // Only used for files return s_handle; } FileHandle* File::GetStdInput() { static FileHandle* s_handle = NULL; if (s_handle) return s_handle; s_handle = new FileHandle(); s_handle->fd = 0; s_handle->type = kFileTypeChar; s_handle->options = 0; s_handle->accessMode = kFileAccessRead; s_handle->shareMode = -1; // Only used for files return s_handle; } FileHandle* File::GetStdOutput() { static FileHandle* s_handle = NULL; if (s_handle) return s_handle; s_handle = new FileHandle(); s_handle->fd = 1; s_handle->type = kFileTypeChar; s_handle->options = 0; s_handle->accessMode = kFileAccessReadWrite; s_handle->shareMode = -1; // Only used for files return s_handle; } bool File::CreatePipe(FileHandle** read_handle, FileHandle** write_handle) { int error; return File::CreatePipe(read_handle, write_handle, &error); } bool File::CreatePipe(FileHandle** read_handle, FileHandle** write_handle, int* error) { int fds[2]; const int ret = pipe(fds); if (ret == -1) { *error = FileErrnoToErrorCode(errno); return false; } FileHandle *input = new FileHandle(); input->fd = fds[0]; input->type = kFileTypePipe; input->options = 0; input->accessMode = kFileAccessRead; input->shareMode = -1; // Only used for files FileHandle *output = new FileHandle(); output->fd = fds[1]; output->type = kFileTypePipe; output->options = 0; output->accessMode = kFileAccessReadWrite; output->shareMode = -1; // Only used for files *read_handle = input; *write_handle = output; return true; } UnityPalFileAttributes File::GetFileAttributes(const std::string& path, int *error) { struct stat pathStat, linkStat; *error = GetStatAndLinkStat(path, pathStat, linkStat); if (*error != kErrorCodeSuccess) return INVALID_FILE_ATTRIBUTES; return StatToFileAttribute(path, pathStat, &linkStat); } bool File::SetFileAttributes(const std::string& path, UnityPalFileAttributes attributes, int* error) { struct stat pathStat; int ret = stat(path.c_str(), &pathStat); if (ret != 0) { *error = PathErrnoToErrorCode(path, errno); return false; } if (attributes & kFileAttributeReadOnly) ret = chmod(path.c_str(), pathStat.st_mode & ~(S_IWUSR | S_IWOTH | S_IWGRP)); else ret = chmod(path.c_str(), pathStat.st_mode | S_IWUSR); if (ret != 0) { *error = PathErrnoToErrorCode(path, errno); return false; } // Mono ignores all other attributes if (attributes & kFileAttributeInternalMonoExecutable) { mode_t exec_mask = 0; if ((pathStat.st_mode & S_IRUSR) != 0) exec_mask |= S_IXUSR; if ((pathStat.st_mode & S_IRGRP) != 0) exec_mask |= S_IXGRP; if ((pathStat.st_mode & S_IROTH) != 0) exec_mask |= S_IXOTH; ret = chmod(path.c_str(), pathStat.st_mode | exec_mask); if (ret != 0) { *error = PathErrnoToErrorCode(path, errno); return false; } } return true; } bool File::GetFileStat(const std::string& path, il2cpp::os::FileStat * stat, int* error) { struct stat pathStat, linkStat; *error = GetStatAndLinkStat(path, pathStat, linkStat); if (*error != kErrorCodeSuccess) return false; const std::string filename(il2cpp::utils::PathUtils::Basename(path)); const time_t creationTime = pathStat.st_mtime < pathStat.st_ctime ? pathStat.st_mtime : pathStat.st_ctime; stat->name = filename; stat->attributes = StatToFileAttribute(path, pathStat, &linkStat); stat->length = (stat->attributes & kFileAttributeDirectory) > 0 ? 0 : pathStat.st_size; stat->creation_time = TimeToTicks(creationTime); stat->last_access_time = TimeToTicks(pathStat.st_atime); stat->last_write_time = TimeToTicks(pathStat.st_mtime); return true; } FileType File::GetFileType(FileHandle* handle) { return ((FileHandle*)handle)->type; } bool File::DeleteFile(const std::string& path, int *error) { const UnityPalFileAttributes attributes = GetFileAttributes(path, error); if (*error != kErrorCodeSuccess) { return false; } if (attributes & kFileAttributeReadOnly) { *error = kErrorCodeAccessDenied; return false; } const int ret = unlink(path.c_str()); if (ret == -1) { *error = PathErrnoToErrorCode(path, errno); return false; } *error = kErrorCodeSuccess; return true; } bool File::CopyFile(const std::string& src, const std::string& dest, bool overwrite, int* error) { const int srcFd = open(src.c_str(), O_RDONLY, 0); if (srcFd < 0) { *error = PathErrnoToErrorCode(src, errno); return false; } struct stat srcStat; if (fstat(srcFd, &srcStat) < 0) { *error = FileErrnoToErrorCode(errno); close(srcFd); return false; } int destFd; if (!overwrite) { destFd = open(dest.c_str(), O_WRONLY | O_CREAT | O_EXCL, srcStat.st_mode); } else { destFd = open(dest.c_str(), O_WRONLY | O_TRUNC, srcStat.st_mode); if (destFd < 0) destFd = open(dest.c_str(), O_WRONLY | O_CREAT | O_TRUNC, srcStat.st_mode); else *error = kErrorCodeAlreadyExists; // Apparently this error is set if we overwrite the dest file } if (destFd < 0) { *error = FileErrnoToErrorCode(errno); close(srcFd); return false; } const bool ret = InternalCopyFile(srcFd, destFd, srcStat, error); close(srcFd); close(destFd); return ret; } bool File::MoveFile(const std::string& src, const std::string& dest, int* error) { struct stat srcStat, destStat; if (stat(src.c_str(), &srcStat) < 0) { *error = PathErrnoToErrorCode(src.c_str(), errno); return false; } // In C# land we check for the existence of src, but not for dest. // We check it here and return the failure if dest exists and is not // the same file as src. if (stat(dest.c_str(), &destStat) == 0) // dest exists { if (destStat.st_dev != srcStat.st_dev || destStat.st_ino != srcStat.st_ino) { *error = kErrorCodeAlreadyExists; return false; } } if (!ShareAllowOpen(srcStat, kFileShareNone, kFileAccessWrite)) { *error = kErrorCodeSharingViolation; return false; } const int ret = rename(src.c_str(), dest.c_str()); if (ret == -1) { if (errno == EEXIST) { *error = kErrorCodeAlreadyExists; return false; } else if (errno == EXDEV) { if (S_ISDIR(srcStat.st_mode)) { *error = kErrorCodeNotSameDevice; return false; } if (!CopyFile(src, dest, true, error)) { // CopyFile sets the error return false; } return DeleteFile(src, error); // DeleteFile sets the error } else { *error = PathErrnoToErrorCode(src.c_str(), errno); return false; } } *error = kErrorCodeSuccess; return true; } bool File::ReplaceFile(const std::string& sourceFileName, const std::string& destinationFileName, const std::string& destinationBackupFileName, bool ignoreMetadataErrors, int* error) { const bool backupFile = !destinationBackupFileName.empty(); // Open the backup file for read so we can restore the file if an error occurs. const int backupFd = backupFile ? open(destinationBackupFileName.c_str(), O_RDONLY, 0) : -1; // dest -> backup if (backupFile) { const int retDest = rename(destinationFileName.c_str(), destinationBackupFileName.c_str()); if (retDest == -1) { if (backupFd != -1) close(backupFd); *error = PathErrnoToErrorCode(destinationFileName.c_str(), errno); return false; } } // source -> dest const int restSource = rename(sourceFileName.c_str(), destinationFileName.c_str()); if (restSource == -1) { // backup -> dest if (backupFile) rename(destinationBackupFileName.c_str(), destinationFileName.c_str()); // Copy backup data -> dest struct stat backupStat; if (backupFd != -1 && fstat(backupFd, &backupStat) == 0) { const int destFd = open(destinationBackupFileName.c_str(), O_WRONLY | O_CREAT | O_TRUNC, backupStat.st_mode); if (destFd != -1) { int unusedCopyFileError; InternalCopyFile(backupFd, destFd, backupStat, &unusedCopyFileError); close(destFd); } } if (backupFd != -1) close(backupFd); *error = PathErrnoToErrorCode(sourceFileName.c_str(), errno); return false; } if (backupFd != -1) close(backupFd); *error = kErrorCodeSuccess; return true; } static int ConvertFlags(int fileaccess, int createmode) { int flags; switch (fileaccess) { case kFileAccessRead: flags = O_RDONLY; break; case kFileAccessWrite: flags = O_WRONLY; break; case kFileAccessReadWrite: flags = O_RDWR; break; default: flags = 0; break; } switch (createmode) { case kFileModeCreateNew: flags |= O_CREAT | O_EXCL; break; case kFileModeCreate: flags |= O_CREAT | O_TRUNC; break; case kFileModeOpen: break; case kFileModeOpenOrCreate: case kFileModeAppend: flags |= O_CREAT; break; case kFileModeTruncate: flags |= O_TRUNC; break; default: flags = 0; break; } return flags; } #ifndef S_ISFIFO #define S_ISFIFO(m) ((m & S_IFIFO) != 0) #endif FileHandle* File::Open(const std::string& path, int mode, int accessMode, int shareMode, int options, int *error) { const int flags = ConvertFlags(accessMode, mode); /* we don't use sharemode, because that relates to sharing of * the file when the file is open and is already handled by * other code, perms instead are the on-disk permissions and * this is a sane default. */ const mode_t perms = options & kFileOptionsTemporary ? 0600 : 0666; int fd = open(path.c_str(), flags, perms); /* If we were trying to open a directory with write permissions * (e.g. O_WRONLY or O_RDWR), this call will fail with * EISDIR. However, this is a bit bogus because calls to * manipulate the directory (e.g. SetFileTime) will still work on * the directory because they use other API calls * (e.g. utime()). Hence, if we failed with the EISDIR error, try * to open the directory again without write permission. */ // Try again but don't try to make it writable if (fd == -1) { if (errno == EISDIR) { fd = open(path.c_str(), flags & ~(O_RDWR | O_WRONLY), perms); if (fd == -1) { *error = PathErrnoToErrorCode(path, errno); return INVALID_FILE_HANDLE; } } else { *error = PathErrnoToErrorCode(path, errno); return INVALID_FILE_HANDLE; } } struct stat statbuf; const int ret = fstat(fd, &statbuf); if (ret == -1) { *error = FileErrnoToErrorCode(errno); close(fd); return INVALID_FILE_HANDLE; } if (!ShareAllowOpen(statbuf, shareMode, accessMode)) { *error = kErrorCodeSharingViolation; close(fd); return INVALID_FILE_HANDLE; } FileHandle* fileHandle = new FileHandle(); fileHandle->fd = fd; fileHandle->path = path; fileHandle->options = options; fileHandle->accessMode = accessMode; fileHandle->shareMode = shareMode; fileHandle->device = statbuf.st_dev; fileHandle->inode = statbuf.st_ino; // Add to linked list AddFileHandle(fileHandle); #ifdef HAVE_POSIX_FADVISE if (options & kFileOptionsSequentialScan) posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL); if (options & kFileOptionsRandomAccess) posix_fadvise(fd, 0, 0, POSIX_FADV_RANDOM); #endif if (S_ISFIFO(statbuf.st_mode)) fileHandle->type = kFileTypePipe; else if (S_ISCHR(statbuf.st_mode)) fileHandle->type = kFileTypeChar; else fileHandle->type = kFileTypeDisk; *error = kErrorCodeSuccess; return fileHandle; } bool File::Close(FileHandle* handle, int *error) { if (handle->type == kFileTypeDisk && handle->options & kFileOptionsDeleteOnClose) unlink(handle->path.c_str()); close(handle->fd); // Remove from linked list RemoveFileHandle(handle); delete handle; *error = kErrorCodeSuccess; return true; } bool File::SetFileTime(FileHandle* handle, int64_t creation_time, int64_t last_access_time, int64_t last_write_time, int* error) { if ((handle->accessMode & kFileAccessWrite) == 0) { *error = kErrorCodeAccessDenied; return false; } struct stat statbuf; const int ret = fstat(handle->fd, &statbuf); if (ret == -1) { *error = kErrorCodeInvalidParameter; return false; } struct utimbuf utbuf; // Setting creation time is not implemented in Mono and not supported by utime. if (last_access_time >= 0) { if (last_access_time < TIME_ZERO) { *error = kErrorCodeInvalidParameter; return false; } utbuf.actime = TicksToTime(last_access_time); } else { utbuf.actime = statbuf.st_atime; } if (last_write_time >= 0) { if (last_write_time < TIME_ZERO) { *error = kErrorCodeInvalidParameter; return false; } utbuf.modtime = TicksToTime(last_write_time); } else { utbuf.modtime = statbuf.st_mtime; } const int utimeRet = utime(handle->path.c_str(), &utbuf); if (utimeRet == -1) { *error = kErrorCodeInvalidParameter; return false; } *error = kErrorCodeSuccess; return true; } int64_t File::GetLength(FileHandle* handle, int *error) { if (handle->type != kFileTypeDisk) { *error = kErrorCodeInvalidHandle; return false; } struct stat statbuf; const int ret = fstat(handle->fd, &statbuf); if (ret == -1) { *error = FileErrnoToErrorCode(errno); return -1; } *error = kErrorCodeSuccess; return statbuf.st_size; } bool File::SetLength(FileHandle* handle, int64_t length, int *error) { if (handle->type != kFileTypeDisk) { *error = kErrorCodeInvalidHandle; return false; } // Save current position const off_t currentPosition = lseek(handle->fd, 0, SEEK_CUR); if (currentPosition == -1) { *error = FileErrnoToErrorCode(errno); return false; } const off_t setLength = lseek(handle->fd, length, SEEK_SET); if (setLength == -1) { *error = FileErrnoToErrorCode(errno); return false; } int ret = 0; do { ret = ftruncate(handle->fd, length); } while (ret == -1 && errno == EINTR); if (ret == -1) { *error = FileErrnoToErrorCode(errno); return false; } const off_t oldPosition = lseek(handle->fd, currentPosition, SEEK_SET); if (oldPosition == -1) { *error = FileErrnoToErrorCode(errno); return false; } *error = kErrorCodeSuccess; return true; } int64_t File::Seek(FileHandle* handle, int64_t offset, int origin, int *error) { if (handle->type != kFileTypeDisk) { *error = kErrorCodeInvalidHandle; return false; } int whence; switch (origin) { case kFileSeekOriginBegin: whence = SEEK_SET; break; case kFileSeekOriginCurrent: whence = SEEK_CUR; break; case kFileSeekOriginEnd: whence = SEEK_END; break; default: { *error = kErrorCodeInvalidParameter; return -1; } } const off_t position = lseek(handle->fd, offset, whence); if (position == -1) { *error = FileErrnoToErrorCode(errno); return -1; } *error = kErrorCodeSuccess; return position; } int File::Read(FileHandle* handle, char *dest, int count, int *error) { if ((handle->accessMode & kFileAccessRead) == 0) { *error = kErrorCodeAccessDenied; return 0; } int ret; do { ret = (int)read(handle->fd, dest, count); } while (ret == -1 && errno == EINTR); if (ret == -1) { *error = FileErrnoToErrorCode(errno); return 0; } return ret; } int32_t File::Write(FileHandle* handle, const char* buffer, int count, int *error) { if ((handle->accessMode & kFileAccessWrite) == 0) { *error = kErrorCodeAccessDenied; return 0; } int ret; do { ret = (int32_t)write(handle->fd, buffer, count); } while (ret == -1 && errno == EINTR); if (ret == -1) { *error = FileErrnoToErrorCode(errno); return 0; } return ret; } bool File::Flush(FileHandle* handle, int* error) { if (handle->type != kFileTypeDisk) { *error = kErrorCodeInvalidHandle; return false; } const int ret = fsync(handle->fd); if (ret == -1) { *error = FileErrnoToErrorCode(errno); return false; } *error = kErrorCodeSuccess; return true; } void File::Lock(FileHandle* handle, int64_t position, int64_t length, int* error) { struct flock lock_data; int ret; lock_data.l_type = F_WRLCK; lock_data.l_whence = SEEK_SET; lock_data.l_start = position; lock_data.l_len = length; do { ret = fcntl(handle->fd, F_SETLK, &lock_data); } while (ret == -1 && errno == EINTR); if (ret == -1) { /* * if locks are not available (NFS for example), * ignore the error */ if (errno == ENOLCK #ifdef EOPNOTSUPP || errno == EOPNOTSUPP #endif #ifdef ENOTSUP || errno == ENOTSUP #endif ) { *error = kErrorCodeSuccess; return; } *error = FileErrnoToErrorCode(errno); return; } *error = kErrorCodeSuccess; } void File::Unlock(FileHandle* handle, int64_t position, int64_t length, int* error) { struct flock lock_data; int ret; lock_data.l_type = F_UNLCK; lock_data.l_whence = SEEK_SET; lock_data.l_start = position; lock_data.l_len = length; do { ret = fcntl(handle->fd, F_SETLK, &lock_data); } while (ret == -1 && errno == EINTR); if (ret == -1) { /* * if locks are not available (NFS for example), * ignore the error */ if (errno == ENOLCK #ifdef EOPNOTSUPP || errno == EOPNOTSUPP #endif #ifdef ENOTSUP || errno == ENOTSUP #endif ) { *error = kErrorCodeSuccess; return; } *error = FileErrnoToErrorCode(errno); return; } *error = kErrorCodeSuccess; } bool File::DuplicateHandle(FileHandle* source_process_handle, FileHandle* source_handle, FileHandle* target_process_handle, FileHandle** target_handle, int access, int inhert, int options, int* error) { NOT_IMPLEMENTED_ICALL(File::DuplicateHandle); return false; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/FileHandle.h ================================================ #pragma once #include "il2cpp-config.h" #if IL2CPP_TARGET_POSIX #include #include #include #include "os/File.h" #include "os/OSGlobalEnums.h" namespace il2cpp { namespace os { struct FileHandle { int fd; FileType type; std::string path; int options; int shareMode; int accessMode; // device and inode are used as key for finding file handles dev_t device; ino_t inode; // Linked list of file handles FileHandle *prev; FileHandle *next; FileHandle() : prev(NULL), next(NULL) { } }; } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/FileSystemWatcher.cpp ================================================ #include "il2cpp-config.h" #if !IL2CPP_USE_GENERIC_ENVIRONMENT && IL2CPP_TARGET_POSIX #include #include "os/FileSystemWatcher.h" namespace il2cpp { namespace os { namespace FileSystemWatcher { int IsSupported() { #if IL2CPP_TARGET_IOS return 0; // Not supported on iOS #else NOT_IMPLEMENTED_ICALL(FileSystemWatcher::IsSupported); return 0; #endif } } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/Image.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_JAVASCRIPT || IL2CPP_TARGET_LINUX || IL2CPP_TARGET_ANDROID || IL2CPP_TARGET_TIZEN #if !IL2CPP_TARGET_JAVASCRIPT #include #endif namespace il2cpp { namespace os { namespace Image { void* GetImageBase() { #if IL2CPP_TARGET_JAVASCRIPT return NULL; #else Dl_info info; void* const anySymbol = reinterpret_cast(&GetImageBase); if (dladdr(anySymbol, &info)) return info.dli_fbase; else return NULL; #endif } } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/LastError.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_POSIX #include #include "os/LastError.h" namespace il2cpp { namespace os { uint32_t LastError::GetLastError() { return errno; } } /* namespace os */ } /* namespace il2cpp*/ #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/LibraryLoader.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_POSIX //#define VERBOSE_OUTPUT #ifdef VERBOSE_OUTPUT #include #endif #include #include #include #include "metadata.h" #include "os/LibraryLoader.h" #include "utils/PathUtils.h" #include "utils/StringUtils.h" #include "utils/Environment.h" #include "vm/Exception.h" #include "vm/PlatformInvoke.h" namespace il2cpp { namespace os { static std::set s_NativeHandlesOpen; typedef std::set::const_iterator OpenHandleIterator; struct LibraryNamePrefixAndSuffix { LibraryNamePrefixAndSuffix(const char* prefix_, const char* suffix_) { prefix = std::string(prefix_); suffix = std::string(suffix_); } std::string prefix; std::string suffix; }; static LibraryNamePrefixAndSuffix LibraryNamePrefixAndSuffixVariations[8] = { LibraryNamePrefixAndSuffix("", ".so"), LibraryNamePrefixAndSuffix("", ".dll"), LibraryNamePrefixAndSuffix("", ".dylib"), LibraryNamePrefixAndSuffix("", ".bundle"), LibraryNamePrefixAndSuffix("lib", ".so"), LibraryNamePrefixAndSuffix("lib", ".dll"), LibraryNamePrefixAndSuffix("lib", ".dylib"), LibraryNamePrefixAndSuffix("lib", ".bundle") }; // Note that testing this code can be a bit difficult, since dlopen will cache // the values it returns, and we don't call dlcose from the C# level. See the // comments in the integration test code for more details. static void* LoadLibraryWithName(const char* name) { #ifdef VERBOSE_OUTPUT printf("Trying name: %s\n", name); #endif void* handle = NULL; #if IL2CPP_TARGET_IOS std::string dirName; if (utils::Environment::GetNumMainArgs() > 0) { std::string main = utils::StringUtils::Utf16ToUtf8(utils::Environment::GetMainArgs()[0]); dirName = utils::PathUtils::DirectoryName(main); } std::string libPath = utils::StringUtils::Printf("%s/%s", dirName.c_str(), name); handle = dlopen(libPath.c_str(), RTLD_LAZY); // Fallback to just using the name. This might be a system dylib. if (handle == NULL) handle = dlopen(name, RTLD_LAZY); #else handle = dlopen(name, RTLD_LAZY); #endif if (handle != NULL) return handle; #ifdef VERBOSE_OUTPUT printf("Error: %s\n", dlerror()); #endif return NULL; } static void* CheckLibraryVariations(const char* name) { int numberOfVariations = sizeof(LibraryNamePrefixAndSuffixVariations) / sizeof(LibraryNamePrefixAndSuffixVariations[0]); for (int i = 0; i < numberOfVariations; ++i) { std::string libraryName = LibraryNamePrefixAndSuffixVariations[i].prefix + name + LibraryNamePrefixAndSuffixVariations[i].suffix; void* handle = LoadLibraryWithName(libraryName.c_str()); if (handle != NULL) return handle; } return NULL; } Il2CppMethodPointer LibraryLoader::GetHardcodedPInvokeDependencyFunctionPointer(const il2cpp::utils::StringView& nativeDynamicLibrary, const il2cpp::utils::StringView& entryPoint) { return NULL; } void* LibraryLoader::LoadDynamicLibrary(const utils::StringView& nativeDynamicLibrary) { #ifdef VERBOSE_OUTPUT printf("Attempting to load dynamic library: %s\n", nativeDynamicLibrary.Str()); #endif if (nativeDynamicLibrary.IsEmpty()) return LoadLibraryWithName(NULL); StringViewAsNullTerminatedStringOf(char, nativeDynamicLibrary, libraryName); void* handle = LoadLibraryWithName(libraryName); if (handle == NULL) handle = CheckLibraryVariations(libraryName); if (handle == NULL) { size_t lengthWithoutDotDll = nativeDynamicLibrary.Length() - 4; if (strncmp(libraryName + lengthWithoutDotDll, ".dll", 4) == 0) { char* nativeDynamicLibraryWithoutExtension = static_cast(alloca((lengthWithoutDotDll + 1) * sizeof(char))); memcpy(nativeDynamicLibraryWithoutExtension, libraryName, lengthWithoutDotDll); nativeDynamicLibraryWithoutExtension[lengthWithoutDotDll] = 0; handle = CheckLibraryVariations(nativeDynamicLibraryWithoutExtension); } } if (handle != NULL) s_NativeHandlesOpen.insert(handle); return handle; } Il2CppMethodPointer LibraryLoader::GetFunctionPointer(void* dynamicLibrary, const PInvokeArguments& pinvokeArgs) { StringViewAsNullTerminatedStringOf(char, pinvokeArgs.entryPoint, entryPoint); if (pinvokeArgs.isNoMangle) return reinterpret_cast(dlsym(dynamicLibrary, entryPoint)); const size_t kBufferOverhead = 10; void* functionPtr = NULL; size_t originalFuncNameLength = strlen(entryPoint) + 1; std::string functionName; functionName.resize(originalFuncNameLength + kBufferOverhead + 1); // Let's index the string from '1', because we might have to prepend an underscore in case of stdcall mangling memcpy(&functionName[1], entryPoint, originalFuncNameLength); memset(&functionName[1] + originalFuncNameLength, 0, kBufferOverhead); // If there's no 'dont mangle' flag set, 'W' function takes priority over original name, but 'A' function does not (yes, really) if (pinvokeArgs.charSet == CHARSET_UNICODE) { functionName[originalFuncNameLength] = 'W'; functionPtr = dlsym(dynamicLibrary, functionName.c_str() + 1); if (functionPtr != NULL) return reinterpret_cast(functionPtr); // If charset specific function lookup failed, try with original name functionPtr = dlsym(dynamicLibrary, entryPoint); } else { functionPtr = dlsym(dynamicLibrary, entryPoint); if (functionPtr != NULL) return reinterpret_cast(functionPtr); // If original name function lookup failed, try with mangled name functionName[originalFuncNameLength] = 'A'; functionPtr = dlsym(dynamicLibrary, functionName.c_str() + 1); } return reinterpret_cast(functionPtr); } Il2CppMethodPointer LibraryLoader::GetFunctionPointer(void* dynamicLibrary, const char* functionName) { #ifdef VERBOSE_OUTPUT printf("Attempting to load method at entry point: %s\n", functionName); #endif Il2CppMethodPointer method = reinterpret_cast(dlsym(dynamicLibrary, functionName)); #ifdef VERBOSE_OUTPUT if (method == NULL) printf("Error: %s\n", dlerror()); #endif return method; } void LibraryLoader::CleanupLoadedLibraries() { for (OpenHandleIterator it = s_NativeHandlesOpen.begin(); it != s_NativeHandlesOpen.end(); it++) { dlclose(*it); } } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/Locale.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_POSIX #include #include #if IL2CPP_TARGET_DARWIN #include #endif #include "os/Locale.h" namespace il2cpp { namespace os { /* * The following method is modified from the ICU source code. (http://oss.software.ibm.com/icu) * Copyright (c) 1995-2003 International Business Machines Corporation and others * All rights reserved. */ std::string Locale::GetLocale() { const char* posix_locale = NULL; posix_locale = getenv("LC_ALL"); if (posix_locale == 0) { posix_locale = getenv("LANG"); if (posix_locale == 0) { posix_locale = setlocale(LC_ALL, NULL); } } if (posix_locale == NULL) return std::string(); if ((strcmp("C", posix_locale) == 0) || (strchr(posix_locale, ' ') != NULL) || (strchr(posix_locale, '/') != NULL)) { /* * HPUX returns 'C C C C C C C' * Solaris can return /en_US/C/C/C/C/C on the second try. * Maybe we got some garbage. */ return std::string(); } return std::string(posix_locale); } #if IL2CPP_SUPPORT_LOCALE_INDEPENDENT_PARSING static locale_t s_cLocale = NULL; #endif void Locale::Initialize() { #if IL2CPP_SUPPORT_LOCALE_INDEPENDENT_PARSING s_cLocale = newlocale(LC_ALL_MASK, "", NULL); #endif } void Locale::UnInitialize() { #if IL2CPP_SUPPORT_LOCALE_INDEPENDENT_PARSING if (s_cLocale) freelocale(s_cLocale); s_cLocale = NULL; #endif } #if IL2CPP_SUPPORT_LOCALE_INDEPENDENT_PARSING double Locale::DoubleParseLocaleIndependentImpl(char *ptr, char** endptr) { return strtod_l(ptr, endptr, s_cLocale); } #endif } /* namespace os */ } /* namespace il2cpp */ #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/MarshalAlloc.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_POSIX #include "os/MarshalAlloc.h" namespace il2cpp { namespace os { void* MarshalAlloc::Allocate(size_t size) { return malloc(size); } void* MarshalAlloc::ReAlloc(void* ptr, size_t size) { return realloc(ptr, size); } void MarshalAlloc::Free(void* ptr) { free(ptr); } } /* namespace os */ } /* namespace il2cpp*/ #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/Memory.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_POSIX || IL2CPP_TARGET_N3DS #include "os/Memory.h" #include #include namespace il2cpp { namespace os { namespace Memory { void* AlignedAlloc(size_t size, size_t alignment) { #if IL2CPP_TARGET_ANDROID || IL2CPP_TARGET_PSP2 return memalign(alignment, size); #else void* ptr = NULL; posix_memalign(&ptr, alignment, size); return ptr; #endif } void* AlignedReAlloc(void* memory, size_t newSize, size_t alignment) { void* newMemory = realloc(memory, newSize); // Fast path: realloc returned aligned memory if ((reinterpret_cast(newMemory) & (alignment - 1)) == 0) return newMemory; // Slow path: realloc returned non-aligned memory void* alignedMemory = AlignedAlloc(newSize, alignment); memcpy(alignedMemory, newMemory, newSize); free(newMemory); return alignedMemory; } void AlignedFree(void* memory) { free(memory); } } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/MemoryMappedFile.cpp ================================================ #include "il2cpp-config.h" #if !IL2CPP_USE_GENERIC_MEMORY_MAPPED_FILE && IL2CPP_TARGET_POSIX #include #include #include "os/File.h" #include "os/MemoryMappedFile.h" #include "os/Mutex.h" #include "FileHandle.h" namespace il2cpp { namespace os { static FastMutex s_Mutex; static std::map s_MappedAddressToMappedLength; void* MemoryMappedFile::Map(FileHandle* file, size_t length, size_t offset) { os::FastAutoLock lock(&s_Mutex); if (length == 0) { int error = 0; length = File::GetLength(file, &error); if (error != 0) return NULL; } void* address = mmap(NULL, length, PROT_READ, MAP_FILE | MAP_PRIVATE, file->fd, offset); if ((intptr_t)address == -1) return NULL; s_MappedAddressToMappedLength[address] = length; return address; } void MemoryMappedFile::Unmap(void* address, size_t length) { os::FastAutoLock lock(&s_Mutex); if (length == 0) { std::map::iterator entry = s_MappedAddressToMappedLength.find(address); if (entry != s_MappedAddressToMappedLength.end()) length = entry->second; } int error = munmap(address, length); IL2CPP_ASSERT(error == 0); (void)error; // Avoid an unused variable warning } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/MutexImpl.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_THREADS_PTHREAD #include "MutexImpl.h" #include "PosixHelpers.h" #include "os/Thread.h" namespace il2cpp { namespace os { MutexImpl::MutexImpl() : posix::PosixWaitObject(kMutex) , m_OwningThread(NULL) , m_RecursionCount(0) { // For a mutex, 1 means unlocked. m_Count = 1; } void MutexImpl::Lock(bool interruptible) { TryLock(posix::kNoTimeout, interruptible); } bool MutexImpl::TryLock(uint32_t milliseconds, bool interruptible) { Thread* currentThread = Thread::GetCurrentThread(); if (m_OwningThread == currentThread) { IL2CPP_ASSERT(m_Count == 0); ++m_RecursionCount; return true; } if (Wait(milliseconds, interruptible) == kWaitStatusSuccess) { m_OwningThread = currentThread; m_RecursionCount = 1; return true; } return false; } void MutexImpl::Unlock() { IL2CPP_ASSERT(m_OwningThread == Thread::GetCurrentThread()); // Undo one locking level. --m_RecursionCount; if (m_RecursionCount > 0) { // Still locked. return; } // Ok, we're releasing the mutex. Lock and signal. We don't absolutely // need the lock as we are already owning the mutex here but play it safe. posix::PosixAutoLock lock(&m_Mutex); IL2CPP_ASSERT(m_Count == 0); m_Count = 1; // Unintuitive but 1 means unlocked. m_OwningThread = NULL; // Signal condition so that either a thread that's already waiting or a thread that // comes around later and waits can claim the mutex. if (HaveWaitingThreads()) pthread_cond_signal(&m_Condition); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/MutexImpl.h ================================================ #pragma once #if IL2CPP_THREADS_PTHREAD #include "os/ErrorCodes.h" #include "os/WaitStatus.h" #include "PosixWaitObject.h" #include namespace il2cpp { namespace os { class Thread; class MutexImpl : public posix::PosixWaitObject { public: MutexImpl(); void Lock(bool interruptible); bool TryLock(uint32_t milliseconds, bool interruptible); void Unlock(); private: /// Thread that currently owns the object. Used for recursion checks. Thread* m_OwningThread; /// Number of recursive locks on the owning thread. uint32_t m_RecursionCount; }; class FastMutexImpl { public: FastMutexImpl() { pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&m_Mutex, &attr); pthread_mutexattr_destroy(&attr); } ~FastMutexImpl() { pthread_mutex_destroy(&m_Mutex); } void Lock() { pthread_mutex_lock(&m_Mutex); } void Unlock() { pthread_mutex_unlock(&m_Mutex); } pthread_mutex_t* GetOSHandle() { return &m_Mutex; } private: pthread_mutex_t m_Mutex; }; } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/NativeMethods.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_POSIX #include "os/NativeMethods.h" #include "os/Process.h" namespace il2cpp { namespace os { bool NativeMethods::CloseProcess(ProcessHandle* handle) { NOT_IMPLEMENTED_ICALL(NativeMethods::CloseProcess); IL2CPP_UNREACHABLE; return false; } bool NativeMethods::GetExitCodeProcess(ProcessHandle* handle, int32_t* exitCode) { NOT_IMPLEMENTED_ICALL(NativeMethods::GetExitCodeProcess); IL2CPP_UNREACHABLE; return false; } int32_t NativeMethods::GetCurrentProcessId() { return Process::GetCurrentProcessId(); } ProcessHandle* NativeMethods::GetCurrentProcess() { return Process::GetProcess(Process::GetCurrentProcessId()); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/Path.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_POSIX #include "os/Environment.h" #include "os/Path.h" #include #if defined(__APPLE__) #include "mach-o/dyld.h" #elif IL2CPP_TARGET_LINUX || IL2CPP_TARGET_ANDROID #include #include #include #include #include #endif namespace il2cpp { namespace os { std::string Path::GetExecutablePath() { #if defined(__APPLE__) char path[1024]; uint32_t size = sizeof(path); if (_NSGetExecutablePath(path, &size) == 0) return path; std::string result; result.resize(size + 1); _NSGetExecutablePath(&result[0], &size); return result; #elif IL2CPP_TARGET_LINUX || IL2CPP_TARGET_ANDROID char path[PATH_MAX]; char dest[PATH_MAX]; struct stat info; pid_t pid = getpid(); sprintf(path, "/proc/%d/exe", pid); if (readlink(path, dest, PATH_MAX) == -1) return std::string(); return dest; #else return std::string(); #endif } std::string Path::GetTempPath() { static const char* tmpdirs[] = { "TMPDIR", "TMP", "TEMP", NULL}; for (size_t i = 0; tmpdirs[i] != NULL; ++i) { std::string tmpdir = Environment::GetEnvironmentVariable(tmpdirs[i]); if (!tmpdir.empty()) return tmpdir; } #if IL2CPP_TARGET_ANDROID return std::string("/data/local/tmp"); #else return std::string("/tmp"); #endif } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/PosixHelpers.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_POSIX #include #include "os/Posix/PosixHelpers.h" namespace il2cpp { namespace os { namespace posix { int Poll(pollfd* handles, int numHandles, int timeout) { int32_t ret = 0; time_t start = time(NULL); timeout = (timeout >= 0) ? (timeout / 1000) : -1; do { ret = poll(handles, numHandles, timeout); if (timeout > 0 && ret < 0) { const int32_t err = errno; const int32_t sec = time(NULL) - start; timeout -= sec * 1000; if (timeout < 0) timeout = 0; errno = err; } } while (ret == -1 && errno == EINTR); return ret; } } } } #endif // IL2CPP_TARGET_POSIX ================================================ FILE: unity_decoder/libil2cpp/os/Posix/PosixHelpers.h ================================================ #pragma once #if IL2CPP_TARGET_POSIX #include #include #include #include "os/Thread.h" #include "os/Socket.h" namespace il2cpp { namespace os { namespace posix { inline timespec MillisecondsToTimespec(uint32_t ms) { timespec result; result.tv_sec = ms / 1000; result.tv_nsec = (ms % 1000) * 1000000; return result; } inline Thread::ThreadId PosixThreadIdToThreadId(pthread_t thread) { Thread::ThreadId threadId = 0; memcpy(&threadId, &thread, std::min(sizeof(threadId), sizeof(thread))); return threadId; } struct PosixAutoLock { pthread_mutex_t* mutex; PosixAutoLock(pthread_mutex_t* m) : mutex(m) { pthread_mutex_lock(mutex); } ~PosixAutoLock() { pthread_mutex_unlock(mutex); } }; inline short PollFlagsToPollEvents(PollFlags flags) { return (short)flags; } inline PollFlags PollEventsToPollFlags(short events) { return (PollFlags)events; } int Poll(pollfd* handles, int numHandles, int timeout); } } } #endif // IL2CPP_TARGET_POSIX ================================================ FILE: unity_decoder/libil2cpp/os/Posix/PosixWaitObject.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_POSIX #include #include #include "PosixWaitObject.h" #include "PosixHelpers.h" #include "ThreadImpl.h" #include "os/Time.h" // Notes: // - Situation // - None of the pthread APIs are interruptible (they all explicitly forbid returning EINTR). // - We cannot do any non-local transfers of control from signal handlers safely (C++ exceptions // or longjmp). Thus we cannot use signals to inject interruptions into a thread. // - Very few of the system APIs we have available support timeouts (at least not on all platforms). // - Ergo: we need to roll our own synchronization primitives based on pthread condition variables // (they support timeouts and have the functionality needed to model the other primitives). // - BUT: the condition variables still involve mutexes which we cannot lock in way that allows // interruptions. This means that there will be time windows where threads will wait and just // block and not allow interruption. namespace il2cpp { namespace os { namespace posix { static pthread_mutex_t s_WaitObjectDeletionLock = PTHREAD_MUTEX_INITIALIZER; PosixWaitObject::PosixWaitObject(Type type) : m_Type(type) , m_Count(0) , m_WaitingThreadCount(0) { pthread_mutex_init(&m_Mutex, NULL); #if IL2CPP_TARGET_JAVASCRIPT ////FIXME: WebGL bombs in pthread_cond_init() with non-NULL attributes ATM. //// We need to fix this once we have proper pthreads on Emscripten. Right now //// this will set up the condition variable incorrectly. pthread_cond_init(&m_Condition, NULL); #elif !IL2CPP_USE_POSIX_COND_TIMEDWAIT_REL // Initialize condition to use CLOCK_MONOTONIC instead of CLOCK_REALTIME. pthread_condattr_t attr; int result = pthread_condattr_init(&attr); pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); pthread_cond_init(&m_Condition, &attr); pthread_condattr_destroy(&attr); pthread_cond_init(&m_Condition, NULL); #else // On OSX and iOS we can use pthread_cond_timedwait_relative_np. pthread_cond_init(&m_Condition, NULL); #endif } PosixWaitObject::~PosixWaitObject() { // Make sure it's okay to delete wait objects. AutoLockWaitObjectDeletion lockDeletion; pthread_mutex_destroy(&m_Mutex); pthread_cond_destroy(&m_Condition); } void PosixWaitObject::LockWaitObjectDeletion() { pthread_mutex_lock(&s_WaitObjectDeletionLock); } void PosixWaitObject::UnlockWaitObjectDeletion() { pthread_mutex_unlock(&s_WaitObjectDeletionLock); } WaitStatus PosixWaitObject::Wait(bool interruptible) { return Wait(kNoTimeout, interruptible); } WaitStatus PosixWaitObject::Wait(uint32_t timeoutMS, bool interruptible) { // IMPORTANT: This function must be exception-safe! APCs may throw. ThreadImpl* currentThread = ThreadImpl::GetCurrentThread(); // Do up-front check about pending APC except this is a zero-timeout // wait (i.e. a wait that is never supposed to block and thus go into // an interruptible state). if (interruptible && timeoutMS != 0) currentThread->CheckForUserAPCAndHandle(); // Lock object. We release this mutex during waiting. posix::PosixAutoLock lock(&m_Mutex); // See if the object is in a state where we can acquire it right away. if (m_Count == 0) { // No, hasn't. If we're not supposed to wait, we're done. if (timeoutMS == 0) return kWaitStatusTimeout; try { // We should wait. Let the world know this thread is now waiting // on this object. if (interruptible) currentThread->SetWaitObject(this); // Check APC queue again to avoid race condition. if (interruptible) currentThread->CheckForUserAPCAndHandle(); // Go into wait until we either have a release or timeout or otherwise fail. uint32_t remainingWaitTime = timeoutMS; WaitStatus waitStatus = kWaitStatusSuccess; while (m_Count == 0) { if (timeoutMS == posix::kNoTimeout) { // Infinite wait. Can only be interrupted by APC. ++m_WaitingThreadCount; // No synchronization necessary; we hold the mutex. int status = pthread_cond_wait(&m_Condition, &m_Mutex); --m_WaitingThreadCount; if (status != 0) { waitStatus = kWaitStatusFailure; break; } } else { // Timed wait. Can be interrupted by APC or timeout. uint32_t waitStartTime = Time::GetTicksMillisecondsMonotonic(); timespec timeout = posix::MillisecondsToTimespec(remainingWaitTime); #if !IL2CPP_USE_POSIX_COND_TIMEDWAIT_REL ////NOTE: this codepath has not been tested! timespec waitStartTimeSpec = posix::MillisecondsToTimespec(waitStartTime); timeout.tv_sec += waitStartTimeSpec.tv_sec; timeout.tv_nsec += waitStartTimeSpec.tv_nsec; #endif ++m_WaitingThreadCount; #if !IL2CPP_USE_POSIX_COND_TIMEDWAIT_REL // For plain POSIX, do an absolute timed wait. int status = pthread_cond_timedwait(&m_Condition, &m_Mutex, &timeout); #else // For OSX and iOS, do a relative timed wait. int status = pthread_cond_timedwait_relative_np(&m_Condition, &m_Mutex, &timeout); #endif --m_WaitingThreadCount; ////TODO: make this atomic for when we fail to reacquire the mutex if (status == ETIMEDOUT) { waitStatus = kWaitStatusTimeout; break; } else if (status != 0) { waitStatus = kWaitStatusFailure; break; } // Update time we have have left to wait. uint32_t waitTimeThisRound = Time::GetTicksMillisecondsMonotonic() - waitStartTime; if (waitTimeThisRound > remainingWaitTime) remainingWaitTime = 0; else remainingWaitTime -= waitTimeThisRound; } // We've received a signal but it may be because of an APC and not because // the semaphore got signaled. If so, handle the APC and go back to waiting. if (interruptible) currentThread->CheckForUserAPCAndHandle(); } // We're done waiting so untie us from the current thread. // NOTE: A thread may have grabbed us and then got paused. If we return now and then our owner // tries to delete us, we would pull the rug from under the other thread. This is prevented by // having a central lock on wait object deletion which any thread trying to deal with wait // objects from other threads has to acquire. if (interruptible) { currentThread->SetWaitObject(NULL); // Avoid race condition by checking APC queue again after unsetting wait object. currentThread->CheckForUserAPCAndHandle(); } // If we failed, bail out now. if (waitStatus != kWaitStatusSuccess) return waitStatus; } catch (...) { if (interruptible) currentThread->SetWaitObject(NULL); throw; } } // At this point, we should be in signaled state and have the lock on // the object. // Object has been released. Acquire it for this thread. IL2CPP_ASSERT(m_Count > 0); switch (m_Type) { case kManualResetEvent: // Nothing to do. break; case kMutex: case kAutoResetEvent: m_Count = 0; break; case kSemaphore: if (m_Count > 0) // Defensive. { --m_Count; if (m_Count > 0) { // There's more releases on the semaphore. Signal the next thread in line. if (HaveWaitingThreads()) pthread_cond_signal(&m_Condition); } } break; } return kWaitStatusSuccess; } void PosixWaitObject::InterruptWait() { pthread_cond_broadcast(&m_Condition); } } } } #endif // IL2CPP_TARGET_POSIX ================================================ FILE: unity_decoder/libil2cpp/os/Posix/PosixWaitObject.h ================================================ #pragma once #if IL2CPP_TARGET_POSIX #include #include #include "utils/NonCopyable.h" #include "os/WaitStatus.h" #if (IL2CPP_USE_POSIX_COND_TIMEDWAIT_REL) int pthread_cond_timedwait_relative_np(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *spec); #endif namespace il2cpp { namespace os { class ThreadImpl; namespace posix { const uint32_t kNoTimeout = UINT_MAX; ////TODO: generalize this so that it can be used with c++11 condition variables /// Base class for all synchronization primitives when running on POSIX. /// /// To support interruption and timeouts for all synchronization primitives (events, mutexes, and /// semaphores) we implement these primitives ourselves instead of using their standard POSIX/Mach /// system counterparts. See PosixWaitObject.cpp for an explanation why. class PosixWaitObject : public il2cpp::utils::NonCopyable { public: ~PosixWaitObject(); WaitStatus Wait(bool interruptible = false); WaitStatus Wait(uint32_t ms, bool interruptible = false); /// Cause an ongoing blocking wait on this object to exit and check for pending APCs. /// If the object is not currently being waited on, will cause the next wait to exit /// right away and check for APCs. After APCs have been handled, the object will go /// back to waiting except if the wait timeout has expired. void InterruptWait(); static void LockWaitObjectDeletion(); static void UnlockWaitObjectDeletion(); protected: enum Type { kMutex, /// All mutexes are recursive. kManualResetEvent, kAutoResetEvent, kSemaphore }; PosixWaitObject(Type type); Type m_Type; /// Always have to acquire this mutex to touch m_Count. pthread_mutex_t m_Mutex; /// Signal other threads of changes to m_Count. pthread_cond_t m_Condition; /// "Release" count for the primitive. Means different things depending on the type of primitive /// but for all primitives, we wait until this is zero. Semaphores are the only primitive for which /// this can go past 1. uint32_t m_Count; /// Number of threads waiting on this object. This is used to prevent unnecessary signals /// on m_Condition. uint32_t m_WaitingThreadCount; bool HaveWaitingThreads() const { return (m_WaitingThreadCount != 0); } }; struct AutoLockWaitObjectDeletion { AutoLockWaitObjectDeletion() { PosixWaitObject::LockWaitObjectDeletion(); } ~AutoLockWaitObjectDeletion() { PosixWaitObject::UnlockWaitObjectDeletion(); } }; } } } #endif // IL2CPP_TARGET_POSIX ================================================ FILE: unity_decoder/libil2cpp/os/Posix/Process.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_POSIX && !IL2CPP_TARGET_DARWIN #include #include #include "os/Process.h" #include "vm/Exception.h" #include "il2cpp-vm-support.h" struct ProcessHandle { pid_t pid; }; namespace il2cpp { namespace os { int Process::GetCurrentProcessId() { return getpid(); } ProcessHandle* Process::GetProcess(int processId) { // If/when we implement the CreateProcess_internal icall we will likely // need to so something smarter here to find the process if we did // not create it and return a known pseudo-handle. For now this // is sufficient though. return (ProcessHandle*)(intptr_t)processId; } void Process::FreeProcess(ProcessHandle* handle) { // We have nothing to do here. } std::string Process::GetProcessName(ProcessHandle* handle) { IL2CPP_VM_NOT_SUPPORTED(Process::GetProcessName, "GetProcessName is not supported for non-Windows/OSX desktop platforms"); return std::string(); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/SemaphoreImpl.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_THREADS_PTHREAD #include #include #include "SemaphoreImpl.h" #include "ThreadImpl.h" #include "PosixHelpers.h" namespace il2cpp { namespace os { SemaphoreImpl::SemaphoreImpl(int32_t initialValue, int32_t maximumValue) : posix::PosixWaitObject(kSemaphore) , m_MaximumValue(maximumValue) { m_Count = initialValue; } bool SemaphoreImpl::Post(int32_t releaseCount, int32_t* previousCount) { uint32_t oldCount; { posix::PosixAutoLock lock(&m_Mutex); oldCount = m_Count; // Make sure we stay within range. Account for 32bit overflow. if (static_cast(oldCount) + releaseCount > m_MaximumValue) return false; m_Count += releaseCount; pthread_cond_signal(&m_Condition); } if (previousCount) *previousCount = oldCount; return true; } } } #endif // IL2CPP_THREADS_PTHREAD ================================================ FILE: unity_decoder/libil2cpp/os/Posix/SemaphoreImpl.h ================================================ #pragma once #if IL2CPP_THREADS_PTHREAD #include "PosixWaitObject.h" #include "os/ErrorCodes.h" #include "os/WaitStatus.h" #include namespace il2cpp { namespace os { class SemaphoreImpl : public posix::PosixWaitObject { public: SemaphoreImpl(int32_t initialValue, int32_t maximumValue); bool Post(int32_t releaseCount, int32_t* previousCount); protected: uint32_t m_MaximumValue; }; } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/SocketImpl.cpp ================================================ #include "il2cpp-config.h" #if !IL2CPP_USE_GENERIC_SOCKET_IMPL && IL2CPP_TARGET_POSIX // enable support for AF_UNIX and socket paths #define SUPPORT_UNIXSOCKETS (1) // some platforms require a different function to close sockets #define SOCK_CLOSE close // allow option include file to configure platform #if IL2CPP_USE_POSIX_SOCKET_PLATFORM_CONFIG #include "SocketImplPlatformConfig.h" #endif #include #include #include #include #include #include #include #include #include #include #include #if SUPPORT_UNIXSOCKETS #include #endif #include #include #if IL2CPP_TARGET_LINUX || IL2CPP_TARGET_ANDROID || IL2CPP_TARGET_TIZEN #include #endif #include "os/Error.h" #include "os/Socket.h" #include "os/ErrorCodes.h" #include "os/Posix/Error.h" #include "os/Posix/PosixHelpers.h" #include "os/Posix/SocketImpl.h" #include "os/Posix/ThreadImpl.h" #include "utils/StringUtils.h" #include "vm/Exception.h" #include "il2cpp-vm-support.h" namespace il2cpp { namespace os { static bool is_loopback(int32_t family, uint8_t *addr) { if (family == AF_INET) return addr[0] == 127; #if IL2CPP_SUPPORT_IPV6 else if (family == AF_INET6) return (IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr)); #endif return false; } static struct in_addr *get_local_ips(int32_t family, int32_t *nips) { const int32_t max_ifaces = 50; // 50 interfaces should be enough ... *nips = 0; if (family != AF_INET) return NULL; int32_t addr_size = 0; int32_t offset = 0; if (family == AF_INET) { addr_size = sizeof(struct in_addr); offset = offsetof(struct sockaddr_in, sin_addr); #if IL2CPP_SUPPORT_IPV6 } else if (family == AF_INET6) { addr_size = sizeof(struct in6_addr); offset = offsetof(struct sockaddr_in6, sin6_addr); #endif } else { return NULL; } int32_t fd = socket(family, SOCK_STREAM, 0); struct ifconf ifc; ifc.ifc_len = max_ifaces * sizeof(struct ifreq); ifc.ifc_buf = (char*)malloc(ifc.ifc_len); if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) { close(fd); free(ifc.ifc_buf); return NULL; } int32_t count = ifc.ifc_len / sizeof(struct ifreq); *nips = count; if (count == 0) { free(ifc.ifc_buf); close(fd); return NULL; } int32_t i; struct ifreq *ifr; struct ifreq iflags; bool ignore_loopback = false; for (i = 0, ifr = ifc.ifc_req; i < *nips; i++, ifr++) { strcpy(iflags.ifr_name, ifr->ifr_name); if (ioctl(fd, SIOCGIFFLAGS, &iflags) < 0) continue; if ((iflags.ifr_flags & IFF_UP) == 0) { ifr->ifr_name[0] = '\0'; continue; } if ((iflags.ifr_flags & IFF_LOOPBACK) == 0) ignore_loopback = true; } close(fd); uint8_t *result = (uint8_t*)malloc(addr_size * count); uint8_t *tmp_ptr = result; for (i = 0, ifr = ifc.ifc_req; i < count; i++, ifr++) { if (ifr->ifr_name[0] == '\0') { (*nips)--; continue; } if (ignore_loopback && is_loopback(family, ((uint8_t*)&ifr->ifr_addr) + offset)) { (*nips)--; continue; } memcpy(tmp_ptr, ((uint8_t*)&ifr->ifr_addr) + offset, addr_size); tmp_ptr += addr_size; } free(ifc.ifc_buf); return (struct in_addr *)result; } static bool hostent_get_info(struct hostent *he, std::string &name, std::vector &aliases, std::vector &addr_list) { if (he == NULL) return false; if (he->h_length != 4 || he->h_addrtype != AF_INET) return false; name.assign(he->h_name); for (int32_t i = 0; he->h_aliases[i] != NULL; ++i) aliases.push_back(he->h_aliases[i]); for (int32_t i = 0; he->h_addr_list[i] != NULL; ++i) addr_list.push_back( utils::StringUtils::NPrintf("%u.%u.%u.%u", 16, (uint8_t)he->h_addr_list[i][0], (uint8_t)he->h_addr_list[i][1], (uint8_t)he->h_addr_list[i][2], (uint8_t)he->h_addr_list[i][3])); return true; } static bool hostent_get_info_with_local_ips(struct hostent *he, std::string &name, std::vector &aliases, std::vector &addr_list) { int32_t nlocal_in = 0; if (he != NULL) { if (he->h_length != 4 || he->h_addrtype != AF_INET) return false; name.assign(he->h_name); for (int32_t i = 0; he->h_aliases[i] != NULL; ++i) aliases.push_back(he->h_aliases[i]); } struct in_addr *local_in = get_local_ips(AF_INET, &nlocal_in); if (nlocal_in) { for (int32_t i = 0; i < nlocal_in; ++i) { const uint8_t *ptr = (uint8_t*)&local_in[i]; addr_list.push_back( utils::StringUtils::NPrintf("%u.%u.%u.%u", 16, (uint8_t)ptr[0], (uint8_t)ptr[1], (uint8_t)ptr[2], (uint8_t)ptr[3])); } free(local_in); } else if (he == NULL) { // If requesting "" and there are no other interfaces up, MS returns 127.0.0.1 addr_list.push_back("127.0.0.1"); return true; } if (nlocal_in == 0 && he != NULL) { for (int32_t i = 0; he->h_addr_list[i] != NULL; ++i) { addr_list.push_back( utils::StringUtils::NPrintf("%u.%u.%u.%u", 16, (uint8_t)he->h_addr_list[i][0], (uint8_t)he->h_addr_list[i][1], (uint8_t)he->h_addr_list[i][2], (uint8_t)he->h_addr_list[i][3])); } } return true; } static int32_t convert_socket_flags(os::SocketFlags flags) { int32_t c_flags = 0; if (flags) { // Check if contains invalid flag values if (flags & ~(os::kSocketFlagsOutOfBand | os::kSocketFlagsMaxIOVectorLength | os::kSocketFlagsPeek | os::kSocketFlagsDontRoute | os::kSocketFlagsPartial)) { return -1; } #ifdef MSG_OOB if (flags & os::kSocketFlagsOutOfBand) c_flags |= MSG_OOB; #endif if (flags & os::kSocketFlagsPeek) c_flags |= MSG_PEEK; if (flags & os::kSocketFlagsDontRoute) c_flags |= MSG_DONTROUTE; // Ignore Partial - see bug 349688. Don't return -1, because // according to the comment in that bug ms runtime doesn't for // UDP sockets (this means we will silently ignore it for TCP // too) #ifdef MSG_MORE if (flags & os::kSocketFlagsPartial) c_flags |= MSG_MORE; #endif } return c_flags; } void SocketImpl::Startup() { } void SocketImpl::Cleanup() { } #if IL2CPP_SUPPORT_IPV6 static void AddrinfoGetAddresses(struct addrinfo *info, std::string& name, bool add_local_ips, std::vector &addr_list) { if (add_local_ips) { int nlocal_in = 0; int nlocal_in6 = 0; in_addr* local_in = (struct in_addr *)get_local_ips(AF_INET, &nlocal_in); in6_addr* local_in6 = (struct in6_addr *)get_local_ips(AF_INET6, &nlocal_in6); if (nlocal_in || nlocal_in6) { if (nlocal_in) { for (int i = 0; i < nlocal_in; i++) { char addr[16]; inet_ntop(AF_INET, &local_in[i], addr, sizeof(addr)); addr_list.push_back(std::string(addr)); } } if (nlocal_in6) { for (int i = 0; i < nlocal_in6; i++) { char addr[48]; const char* ret = inet_ntop(AF_INET6, &local_in6[i], addr, sizeof(addr)); if (ret != NULL) addr_list.push_back(std::string(addr)); } } } free(local_in); free(local_in6); } bool nameSet = false; for (addrinfo* ai = info; ai != NULL; ai = ai->ai_next) { const char *ret; char buffer[48]; /* Max. size for IPv6 */ if ((ai->ai_family != PF_INET) && (ai->ai_family != PF_INET6)) continue; if (ai->ai_family == PF_INET) ret = inet_ntop(ai->ai_family, (void*)&(((struct sockaddr_in*)ai->ai_addr)->sin_addr), buffer, 16); else ret = inet_ntop(ai->ai_family, (void*)&(((struct sockaddr_in6*)ai->ai_addr)->sin6_addr), buffer, 48); if (ret) addr_list.push_back(std::string(buffer)); else addr_list.push_back(std::string()); if (!nameSet) { if (ai->ai_canonname != NULL) name = std::string(ai->ai_canonname); else name = std::string(); nameSet = true; } } } WaitStatus GetAddressInfo(const char* hostname, bool add_local_ips, std::string &name, std::vector &addr_list) { addrinfo *info = NULL; addrinfo hints; memset(&hints, 0, sizeof(hints)); // Here Mono inspects the ipv4Supported and ipv6Supported properties on the managed Socket class. // This seems to be unnecessary though, as we can use PF_UNSPEC in all cases, and getaddrinfo works. hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; if (*hostname && getaddrinfo(hostname, NULL, &hints, &info) == -1) return kWaitStatusFailure; AddrinfoGetAddresses(info, name, add_local_ips, addr_list); if (info) freeaddrinfo(info); if (name.empty()) name.assign(hostname); return kWaitStatusSuccess; } #endif WaitStatus SocketImpl::GetHostByAddr(const std::string &address, std::string &name, std::vector &aliases, std::vector &addr_list) { #if IL2CPP_SUPPORT_IPV6 struct sockaddr_in saddr; struct sockaddr_in6 saddr6; int32_t family; char hostname[1024] = {0}; int flags = 0; if (inet_pton(AF_INET, address.c_str(), &saddr.sin_addr) <= 0) { /* Maybe an ipv6 address */ if (inet_pton(AF_INET6, address.c_str(), &saddr6.sin6_addr) <= 0) { return kWaitStatusFailure; } else { family = AF_INET6; saddr6.sin6_family = AF_INET6; } } else { family = AF_INET; saddr.sin_family = AF_INET; } if (family == AF_INET) { #if HAVE_SOCKADDR_IN_SIN_LEN saddr.sin_len = sizeof(saddr); #endif if (getnameinfo((struct sockaddr*)&saddr, sizeof(saddr), hostname, sizeof(hostname), NULL, 0, flags) != 0) { return kWaitStatusFailure; } } else if (family == AF_INET6) { #if HAVE_SOCKADDR_IN6_SIN_LEN saddr6.sin6_len = sizeof(saddr6); #endif if (getnameinfo((struct sockaddr*)&saddr6, sizeof(saddr6), hostname, sizeof(hostname), NULL, 0, flags) != 0) { return kWaitStatusFailure; } } return GetAddressInfo(hostname, false, name, addr_list); #else struct in_addr inaddr; if (inet_pton(AF_INET, address.c_str(), &inaddr) <= 0) return kWaitStatusFailure; struct hostent *he = gethostbyaddr((char*)&inaddr, sizeof(inaddr), AF_INET); if (he == NULL) { name = address; addr_list.push_back(name); return kWaitStatusSuccess; } return hostent_get_info(he, name, aliases, addr_list) ? kWaitStatusSuccess : kWaitStatusFailure; #endif } WaitStatus SocketImpl::GetHostByName(const std::string &host, std::string &name, std::vector &aliases, std::vector &addr_list) { char this_hostname[256] = {0}; const char *hostname = host.c_str(); bool add_local_ips = (*hostname == '\0'); if (!add_local_ips && gethostname(this_hostname, sizeof(this_hostname)) != -1) { if (!strcmp(hostname, this_hostname)) add_local_ips = true; } #if IL2CPP_SUPPORT_IPV6 return GetAddressInfo(hostname, add_local_ips, name, addr_list); #else struct hostent *he = NULL; if (*hostname) he = gethostbyname(hostname); if (*hostname && he == NULL) return kWaitStatusFailure; return (add_local_ips ? hostent_get_info_with_local_ips(he, name, aliases, addr_list) : hostent_get_info(he, name, aliases, addr_list)) ? kWaitStatusSuccess : kWaitStatusFailure; #endif } WaitStatus SocketImpl::GetHostName(std::string &name) { char hostname[256]; int32_t ret = gethostname(hostname, sizeof(hostname)); if (ret == -1) return kWaitStatusFailure; name.assign(hostname); return kWaitStatusSuccess; } SocketImpl::SocketImpl(ThreadStatusCallback thread_status_callback) : _is_valid(false) , _fd(-1) , _domain(-1) , _type(-1) , _protocol(-1) , _saved_error(kErrorCodeSuccess) , _still_readable(0) , _thread_status_callback(thread_status_callback) { } SocketImpl::~SocketImpl() { } static int32_t convert_address_family(AddressFamily family) { switch (family) { case kAddressFamilyUnspecified: return AF_UNSPEC; case kAddressFamilyUnix: return AF_UNIX; case kAddressFamilyInterNetwork: return AF_INET; #ifdef AF_IPX case kAddressFamilyIpx: return AF_IPX; #endif #ifdef AF_SNA case kAddressFamilySna: return AF_SNA; #endif #ifdef AF_DECnet case kAddressFamilyDecNet: return AF_DECnet; #endif #ifdef AF_APPLETALK case kAddressFamilyAppleTalk: return AF_APPLETALK; #endif #ifdef AF_INET6 case kAddressFamilyInterNetworkV6: return AF_INET6; #endif #ifdef AF_IRDA case kAddressFamilyIrda: return AF_IRDA; #endif default: break; } return -1; } static AddressFamily convert_define_to_address_family(int32_t family) { switch (family) { case AF_UNSPEC: return kAddressFamilyUnspecified; case AF_UNIX: return kAddressFamilyUnix; case AF_INET: return kAddressFamilyInterNetwork; #ifdef AF_IPX case AF_IPX: return kAddressFamilyIpx; #endif #ifdef AF_SNA case AF_SNA: return kAddressFamilySna; #endif #ifdef AF_DECnet case AF_DECnet: return kAddressFamilyDecNet; #endif #ifdef AF_APPLETALK case AF_APPLETALK: return kAddressFamilyAppleTalk; #endif #ifdef AF_INET6 case AF_INET6: return kAddressFamilyInterNetworkV6; #endif #ifdef AF_IRDA case AF_IRDA: return kAddressFamilyIrda; #endif default: break; } return kAddressFamilyError; } static int32_t convert_socket_type(SocketType type) { switch (type) { case kSocketTypeStream: return SOCK_STREAM; case kSocketTypeDgram: return SOCK_DGRAM; case kSocketTypeRaw: return SOCK_RAW; #ifdef SOCK_RDM case kSocketTypeRdm: return SOCK_RDM; #endif #ifdef SOCK_SEQPACKET case kSocketTypeSeqpacket: return SOCK_SEQPACKET; #endif default: break; } return -1; } static int32_t convert_socket_protocol(ProtocolType protocol) { switch (protocol) { case kProtocolTypeIP: case kProtocolTypeIPv6: case kProtocolTypeIcmp: case kProtocolTypeIgmp: case kProtocolTypeGgp: case kProtocolTypeTcp: case kProtocolTypePup: case kProtocolTypeUdp: case kProtocolTypeIdp: // In this case the enum values map exactly. return (int32_t)protocol; default: break; } // Everything else in unsupported and unexpected return -1; } WaitStatus SocketImpl::Create(AddressFamily family, SocketType type, ProtocolType protocol) { _fd = -1; _is_valid = false; _still_readable = 1; _domain = convert_address_family(family); _type = convert_socket_type(type); _protocol = convert_socket_protocol(protocol); IL2CPP_ASSERT(_type != -1 && "Unsupported socket type"); IL2CPP_ASSERT(_domain != -1 && "Unsupported address family"); IL2CPP_ASSERT(_protocol != -1 && "Unsupported protocol type"); _fd = socket(_domain, _type, _protocol); if (_fd == -1 && _domain == AF_INET && _type == SOCK_RAW && _protocol == 0) { // Retry with protocol == 4 (see bug #54565) _protocol = 4; _fd = socket(AF_INET, SOCK_RAW, 4); } if (_fd == -1) { StoreLastError(); return kWaitStatusFailure; } // if (fd >= _wapi_fd_reserve) // { // WSASetLastError (WSASYSCALLFAILURE); // close (fd); // return(INVALID_SOCKET); // } /* .net seems to set this by default for SOCK_STREAM, not for * SOCK_DGRAM (see bug #36322) * * It seems winsock has a rather different idea of what * SO_REUSEADDR means. If it's set, then a new socket can be * bound over an existing listening socket. There's a new * windows-specific option called SO_EXCLUSIVEADDRUSE but * using that means the socket MUST be closed properly, or a * denial of service can occur. Luckily for us, winsock * behaves as though any other system would when SO_REUSEADDR * is true, so we don't need to do anything else here. See * bug 53992. */ { int32_t v = 1; const int32_t ret = setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v)); if (ret == -1) { if (SOCK_CLOSE(_fd) == -1) StoreLastError(); return kWaitStatusFailure; } } #if IL2CPP_TARGET_DARWIN int32_t value = 1; setsockopt(_fd, SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof(value)); #endif // mono_once (&socket_ops_once, socket_ops_init); // handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle); // if (handle == _WAPI_HANDLE_INVALID) { // g_warning ("%s: error creating socket handle", __func__); // WSASetLastError (WSASYSCALLFAILURE); // close (fd); // return(INVALID_SOCKET); // } _is_valid = true; return kWaitStatusSuccess; } WaitStatus SocketImpl::Create(SocketDescriptor fd, int32_t family, int32_t type, int32_t protocol) { _fd = fd; _is_valid = (fd != -1); _still_readable = 1; _domain = family; _type = type; _protocol = protocol; IL2CPP_ASSERT(_type != -1 && "Unsupported socket type"); IL2CPP_ASSERT(_domain != -1 && "Unsupported address family"); IL2CPP_ASSERT(_protocol != -1 && "Unsupported protocol type"); return kWaitStatusSuccess; } WaitStatus SocketImpl::Close() { _saved_error = kErrorCodeSuccess; if (_is_valid && _fd != -1) { if (SOCK_CLOSE(_fd) == -1) StoreLastError(); } _fd = -1; _is_valid = false; _still_readable = 0; _domain = -1; _type = -1; _protocol = -1; return kWaitStatusSuccess; } WaitStatus SocketImpl::SetBlocking(bool blocking) { #if IL2CPP_USE_SOCKET_SETBLOCKING return (WaitStatus)setBlocking(_fd, blocking); #else int32_t flags = fcntl(_fd, F_GETFL, 0); if (flags == -1) { StoreLastError(); return kWaitStatusFailure; } flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK); if (fcntl(_fd, F_SETFL, flags) == -1) { StoreLastError(); return kWaitStatusFailure; } return kWaitStatusSuccess; #endif } ErrorCode SocketImpl::GetLastError() const { return _saved_error; } void SocketImpl::StoreLastError() { const ErrorCode error = SocketErrnoToErrorCode(errno); Error::SetLastError(error); _saved_error = error; } void SocketImpl::StoreLastError(int32_t error_no) { const ErrorCode error = SocketErrnoToErrorCode(error_no); Error::SetLastError(error); _saved_error = error; } #if SUPPORT_UNIXSOCKETS static void sockaddr_from_path(const char *path, struct sockaddr *sa, socklen_t *sa_size) { struct sockaddr_un sa_un = {0}; const size_t len = strlen(path); memcpy(sa_un.sun_path, path, len); *sa_size = (socklen_t)len; *sa = *((struct sockaddr*)&sa_un); } #endif #if IL2CPP_SUPPORT_IPV6 static void sockaddr_from_address(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port, sockaddr_in6* sa, socklen_t *sa_size) { sa->sin6_family = AF_INET6; sa->sin6_port = port; memcpy(&sa->sin6_addr, &address[0], 16); sa->sin6_scope_id = scope; *sa_size = sizeof(struct sockaddr_in6); } #endif static void sockaddr_from_address(uint32_t address, uint16_t port, struct sockaddr *sa, socklen_t *sa_size) { struct sockaddr_in sa_in = {0}; sa_in.sin_family = AF_INET; sa_in.sin_port = port; sa_in.sin_addr.s_addr = address; *sa_size = sizeof(struct sockaddr_in); *sa = *((struct sockaddr*)&sa_in); } static bool socketaddr_to_endpoint_info(const struct sockaddr *address, socklen_t address_len, EndPointInfo &info) { info.family = convert_define_to_address_family(address->sa_family); if (info.family == os::kAddressFamilyInterNetwork) { const struct sockaddr_in *address_in = (const struct sockaddr_in *)address; info.data.inet.port = ntohs(address_in->sin_port); info.data.inet.address = ntohl(address_in->sin_addr.s_addr); return true; } if (info.family == os::kAddressFamilyUnix) { for (int32_t i = 0; i < address_len; i++) info.data.path[i] = address->sa_data[i]; return true; } #if IL2CPP_SUPPORT_IPV6 if (info.family == os::kAddressFamilyInterNetworkV6) { const struct sockaddr_in6 *address_in = (const struct sockaddr_in6 *)address; uint16_t port = ntohs(address_in->sin6_port); info.data.raw[2] = (port >> 8) & 0xff; info.data.raw[3] = port & 0xff; for (int i = 0; i < 16; i++) info.data.raw[i + 8] = address_in->sin6_addr.s6_addr[i]; info.data.raw[24] = address_in->sin6_scope_id & 0xff; info.data.raw[25] = (address_in->sin6_scope_id >> 8) & 0xff; info.data.raw[26] = (address_in->sin6_scope_id >> 16) & 0xff; info.data.raw[27] = (address_in->sin6_scope_id >> 24) & 0xff; return true; } #endif return false; } WaitStatus SocketImpl::Bind(const char *path) { #if SUPPORT_UNIXSOCKETS struct sockaddr sa = {0}; socklen_t sa_size = 0; sockaddr_from_path(path, &sa, &sa_size); if (bind(_fd, &sa, sa_size) == -1) { StoreLastError(); return kWaitStatusFailure; } return kWaitStatusSuccess; #else return kWaitStatusFailure; #endif } WaitStatus SocketImpl::Bind(const char *address, uint16_t port) { struct sockaddr sa = {0}; socklen_t sa_size = 0; sockaddr_from_address(inet_addr(address), htons(port), &sa, &sa_size); if (bind(_fd, &sa, sa_size) == -1) { StoreLastError(); return kWaitStatusFailure; } return kWaitStatusSuccess; } WaitStatus SocketImpl::Bind(uint32_t address, uint16_t port) { struct sockaddr sa = {0}; socklen_t sa_size = 0; sockaddr_from_address(htonl(address), htons(port), &sa, &sa_size); if (bind(_fd, &sa, sa_size) == -1) { StoreLastError(); return kWaitStatusFailure; } return kWaitStatusSuccess; } WaitStatus SocketImpl::Bind(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port) { #if IL2CPP_SUPPORT_IPV6 struct sockaddr_in6 sa = { 0 }; socklen_t sa_size = 0; sockaddr_from_address(address, scope, htons(port), &sa, &sa_size); if (bind(_fd, (sockaddr*)&sa, sa_size) == -1) { StoreLastError(); return kWaitStatusFailure; } return kWaitStatusSuccess; #else IL2CPP_VM_NOT_SUPPORTED(sockaddr_from_address, "IPv6 is not supported on this platform."); return kWaitStatusFailure; #endif } WaitStatus SocketImpl::ConnectInternal(struct sockaddr *sa, int32_t sa_size) { if (connect(_fd, sa, (socklen_t)sa_size) != -1) return kWaitStatusSuccess; if (errno != EINTR) { // errnum = errno_to_WSA (errnum, __func__); // if (errnum == WSAEINPROGRESS) // errnum = WSAEWOULDBLOCK; /* see bug #73053 */ StoreLastError(); return kWaitStatusFailure; } struct pollfd fds = {0}; fds.fd = _fd; fds.events = POLLOUT; while (poll(&fds, 1, -1) == -1) { if (errno != EINTR) { StoreLastError(); return kWaitStatusFailure; } } int32_t so_error = 0; socklen_t len = sizeof(so_error); if (getsockopt(_fd, SOL_SOCKET, SO_ERROR, &so_error, &len) == -1) { StoreLastError(); return kWaitStatusFailure; } if (so_error != 0) { StoreLastError(so_error); return kWaitStatusFailure; } return kWaitStatusSuccess; } WaitStatus SocketImpl::Connect(const char *path) { #if SUPPORT_UNIXSOCKETS struct sockaddr sa = {0}; socklen_t sa_size = 0; sockaddr_from_path(path, &sa, &sa_size); return ConnectInternal((struct sockaddr *)&sa, sa_size); #else return kWaitStatusFailure; #endif } WaitStatus SocketImpl::Connect(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port) { #if IL2CPP_SUPPORT_IPV6 struct sockaddr_in6 sa = { 0 }; socklen_t sa_size = 0; sockaddr_from_address(address, scope, htons(port), &sa, &sa_size); return ConnectInternal((struct sockaddr *)&sa, sa_size); #else IL2CPP_VM_NOT_SUPPORTED(sockaddr_from_address, "IPv6 is not supported on this platform."); return kWaitStatusFailure; #endif } WaitStatus SocketImpl::Connect(uint32_t address, uint16_t port) { struct sockaddr sa = {0}; socklen_t sa_size = 0; sockaddr_from_address(htonl(address), htons(port), &sa, &sa_size); return ConnectInternal((struct sockaddr *)&sa, sa_size); } WaitStatus SocketImpl::GetLocalEndPointInfo(EndPointInfo &info) { // Note: the size here could probably be smaller uint8_t buffer[END_POINT_MAX_PATH_LEN + 3] = {0}; socklen_t address_len = sizeof(buffer); if (getsockname(_fd, (struct sockaddr *)buffer, &address_len) == -1) { StoreLastError(); return kWaitStatusFailure; } if (!socketaddr_to_endpoint_info((struct sockaddr *)buffer, address_len, info)) { _saved_error = kWSAeafnosupport; return kWaitStatusFailure; } return kWaitStatusSuccess; } WaitStatus SocketImpl::GetRemoteEndPointInfo(EndPointInfo &info) { // Note: the size here could probably be smaller uint8_t buffer[END_POINT_MAX_PATH_LEN + 3] = {0}; socklen_t address_len = sizeof(buffer); if (getpeername(_fd, (struct sockaddr *)buffer, &address_len) == -1) { StoreLastError(); return kWaitStatusFailure; } if (!socketaddr_to_endpoint_info((struct sockaddr *)buffer, address_len, info)) { _saved_error = kWSAeafnosupport; return kWaitStatusFailure; } return kWaitStatusSuccess; } WaitStatus SocketImpl::Listen(int32_t backlog) { if (listen(_fd, backlog) == -1) { StoreLastError(); return kWaitStatusFailure; } return kWaitStatusSuccess; } WaitStatus SocketImpl::Shutdown(int32_t how) { if (shutdown(_fd, how) == -1) { StoreLastError(); return kWaitStatusFailure; } if (how == SHUT_RD || how == SHUT_RDWR) _still_readable = 0; return kWaitStatusSuccess; } WaitStatus SocketImpl::Accept(os::Socket **socket) { int32_t new_fd = 0; *socket = NULL; do { new_fd = accept(_fd, NULL, 0); } while (new_fd == -1 && errno == EINTR); if (new_fd == -1) { StoreLastError(); return kWaitStatusFailure; } *socket = new os::Socket(_thread_status_callback); const WaitStatus status = (*socket)->Create(new_fd, _domain, _type, _protocol); if (status != kWaitStatusSuccess) { delete *socket; *socket = NULL; return status; } return kWaitStatusSuccess; } WaitStatus SocketImpl::Disconnect(bool reuse) { int32_t new_sock = socket(_domain, _type, _protocol); if (new_sock == -1) { StoreLastError(); return kWaitStatusFailure; } // According to Stevens "Advanced Programming in the UNIX // Environment: UNIX File I/O" dup2() is atomic so there // should not be a race condition between the old fd being // closed and the new socket fd being copied over int32_t ret = 0; do { ret = dup2(new_sock, _fd); } while (ret == -1 && errno == EAGAIN); if (ret == -1) { StoreLastError(); return kWaitStatusFailure; } SOCK_CLOSE(new_sock); return kWaitStatusSuccess; } WaitStatus SocketImpl::Receive(const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len) { *len = 0; const int32_t c_flags = convert_socket_flags(flags); if (c_flags == -1) { _saved_error = kWSAeopnotsupp; return kWaitStatusFailure; } return ReceiveFromInternal(data, count, c_flags, len, NULL, 0); } WaitStatus SocketImpl::ReceiveFromInternal(const uint8_t *data, size_t count, int32_t flags, int32_t *len, struct sockaddr *from, int32_t *fromlen) { int32_t ret = 0; do { ret = (int32_t)recvfrom(_fd, (void*)data, count, flags, from, (socklen_t*)fromlen); } while (ret == -1 && errno == EINTR); if (ret == 0 && count > 0) { // According to the Linux man page, recvfrom only // returns 0 when the socket has been shut down // cleanly. Turn this into an EINTR to simulate win32 // behaviour of returning EINTR when a socket is // closed while the recvfrom is blocking (we use a // shutdown() in socket_close() to trigger this.) See // bug 75705. // Distinguish between the socket being shut down at // the local or remote ends, and reads that request 0 // bytes to be read // If this returns FALSE, it means the socket has been // closed locally. If it returns TRUE, but // still_readable != 1 then shutdown // (SHUT_RD|SHUT_RDWR) has been called locally. if (_still_readable != 1) { ret = -1; errno = EINTR; } } if (ret == -1) { StoreLastError(); return kWaitStatusFailure; } *len = ret; return kWaitStatusSuccess; } WaitStatus SocketImpl::Send(const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len) { *len = 0; int32_t c_flags = convert_socket_flags(flags); if (c_flags == -1) { _saved_error = kWSAeopnotsupp; return kWaitStatusFailure; } #if IL2CPP_USE_SEND_NOSIGNAL c_flags |= MSG_NOSIGNAL; #endif int32_t ret = 0; do { ret = (int32_t)send(_fd, (void*)data, count, c_flags); } while (ret == -1 && errno == EINTR); if (ret == -1) { StoreLastError(); return kWaitStatusFailure; } *len = ret; return kWaitStatusSuccess; } WaitStatus SocketImpl::SendArray(WSABuf *wsabufs, int32_t count, int32_t *sent, SocketFlags flags) { int32_t c_flags = convert_socket_flags(flags); if (c_flags == -1) { _saved_error = kWSAeopnotsupp; return kWaitStatusFailure; } struct msghdr hdr = {0}; hdr.msg_iovlen = count; hdr.msg_iov = (struct iovec*)malloc(sizeof(struct iovec) * count); for (int32_t i = 0; i < count; ++i) { hdr.msg_iov[i].iov_base = wsabufs[i].buffer; hdr.msg_iov[i].iov_len = wsabufs[i].length; } #if IL2CPP_USE_SEND_NOSIGNAL c_flags |= MSG_NOSIGNAL; #endif int32_t ret = 0; do { ret = (int32_t)sendmsg(_fd, &hdr, c_flags); } while (ret == -1 && errno == EINTR); free(hdr.msg_iov); if (ret == -1) { *sent = 0; StoreLastError(); return kWaitStatusFailure; } *sent = ret; return kWaitStatusSuccess; } WaitStatus SocketImpl::ReceiveArray(WSABuf *wsabufs, int32_t count, int32_t *len, SocketFlags flags) { const int32_t c_flags = convert_socket_flags(flags); if (c_flags == -1) { _saved_error = kWSAeopnotsupp; return kWaitStatusFailure; } struct msghdr hdr = {0}; hdr.msg_iovlen = count; hdr.msg_iov = (struct iovec*)malloc(sizeof(struct iovec) * count); for (int32_t i = 0; i < count; ++i) { hdr.msg_iov[i].iov_base = wsabufs[i].buffer; hdr.msg_iov[i].iov_len = wsabufs[i].length; } int32_t ret = 0; do { ret = (int32_t)recvmsg(_fd, &hdr, c_flags); } while (ret == -1 && errno == EINTR); if (ret == 0) { // See SocketImpl::ReceiveFromInternal if (_still_readable != 1) { ret = -1; errno = EINTR; } } free(hdr.msg_iov); if (ret == -1) { *len = 0; StoreLastError(); return kWaitStatusFailure; } *len = ret; return kWaitStatusSuccess; } WaitStatus SocketImpl::SendToInternal(struct sockaddr *sa, int32_t sa_size, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len) { int32_t c_flags = convert_socket_flags(flags); if (c_flags == -1) { _saved_error = kWSAeopnotsupp; return kWaitStatusFailure; } #if IL2CPP_USE_SEND_NOSIGNAL c_flags |= MSG_NOSIGNAL; #endif int32_t ret = 0; do { ret = (int32_t)sendto(_fd, (void*)data, count, c_flags, sa, sa_size); } while (ret == -1 && errno == EINTR); if (ret == -1) { StoreLastError(); return kWaitStatusFailure; } *len = ret; return kWaitStatusSuccess; } WaitStatus SocketImpl::SendTo(uint32_t address, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len) { *len = 0; struct sockaddr sa = {0}; socklen_t sa_size = 0; sockaddr_from_address(htonl(address), htons(port), &sa, &sa_size); return SendToInternal(&sa, sa_size, data, count, flags, len); } WaitStatus SocketImpl::SendTo(const char *path, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len) { #if SUPPORT_UNIXSOCKETS *len = 0; struct sockaddr sa = {0}; socklen_t sa_size = 0; sockaddr_from_path(path, &sa, &sa_size); return SendToInternal(&sa, sa_size, data, count, flags, len); #else return kWaitStatusFailure; #endif } WaitStatus SocketImpl::SendTo(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len) { #if IL2CPP_SUPPORT_IPV6 struct sockaddr_in6 sa = { 0 }; socklen_t sa_size = 0; sockaddr_from_address(address, scope, htons(port), &sa, &sa_size); return SendToInternal((sockaddr*)&sa, sa_size, data, count, flags, len); #else IL2CPP_VM_NOT_SUPPORTED(sockaddr_from_address, "IPv6 is not supported on this platform."); return kWaitStatusFailure; #endif } WaitStatus SocketImpl::RecvFrom(uint32_t address, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep) { *len = 0; struct sockaddr sa = {0}; socklen_t sa_size = 0; sockaddr_from_address(htonl(address), htons(port), &sa, &sa_size); const int32_t c_flags = convert_socket_flags(flags); if (c_flags == -1) { _saved_error = kWSAeopnotsupp; return kWaitStatusFailure; } const WaitStatus status = ReceiveFromInternal(data, count, c_flags, len, &sa, (int32_t*)&sa_size); if (status != kWaitStatusSuccess) { ep.family = os::kAddressFamilyError; return status; } if (sa_size == 0) return kWaitStatusSuccess; if (!socketaddr_to_endpoint_info(&sa, sa_size, ep)) { ep.family = os::kAddressFamilyError; _saved_error = kWSAeafnosupport; return kWaitStatusFailure; } return kWaitStatusSuccess; } WaitStatus SocketImpl::RecvFrom(const char *path, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep) { #if SUPPORT_UNIXSOCKETS *len = 0; struct sockaddr sa = {0}; socklen_t sa_size = 0; sockaddr_from_path(path, &sa, &sa_size); const int32_t c_flags = convert_socket_flags(flags); if (c_flags == -1) { _saved_error = kWSAeopnotsupp; return kWaitStatusFailure; } const WaitStatus status = ReceiveFromInternal(data, count, c_flags, len, &sa, (int32_t*)&sa_size); if (status != kWaitStatusSuccess) { ep.family = os::kAddressFamilyError; return kWaitStatusFailure; } if (sa_size == 0) return kWaitStatusSuccess; if (!socketaddr_to_endpoint_info(&sa, sa_size, ep)) { ep.family = os::kAddressFamilyError; _saved_error = kWSAeafnosupport; return kWaitStatusFailure; } return kWaitStatusSuccess; #else return kWaitStatusFailure; #endif } WaitStatus SocketImpl::RecvFrom(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep) { #if IL2CPP_SUPPORT_IPV6 struct sockaddr_in6 sa = { 0 }; socklen_t sa_size = 0; sockaddr_from_address(address, scope, htons(port), &sa, &sa_size); const int32_t c_flags = convert_socket_flags(flags); if (c_flags == -1) { _saved_error = kWSAeopnotsupp; return kWaitStatusFailure; } const WaitStatus status = ReceiveFromInternal(data, count, c_flags, len, (sockaddr*)&sa, (int32_t*)&sa_size); if (status != kWaitStatusSuccess) { ep.family = os::kAddressFamilyError; return kWaitStatusFailure; } if (sa_size == 0) return kWaitStatusSuccess; if (!socketaddr_to_endpoint_info((sockaddr*)&sa, sa_size, ep)) { ep.family = os::kAddressFamilyError; _saved_error = kWSAeafnosupport; return kWaitStatusFailure; } return kWaitStatusSuccess; #else IL2CPP_VM_NOT_SUPPORTED(sockaddr_from_address, "IPv6 is not supported on this platform."); return kWaitStatusFailure; #endif } WaitStatus SocketImpl::Available(int32_t *amount) { // ioctl (fd, FIONREAD, XXX) returns the size of // the UDP header as well on Darwin. // // Use getsockopt SO_NREAD instead to get the // right values for TCP and UDP. // // ai_canonname can be null in some cases on darwin, where the runtime assumes it will // be the value of the ip buffer. *amount = 0; #if IL2CPP_TARGET_DARWIN socklen_t optlen = sizeof(int32_t); if (getsockopt(_fd, SOL_SOCKET, SO_NREAD, amount, &optlen) == -1) #else if (ioctl(_fd, FIONREAD, amount) == -1) #endif { StoreLastError(); return kWaitStatusFailure; } return kWaitStatusSuccess; } WaitStatus SocketImpl::Ioctl(int32_t command, const uint8_t *in_data, int32_t in_len, uint8_t *out_data, int32_t out_len, int32_t *written) { IL2CPP_ASSERT(command != 0xC8000006 /* SIO_GET_EXTENSION_FUNCTION_POINTER */ && "SIO_GET_EXTENSION_FUNCTION_POINTER ioctl command not supported"); uint8_t *buffer = NULL; if (in_len > 0) { buffer = (uint8_t*)malloc(in_len); memcpy(buffer, in_data, in_len); } const int32_t ret = ioctl(_fd, command, buffer); if (ret == -1) { StoreLastError(); free(buffer); return kWaitStatusFailure; } if (buffer == NULL) { *written = 0; return kWaitStatusSuccess; } // We just copy the buffer to the out_data. Some ioctls // don't even out_data any data, but, well ... // // NB: windows returns WSAEFAULT if out_len is too small const int32_t len = (in_len > out_len) ? out_len : in_len; if (len > 0 && out_data != NULL) memcpy(out_data, buffer, len); free(buffer); *written = len; return kWaitStatusSuccess; } #define SKIP_OPTION -2 #define INVALID_OPTION_NAME -1 static int32_t level_and_name_to_system(SocketOptionLevel level, SocketOptionName name, int32_t *system_level, int32_t *system_name) { switch (level) { case kSocketOptionLevelSocket: *system_level = SOL_SOCKET; switch (name) { // This is SO_LINGER, because the setsockopt // internal call maps DontLinger to SO_LINGER // with l_onoff=0 case kSocketOptionNameDontLinger: *system_name = SO_LINGER; break; #ifdef SO_DEBUG case kSocketOptionNameDebug: *system_name = SO_DEBUG; break; #endif #ifdef SO_ACCEPTCONN case kSocketOptionNameAcceptConnection: *system_name = SO_ACCEPTCONN; break; #endif case kSocketOptionNameReuseAddress: *system_name = SO_REUSEADDR; break; case kSocketOptionNameKeepAlive: *system_name = SO_KEEPALIVE; break; #ifdef SO_DONTROUTE case kSocketOptionNameDontRoute: *system_name = SO_DONTROUTE; break; #endif case kSocketOptionNameBroadcast: *system_name = SO_BROADCAST; break; case kSocketOptionNameLinger: *system_name = SO_LINGER; break; #ifdef SO_OOBINLINE case kSocketOptionNameOutOfBandInline: *system_name = SO_OOBINLINE; break; #endif case kSocketOptionNameSendBuffer: *system_name = SO_SNDBUF; break; case kSocketOptionNameReceiveBuffer: *system_name = SO_RCVBUF; break; case kSocketOptionNameSendLowWater: *system_name = SO_SNDLOWAT; break; case kSocketOptionNameReceiveLowWater: *system_name = SO_RCVLOWAT; break; case kSocketOptionNameSendTimeout: *system_name = SO_SNDTIMEO; break; case kSocketOptionNameReceiveTimeout: *system_name = SO_RCVTIMEO; break; case kSocketOptionNameError: *system_name = SO_ERROR; break; case kSocketOptionNameType: *system_name = SO_TYPE; break; case kSocketOptionNameExclusiveAddressUse: #ifdef SO_EXCLUSIVEADDRUSE *system_name = SO_EXCLUSIVEADDRUSE; break; #elif SO_REUSEADDR *system_name = SO_REUSEADDR; break; #endif case kSocketOptionNameUseLoopback: #ifdef SO_USELOOPBACK *system_name = SO_USELOOPBACK; break; #endif case kSocketOptionNameMaxConnections: #ifdef SO_MAXCONN *system_name = SO_MAXCONN; break; #elif defined(SOMAXCONN) *system_name = SOMAXCONN; break; #endif default: return INVALID_OPTION_NAME; } break; case kSocketOptionLevelIP: #ifdef SOL_IP *system_level = SOL_IP; #else *system_level = IPPROTO_IP; #endif switch (name) { #ifdef IP_OPTIONS case kSocketOptionNameIPOptions: *system_name = IP_OPTIONS; break; #endif #ifdef IP_HDRINCL case kSocketOptionNameHeaderIncluded: *system_name = IP_HDRINCL; break; #endif #ifdef IP_TOS case kSocketOptionNameTypeOfService: *system_name = IP_TOS; break; #endif #ifdef IP_TTL case kSocketOptionNameIpTimeToLive: *system_name = IP_TTL; break; #endif case kSocketOptionNameMulticastInterface: *system_name = IP_MULTICAST_IF; break; case kSocketOptionNameMulticastTimeToLive: *system_name = IP_MULTICAST_TTL; break; case kSocketOptionNameMulticastLoopback: *system_name = IP_MULTICAST_LOOP; break; case kSocketOptionNameAddMembership: *system_name = IP_ADD_MEMBERSHIP; break; case kSocketOptionNameDropMembership: *system_name = IP_DROP_MEMBERSHIP; break; #ifdef HAVE_IP_PKTINFO case kSocketOptionNamePacketInformation: *system_name = IP_PKTINFO; break; #endif case kSocketOptionNameDontFragment: #ifdef IP_DONTFRAGMENT *system_name = IP_DONTFRAGMENT; #elif IP_MTU_DISCOVER *system_name = IP_MTU_DISCOVER; #elif IP_DONTFRAG *system_name = IP_DONTFRAG; #else return SKIP_OPTION; #endif break; case kSocketOptionNameAddSourceMembership: case kSocketOptionNameDropSourceMembership: case kSocketOptionNameBlockSource: case kSocketOptionNameUnblockSource: // Can't figure out how to map these, so fall // through default: return INVALID_OPTION_NAME; } break; #if IL2CPP_SUPPORT_IPV6 case kSocketOptionLevelIPv6: #ifdef SOL_IP *system_level = SOL_IPV6; #else *system_level = IPPROTO_IPV6; #endif switch (name) { case kSocketOptionNameMulticastInterface: *system_name = IPV6_MULTICAST_IF; break; case kSocketOptionNameMulticastTimeToLive: *system_name = IPV6_MULTICAST_HOPS; break; case kSocketOptionNameMulticastLoopback: *system_name = IPV6_MULTICAST_LOOP; break; case kSocketOptionNameAddMembership: *system_name = IPV6_JOIN_GROUP; break; case kSocketOptionNameDropMembership: *system_name = IPV6_LEAVE_GROUP; break; case kSocketOptionNamePacketInformation: #ifdef HAVE_IPV6_PKTINFO *system_name = IPV6_PKTINFO; #endif break; case kSocketOptionNameIPv6Only: #ifdef IPV6_V6ONLY *system_name = IPV6_V6ONLY; #endif break; case kSocketOptionNameHeaderIncluded: case kSocketOptionNameIPOptions: case kSocketOptionNameTypeOfService: case kSocketOptionNameDontFragment: case kSocketOptionNameAddSourceMembership: case kSocketOptionNameDropSourceMembership: case kSocketOptionNameBlockSource: case kSocketOptionNameUnblockSource: // Can't figure out how to map these, so fall // through default: return INVALID_OPTION_NAME; } break; #endif // IL2CPP_SUPPORT_IPV6 case kSocketOptionLevelTcp: #ifdef SOL_TCP *system_level = SOL_TCP; #else *system_level = IPPROTO_TCP; #endif switch (name) { case kSocketOptionNameNoDelay: *system_name = TCP_NODELAY; break; default: return INVALID_OPTION_NAME; } break; case kSocketOptionLevelUdp: default: return INVALID_OPTION_NAME; } return 0; } WaitStatus SocketImpl::GetSocketOption(SocketOptionLevel level, SocketOptionName name, uint8_t *buffer, int32_t *length) { int32_t system_level = 0; int32_t system_name = 0; const int32_t o_res = level_and_name_to_system(level, name, &system_level, &system_name); if (o_res == SKIP_OPTION) { *((int32_t*)buffer) = 0; *length = sizeof(int32_t); return kWaitStatusSuccess; } if (o_res == INVALID_OPTION_NAME) { _saved_error = kWSAenoprotoopt; return kWaitStatusFailure; } struct timeval tv; uint8_t *tmp_val = buffer; if (system_level == SOL_SOCKET && (system_name == SO_RCVTIMEO || system_name == SO_SNDTIMEO)) { tmp_val = (uint8_t*)&tv; *length = sizeof(tv); } const int32_t ret = getsockopt(_fd, system_level, system_name, tmp_val, (socklen_t*)length); if (ret == -1) { StoreLastError(); return kWaitStatusFailure; } if (system_level == SOL_SOCKET && (system_name == SO_RCVTIMEO || system_name == SO_SNDTIMEO)) { // milliseconds from microseconds *((int32_t*)buffer) = (int32_t)(tv.tv_sec * 1000 + (tv.tv_usec / 1000)); *length = sizeof(int32_t); return kWaitStatusSuccess; } if (system_name == SO_ERROR) { if (*((int32_t*)buffer) != 0) { StoreLastError(*((int32_t*)buffer)); } else { *((int32_t*)buffer) = _saved_error; } } return kWaitStatusSuccess; } WaitStatus SocketImpl::GetSocketOptionFull(SocketOptionLevel level, SocketOptionName name, int32_t *first, int32_t *second) { int32_t system_level = 0; int32_t system_name = 0; #if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR) if (level == kSocketOptionLevelSocket && name == kSocketOptionNameExclusiveAddressUse) { system_level = SOL_SOCKET; system_name = SO_REUSEADDR; } else #endif { const int32_t o_res = level_and_name_to_system(level, name, &system_level, &system_name); if (o_res == SKIP_OPTION) { *first = 0; *second = 0; return kWaitStatusSuccess; } if (o_res == INVALID_OPTION_NAME) { _saved_error = kWSAenoprotoopt; return kWaitStatusFailure; } } int32_t ret = -1; switch (name) { case kSocketOptionNameLinger: { struct linger linger; socklen_t lingersize = sizeof(linger); ret = getsockopt(_fd, system_level, system_name, &linger, &lingersize); *first = linger.l_onoff; *second = linger.l_linger; } break; case kSocketOptionNameDontLinger: { struct linger linger; socklen_t lingersize = sizeof(linger); ret = getsockopt(_fd, system_level, system_name, &linger, &lingersize); *first = !linger.l_onoff; } break; case kSocketOptionNameSendTimeout: case kSocketOptionNameReceiveTimeout: { socklen_t time_ms_size = sizeof(*first); ret = getsockopt(_fd, system_level, system_name, (char*)first, &time_ms_size); } break; default: { socklen_t valsize = sizeof(*first); ret = getsockopt(_fd, system_level, system_name, first, &valsize); } break; } if (ret == -1) { StoreLastError(); return kWaitStatusFailure; } #if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR) if (level == kSocketOptionLevelSocket && name == kSocketOptionNameExclusiveAddressUse) *first = *first ? 0 : 1; #endif return kWaitStatusSuccess; } WaitStatus SocketImpl::Poll(std::vector &requests, int32_t count, int32_t timeout, int32_t *result, int32_t *error) { const int32_t n_fd = count; pollfd *p_fd = (pollfd*)calloc(n_fd, sizeof(pollfd)); for (int32_t i = 0; i < n_fd; ++i) { if (requests[i].fd == -1) { p_fd[i].fd = -1; p_fd[i].events = kPollFlagsNone; p_fd[i].revents = kPollFlagsNone; } else { p_fd[i].fd = requests[i].fd; p_fd[i].events = posix::PollFlagsToPollEvents(requests[i].events); p_fd[i].revents = kPollFlagsNone; } } int32_t ret = os::posix::Poll(p_fd, n_fd, timeout); *result = ret; if (ret == -1) { free(p_fd); *error = SocketErrnoToErrorCode(errno); return kWaitStatusFailure; } if (ret == 0) { free(p_fd); return kWaitStatusSuccess; } for (int32_t i = 0; i < n_fd; ++i) { requests[i].revents = posix::PollEventsToPollFlags(p_fd[i].revents); } free(p_fd); return kWaitStatusSuccess; } WaitStatus SocketImpl::Poll(std::vector &requests, int32_t timeout, int32_t *result, int32_t *error) { return Poll(requests, (int32_t)requests.size(), timeout, result, error); } WaitStatus SocketImpl::Poll(PollRequest& request, int32_t timeout, int32_t *result, int32_t *error) { std::vector requests; requests.push_back(request); return Poll(requests, 1, timeout, result, error); } WaitStatus SocketImpl::SetSocketOption(SocketOptionLevel level, SocketOptionName name, int32_t value) { int32_t system_level = 0; int32_t system_name = 0; const int32_t o_res = level_and_name_to_system(level, name, &system_level, &system_name); if (o_res == SKIP_OPTION) { return kWaitStatusSuccess; } if (o_res == INVALID_OPTION_NAME) { _saved_error = kWSAenoprotoopt; return kWaitStatusFailure; } struct linger linger; WaitStatus ret = kWaitStatusFailure; switch (name) { case kSocketOptionNameDontLinger: linger.l_onoff = !value; linger.l_linger = 0; ret = SetSocketOptionInternal(system_level, system_name, &linger, sizeof(linger)); break; case kSocketOptionNameDontFragment: #ifdef IP_PMTUDISC_DO // Fiddle with the value slightly if we're turning DF on if (value == 1) value = IP_PMTUDISC_DO; #endif ret = SetSocketOptionInternal(system_level, system_name, (char*)&value, sizeof(value)); break; default: ret = SetSocketOptionInternal(system_level, system_name, (char*)&value, sizeof(value)); break; } return ret; } WaitStatus SocketImpl::SetSocketOptionLinger(SocketOptionLevel level, SocketOptionName name, bool enabled, int32_t seconds) { int32_t system_level = 0; int32_t system_name = 0; const int32_t o_res = level_and_name_to_system(level, name, &system_level, &system_name); if (o_res == SKIP_OPTION) { return kWaitStatusSuccess; } if (o_res == INVALID_OPTION_NAME) { _saved_error = kWSAenoprotoopt; return kWaitStatusFailure; } struct linger linger; linger.l_onoff = enabled; linger.l_linger = seconds; return SetSocketOptionInternal(system_level, system_name, &linger, sizeof(linger)); } WaitStatus SocketImpl::SetSocketOptionArray(SocketOptionLevel level, SocketOptionName name, const uint8_t *buffer, int32_t length) { int32_t system_level = 0; int32_t system_name = 0; const int32_t o_res = level_and_name_to_system(level, name, &system_level, &system_name); if (o_res == SKIP_OPTION) { return kWaitStatusSuccess; } if (o_res == INVALID_OPTION_NAME) { _saved_error = kWSAenoprotoopt; return kWaitStatusFailure; } struct linger linger; WaitStatus ret = kWaitStatusFailure; switch (name) { case kSocketOptionNameDontLinger: if (length == 1) { linger.l_linger = 0; linger.l_onoff = (*((char*)buffer)) ? 0 : 1; ret = SetSocketOptionInternal(system_level, system_name, &linger, sizeof(linger)); } else { _saved_error = kWSAeinval; return kWaitStatusFailure; } break; default: ret = SetSocketOptionInternal(system_level, system_name, buffer, length); break; } return ret; } WaitStatus SocketImpl::SetSocketOptionMembership(SocketOptionLevel level, SocketOptionName name, uint32_t group_address, uint32_t local_address) { int32_t system_level = 0; int32_t system_name = 0; const int32_t o_res = level_and_name_to_system(level, name, &system_level, &system_name); if (o_res == SKIP_OPTION) { return kWaitStatusSuccess; } if (o_res == INVALID_OPTION_NAME) { _saved_error = kWSAenoprotoopt; return kWaitStatusFailure; } struct ip_mreqn mreq = {{0}}; mreq.imr_multiaddr.s_addr = group_address; mreq.imr_address.s_addr = local_address; return SetSocketOptionInternal(system_level, system_name, &mreq, sizeof(mreq)); } #if IL2CPP_TARGET_DARWIN #include #include #include #include static int get_local_interface_id(int family) { struct ifaddrs *ifap = NULL, *ptr; int idx = 0; if (getifaddrs(&ifap)) return 0; for (ptr = ifap; ptr; ptr = ptr->ifa_next) { if (!ptr->ifa_addr || !ptr->ifa_name) continue; if (ptr->ifa_addr->sa_family != family) continue; if ((ptr->ifa_flags & IFF_LOOPBACK) != 0) continue; if ((ptr->ifa_flags & IFF_MULTICAST) == 0) continue; idx = if_nametoindex(ptr->ifa_name); break; } freeifaddrs(ifap); return idx; } #endif // IL2CPP_TARGET_DARWIN #if IL2CPP_SUPPORT_IPV6 WaitStatus SocketImpl::SetSocketOptionMembership(SocketOptionLevel level, SocketOptionName name, IPv6Address ipv6, uint64_t interfaceOffset) { int32_t system_level = 0; int32_t system_name = 0; const int32_t o_res = level_and_name_to_system(level, name, &system_level, &system_name); if (o_res == SKIP_OPTION) { return kWaitStatusSuccess; } if (o_res == INVALID_OPTION_NAME) { _saved_error = kWSAenoprotoopt; return kWaitStatusFailure; } struct ipv6_mreq mreq6 = {{0}}; struct in6_addr in6addr; for (int i = 0; i < 16; ++i) in6addr.s6_addr[i] = ipv6.addr[i]; mreq6.ipv6mr_multiaddr = in6addr; #if IL2CPP_TARGET_DARWIN if (interfaceOffset == 0) interfaceOffset = get_local_interface_id(AF_INET6); #endif mreq6.ipv6mr_interface = interfaceOffset; return SetSocketOptionInternal(system_level, system_name, &mreq6, sizeof(mreq6)); } #endif WaitStatus SocketImpl::SetSocketOptionInternal(int32_t level, int32_t name, const void *value, int32_t len) { const void *real_val = value; struct timeval tv; if (level == SOL_SOCKET && (name == SO_RCVTIMEO || name == SO_SNDTIMEO)) { const int32_t ms = *((int32_t*)value); tv.tv_sec = ms / 1000; tv.tv_usec = (ms % 1000) * 1000; real_val = &tv; len = sizeof(tv); } const int32_t ret = setsockopt(_fd, level, name, real_val, (socklen_t)len); if (ret == -1) { StoreLastError(); return kWaitStatusFailure; } #if defined(SO_REUSEPORT) // BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested. if (level == SOL_SOCKET && name == SO_REUSEADDR) { int32_t type; socklen_t type_len = sizeof(type); if (!getsockopt(_fd, level, SO_TYPE, &type, &type_len)) { if (type == SOCK_DGRAM) setsockopt(_fd, level, SO_REUSEPORT, real_val, len); } } #endif return kWaitStatusSuccess; } WaitStatus SocketImpl::SendFile(const char *filename, TransmitFileBuffers *buffers, TransmitFileOptions options) { int32_t file = open(filename, O_RDONLY); if (file == -1) { StoreLastError(); return kWaitStatusFailure; } int32_t ret; // Write the header if (buffers != NULL && buffers->head != NULL && buffers->head_length > 0) { do { ret = (int32_t)send(_fd, (void*)buffers->head, buffers->head_length, 0); } while (ret == -1 && errno == EINTR); if (ret == -1) { StoreLastError(); SOCK_CLOSE(file); return kWaitStatusFailure; } } struct stat statbuf; ret = fstat(file, &statbuf); if (ret == -1) { StoreLastError(); return kWaitStatusFailure; } do { #if IL2CPP_TARGET_DARWIN ret = sendfile(file, _fd, 0, &statbuf.st_size, NULL, 0); #else ret = sendfile(_fd, file, NULL, statbuf.st_size); #endif } while (ret != -1 && (errno == EINTR || errno == EAGAIN)); if (ret == -1) { StoreLastError(); SOCK_CLOSE(file); return kWaitStatusFailure; } // Write the tail if (buffers != NULL && buffers->tail != NULL && buffers->tail_length > 0) { do { ret = (int32_t)send(_fd, (void*)buffers->tail, buffers->tail_length, 0); } while (ret == -1 && errno == EINTR); if (ret == -1) { StoreLastError(); SOCK_CLOSE(file); return kWaitStatusFailure; } } if (SOCK_CLOSE(file) == -1) { StoreLastError(); return kWaitStatusFailure; } return kWaitStatusSuccess; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/SocketImpl.h ================================================ #pragma once #if IL2CPP_TARGET_POSIX #include #include #include #include "os/Socket.h" #include "os/ErrorCodes.h" #include "os/WaitStatus.h" #include "utils/NonCopyable.h" struct sockaddr; namespace il2cpp { namespace os { class SocketImpl : public il2cpp::utils::NonCopyable { public: typedef int SocketDescriptor; SocketImpl(ThreadStatusCallback thread_status_callback); ~SocketImpl(); inline SocketDescriptor GetDescriptor() { return _fd; } ErrorCode GetLastError() const; WaitStatus Create(SocketDescriptor fd, int32_t family, int32_t type, int32_t protocol); WaitStatus Create(AddressFamily family, SocketType type, ProtocolType protocol); WaitStatus Close(); bool IsClosed() { return (_fd == -1); } WaitStatus SetBlocking(bool blocking); WaitStatus Listen(int32_t blacklog); WaitStatus Bind(const char *path); WaitStatus Bind(const char *address, uint16_t port); WaitStatus Bind(uint32_t address, uint16_t port); WaitStatus Bind(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port); WaitStatus Connect(const char *path); WaitStatus Connect(uint32_t address, uint16_t port); WaitStatus Connect(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port); WaitStatus Disconnect(bool reuse); WaitStatus Shutdown(int32_t how); WaitStatus GetLocalEndPointInfo(EndPointInfo &info); WaitStatus GetRemoteEndPointInfo(EndPointInfo &info); WaitStatus Receive(const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len); WaitStatus ReceiveFromInternal(const uint8_t *data, size_t count, int32_t flags, int32_t *len, struct sockaddr *from, int32_t *fromlen); WaitStatus Send(const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len); WaitStatus SendArray(WSABuf *wsabufs, int32_t count, int32_t *sent, SocketFlags c_flags); WaitStatus ReceiveArray(WSABuf *wsabufs, int32_t count, int32_t *len, SocketFlags c_flags); WaitStatus SendTo(uint32_t address, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len); WaitStatus SendTo(const char *path, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len); WaitStatus SendTo(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len); WaitStatus RecvFrom(uint32_t address, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep); WaitStatus RecvFrom(const char *path, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep); WaitStatus RecvFrom(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep); WaitStatus Available(int32_t *amount); WaitStatus Accept(os::Socket **socket); WaitStatus Ioctl(int32_t command, const uint8_t *in_data, int32_t in_len, uint8_t *out_data, int32_t out_len, int32_t *written); WaitStatus GetSocketOption(SocketOptionLevel level, SocketOptionName name, uint8_t *buffer, int32_t *length); WaitStatus GetSocketOptionFull(SocketOptionLevel level, SocketOptionName name, int32_t *first, int32_t *second); WaitStatus SetSocketOption(SocketOptionLevel level, SocketOptionName name, int32_t value); WaitStatus SetSocketOptionLinger(SocketOptionLevel level, SocketOptionName name, bool enabled, int32_t seconds); WaitStatus SetSocketOptionArray(SocketOptionLevel level, SocketOptionName name, const uint8_t *buffer, int32_t length); WaitStatus SetSocketOptionMembership(SocketOptionLevel level, SocketOptionName name, uint32_t group_address, uint32_t local_address); #if IL2CPP_SUPPORT_IPV6 WaitStatus SetSocketOptionMembership(SocketOptionLevel level, SocketOptionName name, IPv6Address ipv6, uint64_t interfaceOffset); #endif WaitStatus SendFile(const char *filename, TransmitFileBuffers *buffers, TransmitFileOptions options); static WaitStatus Poll(std::vector &requests, int32_t count, int32_t timeout, int32_t *result, int32_t *error); static WaitStatus Poll(std::vector &requests, int32_t timeout, int32_t *result, int32_t *error); static WaitStatus Poll(PollRequest& request, int32_t timeout, int32_t *result, int32_t *error); static WaitStatus GetHostName(std::string &name); static WaitStatus GetHostByName(const std::string &host, std::string &name, std::vector &aliases, std::vector &addr_list); static WaitStatus GetHostByAddr(const std::string &address, std::string &name, std::vector &aliases, std::vector &addr_list); static void Startup(); static void Cleanup(); private: bool _is_valid; SocketDescriptor _fd; int32_t _domain; int32_t _type; int32_t _protocol; ErrorCode _saved_error; int32_t _still_readable; ThreadStatusCallback _thread_status_callback; void StoreLastError(); void StoreLastError(int32_t error_no); WaitStatus ConnectInternal(struct sockaddr *sa, int32_t sa_size); WaitStatus SendToInternal(struct sockaddr *sa, int32_t sa_size, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len); WaitStatus SetSocketOptionInternal(int32_t level, int32_t name, const void *value, int32_t len); }; } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/StackTrace.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_POSIX && !IL2CPP_TARGET_JAVASCRIPT && !IL2CPP_TARGET_ANDROID && !IL2CPP_TARGET_PS4 #include "os/StackTrace.h" #include #include #include #include namespace il2cpp { namespace os { const int kMaxStackFrames = 128; void StackTrace::WalkStack(WalkStackCallback callback, void* context, WalkOrder walkOrder) { void* callstack[kMaxStackFrames]; int frames = backtrace(callstack, kMaxStackFrames); if (walkOrder == kFirstCalledToLastCalled) { for (size_t i = frames; i--;) { if (!callback(reinterpret_cast(callstack[i]), context)) break; } } else { for (size_t i = 0; i < frames; i++) { if (!callback(reinterpret_cast(callstack[i]), context)) break; } } } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/ThreadImpl.cpp ================================================ #include "il2cpp-config.h" #if !IL2CPP_THREADS_STD && IL2CPP_THREADS_PTHREAD #include #include #include #include #if IL2CPP_TARGET_LINUX || IL2CPP_TARGET_TIZEN #include #endif #include "ThreadImpl.h" #include "PosixHelpers.h" #include "os/Mutex.h" namespace il2cpp { namespace os { /// An Event that we never signal. This is used for sleeping threads in an alertable state. They /// simply wait on this object with the sleep timer as the timeout. This way we don't need a separate /// codepath for implementing sleep logic. static Event s_ThreadSleepObject; #define ASSERT_CALLED_ON_CURRENT_THREAD \ IL2CPP_ASSERT(pthread_equal (pthread_self (), m_Handle) && "Must be called on current thread!"); ThreadImpl::ThreadImpl() : m_Handle(0) , m_StartFunc(NULL) , m_StartArg(NULL) , m_CurrentWaitObject(NULL) , m_StackSize(IL2CPP_DEFAULT_STACK_SIZE) { pthread_mutex_init(&m_PendingAPCsMutex, NULL); } ThreadImpl::~ThreadImpl() { pthread_mutex_destroy(&m_PendingAPCsMutex); } ErrorCode ThreadImpl::Run(Thread::StartFunc func, void* arg) { // Store state for run wrapper. m_StartFunc = func; m_StartArg = arg; // Initialize thread attributes. pthread_attr_t attr; int s = pthread_attr_init(&attr); if (s) return kErrorCodeGenFailure; #if defined(IL2CPP_ENABLE_PLATFORM_THREAD_AFFINTY) // set create default core affinity pthread_attr_setaffinity_np(&attr, 0, NULL); #endif #if defined(IL2CPP_ENABLE_PLATFORM_THREAD_STACKSIZE) pthread_attr_setstacksize(&attr, m_StackSize); #endif // Create thread. pthread_t threadId; s = pthread_create(&threadId, &attr, &ThreadStartWrapper, this); if (s) return kErrorCodeGenFailure; // Destroy thread attributes. s = pthread_attr_destroy(&attr); if (s) return kErrorCodeGenFailure; // We're up and running. m_Handle = threadId; return kErrorCodeSuccess; } void* ThreadImpl::ThreadStartWrapper(void* arg) { ThreadImpl* thread = reinterpret_cast(arg); // Also set handle here. No matter which thread proceeds first, // we need to make sure the handle is set. thread->m_Handle = pthread_self(); // Detach this thread since we will manage calling Join at the VM level // if necessary. Detaching it also prevents use from running out of thread // handles for background threads that are never joined. int returnValue = pthread_detach(thread->m_Handle); IL2CPP_ASSERT(returnValue == 0); (void)returnValue; // Run user code. thread->m_StartFunc(thread->m_StartArg); return 0; } uint64_t ThreadImpl::Id() { return posix::PosixThreadIdToThreadId(m_Handle); } void ThreadImpl::SetName(const std::string& name) { // Can only be set on current thread on OSX and Linux. if (pthread_self() != m_Handle) return; #if IL2CPP_TARGET_DARWIN pthread_setname_np(name.c_str()); #elif IL2CPP_TARGET_LINUX || IL2CPP_TARGET_TIZEN || IL2CPP_ENABLE_PLATFORM_THREAD_RENAME pthread_setname_np(m_Handle, name.c_str()); #endif } void ThreadImpl::SetStackSize(size_t newsize) { // only makes sense if it's called BEFORE the thread has been created IL2CPP_ASSERT(m_Handle == NULL); // if newsize is zero we use the per-platform default value for size of stack if (newsize == 0) { newsize = IL2CPP_DEFAULT_STACK_SIZE; } m_StackSize = newsize; } void ThreadImpl::SetPriority(ThreadPriority priority) { ////TODO } ThreadPriority ThreadImpl::GetPriority() { /// TODO return kThreadPriorityNormal; } void ThreadImpl::QueueUserAPC(Thread::APCFunc function, void* context) { IL2CPP_ASSERT(function != NULL); // Put on queue. { pthread_mutex_lock(&m_PendingAPCsMutex); m_PendingAPCs.push_back(APCRequest(function, context)); pthread_mutex_unlock(&m_PendingAPCsMutex); } // Interrupt an ongoing wait. posix::AutoLockWaitObjectDeletion lock; posix::PosixWaitObject* waitObject = m_CurrentWaitObject; if (waitObject) waitObject->InterruptWait(); } void ThreadImpl::CheckForUserAPCAndHandle() { ASSERT_CALLED_ON_CURRENT_THREAD; pthread_mutex_lock(&m_PendingAPCsMutex); while (!m_PendingAPCs.empty()) { APCRequest apcRequest = m_PendingAPCs.front(); // Remove from list. Do before calling the function to make sure the list // is up to date in case the function throws. m_PendingAPCs.erase(m_PendingAPCs.begin()); // Release mutex while we call the function so that we don't deadlock // if the function starts waiting on a thread that tries queuing an APC // on us. pthread_mutex_unlock(&m_PendingAPCsMutex); // Call function. apcRequest.callback(apcRequest.context); // Re-acquire mutex. pthread_mutex_lock(&m_PendingAPCsMutex); } pthread_mutex_unlock(&m_PendingAPCsMutex); } void ThreadImpl::SetWaitObject(posix::PosixWaitObject* waitObject) { // Cannot set wait objects on threads other than the current thread. ASSERT_CALLED_ON_CURRENT_THREAD; // This is an unprotected write as write acccess is restricted to the // current thread. m_CurrentWaitObject = waitObject; } void ThreadImpl::Sleep(uint32_t milliseconds, bool interruptible) { s_ThreadSleepObject.Wait(milliseconds, interruptible); } uint64_t ThreadImpl::CurrentThreadId() { return posix::PosixThreadIdToThreadId(pthread_self()); } ThreadImpl* ThreadImpl::GetCurrentThread() { return Thread::GetCurrentThread()->m_Thread; } ThreadImpl* ThreadImpl::CreateForCurrentThread() { ThreadImpl* thread = new ThreadImpl(); thread->m_Handle = pthread_self(); return thread; } #if NET_4_0 bool ThreadImpl::YieldInternal() { return sched_yield() == 0; } #endif #if IL2CPP_HAS_NATIVE_THREAD_CLEANUP static pthread_key_t s_CleanupKey; static Thread::ThreadCleanupFunc s_CleanupFunc; static void CleanupThreadIfCanceled(void* arg) { if (s_CleanupFunc) s_CleanupFunc(arg); } void ThreadImpl::SetNativeThreadCleanup(Thread::ThreadCleanupFunc cleanupFunction) { if (cleanupFunction) { IL2CPP_ASSERT(!s_CleanupFunc); s_CleanupFunc = cleanupFunction; int result = pthread_key_create(&s_CleanupKey, &CleanupThreadIfCanceled); IL2CPP_ASSERT(!result); NO_UNUSED_WARNING(result); } else { IL2CPP_ASSERT(s_CleanupFunc); int result = pthread_key_delete(s_CleanupKey); IL2CPP_ASSERT(!result); NO_UNUSED_WARNING(result); s_CleanupFunc = NULL; } } void ThreadImpl::RegisterCurrentThreadForCleanup(void* arg) { IL2CPP_ASSERT(s_CleanupFunc); pthread_setspecific(s_CleanupKey, arg); } void ThreadImpl::UnregisterCurrentThreadForCleanup() { IL2CPP_ASSERT(s_CleanupFunc); void* data = pthread_getspecific(s_CleanupKey); if (data != NULL) pthread_setspecific(s_CleanupKey, NULL); } #endif } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/ThreadImpl.h ================================================ #pragma once #if !IL2CPP_THREADS_STD && IL2CPP_THREADS_PTHREAD #include #include #include "PosixWaitObject.h" #include "os/ErrorCodes.h" #include "os/Mutex.h" #include "os/Event.h" #include "os/Thread.h" #include "os/WaitStatus.h" #include "utils/NonCopyable.h" #if defined(IL2CPP_ENABLE_PLATFORM_THREAD_AFFINTY) struct cpu_set_t; int pthread_attr_setaffinity_np(pthread_attr_t *attr, size_t cpusetsize, const cpu_set_t *cpuset); #endif #if defined(IL2CPP_ENABLE_PLATFORM_THREAD_RENAME) int pthread_setname_np(pthread_t handle, const char *name); #endif #if !defined(IL2CPP_DEFAULT_STACK_SIZE) #define IL2CPP_DEFAULT_STACK_SIZE ( 1 * 1024 * 1024) // default .NET stacksize is 1mb #endif namespace il2cpp { namespace os { /// POSIX threads implementation. Supports APCs and interruptible waits. class ThreadImpl : public il2cpp::utils::NonCopyable { public: ThreadImpl(); ~ThreadImpl(); uint64_t Id(); ErrorCode Run(Thread::StartFunc func, void* arg); void QueueUserAPC(Thread::APCFunc func, void* context); void SetName(const std::string& name); void SetPriority(ThreadPriority priority); ThreadPriority GetPriority(); void SetStackSize(size_t newsize); /// Handle any pending APCs. /// NOTE: Can only be called on current thread. void CheckForUserAPCAndHandle(); static void Sleep(uint32_t milliseconds, bool interruptible); static uint64_t CurrentThreadId(); static ThreadImpl* GetCurrentThread(); static ThreadImpl* CreateForCurrentThread(); #if NET_4_0 static bool YieldInternal(); #endif #if IL2CPP_HAS_NATIVE_THREAD_CLEANUP static void SetNativeThreadCleanup(Thread::ThreadCleanupFunc cleanupFunction); static void RegisterCurrentThreadForCleanup(void* arg); static void UnregisterCurrentThreadForCleanup(); #endif private: friend class posix::PosixWaitObject; // SetWaitObject(), CheckForAPCAndHandle() pthread_t m_Handle; /// The synchronization primitive that this thread is currently blocked on. /// /// NOTE: This field effectively turns these wait object into shared resources -- which makes deletion /// a tricky affair. To avoid one thread trying to interrupt a wait while the other thread already /// is in progress of deleting the wait object, we use a global mutex in PosixWaitObject.cpp that /// must be locked by any thread trying to trigger an interrupt. posix::PosixWaitObject* m_CurrentWaitObject; /// Start data. Thread::StartFunc m_StartFunc; void* m_StartArg; /// List of APC requests for this thread. struct APCRequest { Thread::APCFunc callback; void* context; APCRequest(Thread::APCFunc callback, void* context) : callback(callback), context(context) { } }; pthread_mutex_t m_PendingAPCsMutex; std::vector m_PendingAPCs; size_t m_StackSize; // size of stack (can not be adjusted after thread creation) /// Set the synchronization object the thread is about to wait on. /// NOTE: This can only be called on the current thread. void SetWaitObject(posix::PosixWaitObject* waitObject); static void* ThreadStartWrapper(void* arg); }; } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/ThreadLocalValueImpl.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_THREADS_PTHREAD #include "ThreadLocalValueImpl.h" #include #define _unused(x) ((void)x) namespace il2cpp { namespace os { ThreadLocalValueImpl::ThreadLocalValueImpl() { pthread_key_t key; int result = pthread_key_create(&key, NULL); IL2CPP_ASSERT(!result); _unused(result); m_Key = key; } ThreadLocalValueImpl::~ThreadLocalValueImpl() { IL2CPP_ASSERT(!pthread_key_delete(m_Key)); } ErrorCode ThreadLocalValueImpl::SetValue(void* value) { if (pthread_setspecific(m_Key, value)) return kErrorCodeGenFailure; return kErrorCodeSuccess; } ErrorCode ThreadLocalValueImpl::GetValue(void** value) { *value = pthread_getspecific(m_Key); return kErrorCodeSuccess; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/ThreadLocalValueImpl.h ================================================ #pragma once #if IL2CPP_THREADS_PTHREAD #include "os/ErrorCodes.h" #include "utils/NonCopyable.h" #include namespace il2cpp { namespace os { class ThreadLocalValueImpl : public il2cpp::utils::NonCopyable { public: ThreadLocalValueImpl(); ~ThreadLocalValueImpl(); ErrorCode SetValue(void* value); ErrorCode GetValue(void** value); private: pthread_key_t m_Key; }; } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/Time.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_POSIX #include "os/Time.h" #include #include #include #if IL2CPP_TARGET_DARWIN #include #endif #include #if IL2CPP_TARGET_LINUX || IL2CPP_TARGET_TIZEN #include #endif namespace il2cpp { namespace os { const int64_t MTICKS_PER_SEC = 10000000; static int64_t GetBootTime() { #if IL2CPP_TARGET_DARWIN int mib[2]; size_t size; time_t now; struct timeval boottime; (void)time(&now); mib[0] = CTL_KERN; mib[1] = KERN_BOOTTIME; size = sizeof(boottime); if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1) return (int64_t)((now - boottime.tv_sec) * MTICKS_PER_SEC); #else FILE *uptime = fopen("/proc/uptime", "r"); if (uptime) { double upt; if (fscanf(uptime, "%lf", &upt) == 1) { const int64_t now = Time::GetTicks100NanosecondsMonotonic(); fclose(uptime); return now - (int64_t)(upt * MTICKS_PER_SEC); } fclose(uptime); } #endif /* a made up uptime of 300 seconds */ return (int64_t)300 * MTICKS_PER_SEC; } uint32_t Time::GetTicksMillisecondsMonotonic() { static int64_t boot_time = 0; int64_t now; if (!boot_time) boot_time = GetBootTime(); now = GetTicks100NanosecondsMonotonic(); return (uint32_t)((now - boot_time) / 10000); } int64_t Time::GetTicks100NanosecondsMonotonic() { struct timeval tv; #if defined(CLOCK_MONOTONIC) && !defined(IL2CPP_TARGET_DARWIN) struct timespec tspec; static struct timespec tspec_freq = {0}; static int can_use_clock = 0; if (!tspec_freq.tv_nsec) { can_use_clock = clock_getres(CLOCK_MONOTONIC, &tspec_freq) == 0; } if (can_use_clock) { if (clock_gettime(CLOCK_MONOTONIC, &tspec) == 0) { return ((int64_t)tspec.tv_sec * MTICKS_PER_SEC + tspec.tv_nsec / 100); } } #endif if (gettimeofday(&tv, NULL) == 0) return ((int64_t)tv.tv_sec * 1000000 + tv.tv_usec) * 10; return 0; } /* * Magic number to convert a time which is relative to * Jan 1, 1970 into a value which is relative to Jan 1, 0001. */ const uint64_t EPOCH_ADJUST = ((uint64_t)62135596800LL); int64_t Time::GetTicks100NanosecondsDateTime() { struct timeval tv; if (gettimeofday(&tv, NULL) == 0) return (((int64_t)tv.tv_sec + EPOCH_ADJUST) * 1000000 + tv.tv_usec) * 10; return 0; } static const int64_t kSecondsBetween1601And1970 = 11644473600LL; static const int64_t kSecondsTo100NanoSeconds = 10000000; int64_t Time::GetSystemTimeAsFileTime() { timeval currentTime; int getTimeOfDayResult = gettimeofday(¤tTime, NULL); IL2CPP_ASSERT(getTimeOfDayResult == 0 && "gettimeofday() failed"); return kSecondsTo100NanoSeconds * (static_cast(currentTime.tv_sec) + kSecondsBetween1601And1970) + 10 * currentTime.tv_usec; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Posix/TimeZone.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_POSIX #include "os/TimeZone.h" #include #include namespace il2cpp { namespace os { /* * Magic number to convert a time which is relative to * Jan 1, 1970 into a value which is relative to Jan 1, 0001. */ const uint64_t EPOCH_ADJUST = ((uint64_t)62135596800LL); /* * Return's the offset from GMT of a local time. * * tm is a local time * t is the same local time as seconds. */ static int GMTOffset(struct tm *tm, time_t t) { #if defined(HAVE_TM_GMTOFF) return tm->tm_gmtoff; #else struct tm g; time_t t2; g = *gmtime(&t); g.tm_isdst = tm->tm_isdst; t2 = mktime(&g); return (int)difftime(t, t2); #endif } bool TimeZone::GetTimeZoneData(int32_t year, int64_t data[4], std::string names[2]) { struct tm start, tt; time_t t; long int gmtoff; int is_daylight = 0, day; char tzone[64]; /* * no info is better than crashing: we'll need our own tz data * to make this work properly, anyway. The range is probably * reduced to 1970 .. 2037 because that is what mktime is * guaranteed to support (we get into an infinite loop * otherwise). */ memset(&start, 0, sizeof(start)); start.tm_mday = 1; start.tm_year = year - 1900; t = mktime(&start); if ((year < 1970) || (year > 2037) || (t == -1)) { t = time(NULL); tt = *localtime(&t); strftime(tzone, sizeof(tzone), "%Z", &tt); names[0] = tzone; names[1] = tzone; return true; } gmtoff = GMTOffset(&start, t); /* For each day of the year, calculate the tm_gmtoff. */ for (day = 0; day < 365; day++) { t += 3600 * 24; tt = *localtime(&t); /* Daylight saving starts or ends here. */ if (GMTOffset(&tt, t) != gmtoff) { struct tm tt1; time_t t1; /* Try to find the exact hour when daylight saving starts/ends. */ t1 = t; do { t1 -= 3600; tt1 = *localtime(&t1); } while (GMTOffset(&tt1, t1) != gmtoff); /* Try to find the exact minute when daylight saving starts/ends. */ do { t1 += 60; tt1 = *localtime(&t1); } while (GMTOffset(&tt1, t1) == gmtoff); t1 += gmtoff; strftime(tzone, sizeof(tzone), "%Z", &tt); /* Write data, if we're already in daylight saving, we're done. */ if (is_daylight) { names[0] = tzone; data[1] = ((int64_t)t1 + EPOCH_ADJUST) * 10000000L; return true; } else { names[1] = tzone; data[0] = ((int64_t)t1 + EPOCH_ADJUST) * 10000000L; is_daylight = 1; } /* This is only set once when we enter daylight saving. */ data[2] = (int64_t)gmtoff * 10000000L; data[3] = (int64_t)(GMTOffset(&tt, t) - gmtoff) * 10000000L; gmtoff = GMTOffset(&tt, t); } } if (!is_daylight) { strftime(tzone, sizeof(tzone), "%Z", &tt); names[0] = tzone; names[1] = tzone; data[0] = 0; data[1] = 0; data[2] = (int64_t)gmtoff * 10000000L; data[3] = 0; } return true; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Process.h ================================================ #pragma once #include namespace il2cpp { namespace os { struct ProcessHandle; class Process { public: static int GetCurrentProcessId(); static ProcessHandle* GetProcess(int processId); static void FreeProcess(ProcessHandle* handle); static std::string GetProcessName(ProcessHandle* handle); }; } } ================================================ FILE: unity_decoder/libil2cpp/os/Semaphore.cpp ================================================ #include "il2cpp-config.h" #include "os/Semaphore.h" #include "os/Atomic.h" #if IL2CPP_TARGET_WINDOWS #include "os/Win32/SemaphoreImpl.h" #elif IL2CPP_TARGET_POSIX #include "os/Posix/SemaphoreImpl.h" #else #include "os/SemaphoreImpl.h" #endif namespace il2cpp { namespace os { Semaphore::Semaphore(int32_t initialValue, int32_t maximumValue) : m_Semaphore(new SemaphoreImpl(initialValue, maximumValue)) { } Semaphore::~Semaphore() { delete m_Semaphore; } bool Semaphore::Post(int32_t releaseCount, int32_t* previousCount) { return m_Semaphore->Post(releaseCount, previousCount); } WaitStatus Semaphore::Wait(bool interruptible) { return m_Semaphore->Wait(interruptible); } WaitStatus Semaphore::Wait(uint32_t ms, bool interruptible) { return m_Semaphore->Wait(ms, interruptible); } } } ================================================ FILE: unity_decoder/libil2cpp/os/Semaphore.h ================================================ #pragma once #include "os/ErrorCodes.h" #include "os/WaitStatus.h" #include "os/Handle.h" #include "utils/NonCopyable.h" namespace il2cpp { namespace os { class SemaphoreImpl; class Semaphore : public il2cpp::utils::NonCopyable { public: Semaphore(int32_t initialValue = 0, int32_t maximumValue = 1); ~Semaphore(); bool Post(int32_t releaseCount = 1, int32_t* previousCount = NULL); WaitStatus Wait(bool interruptible = false); WaitStatus Wait(uint32_t ms, bool interruptible = false); private: SemaphoreImpl* m_Semaphore; }; class SemaphoreHandle : public Handle { public: SemaphoreHandle(Semaphore* semaphore) : m_Semaphore(semaphore) {} virtual ~SemaphoreHandle() { delete m_Semaphore; } virtual bool Wait() { m_Semaphore->Wait(true); return true; } virtual bool Wait(uint32_t ms) { return m_Semaphore->Wait(ms, true) != kWaitStatusTimeout; } virtual void Signal() { m_Semaphore->Post(1, NULL); } Semaphore& Get() { return *m_Semaphore; } private: Semaphore* m_Semaphore; }; } } ================================================ FILE: unity_decoder/libil2cpp/os/Socket.cpp ================================================ #include "il2cpp-config.h" #include #include "os/Socket.h" #include "os/Atomic.h" #include "os/Mutex.h" #if IL2CPP_TARGET_POSIX && !IL2CPP_TARGET_JAVASCRIPT // Note: sockets are not supported when targetting WebGL, even if it is considered a POSIX platform. # include "os/Posix/SocketImpl.h" #elif IL2CPP_TARGET_WINDOWS # include "os/Win32/SocketImpl.h" #elif IL2CPP_TARGET_SWITCH # include "os/SocketImpl.h" #else # include "os/Generic/SocketImpl.h" #endif namespace il2cpp { namespace os { struct SocketHandleEntry { Socket* m_Socket; uint32_t m_RefCount; }; typedef std::map SocketHandleTable; SocketHandle g_LastSocketHandle; FastMutex g_SocketHandleTableMutex; SocketHandleTable g_SocketHandleTable; SocketHandle CreateSocketHandle(Socket* socket) { // Allocate handle. SocketHandle newHandle = Atomic::Increment(&g_LastSocketHandle); // Populate entry. SocketHandleEntry handleEntry; handleEntry.m_Socket = socket; handleEntry.m_RefCount = 1; // Add to table. { FastAutoLock lock(&g_SocketHandleTableMutex); g_SocketHandleTable.insert(SocketHandleTable::value_type(newHandle, handleEntry)); } return newHandle; } Socket* AcquireSocketHandle(SocketHandle handle) { if (handle == kInvalidSocketHandle) return NULL; FastAutoLock lock(&g_SocketHandleTableMutex); // Look up in table. SocketHandleTable::iterator iter = g_SocketHandleTable.find(handle); if (iter == g_SocketHandleTable.end()) return NULL; // Increase reference count. SocketHandleEntry& entry = iter->second; ++entry.m_RefCount; return entry.m_Socket; } void ReleaseSocketHandle(SocketHandle handle) { if (handle == kInvalidSocketHandle) return; Socket* socketToDelete = NULL; { FastAutoLock lock(&g_SocketHandleTableMutex); // Look up in table. SocketHandleTable::iterator iter = g_SocketHandleTable.find(handle); if (iter == g_SocketHandleTable.end()) return; // Decrease reference count. SocketHandleEntry& entry = iter->second; --entry.m_RefCount; if (!entry.m_RefCount) { // Kill socket. Should be the only place where we directly delete sockets that // have made it past the creation step. socketToDelete = entry.m_Socket; g_SocketHandleTable.erase(iter); } } // Perform the deletion after we have released the lock so we don't unnecessarily // prevent other threads from accessing the table. if (socketToDelete) delete socketToDelete; } void Socket::Startup() { return SocketImpl::Startup(); } void Socket::Cleanup() { return SocketImpl::Cleanup(); } WaitStatus Socket::GetHostName(std::string &name) { return SocketImpl::GetHostName(name); } WaitStatus Socket::GetHostByAddr(const std::string &address, std::string &name, std::vector &aliases, std::vector &addr_list) { return SocketImpl::GetHostByAddr(address, name, aliases, addr_list); } WaitStatus Socket::GetHostByName(const std::string &host, std::string &name, std::vector &aliases, std::vector &addr_list) { return SocketImpl::GetHostByName(host, name, aliases, addr_list); } Socket::Socket(ThreadStatusCallback thread_status_callback) : m_Socket(new SocketImpl(thread_status_callback)) { } Socket::~Socket() { if (!IsClosed()) Close(); delete m_Socket; m_Socket = 0; } int64_t Socket::GetDescriptor() { if (IsClosed()) return -1; return m_Socket->GetDescriptor(); } WaitStatus Socket::Create(int64_t fd, int32_t family, int32_t type, int32_t protocol) { return m_Socket->Create((SocketImpl::SocketDescriptor)fd, family, type, protocol); } WaitStatus Socket::Create(AddressFamily family, SocketType type, ProtocolType protocol) { return m_Socket->Create(family, type, protocol); } bool Socket::IsClosed() { return m_Socket->IsClosed(); } void Socket::Close() { m_Socket->Close(); } ErrorCode Socket::GetLastError() const { return m_Socket->GetLastError(); } WaitStatus Socket::SetBlocking(bool blocking) { return m_Socket->SetBlocking(blocking); } WaitStatus Socket::Bind(const char *path) { return m_Socket->Bind(path); } WaitStatus Socket::Bind(uint32_t address, uint16_t port) { return m_Socket->Bind(address, port); } WaitStatus Socket::Bind(const char *address, uint16_t port) { return m_Socket->Bind(address, port); } WaitStatus Socket::Bind(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port) { return m_Socket->Bind(address, scope, port); } WaitStatus Socket::Connect(const char *path) { return m_Socket->Connect(path); } WaitStatus Socket::Connect(uint32_t address, uint16_t port) { return m_Socket->Connect(address, port); } WaitStatus Socket::Connect(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port) { return m_Socket->Connect(address, scope, port); } WaitStatus Socket::Disconnect(bool reuse) { return m_Socket->Disconnect(reuse); } WaitStatus Socket::Shutdown(int32_t how) { return m_Socket->Shutdown(how); } WaitStatus Socket::GetLocalEndPointInfo(EndPointInfo &info) { return m_Socket->GetLocalEndPointInfo(info); } WaitStatus Socket::GetRemoteEndPointInfo(EndPointInfo &info) { return m_Socket->GetRemoteEndPointInfo(info); } WaitStatus Socket::Listen(int32_t backlog) { return m_Socket->Listen(backlog); } WaitStatus Socket::Accept(Socket **socket) { return m_Socket->Accept(socket); } WaitStatus Socket::Receive(const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len) { return m_Socket->Receive(data, count, flags, len); } WaitStatus Socket::ReceiveArray(WSABuf *wsabufs, int32_t count, int32_t *len, SocketFlags c_flags) { return m_Socket->ReceiveArray(wsabufs, count, len, c_flags); } WaitStatus Socket::Send(const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len) { return m_Socket->Send(data, count, flags, len); } WaitStatus Socket::SendArray(WSABuf *wsabufs, int32_t count, int32_t *sent, SocketFlags c_flags) { return m_Socket->SendArray(wsabufs, count, sent, c_flags); } WaitStatus Socket::SendTo(uint32_t address, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len) { return m_Socket->SendTo(address, port, data, count, flags, len); } WaitStatus Socket::SendTo(const char *path, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len) { return m_Socket->SendTo(path, data, count, flags, len); } WaitStatus Socket::SendTo(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len) { return m_Socket->SendTo(address, scope, port, data, count, flags, len); } WaitStatus Socket::RecvFrom(uint32_t address, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep) { return m_Socket->RecvFrom(address, port, data, count, flags, len, ep); } WaitStatus Socket::RecvFrom(const char *path, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep) { return m_Socket->RecvFrom(path, data, count, flags, len, ep); } WaitStatus Socket::RecvFrom(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep) { return m_Socket->RecvFrom(address, scope, port, data, count, flags, len, ep); } WaitStatus Socket::Available(int32_t *amount) { return m_Socket->Available(amount); } WaitStatus Socket::Ioctl(int32_t command, const uint8_t *in_data, int32_t in_len, uint8_t *out_data, int32_t out_len, int32_t *written) { return m_Socket->Ioctl(command, in_data, in_len, out_data, out_len, written); } WaitStatus Socket::GetSocketOption(SocketOptionLevel level, SocketOptionName name, uint8_t *buffer, int32_t *length) { return m_Socket->GetSocketOption(level, name, buffer, length); } WaitStatus Socket::GetSocketOptionFull(SocketOptionLevel level, SocketOptionName name, int32_t *first, int32_t *second) { return m_Socket->GetSocketOptionFull(level, name, first, second); } WaitStatus Socket::Poll(std::vector &requests, int32_t count, int32_t timeout, int32_t *result, int32_t *error) { return SocketImpl::Poll(requests, count, timeout, result, error); } WaitStatus Socket::Poll(std::vector &requests, int32_t timeout, int32_t *result, int32_t *error) { return SocketImpl::Poll(requests, timeout, result, error); } WaitStatus Socket::Poll(PollRequest& request, int32_t timeout, int32_t *result, int32_t *error) { return SocketImpl::Poll(request, timeout, result, error); } WaitStatus Socket::SetSocketOption(SocketOptionLevel level, SocketOptionName name, int32_t value) { return m_Socket->SetSocketOption(level, name, value); } WaitStatus Socket::SetSocketOptionLinger(SocketOptionLevel level, SocketOptionName name, bool enabled, int32_t seconds) { return m_Socket->SetSocketOptionLinger(level, name, enabled, seconds); } WaitStatus Socket::SetSocketOptionArray(SocketOptionLevel level, SocketOptionName name, const uint8_t *buffer, int32_t length) { return m_Socket->SetSocketOptionArray(level, name, buffer, length); } WaitStatus Socket::SetSocketOptionMembership(SocketOptionLevel level, SocketOptionName name, uint32_t group_address, uint32_t local_address) { return m_Socket->SetSocketOptionMembership(level, name, group_address, local_address); } #if IL2CPP_SUPPORT_IPV6 WaitStatus Socket::SetSocketOptionMembership(SocketOptionLevel level, SocketOptionName name, IPv6Address ipv6, uint64_t interfaceOffset) { return m_Socket->SetSocketOptionMembership(level, name, ipv6, interfaceOffset); } #endif WaitStatus Socket::SendFile(const char *filename, TransmitFileBuffers *buffers, TransmitFileOptions options) { return m_Socket->SendFile(filename, buffers, options); } } } ================================================ FILE: unity_decoder/libil2cpp/os/Socket.h ================================================ #pragma once #include #include #include "il2cpp-config.h" #include "os/ErrorCodes.h" #include "os/Atomic.h" #include "os/Mutex.h" #include "os/WaitStatus.h" #include "utils/NonCopyable.h" namespace il2cpp { namespace os { class SocketImpl; enum AddressFamily { kAddressFamilyError = -1, kAddressFamilyUnspecified = 0,// AF_UNSPEC kAddressFamilyUnix = 1,// AF_UNIX kAddressFamilyInterNetwork = 2,// AF_INET kAddressFamilyIpx = 3,// AF_IPX kAddressFamilySna = 4,// AF_SNA kAddressFamilyDecNet = 5,// AF_DECnet kAddressFamilyAppleTalk = 6,// AF_APPLETALK kAddressFamilyInterNetworkV6 = 7,// AF_INET6 kAddressFamilyIrda = 8,// AF_IRDA }; enum SocketType { kSocketTypeError = -1, kSocketTypeStream = 0,// SOCK_STREAM kSocketTypeDgram = 1,// SOCK_DGRAM kSocketTypeRaw = 2,// SOCK_RAW kSocketTypeRdm = 3,// SOCK_RDM kSocketTypeSeqpacket = 4,// SOCK_SEQPACKET }; enum ProtocolType { kProtocolTypeUnknown = -1, kProtocolTypeIP = 0, kProtocolTypeIcmp = 1, kProtocolTypeIgmp = 2, kProtocolTypeGgp = 3, kProtocolTypeTcp = 6, kProtocolTypePup = 12, kProtocolTypeUdp = 17, kProtocolTypeIdp = 22, kProtocolTypeND = 77, kProtocolTypeRaw = 255, kProtocolTypeUnspecified = 0, kProtocolTypeIpx = 1000, kProtocolTypeSpx = 1256, kProtocolTypeSpxII = 1257, // #if NET_1_1 kProtocolTypeIPv6 = 41, // #endif // #if NET_2_0 kProtocolTypeIPv4 = 4, kProtocolTypeIPv6RoutingHeader = 43, kProtocolTypeIPv6FragmentHeader = 44, kProtocolTypeIPSecEncapsulatingSecurityPayload = 50, kProtocolTypeIPSecAuthenticationHeader = 51, kProtocolTypeIcmpV6 = 58, kProtocolTypeIPv6NoNextHeader = 59, kProtocolTypeIPv6DestinationOptions = 60, kProtocolTypeIPv6HopByHopOptions = 0, // #endif }; enum SocketFlags { kSocketFlagsNone = 0x00000000, kSocketFlagsOutOfBand = 0x00000001, kSocketFlagsPeek = 0x00000002, kSocketFlagsDontRoute = 0x00000004, kSocketFlagsMaxIOVectorLength = 0x00000010, // #if NET_2_0 kSocketFlagsTruncated = 0x00000100, kSocketFlagsControlDataTruncated = 0x00000200, kSocketFlagsBroadcast = 0x00000400, kSocketFlagsMulticast = 0x00000800, // #endif kSocketFlagsPartial = 0x00008000, }; enum SocketOptionLevel { kSocketOptionLevelSocket = 65535, kSocketOptionLevelIP = 0, kSocketOptionLevelTcp = 6, kSocketOptionLevelUdp = 17, //#if NET_1_1 kSocketOptionLevelIPv6 = 41, //#endif }; enum SocketOptionName { kSocketOptionNameDebug = 1, kSocketOptionNameAcceptConnection = 2, kSocketOptionNameReuseAddress = 4, kSocketOptionNameKeepAlive = 8, kSocketOptionNameDontRoute = 16, kSocketOptionNameBroadcast = 32, kSocketOptionNameUseLoopback = 64, kSocketOptionNameLinger = 128, kSocketOptionNameOutOfBandInline = 256, kSocketOptionNameDontLinger = -129, kSocketOptionNameExclusiveAddressUse = -5, kSocketOptionNameSendBuffer = 4097, kSocketOptionNameReceiveBuffer = 4098, kSocketOptionNameSendLowWater = 4099, kSocketOptionNameReceiveLowWater = 4100, kSocketOptionNameSendTimeout = 4101, kSocketOptionNameReceiveTimeout = 4102, kSocketOptionNameError = 4103, kSocketOptionNameType = 4104, kSocketOptionNameMaxConnections = 2147483647, kSocketOptionNameIPOptions = 1, kSocketOptionNameHeaderIncluded = 2, kSocketOptionNameTypeOfService = 3, kSocketOptionNameIpTimeToLive = 4, kSocketOptionNameMulticastInterface = 9, kSocketOptionNameMulticastTimeToLive = 10, kSocketOptionNameMulticastLoopback = 11, kSocketOptionNameAddMembership = 12, kSocketOptionNameDropMembership = 13, kSocketOptionNameDontFragment = 14, kSocketOptionNameAddSourceMembership = 15, kSocketOptionNameDropSourceMembership = 16, kSocketOptionNameBlockSource = 17, kSocketOptionNameUnblockSource = 18, kSocketOptionNamePacketInformation = 19, kSocketOptionNameNoDelay = 1, kSocketOptionNameBsdUrgent = 2, kSocketOptionNameExpedited = 2, kSocketOptionNameNoChecksum = 1, kSocketOptionNameChecksumCoverage = 20, kSocketOptionNameIPv6Only = 27, // #if NET_2_0 kSocketOptionNameHopLimit = 21, kSocketOptionNameUpdateAcceptContext = 28683, kSocketOptionNameUpdateConnectContext = 28688, // #endif }; enum PollFlags { kPollFlagsNone = 0, kPollFlagsIn = 1, kPollFlagsPri = 2, kPollFlagsOut = 4, kPollFlagsErr = 8, kPollFlagsHup = 0x10, kPollFlagsNVal = 0x20, kPollFlagsAny = 0xffffffff }; enum SocketError { kInterrupted = 4,// EINTR on POSIX and WSAEINTR on Windows kInvalidHandle = 9 // EBADF on POSIX and WSAEBADF on Windows }; inline void operator|=(PollFlags& left, PollFlags right) { left = static_cast(static_cast(left) | static_cast(right)); } enum TransmitFileOptions { kTransmitFileOptionsUseDefaultWorkerThread = 0x00000000, kTransmitFileOptionsDisconnect = 0x00000001, kTransmitFileOptionsReuseSocket = 0x00000002, kTransmitFileOptionsWriteBehind = 0x00000004, kTransmitFileOptionsUseSystemThread = 0x00000010, kTransmitFileOptionsUseKernelApc = 0x00000020, }; class Socket; struct PollRequest { int64_t fd; PollFlags events; PollFlags revents; }; #if IL2CPP_SUPPORT_IPV6 struct IPv6Address { uint8_t addr[16]; }; #endif // TODO: this should really be UNIX_PATH_MAX or SUN_LEN(n) #define END_POINT_MAX_PATH_LEN 255 #if IL2CPP_COMPILER_MSVC #pragma warning( push ) #pragma warning( disable : 4200 ) #endif struct EndPointInfo { AddressFamily family; union { struct { uint32_t port; uint32_t address; } inet; char path[END_POINT_MAX_PATH_LEN]; uint8_t raw[IL2CPP_ZERO_LEN_ARRAY]; } data; }; #if IL2CPP_COMPILER_MSVC #pragma warning( pop ) #endif // NOTE(gab): this must be binary compatible with Windows's WSABUF struct WSABuf { uint32_t length; void *buffer; }; // NOTE(gab): this must be binary compatible with Window's TRANSMIT_FILE_BUFFERS struct TransmitFileBuffers { void *head; uint32_t head_length; void *tail; uint32_t tail_length; }; // Note: this callback can be invoked by the os-specific implementation when an // interrupt is received or when the native code is looping in a potentially long // loop. // If the callback retun false, the executiong of the os-specific method is // gracefully interrupted, and an error is supposed to be returned by the // os-specific implementation. // The callback is allowed to throw exceptions (for example a ThreadAborted exception): // in this case, it is up to the os-specific implementation to properly deal with // cleaning up the temporarely allocated memory (if any). typedef bool (*ThreadStatusCallback)(); class Socket : public il2cpp::utils::NonCopyable { public: Socket(ThreadStatusCallback thread_status_callback); ~Socket(); // Note: this Create is only used internally WaitStatus Create(int64_t fd, int32_t family, int32_t type, int32_t protocol); WaitStatus Create(AddressFamily family, SocketType type, ProtocolType protocol); bool IsClosed(); void Close(); int64_t GetDescriptor(); ErrorCode GetLastError() const; WaitStatus SetBlocking(bool blocking); WaitStatus Listen(int32_t blacklog); WaitStatus Bind(const char *path); WaitStatus Bind(uint32_t address, uint16_t port); WaitStatus Bind(const char *address, uint16_t port); WaitStatus Bind(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port); WaitStatus Connect(const char *path); WaitStatus Connect(uint32_t address, uint16_t port); WaitStatus Connect(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port); WaitStatus Disconnect(bool reuse); WaitStatus Shutdown(int32_t how); WaitStatus GetLocalEndPointInfo(EndPointInfo &info); WaitStatus GetRemoteEndPointInfo(EndPointInfo &info); WaitStatus Receive(const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len); WaitStatus Send(const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len); WaitStatus SendArray(WSABuf *wsabufs, int32_t count, int32_t *sent, SocketFlags c_flags); WaitStatus ReceiveArray(WSABuf *wsabufs, int32_t count, int32_t *len, SocketFlags c_flags); WaitStatus SendTo(uint32_t address, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len); WaitStatus SendTo(const char *path, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len); WaitStatus SendTo(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len); WaitStatus RecvFrom(uint32_t address, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep); WaitStatus RecvFrom(const char *path, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep); WaitStatus RecvFrom(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep); WaitStatus Available(int32_t *amount); WaitStatus Accept(Socket **socket); WaitStatus Ioctl(int32_t command, const uint8_t *in_data, int32_t in_len, uint8_t *out_data, int32_t out_len, int32_t *written); WaitStatus GetSocketOption(SocketOptionLevel level, SocketOptionName name, uint8_t *buffer, int32_t *length); WaitStatus GetSocketOptionFull(SocketOptionLevel level, SocketOptionName name, int32_t *first, int32_t *second); WaitStatus SetSocketOption(SocketOptionLevel level, SocketOptionName name, int32_t value); WaitStatus SetSocketOptionLinger(SocketOptionLevel level, SocketOptionName name, bool enabled, int32_t seconds); WaitStatus SetSocketOptionArray(SocketOptionLevel level, SocketOptionName name, const uint8_t *buffer, int32_t length); WaitStatus SetSocketOptionMembership(SocketOptionLevel level, SocketOptionName name, uint32_t group_address, uint32_t local_address); #if IL2CPP_SUPPORT_IPV6 WaitStatus SetSocketOptionMembership(SocketOptionLevel level, SocketOptionName name, IPv6Address ipv6, uint64_t interfaceOffset); #endif WaitStatus SendFile(const char *filename, TransmitFileBuffers *buffers, TransmitFileOptions options); static WaitStatus Poll(std::vector &requests, int32_t count, int32_t timeout, int32_t *result, int32_t *error); static WaitStatus Poll(std::vector &requests, int32_t timeout, int32_t *result, int32_t *error); static WaitStatus Poll(PollRequest &request, int32_t timeout, int32_t *result, int32_t *error); static WaitStatus GetHostName(std::string &name); static WaitStatus GetHostByName(const std::string &host, std::string &name, std::vector &aliases, std::vector &addr_list); static WaitStatus GetHostByAddr(const std::string &address, std::string &name, std::vector &aliases, std::vector &addr_list); static void Startup(); static void Cleanup(); private: SocketImpl* m_Socket; }; /// Sockets should generally be referenced through SocketHandles for thread-safety. /// Handles are stored in a table and can be safely used even when the socket has already /// been deleted. typedef uint32_t SocketHandle; enum { kInvalidSocketHandle = 0 }; SocketHandle CreateSocketHandle(Socket* socket); Socket* AcquireSocketHandle(SocketHandle handle); void ReleaseSocketHandle(SocketHandle handle); inline SocketHandle PointerToSocketHandle(void* ptr) { // Double cast to avoid warnings. return static_cast(reinterpret_cast(ptr)); } /// Helper to automatically acquire and release a Socket within a scope. struct SocketHandleWrapper { SocketHandleWrapper() : m_Handle(kInvalidSocketHandle) , m_Socket(NULL) {} SocketHandleWrapper(SocketHandle handle) : m_Handle(handle) { m_Socket = AcquireSocketHandle(handle); } SocketHandleWrapper(const SocketHandleWrapper& other) { m_Handle = other.m_Handle; if (m_Handle != kInvalidSocketHandle) m_Socket = AcquireSocketHandle(m_Handle); else m_Socket = NULL; } ~SocketHandleWrapper() { Release(); } void Acquire(SocketHandle handle) { Release(); m_Handle = handle; m_Socket = AcquireSocketHandle(handle); } void Release() { if (m_Socket) ReleaseSocketHandle(m_Handle); m_Socket = NULL; m_Handle = kInvalidSocketHandle; } bool IsValid() const { return (m_Socket != NULL); } SocketHandle GetHandle() const { return m_Handle; } Socket* GetSocket() const { return m_Socket; } Socket* operator->() const { return GetSocket(); } SocketHandleWrapper& operator=(const SocketHandleWrapper& other) { Acquire(other.GetHandle()); return *this; } private: SocketHandle m_Handle; Socket* m_Socket; }; } } ================================================ FILE: unity_decoder/libil2cpp/os/StackTrace.h ================================================ #pragma once #include #include namespace il2cpp { namespace os { typedef bool(*WalkStackCallback)(Il2CppMethodPointer frame, void* context); class StackTrace { public: enum WalkOrder { kFirstCalledToLastCalled, kLastCalledToFirstCalled }; // Walks the stack calling callback for each frame in the stack // Stops when callback returns false static void WalkStack(WalkStackCallback callback, void* context, WalkOrder walkOrder); }; } } ================================================ FILE: unity_decoder/libil2cpp/os/Std/ThreadImpl.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_THREADS_STD #include "os/Thread.h" #include "ThreadImpl.h" #include namespace il2cpp { namespace os { struct StartData { Thread::StartFunc m_StartFunc; void* m_StartArg; }; static void ThreadStartWrapper(void* arg) { StartData* startData = (StartData*)arg; startData->m_StartFunc(startData->m_StartArg); free(startData); } uint64_t ThreadImpl::Id() { return m_Thread.get_id().hash(); } ErrorCode ThreadImpl::Run(Thread::StartFunc func, void* arg) { StartData* startData = (StartData*)malloc(sizeof(StartData)); startData->m_StartFunc = func; startData->m_StartArg = arg; std::thread t(ThreadStartWrapper, startData); m_Thread.swap(t); return kErrorCodeSuccess; } WaitStatus ThreadImpl::Join(uint32_t ms) { m_Thread.join(); return kWaitStatusSuccess; } ErrorCode ThreadImpl::Sleep(uint32_t milliseconds) { std::chrono::milliseconds dura(milliseconds); std::this_thread::sleep_for(dura); return kErrorCodeSuccess; } uint64_t ThreadImpl::CurrentThreadId() { return std::this_thread::get_id().hash(); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Std/ThreadImpl.h ================================================ #pragma once #if IL2CPP_THREADS_STD #include "os/ErrorCodes.h" #include "os/Thread.h" #include "os/WaitStatus.h" #include "utils/NonCopyable.h" #include namespace il2cpp { namespace os { class ThreadImpl : public il2cpp::utils::NonCopyable { public: ThreadImpl(); ~ThreadImpl(); uint64_t Id(); ErrorCode Run(Thread::StartFunc func, void* arg); WaitStatus Join(); WaitStatus Join(uint32_t ms); static WaitStatus Sleep(uint32_t milliseconds); static uint64_t CurrentThreadId(); private: std::thread m_Thread; }; } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Thread.cpp ================================================ #include "il2cpp-config.h" #include "os/Mutex.h" #include "os/Thread.h" #include "os/ThreadLocalValue.h" #if IL2CPP_THREADS_STD #include "os/Std/ThreadImpl.h" #elif IL2CPP_TARGET_WINDOWS #include "os/Win32/ThreadImpl.h" #elif IL2CPP_THREADS_PTHREAD #include "os/Posix/ThreadImpl.h" #else #include "os/ThreadImpl.h" #endif #include "utils/dynamic_array.h" #include namespace il2cpp { namespace os { /// TLS variable referring to current thread. static ThreadLocalValue s_CurrentThread; // TLS variable referring to whether this thread is currently executing Thread::Shutdown // It is thread local for thread safety static ThreadLocalValue s_IsCleaningUpThreads; static FastMutex s_AliveThreadsMutex; static il2cpp::utils::dynamic_array s_AliveThreads; static bool GetIsCleaningUpThreads() { void* value = NULL; s_IsCleaningUpThreads.GetValue(&value); return reinterpret_cast(value) != 0; } static void SetIsCleaningUpThreads(bool value) { s_IsCleaningUpThreads.SetValue(reinterpret_cast(static_cast(value))); } Thread::Thread() : m_Thread(new ThreadImpl()) , m_State(kThreadCreated) , m_ThreadExitedEvent(true) // Manual reset event , m_CleanupFunc(NULL) , m_CleanupFuncArg(NULL) { FastAutoLock lock(&s_AliveThreadsMutex); s_AliveThreads.push_back(this); } Thread::Thread(ThreadImpl* thread) : m_Thread(thread) , m_State(kThreadRunning) , m_CleanupFunc(NULL) , m_CleanupFuncArg(NULL) { FastAutoLock lock(&s_AliveThreadsMutex); s_AliveThreads.push_back(this); } Thread::~Thread() { delete m_Thread; if (!GetIsCleaningUpThreads()) { FastAutoLock lock(&s_AliveThreadsMutex); size_t count = s_AliveThreads.size(); for (size_t i = 0; i < count; i++) { if (s_AliveThreads[i] == this) { s_AliveThreads.erase_swap_back(&s_AliveThreads[i]); break; } } } } void Thread::Init() { Thread* thread = GetOrCreateCurrentThread(); if (thread->GetApartment() == kApartmentStateUnknown) thread->SetApartment(kApartmentStateInMTA); } void Thread::Shutdown() { Thread* thread = GetCurrentThread(); thread->SetApartment(kApartmentStateUnknown); SetIsCleaningUpThreads(true); FastAutoLock lock(&s_AliveThreadsMutex); size_t count = s_AliveThreads.size(); for (size_t i = 0; i < count; i++) delete s_AliveThreads[i]; s_AliveThreads.clear(); SetIsCleaningUpThreads(false); } Thread::ThreadId Thread::Id() { return m_Thread->Id(); } void Thread::SetName(const std::string& name) { m_Thread->SetName(name); } void Thread::SetPriority(ThreadPriority priority) { m_Thread->SetPriority(priority); } ThreadPriority Thread::GetPriority() { return m_Thread->GetPriority(); } void Thread::SetStackSize(size_t stackSize) { m_Thread->SetStackSize(stackSize); } struct StartData { Thread* thread; Thread::StartFunc startFunction; void* startFunctionArgument; }; /// Wrapper for the user's thread start function. Sets s_CurrentThread. void Thread::RunWrapper(void* arg) { StartData* data = reinterpret_cast(arg); // Store thread reference. Thread* thread = data->thread; const ApartmentState apartment = thread->GetExplicitApartment(); if (apartment != kApartmentStateUnknown) { thread->SetExplicitApartment(kApartmentStateUnknown); thread->SetApartment(apartment); } s_CurrentThread.SetValue(thread); // Get rid of StartData. StartFunc startFunction = data->startFunction; void* startFunctionArgument = data->startFunctionArgument; delete data; // Make sure thread exit event is not signaled. thread->m_ThreadExitedEvent.Reset(); // Run user thread start function. thread->m_State = kThreadRunning; startFunction(startFunctionArgument); thread->m_State = kThreadExited; thread->SetApartment(kApartmentStateUnknown); CleanupFunc cleanupFunc = thread->m_CleanupFunc; void* cleanupFuncArg = thread->m_CleanupFuncArg; // Signal that we've finished execution. thread->m_ThreadExitedEvent.Set(); if (cleanupFunc) cleanupFunc(cleanupFuncArg); } ErrorCode Thread::Run(StartFunc func, void* arg) { IL2CPP_ASSERT(m_State == kThreadCreated || m_State == kThreadExited); StartData* startData = new StartData; startData->startFunction = func; startData->startFunctionArgument = arg; startData->thread = this; return m_Thread->Run(RunWrapper, startData); } WaitStatus Thread::Join() { IL2CPP_ASSERT(this != GetCurrentThread() && "Trying to join the current thread will deadlock"); return Join(std::numeric_limits::max()); } WaitStatus Thread::Join(uint32_t ms) { // Wait for thread exit event. if (m_ThreadExitedEvent.Wait(ms, true) != kWaitStatusSuccess) return kWaitStatusFailure; return kWaitStatusSuccess; } void Thread::QueueUserAPC(APCFunc func, void* context) { m_Thread->QueueUserAPC(func, context); } ApartmentState Thread::GetApartment() { #if IL2CPP_THREAD_IMPL_HAS_COM_APARTMENTS return m_Thread->GetApartment(); #else return kApartmentStateUnknown; #endif } ApartmentState Thread::GetExplicitApartment() { #if IL2CPP_THREAD_IMPL_HAS_COM_APARTMENTS return m_Thread->GetExplicitApartment(); #else return kApartmentStateUnknown; #endif } ApartmentState Thread::SetApartment(ApartmentState state) { #if IL2CPP_THREAD_IMPL_HAS_COM_APARTMENTS return m_Thread->SetApartment(state); #else NO_UNUSED_WARNING(state); return GetApartment(); #endif } void Thread::SetExplicitApartment(ApartmentState state) { #if IL2CPP_THREAD_IMPL_HAS_COM_APARTMENTS m_Thread->SetExplicitApartment(state); #else NO_UNUSED_WARNING(state); #endif } void Thread::Sleep(uint32_t milliseconds, bool interruptible) { ThreadImpl::Sleep(milliseconds, interruptible); } uint64_t Thread::CurrentThreadId() { return ThreadImpl::CurrentThreadId(); } Thread* Thread::GetCurrentThread() { void* value; s_CurrentThread.GetValue(&value); IL2CPP_ASSERT(value != NULL); return reinterpret_cast(value); } Thread* Thread::GetOrCreateCurrentThread() { Thread* thread = NULL; s_CurrentThread.GetValue(reinterpret_cast(&thread)); if (thread) return thread; thread = new Thread(ThreadImpl::CreateForCurrentThread()); s_CurrentThread.SetValue(thread); return thread; } void Thread::DetachCurrentThread() { #if IL2CPP_DEBUG void* value; s_CurrentThread.GetValue(&value); IL2CPP_ASSERT(value != NULL); #endif s_CurrentThread.SetValue(NULL); } #if NET_4_0 bool Thread::YieldInternal() { return ThreadImpl::YieldInternal(); } #endif #if IL2CPP_HAS_NATIVE_THREAD_CLEANUP void Thread::SetNativeThreadCleanup(ThreadCleanupFunc cleanupFunction) { ThreadImpl::SetNativeThreadCleanup(cleanupFunction); } void Thread::RegisterCurrentThreadForCleanup(void* arg) { ThreadImpl::RegisterCurrentThreadForCleanup(arg); } void Thread::UnregisterCurrentThreadForCleanup() { ThreadImpl::UnregisterCurrentThreadForCleanup(); } #endif } } ================================================ FILE: unity_decoder/libil2cpp/os/Thread.h ================================================ #pragma once #include "os/ErrorCodes.h" #include "os/Handle.h" #include "os/Event.h" #include "os/WaitStatus.h" #include "utils/NonCopyable.h" namespace il2cpp { namespace os { class ThreadImpl; enum ThreadPriority { kThreadPriorityLowest = 0, kThreadPriorityLow = 1, kThreadPriorityNormal = 2, kThreadPriorityHigh = 3, kThreadPriorityHighest = 4 }; enum ApartmentState { kApartmentStateInSTA = 0, kApartmentStateInMTA = 1, kApartmentStateUnknown = 2, kApartmentStateCoInitialized = 4, }; class Thread : public il2cpp::utils::NonCopyable { public: Thread(); ~Thread(); typedef void (*StartFunc) (void* arg); // Use STDCALL calling convention on Windows, as it will be called back directly from the OS. This is defined as nothing on other platforms. typedef void (STDCALL * APCFunc)(void* context); typedef uint64_t ThreadId; typedef void (*CleanupFunc) (void* arg); /// Initialize/Shutdown thread subsystem. Must be called on main thread. static void Init(); static void Shutdown(); ErrorCode Run(StartFunc func, void* arg); ThreadId Id(); /// Set thread name for debugging purposes. Won't do anything if not supported /// by platform. void SetName(const std::string& name); void SetPriority(ThreadPriority priority); ThreadPriority GetPriority(); void SetStackSize(size_t stackSize); void SetCleanupFunction(CleanupFunc cleanupFunc, void* arg) { m_CleanupFunc = cleanupFunc; m_CleanupFuncArg = arg; } /// Interruptible, infinite wait join. WaitStatus Join(); /// Interruptible, timed wait join. WaitStatus Join(uint32_t ms); /// Execute the given function on the thread the next time the thread executes /// an interruptible blocking operation. /// NOTE: The APC is allowed to raise exceptions! void QueueUserAPC(APCFunc func, void* context); // Explicit versions modify state without actually changing COM state. // Used to set thread state before it's started. ApartmentState GetApartment(); ApartmentState GetExplicitApartment(); ApartmentState SetApartment(ApartmentState state); void SetExplicitApartment(ApartmentState state); /// Interruptible, timed sleep. static void Sleep(uint32_t ms, bool interruptible = false); static ThreadId CurrentThreadId(); static Thread* GetCurrentThread(); static Thread* GetOrCreateCurrentThread(); static void DetachCurrentThread(); #if NET_4_0 static bool YieldInternal(); #endif #if IL2CPP_HAS_NATIVE_THREAD_CLEANUP typedef void (*ThreadCleanupFunc) (void* arg); static void SetNativeThreadCleanup(ThreadCleanupFunc cleanupFunction); static void RegisterCurrentThreadForCleanup(void* arg); static void UnregisterCurrentThreadForCleanup(); #endif static const uint64_t kInvalidThreadId = 0; private: enum ThreadState { kThreadCreated, kThreadRunning, kThreadWaiting, kThreadExited }; ThreadState m_State; friend class ThreadImpl; // m_Thread ThreadImpl* m_Thread; /// Event that the thread signals when it finishes execution. Used for joins. /// Supports interruption. Event m_ThreadExitedEvent; CleanupFunc m_CleanupFunc; void* m_CleanupFuncArg; Thread(ThreadImpl* thread); static void RunWrapper(void* arg); }; } } ================================================ FILE: unity_decoder/libil2cpp/os/ThreadLocalValue.cpp ================================================ #include "il2cpp-config.h" #include "os/ThreadLocalValue.h" #if IL2CPP_THREADS_WIN32 #include "os/Win32/ThreadLocalValueImpl.h" #elif IL2CPP_THREADS_PSP2 #include "os/PSP2/ThreadLocalValueImpl.h" #elif IL2CPP_THREADS_PTHREAD #include "os/Posix/ThreadLocalValueImpl.h" #else #include "os/ThreadLocalValueImpl.h" #endif namespace il2cpp { namespace os { ThreadLocalValue::ThreadLocalValue() : m_ThreadLocalValue(new ThreadLocalValueImpl()) { } ThreadLocalValue::~ThreadLocalValue() { delete m_ThreadLocalValue; } ErrorCode ThreadLocalValue::SetValue(void* value) { return m_ThreadLocalValue->SetValue(value); } ErrorCode ThreadLocalValue::GetValue(void** value) { return m_ThreadLocalValue->GetValue(value); } } } ================================================ FILE: unity_decoder/libil2cpp/os/ThreadLocalValue.h ================================================ #pragma once #include "os/ErrorCodes.h" namespace il2cpp { namespace os { class ThreadLocalValueImpl; class ThreadLocalValue { public: ThreadLocalValue(); ~ThreadLocalValue(); ErrorCode SetValue(void* value); ErrorCode GetValue(void** value); private: ThreadLocalValueImpl* m_ThreadLocalValue; }; } } ================================================ FILE: unity_decoder/libil2cpp/os/Time.h ================================================ #pragma once #include namespace il2cpp { namespace os { class Time { public: /* Returns the number of milliseconds from boot time: this should be monotonic */ static uint32_t GetTicksMillisecondsMonotonic(); /* Returns the number of 100ns ticks from unspecified time: this should be monotonic */ static int64_t GetTicks100NanosecondsMonotonic(); /* Returns the number of 100ns ticks since 1/1/1, UTC timezone */ static int64_t GetTicks100NanosecondsDateTime(); // Retrieves the current system date and time. The information is in Coordinated Universal Time(UTC) format. static int64_t GetSystemTimeAsFileTime(); }; } } ================================================ FILE: unity_decoder/libil2cpp/os/TimeZone.h ================================================ #pragma once #include #include namespace il2cpp { namespace os { class TimeZone { public: /* * This is heavily based on zdump.c from glibc 2.2. * * * data[0]: start of daylight saving time (in DateTime ticks). * * data[1]: end of daylight saving time (in DateTime ticks). * * data[2]: utcoffset (in TimeSpan ticks). * * data[3]: additional offset when daylight saving (in TimeSpan ticks). * * name[0]: name of this timezone when not daylight saving. * * name[1]: name of this timezone when daylight saving. * * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while * the class library allows years between 1 and 9999. * * Returns true on success and zero on failure. */ static bool GetTimeZoneData(int32_t year, int64_t data[4], std::string names[2]); }; } } ================================================ FILE: unity_decoder/libil2cpp/os/Tizen/ExtendedAtomicOps.h ================================================ #pragma once #define ASM_LABEL(i) #i ":\n\t" #define ATOMIC_LOAD(PRE, POST) \ atomic_word res; \ __asm__ __volatile__ \ ( \ PRE \ "ldr %0, %1\n\t" \ POST \ : "=r" (res) \ : "m" (*p) \ : "memory" \ ); \ return res; #define ATOMIC_LOAD2(PRE, POST) \ atomic_word2 ret; \ atomic_word res; \ __asm__ __volatile__ \ ( \ PRE \ "ldr %0, %1\n\t" \ POST \ : "=r" (res) \ : "m" (*p) \ : "memory" \ ); \ ret.v = res; \ return ret; #define ATOMIC_STORE(PRE, POST) \ __asm__ __volatile__ \ ( \ PRE \ "str %1, %0\n\t" \ POST \ : "=m" (*p) \ : "r" (v) \ : "memory" \ ); #define ATOMIC_XCHG(PRE, POST) \ atomic_word res; \ atomic_word success; \ __asm__ __volatile__ \ ( \ PRE \ ASM_LABEL (0) \ "ldrex %2, [%4]\n\t" \ "strex %0, %3, [%4]\n\t" \ "teq %0, #0\n\t" \ "bne 0b\n\t" \ POST \ : "=&r" (success), "+m" (*p), "=&r" (res) \ : "r" (v), "r" (p) \ : "cc", "memory" \ ); \ return res; #define ATOMIC_XCHG2(PRE, POST) \ atomic_word2 ret; \ atomic_word res; \ atomic_word success; \ __asm__ __volatile__ \ ( \ PRE \ ASM_LABEL (0) \ "ldrex %2, [%4]\n\t" \ "strex %0, %3, [%4]\n\t" \ "teq %0, #0\n\t" \ "bne 0b\n\t" \ POST \ : "=&r" (success), "+m" (*p), "=&r" (res) \ : "r" (v), "r" (p) \ : "cc", "memory" \ ); \ ret.v = res; \ return ret; static inline void atomic_thread_fence(int) { __sync_synchronize(); } static inline atomic_word atomic_load_explicit(const volatile atomic_word* p, int) { ATOMIC_LOAD("", "") } static inline void atomic_store_explicit(volatile atomic_word* p, atomic_word v, int) { ATOMIC_STORE("", "") } static inline atomic_word atomic_exchange_explicit(volatile atomic_word* p, atomic_word v, int) { ATOMIC_XCHG("", "") } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word* oldval, atomic_word newval, int, int) { return __sync_val_compare_and_swap(p, oldval, newval); } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word* oldval, atomic_word newval, int, int) { return __sync_val_compare_and_swap(p, oldval, newval); } static inline atomic_word atomic_fetch_add_explicit(volatile atomic_word *p, atomic_word val, int) { return __sync_fetch_and_add(p, val); } static inline atomic_word atomic_fetch_sub_explicit(volatile atomic_word *p, atomic_word val, int) { return __sync_fetch_and_add(p, -val); } /* * extensions */ static inline void atomic_retain(volatile int *p) { __sync_fetch_and_add(p, 1); } static inline bool atomic_release(volatile int *p) { return __sync_fetch_and_add(p, -1) == 1; } // double word static inline atomic_word2 atomic_load_explicit(const volatile atomic_word2* p, int) { ATOMIC_LOAD2("", "") } static inline void atomic_store_explicit(volatile atomic_word2* p, atomic_word2 v, int) { ATOMIC_STORE("", "") } static inline atomic_word2 atomic_exchange_explicit(volatile atomic_word2* p, atomic_word2 v, int) { ATOMIC_XCHG2("", "") } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word2* p, atomic_word2* oldval, atomic_word2 newval, int, int) { return __sync_val_compare_and_swap(&p->v, &oldval->v, newval.v); } ================================================ FILE: unity_decoder/libil2cpp/os/Unity/AtomicQueue.cpp ================================================ #include "AtomicQueue.h" #include "ExtendedAtomicOps.h" UNITY_PLATFORM_BEGIN_NAMESPACE; // // AtomicNode // AtomicNode* AtomicNode::Link(AtomicNode* next) { #if defined(ATOMIC_HAS_QUEUE) AtomicNode* old = Next(); atomic_store_explicit(&_next, (atomic_word)next, memory_order_relaxed); return old; #else AtomicNode* old = Next(); _next = (atomic_word)next; return old; #endif } #if defined(ATOMIC_HAS_QUEUE) // // AtomicStack // AtomicStack::AtomicStack() { #if defined(ATOMIC_HAS_DCAS) atomic_word2 w; w.lo = w.hi = 0; atomic_store_explicit(&_top, w, memory_order_relaxed); #else atomic_store_explicit(&_top, 0, memory_order_relaxed); #endif } AtomicStack::~AtomicStack() { } int AtomicStack::IsEmpty() const { #if defined(ATOMIC_HAS_DCAS) atomic_word2 top = atomic_load_explicit(&_top, memory_order_relaxed); return top.lo == 0; #else return atomic_load_explicit(&_top, memory_order_relaxed) == 0; #endif } void AtomicStack::Push(AtomicNode* node) { #if defined(ATOMIC_HAS_DCAS) atomic_word2 top = atomic_load_explicit(&_top, memory_order_relaxed); atomic_word2 newtop; newtop.lo = (atomic_word)node; do { atomic_store_explicit(&node->_next, top.lo, memory_order_relaxed); newtop.hi = top.hi + 1; } while (!atomic_compare_exchange_strong_explicit(&_top, &top, newtop, memory_order_release, memory_order_relaxed)); #elif defined(__arm64__) AtomicNode* top; long success; __asm__ __volatile__ ( "0:\n\t" "ldxr\t%0, [%4]\n\t" "str %0, [%5]\n\t" "stlxr\t%w3, %5, [%4]\n\t" "cbnz\t%w3, 0b\n\t" : "=&r" (top), "=m" (*node), "+m" (_top), "=&r" (success) : "r" (&_top), "r" (node) : "cc", "memory" ); #elif PLATFORM_N3DS AtomicNode* top; int success; __asm__ __volatile__ { //dmb ishst //not supported on N3DS one: ldrex top, [&_top] str top, [node] strex success, node, [&_top] teq success, #0 bne one } #elif defined(__arm__) AtomicNode* top; int success; __asm__ __volatile__ ( "dmb\tish\n\t" "0:\n\t" "ldrex\t%0, [%4]\n\t" "str %0, [%5]\n\t" "strex\t%3, %5, [%4]\n\t" "teq %3, #0\n\t" "bne\t0b\n\t" : "=&r" (top), "=m" (*node), "+m" (_top), "=&r" (success) : "r" (&_top), "r" (node) : "cc", "memory" ); #elif defined(__ppc64__) || defined(_ARCH_PPC64) AtomicNode* top; AtomicNode* tmp; __asm__ __volatile__ ( "ld\t\t%0, 0(%4)\n\t" "0:\n\t" "mr\t\t%3, %0\n\t" "std %0, 0(%5)\n\t" "lwsync\n\t" "ldarx\t%0, 0, %4\n\t" "cmpd\t%0, %3\n\t" "bne-\t0b\n\t" "stdcx.\t%5, 0, %4\n\t" "bne-\t0b\n\t" : "=&b" (top), "+m" (_top), "=m" (*node), "=&b" (tmp) : "b" (&_top), "b" (node) : "cr0", "memory" ); #elif defined(__ppc__) AtomicNode* top; AtomicNode* tmp; __asm__ __volatile__ ( "lwz\t%0, 0(%4)\n\t" "0:\n\t" "mr\t\t%3, %0\n\t" "stw %0, 0(%5)\n\t" "lwsync\n\t" "lwarx\t%0, 0, %4\n\t" "cmpw\t%0, %3\n\t" "bne-\t0b\n\t" "stwcx.\t%5, 0, %4\n\t" "bne-\t0b\n\t" : "=&b" (top), "+m" (_top), "=m" (*node), "=&b" (tmp) : "b" (&_top), "b" (node) : "cr0", "memory" ); #else # error #endif } void AtomicStack::PushAll(AtomicNode* first, AtomicNode* last) { #if defined(ATOMIC_HAS_DCAS) atomic_word2 top = atomic_load_explicit(&_top, memory_order_relaxed); atomic_word2 newtop; newtop.lo = (atomic_word)first; do { atomic_store_explicit(&last->_next, top.lo, memory_order_relaxed); newtop.hi = top.hi + 1; } while (!atomic_compare_exchange_strong_explicit(&_top, &top, newtop, memory_order_release, memory_order_relaxed)); #elif defined(__arm64__) AtomicNode* top; long success; __asm__ __volatile__ ( "0:\n\t" "ldxr\t%0, [%4]\n\t" "str %0, [%6]\n\t" "stlxr\t%w3, %5, [%4]\n\t" "cbnz\t%w3, 0b\n\t" : "=&r" (top), "+m" (_top), "=m" (*last), "=&r" (success) : "r" (&_top), "r" (first), "r" (last) : "cc", "memory" ); #elif PLATFORM_N3DS AtomicNode* top; int success; __asm__ __volatile__ ( //"dmb ishst\n\t" //not supported on N3DS "0:\n\t" "ldrex\ttop, [&_top]\n\t" "str top, [last]\n\t" "strex\tsuccess, first, [&_top]\n\t" "teq success, #0\n\t" "bne\t0b\n\t" ); #elif defined(__arm__) AtomicNode* top; int success; __asm__ __volatile__ ( "dmb\tish\n\t" "0:\n\t" "ldrex\t%0, [%4]\n\t" "str %0, [%6]\n\t" "strex\t%3, %5, [%4]\n\t" "teq %3, #0\n\t" "bne\t0b\n\t" : "=&r" (top), "+m" (_top), "=m" (*last), "=&r" (success) : "r" (&_top), "r" (first), "r" (last) : "cc", "memory" ); #elif defined(__ppc64__) || defined(_ARCH_PPC64) AtomicNode* top; AtomicNode* tmp; __asm__ __volatile__ ( "ld\t\t%0, 0(%4)\n\t" "0:\n\t" "mr\t\t%3, %0\n\t" "std %0, 0(%6)\n\t" "lwsync\n\t" "ldarx\t%0, 0, %4\n\t" "cmpd\t%0, %3\n\t" "bne-\t0b\n\t" "stdcx.\t%5, 0, %4\n\t" "bne-\t0b\n\t" : "=&b" (top), "+m" (_top), "=m" (*last), "=&b" (tmp) : "b" (&_top), "r" (first), "b" (last) : "cr0", "memory" ); #elif defined(__ppc__) AtomicNode* top; AtomicNode* tmp; __asm__ __volatile__ ( "lwz\t%0, 0(%4)\n\t" "0:\n\t" "mr\t\t%3, %0\n\t" "stw %0, 0(%6)\n\t" "lwsync\n\t" "lwarx\t%0, 0, %4\n\t" "cmpw\t%0, %3\n\t" "bne-\t0b\n\t" "stwcx.\t%5, 0, %4\n\t" "bne-\t0b\n\t" : "=&b" (top), "=m" (*last), "+m" (_top), "=&b" (tmp) : "b" (&_top), "r" (first), "b" (last) : "cr0", "memory" ); #else # error #endif } AtomicNode* AtomicStack::Pop() { #if defined(ATOMIC_HAS_DCAS) atomic_word2 top = atomic_load_explicit(&_top, memory_order_relaxed); atomic_word2 newtop; AtomicNode* node; do { node = (AtomicNode*)top.lo; if (!node) break; newtop.lo = (atomic_word)atomic_load_explicit(&node->_next, memory_order_relaxed); newtop.hi = top.hi + 1; } while (!atomic_compare_exchange_strong_explicit(&_top, &top, newtop, memory_order_acquire, memory_order_relaxed)); return node; #elif defined(__arm64__) AtomicNode* top = NULL; AtomicNode* tmp; long success; __asm__ __volatile__ ( "0:\n\t" "ldaxr\t%0, [%4]\n\t" "cbz\t%0, 1f\n\t" "ldr %1, [%0]\n\t" "stxr\t%w3, %1, [%4]\n\t" "cbnz\t%w3, 0b\n\t" "1:\n\t" : "=&r" (top), "=&r" (tmp), "+m" (_top), "=&r" (success) : "r" (&_top) : "cc", "memory" ); return top; #elif PLATFORM_N3DS AtomicNode* top = NULL; AtomicNode* tmp; int success = 0; __asm__ __volatile__ { one: ldrex top, [&_top] cmp top, #0 beq two ldr tmp, [top] strex success, tmp, [&_top] teq success, #0 bne one //isb two: } return top; #elif defined(__arm__) AtomicNode* top = NULL; AtomicNode* tmp; int success; __asm__ __volatile__ ( "0:\n\t" "ldrex\t%0, [%4]\n\t" "cmp\t%0, #0\n\t" "beq\t1f\n\t" "ldr %1, [%0]\n\t" "strex\t%3, %1, [%4]\n\t" "teq\t%3, #0\n\t" "bne\t0b\n\t" "isb\n\t" "1:\n\t" : "=&r" (top), "=&r" (tmp), "+m" (_top), "=&r" (success) : "r" (&_top) : "cc", "memory" ); return top; #elif defined(__ppc64__) || defined(_ARCH_PPC64) AtomicNode* top = NULL; AtomicNode* tmp; __asm__ __volatile__ ( "0:\n\t" "ldarx\t%0, 0, %3\n\t" "cmpdi %0, 0\n\t" "beq- 1f\n\t" "ld %1, 0(%0)\n\t" "stdcx. %1, 0, %3\n\t" "bne- 0b\n\t" "isync\n\t" "b\t\t2f\n\f" "1:\n\t" "stdcx.\t%0, 0, %3\n\t" "bne-\t0b\n\t" "2:\n\t" : "=&b" (top), "=&b" (tmp), "+m" (_top) : "b" (&_top) : "cr0", "memory" ); return top; #elif defined(__ppc__) AtomicNode* top = NULL; AtomicNode* tmp; __asm__ __volatile__ ( "0:\n\t" "lwarx\t%0, 0, %3\n\t" "cmpwi %0, 0\n\t" "beq- 1f\n\t" "lwz %1, 0(%0)\n\t" "stwcx. %1, 0, %3\n\t" "bne- 0b\n\t" "isync\n\t" "b\t\t2f\n\f" "1:\n\t" "stwcx.\t%0, 0, %3\n\t" "bne-\t0b\n\t" "2:\n\t" : "=&b" (top), "=&b" (tmp), "+m" (_top) : "b" (&_top) : "cr0", "memory" ); return top; #else # error #endif } AtomicNode* AtomicStack::PopAll() { #if defined(ATOMIC_HAS_DCAS) atomic_word2 top = atomic_load_explicit(&_top, memory_order_relaxed); atomic_word2 newtop; AtomicNode* node; do { node = (AtomicNode*)top.lo; if (!node) break; newtop.lo = 0; newtop.hi = top.hi + 1; } while (!atomic_compare_exchange_strong_explicit(&_top, &top, newtop, memory_order_acquire, memory_order_relaxed)); return node; #elif defined(__arm64__) AtomicNode* top; AtomicNode* tmp; long success; __asm__ __volatile__ ( "0:\n\t" "ldaxr\t%0, [%4]\n\t" "cbz\t%0, 1f\n\t" "stxr\t%w3, %5, [%4]\n\t" "cbnz\t%w3, 0b\n\t" "1:\n\t" : "=&r" (top), "=&r" (tmp), "+m" (_top), "=&r" (success) : "r" (&_top), "r" (0) : "cc", "memory" ); return top; #elif PLATFORM_N3DS AtomicNode* top; AtomicNode* tmp; int success; __asm__ __volatile__ ( "0:\n\t" "ldrex\ttop, [&_top]\n\t" "cmp\ttop, #0\n\t" "beq\t1f\n\t" "strex\tsuccess, #0, [&_top]\n\t" "teq\tsuccess, #0\n\t" "bne\t0b\n\t" //"isb\n\t" //not supported on N3DS "1:\n\t" ); return top; #elif defined(__arm__) AtomicNode* top; AtomicNode* tmp; int success; __asm__ __volatile__ ( "0:\n\t" "ldrex\t%0, [%4]\n\t" "cmp\t%0, #0\n\t" "beq\t1f\n\t" "strex\t%3, %5, [%4]\n\t" "teq\t%3, #0\n\t" "bne\t0b\n\t" "isb\n\t" "1:\n\t" : "=&r" (top), "=&r" (tmp), "+m" (_top), "=&r" (success) : "r" (&_top), "r" (0) : "cc", "memory" ); return top; #elif defined(__ppc64__) || defined(_ARCH_PPC64) AtomicNode* top; AtomicNode* tmp; __asm__ __volatile__ ( "0:\n\t" "ldarx\t%0, 0, %3\n\t" "cmpdi %0, 0\n\t" "beq- 1f\n\t" "stdcx. %4, 0, %3\n\t" "bne- 0b\n\t" "isync\n\t" "1:\n\t" : "=&b" (top), "=&b" (tmp), "+m" (_top) : "b" (&_top), "r" (0) : "cr0", "memory" ); return top; #elif defined(__ppc__) AtomicNode* top; AtomicNode* tmp; __asm__ __volatile__ ( "0:\n\t" "lwarx\t%0, 0, %3\n\t" "cmpwi %0, 0\n\t" "beq- 1f\n\t" "stwcx. %4, 0, %3\n\t" "bne- 0b\n\t" "isync\n\t" "1:\n\t" : "=&b" (top), "=&b" (tmp), "+m" (_top) : "b" (&_top), "r" (0) : "cr0", "memory" ); return top; #else # error #endif } AtomicStack* CreateAtomicStack() { // should be properly aligned #if defined(ATOMIC_HAS_DCAS) return UNITY_PLATFORM_NEW_ALIGNED(AtomicStack, kMemThread, sizeof(atomic_word2)); #else return UNITY_PLATFORM_NEW_ALIGNED(AtomicStack, kMemThread, sizeof(atomic_word)); #endif } void DestroyAtomicStack(AtomicStack* s) { UNITY_PLATFORM_DELETE(s, kMemThread); } // // AtomicQueue // AtomicQueue::AtomicQueue() { #if defined(ATOMIC_HAS_DCAS) AtomicNode* dummy = UNITY_PLATFORM_NEW(AtomicNode, kMemThread); atomic_word2 w; w.lo = (atomic_word)dummy; w.hi = 0; atomic_store_explicit(&dummy->_next, 0, memory_order_relaxed); atomic_store_explicit(&_tail, w, memory_order_relaxed); atomic_store_explicit(&_head, (atomic_word)dummy, memory_order_release); #else AtomicNode* dummy = UNITY_PLATFORM_NEW(AtomicNode, kMemThread); atomic_store_explicit(&dummy->_next, 0, memory_order_relaxed); atomic_store_explicit(&_tail, (atomic_word)dummy, memory_order_relaxed); atomic_store_explicit(&_head, (atomic_word)dummy, memory_order_release); #endif } AtomicQueue::~AtomicQueue() { AtomicNode* dummy = (AtomicNode*)atomic_load_explicit(&_head, memory_order_relaxed); UNITY_PLATFORM_DELETE(dummy, kMemThread); } int AtomicQueue::IsEmpty() const { #if defined(ATOMIC_HAS_DCAS) atomic_word2 cmp = atomic_load_explicit(&_tail, memory_order_relaxed); return atomic_load_explicit(&((AtomicNode*)cmp.lo)->_next, memory_order_relaxed) == 0; #else atomic_word cmp = atomic_load_explicit(&_tail, memory_order_relaxed); return atomic_load_explicit(&((AtomicNode*)cmp)->_next, memory_order_relaxed) == 0; #endif } void AtomicQueue::Enqueue(AtomicNode* node) { #if defined(ATOMIC_HAS_DCAS) AtomicNode* prev; atomic_store_explicit(&node->_next, 0, memory_order_relaxed); prev = (AtomicNode*)atomic_exchange_explicit(&_head, (atomic_word)node, memory_order_release); atomic_store_explicit(&prev->_next, (atomic_word)node, memory_order_release); #elif defined(__arm64__) AtomicNode* head; long success; __asm__ __volatile__ ( "0:\n\t" "ldxr\t%0, [%3]\n\t" "stlxr\t%w2, %4, [%3]\n\t" "cbnz\t%w2, 0b\n\t" "str %4, [%0]\n\t" : "=&r" (head), "+m" (_head), "=&r" (success) : "r" (&_head), "r" (node) : "cc", "memory" ); #elif PLATFORM_N3DS AtomicNode* head; int success; __asm__ __volatile__ ( //"dmb ishst\n\t" //not supported on N3DS "0:\n\t" "ldrex\thead, [&_head]\n\t" "strex\tsuccess, node, [&_head]\n\t" "teq success, #0\n\t" "bne\t0b\n\t" "str node, [head]\n\t" ); #elif defined(__arm__) AtomicNode* head; int success; __asm__ __volatile__ ( "dmb\tish\n\t" "0:\n\t" "ldrex\t%0, [%3]\n\t" "strex\t%2, %4, [%3]\n\t" "teq %2, #0\n\t" "bne\t0b\n\t" "str %4, [%0]\n\t" : "=&r" (head), "+m" (_head), "=&r" (success) : "r" (&_head), "r" (node) : "cc", "memory" ); #elif defined(__ppc64__) || defined(_ARCH_PPC64) AtomicNode* head; __asm__ __volatile__ ( "lwsync\n\t" "0:\n\t" "ldarx\t%0, 0, %2\n\t" "stdcx.\t%3, 0, %2\n\t" "bne-\t0b\n\t" "std %3, 0(%0)\n\t" : "=&b" (head), "+m" (_head) : "b" (&_head), "r" (node) : "cr0", "memory" ); #elif defined(__ppc__) AtomicNode* head; __asm__ __volatile__ ( "lwsync\n\t" "0:\n\t" "lwarx\t%0, 0, %2\n\t" "stwcx.\t%3, 0, %2\n\t" "bne-\t0b\n\t" "stw %3, 0(%0)\n\t" : "=&b" (head), "+m" (_head) : "b" (&_head), "r" (node) : "cr0", "memory" ); #else # error #endif } void AtomicQueue::EnqueueAll(AtomicNode* first, AtomicNode* last) { atomic_store_explicit(&last->_next, 0, memory_order_relaxed); #if defined(ATOMIC_HAS_DCAS) AtomicNode* prev; prev = (AtomicNode*)atomic_exchange_explicit(&_head, (atomic_word)last, memory_order_release); atomic_store_explicit(&prev->_next, (atomic_word)first, memory_order_release); #elif defined(__arm64__) AtomicNode* head; long success; __asm__ __volatile__ ( "0:\n\t" "ldxr\t%0, [%3]\n\t" "stlxr\t%w2, %5, [%3]\n\t" "cbnz\t%w2, 0b\n\t" "str %4, [%0]\n\t" : "=&r" (head), "+m" (_head), "=&r" (success) : "r" (&_head), "r" (first), "r" (last) : "cc", "memory" ); #elif PLATFORM_N3DS AtomicNode* head; int success; __asm__ __volatile__ ( //"dmb ishst\n\t" //not supported on N3DS "0:\n\t" "ldrex\thead, [&_head]\n\t" "strex\tsuccess, last, [&_head]\n\t" "teq success, #0\n\t" "bne\t0b\n\t" "str first, [head]\n\t" ); #elif defined(__arm__) AtomicNode* head; int success; __asm__ __volatile__ ( "dmb\tish\n\t" "0:\n\t" "ldrex\t%0, [%3]\n\t" "strex\t%2, %5, [%3]\n\t" "teq %2, #0\n\t" "bne\t0b\n\t" "str %4, [%0]\n\t" : "=&r" (head), "+m" (_head), "=&r" (success) : "r" (&_head), "r" (first), "r" (last) : "cc", "memory" ); #elif defined(__ppc64__) || defined(_ARCH_PPC64) AtomicNode* head; __asm__ __volatile__ ( "lwsync\n\t" "0:\n\t" "ldarx\t%0, 0, %2\n\t" "stdcx.\t%4, 0, %2\n\t" "bne-\t0b\n\t" "std %3, 0(%0)\n\t" : "=&b" (head), "+m" (_head) : "b" (&_head), "r" (first), "r" (last) : "cr0", "memory" ); #elif defined(__ppc__) AtomicNode* head; __asm__ __volatile__ ( "lwsync\n\t" "0:\n\t" "lwarx\t%0, 0, %2\n\t" "stwcx.\t%4, 0, %2\n\t" "bne-\t0b\n\t" "stw %3, 0(%0)\n\t" : "=&b" (head), "+m" (_head) : "b" (&_head), "r" (first), "r" (last) : "cr0", "memory" ); #else # error #endif } AtomicNode* AtomicQueue::Dequeue() { #if defined(ATOMIC_HAS_DCAS) AtomicNode* res, * next; void* data0; void* data1; void* data2; atomic_word2 tail = atomic_load_explicit(&_tail, memory_order_acquire); atomic_word2 newtail; do { res = (AtomicNode*)tail.lo; next = (AtomicNode*)atomic_load_explicit(&res->_next, memory_order_relaxed); if (next == 0) return NULL; data0 = next->data[0]; data1 = next->data[1]; data2 = next->data[2]; newtail.lo = (atomic_word)next; newtail.hi = tail.hi + 1; } while (!atomic_compare_exchange_strong_explicit(&_tail, &tail, newtail, memory_order_seq_cst, memory_order_relaxed)); res->data[0] = data0; res->data[1] = data1; res->data[2] = data2; return res; #elif defined(__arm64__) AtomicNode* tail; AtomicNode* tmp; void* data0; void* data1; void* data2; long success; __asm__ __volatile__ ( "0:\n\t" "ldaxr\t%0, [%7]\n\t" "ldr\t%1, [%0]\n\t" "cbz\t%1, 1f\n\t" "ldr %4, [%1, #8]\n\t" "ldr %5, [%1, #16]\n\t" "ldr %6, [%1, #24]\n\t" // create an artificial dependency to ensure previous loads are not reordered "csel\t%7, %7, %3, #15\n\t" // nop "csel\t%7, %7, %4, #15\n\t" // nop "csel\t%7, %7, %5, #15\n\t" // nop "stxr\t%w3, %1, [%7]\n\t" "cbnz\t%w3, 0b\n\t" "1:\n\t" : "=&r" (tail), "=&r" (tmp), "+m" (_tail), "=&r" (success), "=&r" (data0), "=&r" (data1), "=&r" (data2) : "r" (&_tail) : "cc", "memory" ); if (tmp) { tail->data[0] = data0; tail->data[1] = data1; tail->data[2] = data2; } else { tail = 0; } return tail; #elif PLATFORM_N3DS AtomicNode* tail; AtomicNode* tmp; void* data0; void* data1; void* data2 = 0; int success = 1; __asm__ __volatile__ ( "0:\n\t" "ldrex\ttail, [data2]\n\t" "ldr\ttmp, [tail]\n\t" "cmp\ttmp, #0\n\t" "beq\t1f\n\t" "ldr\ttail, [tmp, #4]\n\t" "ldr\tdata0, [tmp, #8]\n\t" "ldr\tdata1, [tmp, #12]\n\t" // create an artificial dependency to ensure previous loads are not reordered "orr\tdata2, data2, success, lsr #32\n\t" // nop "orr\tdata2, data2, tail, lsr #32\n\t" // nop "orr\tdata2, data2, data0, lsr #32\n\t" // nop "strex\tsuccess, tmp, [data2]\n\t" "teq\tsuccess, #0\n\t" "bne\t0b\n\t" // "isb\n\t" //not available on N3DS "1:\n\t" ); if (tmp) { tail->data[0] = data0; tail->data[1] = data1; tail->data[2] = data2; } else { tail = 0; } return tail; #elif defined(__arm__) AtomicNode* tail; AtomicNode* tmp; void* data0; void* data1; void* data2; int success; __asm__ __volatile__ ( "0:\n\t" "ldrex\t%0, [%7]\n\t" "ldr\t%1, [%0]\n\t" "cmp\t%1, #0\n\t" "beq\t1f\n\t" "ldr\t%4, [%1, #4]\n\t" "ldr\t%5, [%1, #8]\n\t" "ldr\t%6, [%1, #12]\n\t" // create an artificial dependency to ensure previous loads are not reordered "orr\t%7, %7, %3, lsr #32\n\t" // nop "orr\t%7, %7, %4, lsr #32\n\t" // nop "orr\t%7, %7, %5, lsr #32\n\t" // nop "strex\t%3, %1, [%7]\n\t" "teq\t%3, #0\n\t" "bne\t0b\n\t" "isb\n\t" "1:\n\t" : "=&r" (tail), "=&r" (tmp), "+m" (_tail), "=&r" (success), "=&r" (tail), "=&r" (data0), "=&r" (data1), "=&r" (data2) : "r" (&_tail) : "cc", "memory" ); if (tmp) { tail->data[0] = data0; tail->data[1] = data1; tail->data[2] = data2; } else { tail = 0; } return tail; #elif defined(__ppc64__) || defined(_ARCH_PPC64) AtomicNode* tail; AtomicNode* tmp; void* data0; void* data1; void* data2; __asm__ __volatile__ ( "0:\n\t" "ldarx\t%0, 0, %6\n\t" "ld %1, 0(%0)\n\t" "cmpdi %1, 0\n\t" "beq- 1f\n\t" "ld %3, 8(%1)\n\t" "ld %4, 16(%1)\n\t" "ld %5, 24(%1)\n\t" // create a data dependency to ensure previous loads are not reordered "tdi\t0, %4, 0\n\t" "tdi\t0, %5, 0\n\t" "tdi\t0, %6, 0\n\t" "isync\n\t" "stdcx. %1, 0, %6\n\t" "bne- 0b\n\t" "isync\n\t" "1:\n\t" : "=&b" (tail), "=&b" (tmp), "+m" (_tail), "=&b" (data0), "=&b" (data1), "=&b" (data2) : "b" (&_tail) : "cr0", "memory" ); if (tmp) { tail->data[0] = data0; tail->data[1] = data1; tail->data[2] = data2; } else { tail = 0; } return tail; #elif defined(__ppc__) AtomicNode* tail; AtomicNode* tmp; void* data0; void* data1; void* data2; __asm__ __volatile__ ( "0:\n\t" "lwarx\t%0, 0, %6\n\t" "lwz %1, 0(%0)\n\t" "cmpwi %1, 0\n\t" "beq- 1f\n\t" "lwz %3, 4(%1)\n\t" "lwz %4, 8(%1)\n\t" "lwz %5, 12(%1)\n\t" // create a data dependency to ensure previous loads are not reordered "twi\t0, %4, 0\n\t" "twi\t0, %5, 0\n\t" "twi\t0, %6, 0\n\t" "isync\n\t" "stwcx. %1, 0, %6\n\t" "bne- 0b\n\t" "isync\n\t" "1:\n\t" : "=&b" (tail), "=&b" (tmp), "+m" (_tail), "=&b" (data0), "=&b" (data1), "=&b" (data2) : "b" (&_tail) : "cr0", "memory" ); if (tmp) { tail->data[0] = data0; tail->data[1] = data1; tail->data[2] = data2; } else { tail = 0; } return tail; #else # error #endif } AtomicQueue* CreateAtomicQueue() { // should be properly aligned #if defined(ATOMIC_HAS_DCAS) return UNITY_PLATFORM_NEW_ALIGNED(AtomicQueue, kMemThread, sizeof(atomic_word2)); #elif PLATFORM_N3DS //seems like UNITY_PLATFORM_NEW shouldn't take an alignment...? return UNITY_PLATFORM_NEW(AtomicQueue, kMemThread); #else return UNITY_PLATFORM_NEW(AtomicQueue, kMemThread, sizeof(atomic_word)); #endif } void DestroyAtomicQueue(AtomicQueue* s) { UNITY_PLATFORM_DELETE(s, kMemThread); } // // AtomicList // void AtomicList::Init() { #if defined(ATOMIC_HAS_DCAS) atomic_word2 w; w.lo = w.hi = 0; atomic_store_explicit(&_top, w, memory_order_relaxed); #else atomic_store_explicit(&_top, 0, memory_order_relaxed); atomic_store_explicit(&_ver, 0, memory_order_relaxed); #endif } atomic_word AtomicList::Tag() { #if defined(ATOMIC_HAS_DCAS) atomic_word2 w = atomic_load_explicit((volatile atomic_word2*)&_top, memory_order_relaxed); return w.hi; #else return atomic_load_explicit(&_ver, memory_order_relaxed); #endif } AtomicNode* AtomicList::Peek() { #if defined(ATOMIC_HAS_DCAS) atomic_word2 w = atomic_load_explicit((volatile atomic_word2*)&_top, memory_order_relaxed); return (AtomicNode*)w.lo; #else return (AtomicNode*)atomic_load_explicit(&_top, memory_order_relaxed); #endif } AtomicNode* AtomicList::Load(atomic_word &tag) { #if defined(ATOMIC_HAS_DCAS) atomic_word2 w = atomic_load_explicit((volatile atomic_word2*)&_top, memory_order_acquire); tag = w.hi; return (AtomicNode*)w.lo; #else atomic_word w; do { w = atomic_load_explicit(&_top, memory_order_relaxed); tag = atomic_load_explicit(&_ver, memory_order_relaxed); } while (tag != atomic_load_explicit(&_ver, memory_order_acquire)); return (AtomicNode*)w; #endif } bool AtomicList::Add(AtomicNode *first, AtomicNode *last, atomic_word tag) { #if defined(ATOMIC_HAS_DCAS) atomic_word2 oldval, newval; bool res = false; newval.lo = (atomic_word)first; newval.hi = tag; oldval = atomic_load_explicit((volatile const atomic_word2*)&_top, memory_order_relaxed); while (oldval.hi == tag) { last->Link((AtomicNode*)oldval.lo); res = atomic_compare_exchange_strong_explicit((volatile atomic_word2*)&_top, &oldval, newval, memory_order_acq_rel, memory_order_relaxed); if (res) { break; } } return res; #elif defined(__arm64__) AtomicNode* res; AtomicNode* tmp; long failure = 1; __asm__ __volatile__ ( "0:\n\t" "ldxr\t%0, [%4]\n\t" "csel\t%4, %4, %0, #15\n\t" // nop "ldr\t%1, [%4, #8]\n\t" "cmp\t%1, %7\n\t" "b.ne\t1f\n\t" "str %0, [%6]\n\t" "stlxr\t%w3, %5, [%4]\n\n" "cbnz\t%w3, 0b\n\t" "1:\n\t" : "=&r" (res), "=&r" (tmp), "+m" (_top), "=&r" (failure) : "r" (&_top), "r" (first), "r" (last), "r" (tag) : "cc", "memory" ); return failure == 0; #elif PLATFORM_N3DS /* AtomicNode* res; AtomicNode* tmp; int failure = 1; __asm__ __volatile__ ( "dmb ishst\n\t" "0:\n\t" "ldrex %0, [%4]\n\t" "add %4, %4, %0\n\t" // nop "sub %4, %4, %0\n\t" // nop "ldr %1, [%4, #4]\n\t" "cmp %1, %7\n\t" "bne 1f\n\t" "str %0, [%6]\n\t" "strex %3, %5, [%4]\n\t" "teq %3, #0\n\t" "bne 0b\n\t" "1:\n\t" ); return res; */ return false; #elif defined(__arm__) AtomicNode* res; AtomicNode* tmp; int failure = 1; __asm__ __volatile__ ( "dmb\tishst\n\t" "0:\n\t" "ldrex\t%0, [%4]\n\t" "add\t%4, %4, %0\n\t" // nop "sub\t%4, %4, %0\n\t" // nop "ldr\t%1, [%4, #4]\n\t" "cmp\t%1, %7\n\t" "bne\t1f\n\t" "str\t%0, [%6]\n\t" "strex\t%3, %5, [%4]\n\t" "teq\t%3, #0\n\t" "bne\t0b\n\t" "1:\n\t" : "=&r" (res), "=&r" (tmp), "+m" (_top), "=&r" (failure) : "r" (&_top), "r" (first), "r" (last), "r" (tag) : "cc", "memory" ); return failure == 0; #elif defined(__ppc__) AtomicNode* res; AtomicNode* tmp; int failure = 1; __asm__ __volatile__ ( "0:\n\t" "lwsync\n\t" "lwarx\t%0, 0, %4\n\t" "add\t%4, %4, %0\n\t" // nop "sub\t%4, %4, %0\n\t" // nop "lwz\t%1, 4(%4)\n\t" "cmpw\t%1, %7\n\t" "bne-\t1f\n\t" "std\t%0, 0(%6)\n\t" "stwcx.\t%5, 0, %4\n\t" "bne-\t0b\n\t" "eor\t%3, %3, %3\n\t" "1:\n\t" : "=&r" (res), "=&r" (tmp), "+m" (_top), "=&r" (failure) : "r" (&_top), "r" (first), "r" (last), "r" (tag) : "cr0", "memory" ); return failure == 0; #elif defined(__ppc64__) || defined(_ARCH_PPC64) AtomicNode* res; AtomicNode* tmp; int failure = 1; __asm__ __volatile__ ( "lwsync\n\t" "0:\n\t" "ldarx\t%0, 0, %4\n\t" "add\t%4, %4, %0\n\t" // nop "sub\t%4, %4, %0\n\t" // nop "ld\t\t%1, 8(%4)\n\t" "cmpd\t%1, %7\n\t" "bne-\t1f\n\t" "std\t%0, 0(%6)\n\t" "stdcx.\t%5, 0, %4\n\t" "bne-\t0b\n\t" "eord\t%3, %3, %3\n\t" "1:\n\t" : "=&r" (res), "=&r" (tmp), "+m" (_top), "=&r" (failure) : "r" (&_top), "r" (first), "r" (last), "r" (tag) : "cr0", "memory" ); return failure == 0; #else # error #endif } AtomicNode* AtomicList::Touch(atomic_word tag) { #if defined(ATOMIC_HAS_DCAS) atomic_word2 w; w.lo = 0; w.hi = tag; w = atomic_exchange_explicit((volatile atomic_word2*)&_top, w, memory_order_acq_rel); return (AtomicNode*)w.lo; #else atomic_store_explicit(&_ver, tag, memory_order_release); atomic_word w = atomic_exchange_explicit(&_top, 0, memory_order_acquire); return (AtomicNode*)w; #endif } void AtomicList::Reset(AtomicNode* node, atomic_word tag) { #if defined(ATOMIC_HAS_DCAS) atomic_word2 w; w.lo = (atomic_word)node; w.hi = tag; atomic_store_explicit(&_top, w, memory_order_relaxed); #else atomic_store_explicit(&_top, (atomic_word)node, memory_order_relaxed); atomic_store_explicit(&_ver, tag, memory_order_relaxed); #endif } AtomicNode* AtomicList::Clear(AtomicNode* old, atomic_word tag) { #if defined(ATOMIC_HAS_DCAS) atomic_word2 top; atomic_word2 newtop; top.lo = (atomic_word)old; top.hi = tag; newtop.lo = 0; newtop.hi = tag + 1; if (atomic_compare_exchange_strong_explicit((volatile atomic_word2*)&_top, &top, newtop, memory_order_acquire, memory_order_relaxed)) { return (AtomicNode*)top.lo; } else { return NULL; } #elif defined(__arm64__) AtomicNode* res; AtomicNode* tmp; long success; __asm__ __volatile__ ( "0:\n\t" "ldaxr\t%0, [%4]\n\t" "cbz\t%0, 2f\n\t" "ldr %1, [%0]\n\t" "stxr\t%w3, %1, [%4]\n\t" "cbnz\t%w3, 0b\n\t" "1:\n\t" "ldxr\t%1, [%4, #8]\n\t" "add\t%1, %1, 1\n\t" "stxr\t%w3, %1, [%4, #8]\n\t" "cbnz\t%w3, 1b\n\t" "2:\n\t" : "=&r" (res), "=&r" (tmp), "+m" (_top), "=&r" (success) : "r" (&_top) : "cc", "memory" ); return res; #elif PLATFORM_N3DS AtomicNode* res; AtomicNode* tmp; int success; int theTop = (int)(&_top); __asm__ __volatile__ ( "0:\n\t" "ldrex\tres, [theTop]\n\t" "cmp\tres, #0\n\t" "beq\t2f\n\t" "ldr tmp, [res]\n\t" "strex\tsuccess, tmp, [theTop]\n\t" "teq\tsuccess, #0\n\t" "bne\t0b\n\t" "add\ttheTop, theTop, 4\n\t" "1:\n\t" "ldrex\tsuccess, [theTop]\n\t" "add\tsuccess, success, 1\n\t" "strex\tsuccess, success, [theTop]\n\t" "teq\tsuccess, #0\n\t" "bne\t1b\n\t" "sub\ttheTop, theTop, 4\n\t" //"isb\n\t" //not available on N3DS "2:\n\t" ); return res; #elif defined(__arm__) AtomicNode* res; AtomicNode* tmp; int success; __asm__ __volatile__ ( "0:\n\t" "ldrex\t%0, [%4]\n\t" "cmp\t%0, #0\n\t" "beq\t2f\n\t" "ldr %1, [%0]\n\t" "strex\t%3, %1, [%4]\n\t" "teq\t%3, #0\n\t" "bne\t0b\n\t" "add\t%4, %4, 4\n\t" "1:\n\t" "ldrex\t%3, [%4]\n\t" "add\t%3, %3, 1\n\t" "strex\t%3, %3, [%4]\n\t" "teq\t%3, #0\n\t" "bne\t1b\n\t" "sub\t%4, %4, 4\n\t" "isb\n\t" "2:\n\t" : "=&r" (res), "=&r" (tmp), "+m" (_top), "=&r" (success) : "r" (&_top) : "cc", "memory" ); return res; #elif defined(__ppc64__) || defined(_ARCH_PPC64) AtomicNode* res; AtomicNode* tmp; __asm__ __volatile__ ( "0:\n\t" "ldarx\t%0, 0, %3\n\t" "cmpdi %0, 0\n\t" "beq- 2f\n\t" "ld %1, 0(%0)\n\t" "stdcx. %1, 0, %3\n\t" "bne- 0b\n\t" "1:\n\t" "ldarx\t%1, 8, %3\n\t" "addi\t%1, %1, 1\n\t" "stdcx.\t%1, 8, %3\n\t" "bne-\t1b\n\t" "isync\n\t" "b\t\t3f\n\f" "2:\n\t" "stdcx.\t%0, 0, %3\n\t" "bne-\t0b\n\t" "3:\n\t" : "=&b" (res), "=&b" (tmp), "+m" (_top) : "b" (&_top) : "cr0", "memory" ); return res; #elif defined(__ppc__) AtomicNode* res; AtomicNode* tmp; __asm__ __volatile__ ( "0:\n\t" "lwarx\t%0, 0, %3\n\t" "cmpwi %0, 0\n\t" "beq- 2f\n\t" "lwz %1, 0(%0)\n\t" "stwcx. %1, 0, %3\n\t" "bne- 0b\n\t" "1:\n\t" "lwarx\t%1, 4, %3\n\t" "addiw\t%1, %1, 1\n\t" "stwcx.\t%1, 4, %3\n\t" "bne-\t1b\n\t" "isync\n\t" "b\t\t3f\n\f" "2:\n\t" "stwcx.\t%0, 0, %3\n\t" "bne-\t0b\n\t" "3:\n\t" : "=&b" (res), "=&b" (tmp), "+m" (_top) : "b" (&_top) : "cr0", "memory" ); return res; #else # error #endif } #else // !ATOMIC_HAS_QUEUE // // AtomicList // void AtomicList::Init() { _top = 0; _ver = 0; } atomic_word AtomicList::Tag() { return _ver; } AtomicNode* AtomicList::Peek() { return (AtomicNode*)_top; } AtomicNode* AtomicList::Load(atomic_word &tag) { tag = _ver; return (AtomicNode*)_top; } bool AtomicList::Add(AtomicNode *first, AtomicNode *last, atomic_word tag) { last->Link((AtomicNode*)_top); _top = (atomic_word)first; return true; } AtomicNode* AtomicList::Touch(atomic_word tag) { AtomicNode* res = (AtomicNode*)_top; _top = 0; _ver = tag; return res; } void AtomicList::Reset(AtomicNode* node, atomic_word tag) { _top = (atomic_word)node; _ver = tag; } AtomicNode* AtomicList::Clear(AtomicNode* old, atomic_word tag) { if (_top == (atomic_word)old && _ver == tag) { _top = 0; ++_ver; return old; } else { return NULL; } } #endif void AtomicList::Relax() { #if defined(_MSC_VER) YieldProcessor(); #elif defined(__x86_64__) || defined(_M_X64) __asm__ __volatile__ ("pause" ::: "memory"); #elif defined(__x86__) || defined(__i386__) || defined(_M_IX86) __asm__ __volatile__ ("rep; nop" ::: "memory"); #elif PLATFORM_N3DS __asm__ __volatile__ ("yield"); #elif PLATFORM_SWITCH // The embedded asm for arm64 seems to be ignored(!) by Switch's compiler. So, we do something different. NXAtomicListRelax(); #elif (defined(__arm64__) || (defined(__arm__) && (defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)))) && (defined(__clang__) || defined(__GNUC__)) // could be interesting to use wfe/sev instead of a semaphore __asm__ __volatile__ ("yield"); #elif PLATFORM_PSVITA // There is no yield on Vita but we can give the scheduler a "kick" by delaying the thread (sleeping), not ideal but the best we can do for now. PSP2AtomicListRelax(); #else #endif } UNITY_PLATFORM_END_NAMESPACE; ================================================ FILE: unity_decoder/libil2cpp/os/Unity/AtomicQueue.h ================================================ #pragma once #include "UnityPlatformConfigure.h" #include "ExtendedAtomicTypes.h" UNITY_PLATFORM_BEGIN_NAMESPACE; #if defined(ATOMIC_HAS_DCAS) #define ATOMIC_HAS_QUEUE 2 #elif defined(__arm64__) && (defined(__clang__) || defined(__GNUC__)) #define ATOMIC_HAS_QUEUE 1 #elif defined(__arm__) && (defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)) && (!UNITY_STV_API) && (defined(__clang__) || defined(__GNUC__) || defined(SN_TARGET_PSP2)) #define ATOMIC_HAS_QUEUE 1 #endif class AtomicNode { friend class AtomicStack; friend class AtomicQueue; volatile atomic_word _next; public: void* data[3]; AtomicNode *Next() const { return (AtomicNode*)_next; } AtomicNode *Link(AtomicNode *next); }; #if defined(ATOMIC_HAS_QUEUE) // A generic lockfree stack. // Any thread can Push / Pop nodes to the stack. // The stack is lockfree and highly optimized. It has different implementations for different architectures. // On intel / arm it is built with double CAS: // http://en.wikipedia.org/wiki/Double_compare-and-swap // On PPC it is built on LL/SC: // http://en.wikipedia.org/wiki/Load-link/store-conditional class AtomicStack { #if defined(ATOMIC_HAS_DCAS) volatile atomic_word2 _top; #else volatile atomic_word _top; #endif public: AtomicStack(); ~AtomicStack(); int IsEmpty() const; void Push(AtomicNode *node); void PushAll(AtomicNode *first, AtomicNode *last); AtomicNode *Pop(); AtomicNode *PopAll(); }; AtomicStack* CreateAtomicStack(); void DestroyAtomicStack(AtomicStack* s); // A generic lockfree queue FIFO queue. // Any thread can Enqueue / Dequeue in paralell. // When pushing / popping a node there is no guarantee that the pointer to the node is the same (void* data[3]) // We do guarantee that all 3 data pointer are the same after deqeuing. // The queue is lockfree and highly optimized. It has different implementations for different archectures. // On intel / arm it is built with double CAS: // http://en.wikipedia.org/wiki/Double_compare-and-swap // On PPC it is built on LL/SC: // http://en.wikipedia.org/wiki/Load-link/store-conditional class AtomicQueue { #if defined(ATOMIC_HAS_DCAS) volatile atomic_word2 _tail; #else volatile atomic_word _tail; #endif volatile atomic_word _head; public: AtomicQueue(); ~AtomicQueue(); int IsEmpty() const; void Enqueue(AtomicNode *node); void EnqueueAll(AtomicNode *first, AtomicNode *last); AtomicNode *Dequeue(); }; AtomicQueue* CreateAtomicQueue(); void DestroyAtomicQueue(AtomicQueue* s); #elif IL2CPP_SUPPORT_THREADS #error Platform is missing atomic queue implementation #endif // // Special concurrent list for JobQueue // This code is not meant to be general purpose and should not be used outside of the job queue. class AtomicList { #if defined(ATOMIC_HAS_DCAS) volatile atomic_word2 _top; #else volatile atomic_word _top; volatile atomic_word _ver; #endif public: void Init(); atomic_word Tag(); AtomicNode *Peek(); AtomicNode *Load(atomic_word &tag); AtomicNode *Clear(AtomicNode *old, atomic_word tag); bool Add(AtomicNode *first, AtomicNode *last, atomic_word tag); AtomicNode* Touch(atomic_word tag); void Reset(AtomicNode *node, atomic_word tag); static void Relax(); }; UNITY_PLATFORM_END_NAMESPACE; ================================================ FILE: unity_decoder/libil2cpp/os/Unity/ExtendedAtomicOps-arm.h ================================================ #if defined(_MSC_VER) # include "os/Win32/WindowsHeaders.h" # include #else # define ASM_DMB_ISH "dmb ish\n\t" # if defined(__ARM_ARCH_7S__) // this is sufficient for Swift processors # define ASM_REL "dmb ishst\n\t" # else # define ASM_REL "dmb ish\n\t" # endif # define ASM_CLREX "clrex\n\t" # define ASM_ISB "isb\n\t" # define ASM_LABEL(i) #i ":\n\t" #endif static inline void atomic_pause() { } static inline void atomic_thread_fence(memory_order_relaxed_t) { } static inline void atomic_thread_fence(memory_order_release_t) { #if defined(_MSC_VER) __dmb(_ARM_BARRIER_ISH); #else __asm__ __volatile__ (ASM_REL : : : "memory"); #endif } static inline void atomic_thread_fence(memory_order_acquire_t) { #if defined(_MSC_VER) __dmb(_ARM_BARRIER_ISH); #else __asm__ __volatile__ (ASM_DMB_ISH : : : "memory"); #endif } static inline void atomic_thread_fence(memory_order_acq_rel_t) { #if defined(_MSC_VER) __dmb(_ARM_BARRIER_ISH); #else __asm__ __volatile__ (ASM_DMB_ISH : : : "memory"); #endif } static inline void atomic_thread_fence(int /* memory_order_seq_cst_t */) { #if defined(_MSC_VER) __dmb(_ARM_BARRIER_ISH); #else __asm__ __volatile__ (ASM_DMB_ISH : : : "memory"); #endif } #define ATOMIC_LOAD(PRE, POST) \ atomic_word res; \ __asm__ __volatile__ \ ( \ PRE \ "ldr %0, %1\n\t" \ POST \ : "=r" (res) \ : "m" (*p) \ : "memory" \ ); \ return res; static inline atomic_word atomic_load_explicit(const volatile atomic_word* p, memory_order_relaxed_t) { #if defined(_MSC_VER) return (atomic_word)__iso_volatile_load32((const volatile __int32*)p); #else ATOMIC_LOAD("", "") #endif } static inline atomic_word atomic_load_explicit(const volatile atomic_word* p, memory_order_acquire_t) { #if defined(_MSC_VER) atomic_word res = (atomic_word)__iso_volatile_load32((const volatile __int32*)p); __dmb(_ARM_BARRIER_ISH); return res; #else ATOMIC_LOAD("", ASM_DMB_ISH) #endif } static inline atomic_word atomic_load_explicit(const volatile atomic_word* p, int /* memory_order_seq_cst_t */) { #if defined(_MSC_VER) atomic_word res = (atomic_word)__iso_volatile_load32((const volatile __int32*)p); __dmb(_ARM_BARRIER_ISH); return res; #else ATOMIC_LOAD("", ASM_DMB_ISH) #endif } #define ATOMIC_STORE(PRE, POST) \ __asm__ __volatile__ \ ( \ PRE \ "str %1, %0\n\t" \ POST \ : "=m" (*p) \ : "r" (v) \ : "memory" \ ); static inline void atomic_store_explicit(volatile atomic_word* p, atomic_word v, memory_order_relaxed_t) { #if defined(_MSC_VER) __iso_volatile_store32((volatile __int32*)p, (__int32)v); #else ATOMIC_STORE("", "") #endif } static inline void atomic_store_explicit(volatile atomic_word* p, atomic_word v, memory_order_release_t) { #if defined(_MSC_VER) __dmb(_ARM_BARRIER_ISH); __iso_volatile_store32((volatile __int32*)p, (__int32)v); #else ATOMIC_STORE(ASM_REL, "") #endif } static inline void atomic_store_explicit(volatile atomic_word* p, atomic_word v, int /* memory_order_seq_cst_t */) { #if defined(_MSC_VER) __dmb(_ARM_BARRIER_ISH); __iso_volatile_store32((volatile __int32*)p, (__int32)v); __dmb(_ARM_BARRIER_ISH); #else ATOMIC_STORE(ASM_REL, ASM_DMB_ISH) #endif } #define ATOMIC_XCHG(PRE, POST) \ atomic_word res; \ atomic_word success; \ __asm__ __volatile__ \ ( \ PRE \ ASM_LABEL (0) \ "ldrex %2, [%4]\n\t" \ "strex %0, %3, [%4]\n\t" \ "teq %0, #0\n\t" \ "bne 0b\n\t" \ POST \ : "=&r" (success), "+m" (*p), "=&r" (res) \ : "r" (v), "r" (p) \ : "cc", "memory" \ ); \ return res; static inline atomic_word atomic_exchange_explicit(volatile atomic_word* p, atomic_word v, memory_order_relaxed_t) { #if defined(_MSC_VER) return (atomic_word)_InterlockedExchange_nf((long volatile*)p, (long)v); #else ATOMIC_XCHG("", "") #endif } static inline atomic_word atomic_exchange_explicit(volatile atomic_word* p, atomic_word v, memory_order_release_t) { #if defined(_MSC_VER) // _InterlockedExchange_rel is documented by Microsoft, but it doesn't seem to be defined __dmb(_ARM_BARRIER_ISH); return (atomic_word)_InterlockedExchange_nf((long volatile*)p, (long)v); #else ATOMIC_XCHG(ASM_REL, "") #endif } static inline atomic_word atomic_exchange_explicit(volatile atomic_word* p, atomic_word v, memory_order_acquire_t) { #if defined(_MSC_VER) return (atomic_word)_InterlockedExchange_acq((long volatile*)p, (long)v); #else ATOMIC_XCHG("", ASM_ISB) #endif } static inline atomic_word atomic_exchange_explicit(volatile atomic_word* p, atomic_word v, memory_order_acq_rel_t) { #if defined(_MSC_VER) __dmb(_ARM_BARRIER_ISH); return (atomic_word)_InterlockedExchange_acq((long volatile*)p, (long)v); #else ATOMIC_XCHG(ASM_REL, ASM_ISB) #endif } static inline atomic_word atomic_exchange_explicit(volatile atomic_word* p, atomic_word v, int /* memory_order_seq_cst_t */) { #if defined(_MSC_VER) // _InterlockedExchange_rel is documented by Microsoft, but it doesn't seem to be defined __dmb(_ARM_BARRIER_ISH); atomic_word res = (atomic_word)_InterlockedExchange_nf((long volatile*)p, (long)v); __dmb(_ARM_BARRIER_ISH); return res; #else ATOMIC_XCHG(ASM_REL, ASM_DMB_ISH) #endif } #if !defined(_MSC_VER) // atomic_compare_exchange_weak_explicit: can fail spuriously even if *p == *oldval #define ATOMIC_CMP_XCHG(PRE, POST) \ atomic_word res; \ atomic_word success = 0; \ __asm__ __volatile__ \ ( \ PRE \ "ldrex %2, [%4]\n\t" \ "teq %2, %5\n\t" \ "it eq\n\t" \ "strexeq %0, %3, [%4]\n\t" \ POST \ : "+r" (success), "+m" (*p), "=&r" (res) \ : "r" (newval), "r" (p), "r" (*oldval) \ : "cc", "memory" \ ); \ *oldval = res; \ return success; static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_relaxed_t, memory_order_relaxed_t) { ATOMIC_CMP_XCHG("", "") } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_release_t, memory_order_relaxed_t) { ATOMIC_CMP_XCHG(ASM_REL, "") } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_acquire_t, memory_order_relaxed_t) { ATOMIC_CMP_XCHG("", "teq %0, #0\n\tbne 1f\n\t" ASM_ISB ASM_LABEL(1)) } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_acq_rel_t, memory_order_relaxed_t) { ATOMIC_CMP_XCHG(ASM_REL, "teq %0, #0\n\tbne 1f\n\t" ASM_ISB ASM_LABEL(1)) } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, int /* memory_order_seq_cst_t */, memory_order_relaxed_t) { ATOMIC_CMP_XCHG(ASM_REL, "teq %0, #0\n\tbne 1f\n\t" ASM_DMB_ISH ASM_LABEL(1)) } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_release_t, memory_order_release_t) { ATOMIC_CMP_XCHG(ASM_REL, "") } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_acquire_t, memory_order_acquire_t) { ATOMIC_CMP_XCHG("", ASM_ISB) } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_acq_rel_t, memory_order_acq_rel_t) { ATOMIC_CMP_XCHG(ASM_REL, ASM_ISB) } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, int /* memory_order_seq_cst_t */, int /* memory_order_seq_cst_t */) { ATOMIC_CMP_XCHG(ASM_REL, ASM_DMB_ISH) } #endif // atomic_compare_exchange_strong_explicit: does loop and only returns false if *p != *oldval #undef ATOMIC_CMP_XCHG #define ATOMIC_CMP_XCHG(PRE, POST) \ atomic_word res; \ atomic_word success = 0; \ __asm__ __volatile__ \ ( \ PRE \ ASM_LABEL (0) \ "ldrex %2, [%4]\n\t" \ "teq %2, %5\n\t" \ "bne 1f\n\t" \ "strex %0, %3, [%4]\n\t" \ "teq %0, #0\n\t" \ "bne 0b\n\t" \ POST \ : "=&r" (success), "+m" (*p), "=&r" (res) \ : "r" (newval), "r" (p), "r" (*oldval) \ : "cc", "memory" \ ); \ *oldval = res; \ return success; static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_relaxed_t, memory_order_relaxed_t) { #if defined(_MSC_VER) long tmp = _InterlockedCompareExchange_nf((long volatile*)p, (long)newval, (long)*oldval); return *oldval == tmp ? true : (*oldval = tmp, false); #else ATOMIC_CMP_XCHG("", ASM_LABEL(1) ASM_CLREX) #endif } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_release_t, memory_order_release_t) { #if defined(_MSC_VER) long tmp = _InterlockedCompareExchange_rel((long volatile*)p, (long)newval, (long)*oldval); return *oldval == tmp ? true : (*oldval = tmp, false); #else ATOMIC_CMP_XCHG(ASM_REL, ASM_LABEL(1) ASM_CLREX) #endif } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_acquire_t, memory_order_acquire_t) { #if defined(_MSC_VER) long tmp = _InterlockedCompareExchange_acq((long volatile*)p, (long)newval, (long)*oldval); return *oldval == tmp ? true : (*oldval = tmp, false); #else ATOMIC_CMP_XCHG("", ASM_LABEL(1) ASM_CLREX ASM_ISB) #endif } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_acq_rel_t, memory_order_acq_rel_t) { #if defined(_MSC_VER) __dmb(_ARM_BARRIER_ISH); long tmp = _InterlockedCompareExchange_acq((long volatile*)p, (long)newval, (long)*oldval); return *oldval == tmp ? true : (*oldval = tmp, false); #else ATOMIC_CMP_XCHG(ASM_REL, ASM_LABEL(1) ASM_CLREX ASM_ISB) #endif } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, int /* memory_order_seq_cst_t */, int /* memory_order_seq_cst_t */) { #if defined(_MSC_VER) long tmp = _InterlockedCompareExchange_rel((long volatile*)p, (long)newval, (long)*oldval); __dmb(_ARM_BARRIER_ISH); return *oldval == tmp ? true : (*oldval = tmp, false); #else ATOMIC_CMP_XCHG(ASM_REL, ASM_LABEL(1) ASM_CLREX ASM_DMB_ISH) #endif } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_release_t, memory_order_relaxed_t) { #if defined(_MSC_VER) return atomic_compare_exchange_strong_explicit(p, oldval, newval, memory_order_release, memory_order_release); #else ATOMIC_CMP_XCHG(ASM_REL, ASM_LABEL(1) ASM_CLREX) #endif } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_acquire_t, memory_order_relaxed_t) { #if defined(_MSC_VER) return atomic_compare_exchange_strong_explicit(p, oldval, newval, memory_order_acquire, memory_order_acquire); #else ATOMIC_CMP_XCHG("", ASM_ISB ASM_LABEL(1) ASM_CLREX) #endif } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_acq_rel_t, memory_order_relaxed_t) { #if defined(_MSC_VER) return atomic_compare_exchange_strong_explicit(p, oldval, newval, memory_order_acq_rel, memory_order_acq_rel); #else ATOMIC_CMP_XCHG(ASM_REL, ASM_ISB ASM_LABEL(1) ASM_CLREX) #endif } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, int /* memory_order_seq_cst_t */, memory_order_relaxed_t) { #if defined(_MSC_VER) return atomic_compare_exchange_strong_explicit(p, oldval, newval, memory_order_seq_cst, memory_order_seq_cst); #else ATOMIC_CMP_XCHG(ASM_REL, ASM_DMB_ISH ASM_LABEL(1) ASM_CLREX) #endif } #if defined(_MSC_VER) static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_relaxed_t, memory_order_relaxed_t) { return atomic_compare_exchange_strong_explicit(p, oldval, newval, memory_order_relaxed, memory_order_relaxed); } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_release_t, memory_order_relaxed_t) { return atomic_compare_exchange_strong_explicit(p, oldval, newval, memory_order_release, memory_order_relaxed); } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_acquire_t, memory_order_relaxed_t) { return atomic_compare_exchange_strong_explicit(p, oldval, newval, memory_order_acquire, memory_order_relaxed); } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_acq_rel_t, memory_order_relaxed_t) { return atomic_compare_exchange_strong_explicit(p, oldval, newval, memory_order_acq_rel, memory_order_relaxed); } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, int /* memory_order_seq_cst_t */, memory_order_relaxed_t) { return atomic_compare_exchange_strong_explicit(p, oldval, newval, memory_order_seq_cst, memory_order_relaxed); } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_release_t, memory_order_release_t) { return atomic_compare_exchange_strong_explicit(p, oldval, newval, memory_order_release, memory_order_release); } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_acquire_t, memory_order_acquire_t) { return atomic_compare_exchange_strong_explicit(p, oldval, newval, memory_order_acquire, memory_order_acquire); } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_acq_rel_t, memory_order_acq_rel_t) { return atomic_compare_exchange_strong_explicit(p, oldval, newval, memory_order_acq_rel, memory_order_acq_rel); } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, int /* memory_order_seq_cst_t */, int /* memory_order_seq_cst_t */) { return atomic_compare_exchange_strong_explicit(p, oldval, newval, memory_order_seq_cst, memory_order_seq_cst); } #endif #define ATOMIC_OP(PRE, OP, POST) \ atomic_word res, tmp; \ atomic_word success; \ __asm__ __volatile__ \ ( \ PRE \ ASM_LABEL (0) \ "ldrex %2, [%5]\n\t" \ OP " %3, %2, %4\n\t" \ "strex %0, %3, [%5]\n\t" \ "teq %0, #0\n\t" \ "bne 0b\n\t" \ POST \ : "=&r" (success), "+m" (*p), "=&r" (res), "=&r" (tmp) \ : "Ir" (v), "r" (p) \ : "cc", "memory" \ ); \ return res; static inline atomic_word atomic_fetch_add_explicit(volatile atomic_word* p, atomic_word v, memory_order_relaxed_t) { #if defined(_MSC_VER) return (atomic_word)_InterlockedExchangeAdd_nf((volatile long*)p, (long)v); #else ATOMIC_OP("", "add", "") #endif } static inline atomic_word atomic_fetch_add_explicit(volatile atomic_word* p, atomic_word v, memory_order_release_t) { #if defined(_MSC_VER) return (atomic_word)_InterlockedExchangeAdd_rel((volatile long*)p, (long)v); #else ATOMIC_OP(ASM_REL, "add", "") #endif } static inline atomic_word atomic_fetch_add_explicit(volatile atomic_word* p, atomic_word v, memory_order_acquire_t) { #if defined(_MSC_VER) return (atomic_word)_InterlockedExchangeAdd_acq((volatile long*)p, (long)v); #else ATOMIC_OP("", "add", ASM_ISB) #endif } static inline atomic_word atomic_fetch_add_explicit(volatile atomic_word* p, atomic_word v, memory_order_acq_rel_t) { #if defined(_MSC_VER) __dmb(_ARM_BARRIER_ISH); return (atomic_word)_InterlockedExchangeAdd_acq((volatile long*)p, (long)v); #else ATOMIC_OP(ASM_REL, "add", ASM_ISB) #endif } static inline atomic_word atomic_fetch_add_explicit(volatile atomic_word* p, atomic_word v, int /* memory_order_seq_cst_t */) { #if defined(_MSC_VER) long oldval = _InterlockedExchangeAdd_rel((volatile long*)p, (long)v); __dmb(_ARM_BARRIER_ISH); return (atomic_word)oldval; #else ATOMIC_OP(ASM_REL, "add", ASM_DMB_ISH) #endif } static inline atomic_word atomic_fetch_sub_explicit(volatile atomic_word* p, atomic_word v, memory_order_relaxed_t) { #if defined(_MSC_VER) return atomic_fetch_add_explicit(p, -v, memory_order_relaxed); #else ATOMIC_OP("", "sub", "") #endif } static inline atomic_word atomic_fetch_sub_explicit(volatile atomic_word* p, atomic_word v, memory_order_release_t) { #if defined(_MSC_VER) return atomic_fetch_add_explicit(p, -v, memory_order_release); #else ATOMIC_OP(ASM_REL, "sub", "") #endif } static inline atomic_word atomic_fetch_sub_explicit(volatile atomic_word* p, atomic_word v, memory_order_acquire_t) { #if defined(_MSC_VER) return atomic_fetch_add_explicit(p, -v, memory_order_acquire); #else ATOMIC_OP("", "sub", ASM_ISB) #endif } static inline atomic_word atomic_fetch_sub_explicit(volatile atomic_word* p, atomic_word v, memory_order_acq_rel_t) { #if defined(_MSC_VER) return atomic_fetch_add_explicit(p, -v, memory_order_acq_rel); #else ATOMIC_OP(ASM_REL, "sub", ASM_ISB) #endif } static inline atomic_word atomic_fetch_sub_explicit(volatile atomic_word* p, atomic_word v, int /* memory_order_seq_cst_t */) { #if defined(_MSC_VER) return atomic_fetch_add_explicit(p, -v, memory_order_seq_cst); #else ATOMIC_OP(ASM_REL, "sub", ASM_DMB_ISH) #endif } /* * extensions */ static inline void atomic_retain(volatile int* p) { #if defined(_MSC_VER) _InterlockedIncrement_nf((volatile long*)p); #else atomic_fetch_add_explicit(p, 1, memory_order_relaxed); #endif } static inline bool atomic_release(volatile int* p) { #if defined(_MSC_VER) // _interlockedDecrement returns the resulting decremented value bool res = _InterlockedDecrement_rel((volatile long*)p) == 0; if (res) { __dmb(_ARM_BARRIER_ISH); } #else bool res = atomic_fetch_sub_explicit(p, 1, memory_order_release) == 1; if (res) { atomic_thread_fence(memory_order_acquire); } #endif return res; } /* * double word */ // Note: the only way to get atomic 64-bit memory accesses on ARM is to use ldrexd/strexd with a loop // (ldrd and strd instructions are not guaranteed to appear atomic) static inline atomic_word2 atomic_load_explicit(const volatile atomic_word2* p, memory_order_relaxed_t) { #if defined(_MSC_VER) // atomic_word2 r; r.v = __iso_volatile_load64 ((volatile __int64*) p); return r; atomic_word2 r; r.v = _InterlockedCompareExchange64_nf((volatile __int64*)p, (__int64)0, (__int64)0); return r; #else register atomic_word lo __asm__ ("r2"); register atomic_word hi __asm__ ("r3"); atomic_word success; __asm__ __volatile__ ( ASM_LABEL(0) "ldrexd\t%1, %2, [%3]\n\t" "strexd\t%0, %1, %2, [%3]\n\t" "teq\t%0, #0\n\t" "bne\t0b\n\t" : "=&r" (success), "=&r" (lo), "=&r" (hi) : "r" (p) : "cc", "r2", "r3" ); atomic_word2 w; w.lo = lo; w.hi = hi; return w; #endif } static inline atomic_word2 atomic_load_explicit(const volatile atomic_word2* p, memory_order_acquire_t) { #if defined(_MSC_VER) atomic_word2 r; r.v = _InterlockedCompareExchange64_acq((volatile __int64*)p, (__int64)0, (__int64)0); return r; #else register atomic_word lo __asm__ ("r2"); register atomic_word hi __asm__ ("r3"); atomic_word success; __asm__ __volatile__ ( ASM_LABEL(0) "ldrexd\t%1, %2, [%3]\n\t" "strexd\t%0, %1, %2, [%3]\n\t" "teq\t%0, #0\n\t" "bne\t0b\n\t" ASM_ISB : "=&r" (success), "=&r" (lo), "=&r" (hi) : "r" (p) : "cc", "memory", "r2", "r3" ); atomic_word2 w; w.lo = lo; w.hi = hi; return w; #endif } static inline void atomic_store_explicit(volatile atomic_word2* p, atomic_word2 v, memory_order_relaxed_t) { #if defined(_MSC_VER) atomic_word2 w, x; w = v; x = v; do { w.v = _InterlockedCompareExchange64_nf((volatile __int64*)p, x.v, w.v); } while (w.v != x.v); #else register atomic_word l __asm__ ("r2"); register atomic_word h __asm__ ("r3"); register atomic_word lo __asm__ ("r0") = v.lo; register atomic_word hi __asm__ ("r1") = v.hi; atomic_word success; __asm__ __volatile__ ( ASM_LABEL(0) "ldrexd\t%2, %3, [%6]\n\t" "strexd\t%0, %4, %5, [%6]\n\t" "teq\t%0, #0\n\t" "bne\t0b\n\t" : "=&r" (success), "=m" (*p), "=&r" (l), "=&r" (h) : "r" (lo), "r" (hi), "r" (p) : "cc", "memory", "r2", "r3" ); #endif } static inline void atomic_store_explicit(volatile atomic_word2* p, atomic_word2 v, memory_order_release_t) { #if defined(_MSC_VER) atomic_word2 w, x; w = v; x = v; do { w.v = _InterlockedCompareExchange64_rel((volatile __int64*)p, x.v, w.v); } while (w.v != x.v); #else register atomic_word l __asm__ ("r2"); register atomic_word h __asm__ ("r3"); register atomic_word lo __asm__ ("r0") = v.lo; register atomic_word hi __asm__ ("r1") = v.hi; atomic_word success; __asm__ __volatile__ ( ASM_REL ASM_LABEL(0) "ldrexd\t%2, %3, [%6]\n\t" "strexd\t%0, %4, %5, [%6]\n\t" "teq\t%0, #0\n\t" "bne\t0b\n\t" : "=&r" (success), "=m" (*p), "=&r" (l), "=&r" (h) : "r" (lo), "r" (hi), "r" (p) : "cc", "memory", "r2", "r3" ); #endif } static inline atomic_word2 atomic_exchange_explicit(volatile atomic_word2* p, atomic_word2 val, memory_order_acq_rel_t) { #if defined(_MSC_VER) __dmb(_ARM_BARRIER_ISH); atomic_word2 w; w.v = _InterlockedExchange64_acq((__int64 volatile*)p, (__int64)val.v); return w; #else register atomic_word l __asm__ ("r0"); register atomic_word h __asm__ ("r1"); register atomic_word lo __asm__ ("r2") = val.lo; register atomic_word hi __asm__ ("r3") = val.hi; atomic_word success; __asm__ __volatile__ ( ASM_REL ASM_LABEL(0) "ldrexd\t%2, %3, [%6]\n\t" "strexd\t%0, %5, %4, [%6]\n\t" "teq\t%0, #0\n\t" "bne\t0b\n\t" ASM_ISB : "=&r" (success), "=m" (*p), "=&r" (l), "=&r" (h) : "r" (hi), "r" (lo), "r" (p) : "cc", "memory", "r0", "r1", "r3" ); val.lo = l; val.hi = h; return val; #endif } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word2* p, atomic_word2* oldval, atomic_word2 newval, memory_order_acquire_t, memory_order_relaxed_t) { #if defined(_MSC_VER) __int64 tmp = _InterlockedCompareExchange64_acq((volatile __int64*)p, newval.v, oldval->v); return oldval->v == tmp ? true : (oldval->v = tmp, false); #else register atomic_word l __asm__ ("r2"); register atomic_word h __asm__ ("r3"); register atomic_word lo __asm__ ("r0") = newval.lo; register atomic_word hi __asm__ ("r1") = newval.hi; atomic_word success; __asm__ __volatile__ ( ASM_LABEL(0) "ldrexd\t%2, %3, [%8]\n\t" "teq\t%3, %5\n\t" "it\t\teq\n\t" "teqeq\t%2, %4\n\t" "bne\t1f\n\t" "strexd\t%0, %6, %7, [%8]\n\t" "teq\t%0, #0\n\t" "bne\t0b\n\t" ASM_ISB ASM_LABEL(1) "clrex\n\t" : "=&r" (success), "+m" (*p), "=&r" (l), "=&r" (h) : "r" (oldval->lo), "r" (oldval->hi), "r" (lo), "r" (hi), "r" (p), "0" (1) : "cc", "memory", "r2", "r3" ); if (success != 0) { oldval->lo = l; oldval->hi = h; } return success == 0; #endif } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word2* p, atomic_word2* oldval, atomic_word2 newval, memory_order_release_t, memory_order_relaxed_t) { #if defined(_MSC_VER) __int64 tmp = _InterlockedCompareExchange64_rel((volatile __int64*)p, newval.v, oldval->v); return oldval->v == tmp ? true : (oldval->v = tmp, false); #else register atomic_word l __asm__ ("r2"); register atomic_word h __asm__ ("r3"); register atomic_word lo __asm__ ("r0") = newval.lo; register atomic_word hi __asm__ ("r1") = newval.hi; atomic_word success; __asm__ __volatile__ ( ASM_REL ASM_LABEL(0) "ldrexd\t%2, %3, [%8]\n\t" "teq\t%3, %5\n\t" "it\t\teq\n\t" "teqeq\t%2, %4\n\t" "bne\t1f\n\t" "strexd\t%0, %6, %7, [%8]\n\t" "teq\t%0, #0\n\t" "bne\t0b\n\t" ASM_LABEL(1) "clrex\n\t" : "=&r" (success), "+m" (*p), "=&r" (l), "=&r" (h) : "r" (oldval->lo), "r" (oldval->hi), "r" (lo), "r" (hi), "r" (p), "0" (1) : "cc", "memory", "r2", "r3" ); if (success != 0) { oldval->lo = l; oldval->hi = h; } return success == 0; #endif } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word2* p, atomic_word2* oldval, atomic_word2 newval, memory_order_acq_rel_t, memory_order_relaxed_t) { #if defined(_MSC_VER) __dmb(_ARM_BARRIER_ISH); __int64 tmp = _InterlockedCompareExchange64_acq((volatile __int64*)p, newval.v, oldval->v); return oldval->v == tmp ? true : (oldval->v = tmp, false); #else register atomic_word l __asm__ ("r2"); register atomic_word h __asm__ ("r3"); register atomic_word lo __asm__ ("r0") = newval.lo; register atomic_word hi __asm__ ("r1") = newval.hi; atomic_word success; __asm__ __volatile__ ( ASM_REL ASM_LABEL(0) "ldrexd\t%2, %3, [%8]\n\t" "teq\t%3, %5\n\t" "it\t\teq\n\t" "teqeq\t%2, %4\n\t" "bne\t1f\n\t" "strexd\t%0, %6, %7, [%8]\n\t" "teq\t%0, #0\n\t" "bne\t0b\n\t" ASM_ISB ASM_LABEL(1) "clrex\n\t" : "=&r" (success), "+m" (*p), "=&r" (l), "=&r" (h) : "r" (oldval->lo), "r" (oldval->hi), "r" (lo), "r" (hi), "r" (p), "0" (1) : "cc", "memory", "r2", "r3" ); if (success != 0) { oldval->lo = l; oldval->hi = h; } return success == 0; #endif } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word2* p, atomic_word2* oldval, atomic_word2 newval, memory_order_seq_cst_t, memory_order_relaxed_t) { #if defined(_MSC_VER) __int64 tmp = _InterlockedCompareExchange64_rel((volatile __int64*)p, newval.v, oldval->v); __dmb(_ARM_BARRIER_ISH); return oldval->v == tmp ? true : (oldval->v = tmp, false); #else register atomic_word l __asm__ ("r2"); register atomic_word h __asm__ ("r3"); register atomic_word lo __asm__ ("r0") = newval.lo; register atomic_word hi __asm__ ("r1") = newval.hi; atomic_word success; __asm__ __volatile__ ( ASM_REL ASM_LABEL(0) "ldrexd\t%2, %3, [%8]\n\t" "teq\t%3, %5\n\t" "it\t\teq\n\t" "teqeq\t%2, %4\n\t" "bne\t1f\n\t" "strexd\t%0, %6, %7, [%8]\n\t" "teq\t%0, #0\n\t" "bne\t0b\n\t" ASM_DMB_ISH ASM_LABEL(1) "clrex\n\t" : "=&r" (success), "+m" (*p), "=&r" (l), "=&r" (h) : "r" (oldval->lo), "r" (oldval->hi), "r" (lo), "r" (hi), "r" (p), "0" (1) : "cc", "memory", "r2", "r3" ); if (success != 0) { oldval->lo = l; oldval->hi = h; } return success == 0; #endif } ================================================ FILE: unity_decoder/libil2cpp/os/Unity/ExtendedAtomicOps-arm64.h ================================================ #define ASM_DMB_ISH "dmb ish\n\t" #if defined(__ARM_ARCH_7S__) // this is sufficient for Swift processors # define ASM_REL "dmb ishst\n\t" #else # define ASM_REL "dmb ish\n\t" #endif static inline void atomic_pause() { } static inline void atomic_thread_fence(memory_order_relaxed_t) { } static inline void atomic_thread_fence(memory_order_acquire_t) { __asm__ __volatile__ ("dmb ld\n\t" : : : "memory"); } static inline void atomic_thread_fence(memory_order_release_t) { __asm__ __volatile__ (ASM_REL : : : "memory"); } static inline void atomic_thread_fence(memory_order_acq_rel_t) { __asm__ __volatile__ (ASM_DMB_ISH : : : "memory"); } static inline void atomic_thread_fence(int /* memory_order_seq_cst_t */) { __asm__ __volatile__ (ASM_DMB_ISH : : : "memory"); } #define ATOMIC_LOAD(opc) \ atomic_word res; \ __asm__ __volatile__ \ ( \ opc " %0, %1\n\t" \ : "=r" (res) \ : "m" (*p) \ ); \ return res; /* * int support */ static inline int atomic_load_explicit(const volatile int* p, memory_order_relaxed_t) { int res; __asm__ __volatile__ ( "ldr %w0, %w1\n\t" : "=r" (res) : "m" (*p) ); return res; } static inline int atomic_load_explicit(const volatile int* p, memory_order_acquire_t) { int res; __asm__ __volatile__ ( "ldar %w0, %w1\n\t" : "=r" (res) : "m" (*p) ); return res; } static inline int atomic_load_explicit(const volatile int* p, int /* memory_order_seq_cst_t */) { int res; __asm__ __volatile__ ( "ldar %w0, %w1\n\t" : "=r" (res) : "m" (*p) ); return res; } /* * native word support */ static inline atomic_word atomic_load_explicit(const volatile atomic_word* p, memory_order_relaxed_t) { ATOMIC_LOAD("ldr") } static inline atomic_word atomic_load_explicit(const volatile atomic_word* p, memory_order_acquire_t) { ATOMIC_LOAD("ldar") } static inline atomic_word atomic_load_explicit(const volatile atomic_word* p, int /* memory_order_seq_cst_t */) { ATOMIC_LOAD("ldar") } #define ATOMIC_STORE(opc) \ __asm__ __volatile__ \ ( \ opc " %1, %0\n\t" \ : "=m" (*p) \ : "r" (v) \ : "memory" \ ); /* * int support */ static inline void atomic_store_explicit(volatile int* p, int v, memory_order_relaxed_t) { __asm__ __volatile__ ( "str %w1, %w0\n\t" : "=m" (*p) : "r" (v) : "memory" ); } static inline void atomic_store_explicit(volatile int* p, int v, memory_order_release_t) { __asm__ __volatile__ ( "stlr %w1, %w0\n\t" : "=m" (*p) : "r" (v) : "memory" ); } static inline void atomic_store_explicit(volatile int* p, int v, int /* memory_order_seq_cst_t */) { __asm__ __volatile__ ( "stlr %w1, %w0\n\t" : "=m" (*p) : "r" (v) : "memory" ); } /* * native word support */ static inline void atomic_store_explicit(volatile atomic_word* p, atomic_word v, memory_order_relaxed_t) { ATOMIC_STORE("str") } static inline void atomic_store_explicit(volatile atomic_word* p, atomic_word v, memory_order_release_t) { ATOMIC_STORE("stlr") } static inline void atomic_store_explicit(volatile atomic_word* p, atomic_word v, int /* memory_order_seq_cst_t */) { ATOMIC_STORE("stlr") } #define ATOMIC_XCHG(LD, ST) \ atomic_word res; \ atomic_word success; \ __asm__ __volatile__ \ ( \ "0:\n\t" \ LD " %2, [%4]\n\t" \ ST " %w0, %3, [%4]\n\t" \ "cbnz %w0, 0b\n\t" \ : "=&r" (success), "+m" (*p), "=&r" (res) \ : "r" (v), "r" (p) \ : "memory" \ ); \ return res; static inline atomic_word atomic_exchange_explicit(volatile atomic_word* p, atomic_word v, memory_order_relaxed_t) { ATOMIC_XCHG("ldxr", "stxr") } static inline atomic_word atomic_exchange_explicit(volatile atomic_word* p, atomic_word v, memory_order_acquire_t) { ATOMIC_XCHG("ldaxr", "stxr") } static inline atomic_word atomic_exchange_explicit(volatile atomic_word* p, atomic_word v, memory_order_release_t) { ATOMIC_XCHG("ldxr", "stlxr") } static inline atomic_word atomic_exchange_explicit(volatile atomic_word* p, atomic_word v, memory_order_acq_rel_t) { ATOMIC_XCHG("ldaxr", "stlxr") } static inline atomic_word atomic_exchange_explicit(volatile atomic_word* p, atomic_word v, int /* memory_order_seq_cst_t */) { ATOMIC_XCHG("ldaxr", "stlxr") } // atomic_compare_exchange_weak_explicit: can fail spuriously even if *p == *oldval #define ATOMIC_CMP_XCHG(LD, ST) \ atomic_word res; \ atomic_word success = 0; \ __asm__ __volatile__ \ ( \ LD " %2, [%4]\n\t" \ "cmp %2, %5\n\t" \ "b.ne 1f\n\t" \ ST " %w0, %3, [%4]\n" \ "1:\n\t" \ "clrex\n\t" \ : "=&r" (success), "+m" (*p), "=&r" (res) \ : "r" (newval), "r" (p), "r" (*oldval) \ : "cc", "memory" \ ); \ *oldval = res; \ return success == 0; static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_relaxed_t, memory_order_relaxed_t) { ATOMIC_CMP_XCHG("ldxr", "stxr") } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_acquire_t, memory_order_relaxed_t) { ATOMIC_CMP_XCHG("ldaxr", "stxr") } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_release_t, memory_order_relaxed_t) { ATOMIC_CMP_XCHG("ldxr", "stlxr") } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_acq_rel_t, memory_order_relaxed_t) { ATOMIC_CMP_XCHG("ldaxr", "stlxr") } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, int /* memory_order_seq_cst_t */, memory_order_relaxed_t) { ATOMIC_CMP_XCHG("ldaxr", "stlxr") } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_acquire_t, memory_order_acquire_t) { ATOMIC_CMP_XCHG("ldaxr", "stxr") } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_release_t, memory_order_release_t) { ATOMIC_CMP_XCHG("ldxr", "stlxr") } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_acq_rel_t, memory_order_acq_rel_t) { ATOMIC_CMP_XCHG("ldaxr", "stlxr") } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, int /* memory_order_seq_cst_t */, int /* memory_order_seq_cst_t */) { ATOMIC_CMP_XCHG("ldaxr", "stlxr") } // atomic_compare_exchange_strong_explicit: does loop and only returns false if *p != *oldval #undef ATOMIC_CMP_XCHG #define ATOMIC_CMP_XCHG(LD, ST) \ atomic_word res; \ atomic_word success = 0; \ __asm__ __volatile__ \ ( \ "0:\n\t" \ LD " %2, [%4]\n\t" \ "cmp %2, %5\n\t" \ "b.ne 1f\n\t" \ ST " %w0, %3, [%4]\n" \ "cbnz %w0, 0b\n\t" \ "1:\n\t" \ "clrex\n\t" \ : "=&r" (success), "+m" (*p), "=&r" (res) \ : "r" (newval), "r" (p), "r" (*oldval) \ : "cc", "memory" \ ); \ *oldval = res; \ return success == 0; static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_relaxed_t, memory_order_relaxed_t) { ATOMIC_CMP_XCHG("ldxr", "stxr") } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_acquire_t, memory_order_relaxed_t) { ATOMIC_CMP_XCHG("ldaxr", "stxr") } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_release_t, memory_order_relaxed_t) { ATOMIC_CMP_XCHG("ldxr", "stlxr") } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_acq_rel_t, memory_order_relaxed_t) { ATOMIC_CMP_XCHG("ldaxr", "stlxr") } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, int /* memory_order_seq_cst_t */, memory_order_relaxed_t) { ATOMIC_CMP_XCHG("ldaxr", "stlxr") } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_acquire_t, memory_order_acquire_t) { ATOMIC_CMP_XCHG("ldaxr", "stxr") } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_release_t, memory_order_release_t) { ATOMIC_CMP_XCHG("ldxr", "stlxr") } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_acq_rel_t, memory_order_acq_rel_t) { ATOMIC_CMP_XCHG("ldaxr", "stlxr") } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word *oldval, atomic_word newval, int /* memory_order_seq_cst_t */, int /* memory_order_seq_cst_t */) { ATOMIC_CMP_XCHG("ldaxr", "stlxr") } #define ATOMIC_PFIX_int "%w" #define ATOMIC_PFIX_atomic_word "%" #define ATOMIC_PFIX(WORD) ATOMIC_PFIX_##WORD #define ATOMIC_OP(WORD, LD, ST, OP) \ long long res, tmp; \ int success; \ __asm__ __volatile__ \ ( \ "0:\n\t" \ LD " " ATOMIC_PFIX(WORD) "2, [%5]\n\t" \ OP " " ATOMIC_PFIX(WORD) "3, " ATOMIC_PFIX(WORD) "2, " ATOMIC_PFIX(WORD) "4\n\t"\ ST " %w0, " ATOMIC_PFIX(WORD) "3, [%5]\n" \ "cbnz %w0, 0b\n\t" \ : "=&r" (success), "+m" (*p), "=&r" (res), "=&r" (tmp) \ : "Ir" ((long long) v), "r" (p) \ : "cc", "memory" \ ); \ return (WORD) res; static inline int atomic_fetch_add_explicit(volatile int* p, int v, memory_order_relaxed_t) { ATOMIC_OP(int, "ldxr", "stxr", "add") } static inline int atomic_fetch_add_explicit(volatile int* p, int v, memory_order_acquire_t) { ATOMIC_OP(int, "ldaxr", "stxr", "add") } static inline int atomic_fetch_add_explicit(volatile int* p, int v, memory_order_release_t) { ATOMIC_OP(int, "ldxr", "stlxr", "add") } static inline int atomic_fetch_add_explicit(volatile int* p, int v, memory_order_acq_rel_t) { ATOMIC_OP(int, "ldaxr", "stlxr", "add") } static inline int atomic_fetch_add_explicit(volatile int* p, int v, int /* memory_order_seq_cst_t */) { ATOMIC_OP(int, "ldaxr", "stlxr", "add") } static inline atomic_word atomic_fetch_add_explicit(volatile atomic_word* p, atomic_word v, memory_order_relaxed_t) { ATOMIC_OP(atomic_word, "ldxr", "stxr", "add") } static inline atomic_word atomic_fetch_add_explicit(volatile atomic_word* p, atomic_word v, memory_order_acquire_t) { ATOMIC_OP(atomic_word, "ldaxr", "stxr", "add") } static inline atomic_word atomic_fetch_add_explicit(volatile atomic_word* p, atomic_word v, memory_order_release_t) { ATOMIC_OP(atomic_word, "ldxr", "stlxr", "add") } static inline atomic_word atomic_fetch_add_explicit(volatile atomic_word* p, atomic_word v, memory_order_acq_rel_t) { ATOMIC_OP(atomic_word, "ldaxr", "stlxr", "add") } static inline atomic_word atomic_fetch_add_explicit(volatile atomic_word* p, atomic_word v, int /* memory_order_seq_cst_t */) { ATOMIC_OP(atomic_word, "ldaxr", "stlxr", "add") } static inline int atomic_fetch_sub_explicit(volatile int* p, int v, memory_order_relaxed_t) { ATOMIC_OP(int, "ldxr", "stxr", "sub") } static inline int atomic_fetch_sub_explicit(volatile int* p, int v, memory_order_acquire_t) { ATOMIC_OP(int, "ldaxr", "stxr", "sub") } static inline int atomic_fetch_sub_explicit(volatile int* p, int v, memory_order_release_t) { ATOMIC_OP(int, "ldxr", "stlxr", "sub") } static inline int atomic_fetch_sub_explicit(volatile int* p, int v, memory_order_acq_rel_t) { ATOMIC_OP(int, "ldaxr", "stlxr", "sub") } static inline int atomic_fetch_sub_explicit(volatile int* p, int v, int /* memory_order_seq_cst_t */) { ATOMIC_OP(int, "ldaxr", "stlxr", "sub") } static inline atomic_word atomic_fetch_sub_explicit(volatile atomic_word* p, atomic_word v, memory_order_relaxed_t) { ATOMIC_OP(atomic_word, "ldxr", "stxr", "sub") } static inline atomic_word atomic_fetch_sub_explicit(volatile atomic_word* p, atomic_word v, memory_order_acquire_t) { ATOMIC_OP(atomic_word, "ldaxr", "stxr", "sub") } static inline atomic_word atomic_fetch_sub_explicit(volatile atomic_word* p, atomic_word v, memory_order_release_t) { ATOMIC_OP(atomic_word, "ldxr", "stlxr", "sub") } static inline atomic_word atomic_fetch_sub_explicit(volatile atomic_word* p, atomic_word v, memory_order_acq_rel_t) { ATOMIC_OP(atomic_word, "ldaxr", "stlxr", "sub") } static inline atomic_word atomic_fetch_sub_explicit(volatile atomic_word* p, atomic_word v, int /* memory_order_seq_cst_t */) { ATOMIC_OP(atomic_word, "ldaxr", "stlxr", "sub") } /* * extensions */ static inline void atomic_retain(volatile int* p) { atomic_fetch_add_explicit(p, 1, memory_order_relaxed); } static inline bool atomic_release(volatile int* p) { bool res = atomic_fetch_sub_explicit(p, 1, memory_order_release) == 1; if (res) { atomic_thread_fence(memory_order_acquire); } return res; } /* * double word */ // Note: the only way to get atomic 128-bit memory accesses on ARM64 is to use ldxp/stxp with a loop // (ldxp and stxp instructions are not guaranteed to appear atomic) static inline atomic_word2 atomic_load_explicit(const volatile atomic_word2* p, memory_order_relaxed_t) { atomic_word2 v; atomic_word success; __asm__ __volatile__ ( "0:\n\t" "ldxp\t%1, %2, [%3]\n\t" "stxp\t%w0, %1, %2, [%3]\n\t" "cbnz\t%w0, 0b\n\t" : "=&r" (success), "=&r" (v.lo), "=&r" (v.hi) : "r" (p) ); return v; } static inline atomic_word2 atomic_load_explicit(const volatile atomic_word2* p, memory_order_acquire_t) { atomic_word2 v; atomic_word success; __asm__ __volatile__ ( "0:\n\t" "ldaxp\t%1, %2, [%3]\n\t" "stxp\t%w0, %1, %2, [%3]\n\t" "cbnz\t%w0, 0b\n\t" : "=&r" (success), "=&r" (v.lo), "=&r" (v.hi) : "r" (p) ); return v; } static inline void atomic_store_explicit(volatile atomic_word2* p, atomic_word2 v, memory_order_relaxed_t) { atomic_word lo; atomic_word hi; atomic_word success; __asm__ __volatile__ ( "0:\n\t" "ldxp\t%2, %3, [%6]\n\t" "stxp\t%w0, %4, %5, [%6]\n\t" "cbnz\t%w0, 0b\n\t" : "=&r" (success), "=m" (*p), "=&r" (lo), "=&r" (hi) : "r" (v.lo), "r" (v.hi), "r" (p) : "memory" ); } static inline void atomic_store_explicit(volatile atomic_word2* p, atomic_word2 v, memory_order_release_t) { atomic_word lo; atomic_word hi; atomic_word success; __asm__ __volatile__ ( "0:\n\t" "ldxp\t%2, %3, [%6]\n\t" "stlxp\t%w0, %4, %5, [%6]\n\t" "cbnz\t%w0, 0b\n\t" : "=&r" (success), "=m" (*p), "=&r" (lo), "=&r" (hi) : "r" (v.lo), "r" (v.hi), "r" (p) : "memory" ); } static inline atomic_word2 atomic_exchange_explicit(volatile atomic_word2* p, atomic_word2 val, memory_order_acq_rel_t) { atomic_word2 oldval; atomic_word success; __asm__ __volatile__ ( "0:\n\t" "ldaxp\t%2, %3, [%6]\n\t" "stlxp\t%w0, %5, %4, [%6]\n\t" "cbnz\t%w0, 0b\n\t" : "=&r" (success), "+m" (*p), "=&r" (oldval.lo), "=&r" (oldval.hi) : "r" (val.hi), "r" (val.lo), "r" (p) : "memory" ); return oldval; } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word2* p, atomic_word2* oldval, atomic_word2 newval, memory_order_acquire_t, memory_order_relaxed_t) { atomic_word lo = oldval->lo; atomic_word hi = oldval->hi; atomic_word success; __asm__ __volatile__ ( "0:\n\t" "ldaxp\t%2, %3, [%8]\n\t" "cmp\t%3, %5\n\t" "b.ne\t1f\n\t" "cmp\t%2, %4\n\t" "b.ne\t1f\n\t" "stxp\t%w0, %6, %7, [%8]\n\t" "cbnz\t%w0, 0b\n\t" "1:\n\t" "clrex\n\t" : "=&r" (success), "+m" (*p), "=&r" (oldval->lo), "=&r" (oldval->hi) : "r" (lo), "r" (hi), "r" (newval.lo), "r" (newval.hi), "r" (p), "0" (1) : "cc", "memory" ); return success == 0; } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word2* p, atomic_word2* oldval, atomic_word2 newval, memory_order_release_t, memory_order_relaxed_t) { atomic_word lo = oldval->lo; atomic_word hi = oldval->hi; atomic_word success; __asm__ __volatile__ ( "0:\n\t" "ldxp\t%2, %3, [%8]\n\t" "cmp\t%3, %5\n\t" "b.ne\t1f\n\t" "cmp\t%2, %4\n\t" "b.ne\t1f\n\t" "stlxp\t%w0, %6, %7, [%8]\n\t" "cbnz\t%w0, 0b\n\t" "1:\n\t" "clrex\n\t" : "=&r" (success), "+m" (*p), "=&r" (oldval->lo), "=&r" (oldval->hi) : "r" (lo), "r" (hi), "r" (newval.lo), "r" (newval.hi), "r" (p), "0" (1) : "cc", "memory" ); return success == 0; } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word2* p, atomic_word2* oldval, atomic_word2 newval, int /*memory_order_acq_rel_t*/, memory_order_relaxed_t) { atomic_word lo = oldval->lo; atomic_word hi = oldval->hi; atomic_word success; __asm__ __volatile__ ( "0:\n\t" "ldaxp\t%2, %3, [%8]\n\t" "cmp\t%3, %5\n\t" "b.ne\t1f\n\t" "cmp\t%2, %4\n\t" "b.ne\t1f\n\t" "stlxp\t%w0, %6, %7, [%8]\n\t" "cbnz\t%w0, 0b\n\t" "1:\n\t" "clrex\n\t" : "=&r" (success), "+m" (*p), "=&r" (oldval->lo), "=&r" (oldval->hi) : "r" (lo), "r" (hi), "r" (newval.lo), "r" (newval.hi), "r" (p), "0" (1) : "cc", "memory" ); return success == 0; } ================================================ FILE: unity_decoder/libil2cpp/os/Unity/ExtendedAtomicOps-x86-64.h ================================================ #if defined(_MSC_VER) # include "os/Win32/WindowsHeaders.h" # include #endif #if defined(__SSE2__) # include #endif static inline void atomic_pause() { #if defined(_MSC_VER) _mm_pause(); #else __asm__ __volatile__ ("pause"); #endif } static inline void atomic_thread_fence(memory_order_relaxed_t) { } static inline void atomic_thread_fence(memory_order_release_t) { #if defined(_MSC_VER) _ReadWriteBarrier(); #else __asm__ __volatile__ ("" : : : "memory"); #endif } static inline void atomic_thread_fence(memory_order_acquire_t) { #if defined(_MSC_VER) _ReadWriteBarrier(); #else __asm__ __volatile__ ("" : : : "memory"); #endif } static inline void atomic_thread_fence(memory_order_acq_rel_t) { #if defined(_MSC_VER) _ReadWriteBarrier(); #else __asm__ __volatile__ ("" : : : "memory"); #endif } static inline void atomic_thread_fence(int /* memory_order_seq_cst_t */) { #if defined(__SSE2__) _mm_mfence(); #elif defined(_MSC_VER) volatile LONGLONG tmp; _InterlockedOr64(&tmp, 0); #else __asm__ __volatile__ ("lock orl #0, 0(%%esp)" ::: "cc", "memory"); #endif } /* * int support */ static inline atomic_word atomic_load_explicit(const volatile int* p, memory_order_relaxed_t) { return *p; } static inline int atomic_load_explicit(const volatile int* p, int) { int v; #if defined(_MSC_VER) v = *p; _ReadWriteBarrier(); #else __asm__ __volatile__ ("movl %1, %0" : "=r" (v) : "m" (*p) : "memory"); #endif return v; } static inline void atomic_store_explicit(volatile int* p, int v, memory_order_relaxed_t) { *p = v; } static inline void atomic_store_explicit(volatile int* p, int v, memory_order_release_t) { #if defined(_MSC_VER) _ReadWriteBarrier(); *p = v; #else __asm__ __volatile__ ("movl %1, %0" : "=m" (*p) : "r" (v) : "memory"); #endif } static inline void atomic_store_explicit(volatile int* p, int val, int /* memory_order_seq_cst_t */) { #if defined(_MSC_VER) _InterlockedExchange((volatile LONG*)p, (LONG)val); #else // lock prefix is implicit __asm__ __volatile__ ( /*lock*/ "xchgl %1, %0" : "+m" (*p), "+r" (val) : : "memory" ); #endif } /* * native word support */ static inline atomic_word atomic_load_explicit(const volatile atomic_word* p, memory_order_relaxed_t) { return *p; } static inline atomic_word atomic_load_explicit(const volatile atomic_word* p, int) { atomic_word v; #if defined(_MSC_VER) v = *p; _ReadWriteBarrier(); #else __asm__ __volatile__ ("movq %1, %0" : "=r" (v) : "m" (*p) : "memory"); #endif return v; } static inline void atomic_store_explicit(volatile atomic_word* p, atomic_word v, memory_order_relaxed_t) { *p = v; } static inline void atomic_store_explicit(volatile atomic_word* p, atomic_word v, memory_order_release_t) { #if defined(_MSC_VER) _ReadWriteBarrier(); *p = v; #else __asm__ __volatile__ ("movq %1, %0" : "=m" (*p) : "r" (v) : "memory"); #endif } static inline void atomic_store_explicit(volatile atomic_word* p, atomic_word val, int /* memory_order_seq_cst_t */) { #if defined(_MSC_VER) _InterlockedExchange64((volatile LONGLONG*)p, (LONGLONG)val); #else // lock prefix is implicit __asm__ __volatile__ ( /*lock*/ "xchgq %1, %0" : "+m" (*p), "+r" (val) : : "memory" ); #endif } static inline atomic_word atomic_exchange_explicit(volatile atomic_word* p, atomic_word val, int) { #if defined(_MSC_VER) return (atomic_word)_InterlockedExchange64((volatile LONGLONG*)p, (LONGLONG)val); #else // lock prefix is implicit __asm__ __volatile__ ( /*lock*/ "xchgq %1, %0" : "+m" (*p), "+r" (val) : : "memory" ); return val; #endif } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word* oldval, atomic_word newval, int, int) { #if defined(_MSC_VER) atomic_word tmp = (atomic_word)_InterlockedCompareExchange64((volatile LONGLONG*)p, (LONGLONG)newval, (LONGLONG)*oldval); return *oldval == tmp ? true : (*oldval = tmp, false); #else char res; __asm__ __volatile__ ( "lock cmpxchgq %3, %0\n\t" "setz %b1" : "+m" (*p), "=q" (res), "+a" (*oldval) : "r" (newval) : "cc", "memory" ); return res != 0; #endif } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word* oldval, atomic_word newval, int, int) { return atomic_compare_exchange_strong_explicit(p, oldval, newval, memory_order_seq_cst, memory_order_seq_cst); } static inline atomic_word atomic_fetch_add_explicit(volatile int *p, int val, int) { #if defined(_MSC_VER) return _InterlockedExchangeAdd((LONG volatile*)p, (LONG)val); #else __asm__ __volatile__ ( "lock xaddl\t%1, %0" : "+m" (*p), "+r" (val) : : "cc", "memory" ); return val; #endif } static inline atomic_word atomic_fetch_add_explicit(volatile atomic_word *p, atomic_word val, int) { #if defined(_MSC_VER) return _InterlockedExchangeAdd64((LONGLONG volatile*)p, (LONGLONG)val); #else __asm__ __volatile__ ( "lock xaddq %1, %0" : "+m" (*p), "+r" (val) : : "cc", "memory" ); return val; #endif } static inline atomic_word atomic_fetch_sub_explicit(volatile int *p, int val, int mo) { return atomic_fetch_add_explicit(p, -val, mo); } static inline atomic_word atomic_fetch_sub_explicit(volatile atomic_word *p, atomic_word val, int mo) { return atomic_fetch_add_explicit(p, -val, mo); } /* * extensions */ static inline void atomic_retain(volatile int *p) { #if defined(_MSC_VER) _InterlockedIncrement((LONG volatile*)p); #else __asm__ ( "lock incl %0\n\t" : "+m" (*p) : : "cc", "memory" ); #endif } static inline bool atomic_release(volatile int *p) { #if defined(_MSC_VER) return _InterlockedDecrement((LONG volatile*)p) == 0; #else bool res; __asm__ ( "lock decl %0\n\t" "setz %b1" : "+m" (*p), "=q" (res) : : "cc", "memory" ); return res; #endif } /* * double word */ static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word2* p, atomic_word2* oldval, atomic_word2 newval, int, int) { #if defined(_MSC_VER) return _InterlockedCompareExchange128((volatile LONGLONG*)p, (LONGLONG)newval.hi, (LONGLONG)newval.lo, (LONGLONG*)oldval) != 0; #else char res; __asm__ __volatile__ ( "lock cmpxchg16b %0\n\t" "setz %b1\n\t" : "+m" (*p), "=q" (res), "+a" (oldval->lo), "+d" (oldval->hi) : "b" (newval.lo), "c" (newval.hi) : "cc", "memory" ); return res != 0; #endif } static inline atomic_word2 atomic_load_explicit(const volatile atomic_word2* p, int o) { /* atomic_word2 r = { 0, 0 }; atomic_word2 c = { 0, 0 }; atomic_compare_exchange_strong_explicit((volatile atomic_word2*) p, &r, c, o, o); return r; */ atomic_word2 r; r.v = _mm_load_si128((const __m128i*)p); return r; } static inline void atomic_store_explicit(volatile atomic_word2* p, atomic_word2 v, int o) { /* atomic_word2 c = v; while(!atomic_compare_exchange_strong_explicit(p, &c, v, o, o)) {}; */ _mm_store_si128((__m128i*)&p->v, v.v); } static inline atomic_word2 atomic_exchange_explicit(volatile atomic_word2* p, atomic_word2 newval, int) { atomic_word2 oldval; oldval.lo = 0; oldval.hi = newval.hi - 1; while (!atomic_compare_exchange_strong_explicit(p, &oldval, newval, memory_order_seq_cst, memory_order_seq_cst)) ; return oldval; } ================================================ FILE: unity_decoder/libil2cpp/os/Unity/ExtendedAtomicOps-x86.h ================================================ #if defined(_MSC_VER) # include "os/Win32/WindowsHeaders.h" # include #endif #if defined(__SSE2__) # include #endif static inline void atomic_pause() { #if defined(_MSC_VER) _mm_pause(); #else __asm__ __volatile__ ("rep; nop"); #endif } static inline void atomic_thread_fence(memory_order_relaxed_t) { } static inline void atomic_thread_fence(memory_order_release_t) { #if defined(_MSC_VER) _ReadWriteBarrier(); #else __asm__ __volatile__ ("" : : : "memory"); #endif } static inline void atomic_thread_fence(memory_order_acquire_t) { #if defined(_MSC_VER) _ReadWriteBarrier(); #else __asm__ __volatile__ ("" : : : "memory"); #endif } static inline void atomic_thread_fence(memory_order_acq_rel_t) { #if defined(_MSC_VER) _ReadWriteBarrier(); #else __asm__ __volatile__ ("" : : : "memory"); #endif } static inline void atomic_thread_fence(int /* memory_order_seq_cst_t */) { #if defined(__SSE2__) _mm_mfence(); #elif defined(_MSC_VER) volatile LONG tmp; _InterlockedOr(&tmp, 0); #else __asm__ __volatile__ ("lock orl #0, 0(%%esp)" ::: "cc", "memory"); #endif } static inline atomic_word atomic_load_explicit(const volatile atomic_word* p, memory_order_relaxed_t) { return *p; } static inline atomic_word atomic_load_explicit(const volatile atomic_word* p, int) { atomic_word v; #if defined(_MSC_VER) v = *p; _ReadWriteBarrier(); #else __asm__ __volatile__ ("movl %1, %0" : "=r" (v) : "m" (*p) : "memory"); #endif return v; } static inline void atomic_store_explicit(volatile atomic_word* p, atomic_word v, memory_order_relaxed_t) { *p = v; } static inline void atomic_store_explicit(volatile atomic_word* p, atomic_word v, memory_order_release_t) { #if defined(_MSC_VER) _ReadWriteBarrier(); *p = v; #else __asm__ __volatile__ ("movl %1, %0" : "=m" (*p) : "r" (v) : "memory"); #endif } static inline void atomic_store_explicit(volatile atomic_word* p, atomic_word val, int /* memory_order_seq_cst_t */) { #if defined(_MSC_VER) _InterlockedExchange((volatile LONG*)p, (LONG)val); #else // lock prefix is implicit __asm__ __volatile__ ( /*lock*/ "xchgl %1, %0" : "+m" (*p), "+r" (val) : : "memory" ); #endif } static inline atomic_word atomic_exchange_explicit(volatile atomic_word* p, atomic_word val, int) { #if defined(_MSC_VER) return (atomic_word)_InterlockedExchange((volatile LONG*)p, (LONG)val); #else // lock prefix is implicit __asm__ __volatile__ ( /*lock*/ "xchgl %1, %0" : "+m" (*p), "+r" (val) : : "memory" ); return val; #endif } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word* p, atomic_word* oldval, atomic_word newval, int, int) { #if defined(_MSC_VER) atomic_word tmp = (atomic_word)_InterlockedCompareExchange((volatile LONG*)p, (LONG)newval, (LONG)*oldval); return *oldval == tmp ? true : (*oldval = tmp, false); #else char res; __asm__ __volatile__ ( "lock cmpxchgl %3, %0\n\t" "setz %b1" : "+m" (*p), "=q" (res), "+a" (*oldval) : "r" (newval) : "cc", "memory" ); return res != 0; #endif } static inline bool atomic_compare_exchange_weak_explicit(volatile atomic_word* p, atomic_word* oldval, atomic_word newval, int, int) { return atomic_compare_exchange_strong_explicit(p, oldval, newval, memory_order_seq_cst, memory_order_seq_cst); } static inline atomic_word atomic_fetch_add_explicit(volatile atomic_word *p, atomic_word val, int) { #if defined(_MSC_VER) return _InterlockedExchangeAdd((LONG volatile*)p, (LONG)val); #else __asm__ __volatile__ ( "lock xaddl %1, %0" : "+m" (*p), "+r" (val) : : "cc", "memory" ); return val; #endif } static inline atomic_word atomic_fetch_sub_explicit(volatile atomic_word *p, atomic_word val, int mo) { return atomic_fetch_add_explicit(p, -val, mo); } /* * extensions */ static inline void atomic_retain(volatile int *p) { #if defined(_MSC_VER) _InterlockedIncrement((LONG volatile*)p); #else __asm__ ( "lock incl %0\n\t" : "+m" (*p) : : "cc", "memory" ); #endif } static inline bool atomic_release(volatile int *p) { #if defined(_MSC_VER) return _InterlockedDecrement((LONG volatile*)p) == 0; #else bool res; __asm__ ( "lock decl %0\n\t" "setz %b1" : "+m" (*p), "=q" (res) : : "cc", "memory" ); return res; #endif } // double word static inline atomic_word2 atomic_load_explicit(const volatile atomic_word2* p, int) { atomic_word2 r; #if defined(__SSE2__) _mm_store_sd((double*)&r, _mm_load_sd((const double*)p)); #else // using the FPU is the only way to do a 64 bit atomic load if SSE is not available r.d = p->d; #endif return r; } static inline void atomic_store_explicit(volatile atomic_word2* p, atomic_word2 v, int) { #if defined(__SSE2__) _mm_store_sd((double*)p, _mm_load_sd((const double*)&v)); #else // using the FPU is the only way to do a 64 bit atomic store if SSE is not available p->d = v.d; #endif } static inline bool atomic_compare_exchange_strong_explicit(volatile atomic_word2* p, atomic_word2* oldval, atomic_word2 newval, int, int) { #if defined(_MSC_VER) LONGLONG tmp = _InterlockedCompareExchange64((volatile LONGLONG*)p, newval.v, oldval->v); return oldval->v == tmp ? true : (oldval->v = tmp, false); #else char res; __asm__ __volatile__ ( "lock cmpxchg8b %0\n\t" "setz %b1\n\t" : "+m" (*p), "=q" (res), "+a" (oldval->lo), "+d" (oldval->hi) : "b" (newval.lo), "c" (newval.hi) : "cc", "memory" ); return res != 0; #endif } static inline atomic_word2 atomic_exchange_explicit(volatile atomic_word2* p, atomic_word2 newval, int) { atomic_word2 oldval; oldval.lo = 0; oldval.hi = newval.hi - 1; while (!atomic_compare_exchange_strong_explicit(p, &oldval, newval, memory_order_seq_cst, memory_order_seq_cst)) ; return oldval; } ================================================ FILE: unity_decoder/libil2cpp/os/Unity/ExtendedAtomicOps.h ================================================ #pragma once #include "ExtendedAtomicTypes.h" UNITY_PLATFORM_BEGIN_NAMESPACE; enum memory_order_relaxed_t { memory_order_relaxed = 0 }; enum memory_order_acquire_t { memory_order_acquire = 2, memory_order_consume = memory_order_acquire }; enum memory_order_release_t { memory_order_release = 3 }; enum memory_order_acq_rel_t { memory_order_acq_rel = 4 }; enum memory_order_seq_cst_t { memory_order_seq_cst = 5 }; /* Available atomic functions: // non-explicit versions, use sequential consistency semantic by default // atomic load atomic_word atomic_load (const volatile atomic_word* p); // atomic store void atomic_store (volatile atomic_word* p, atomic_word val); // atomic exchange, returns previous value atomic_word atomic_exchange (volatile atomic_word* p, atomic_word val); // atomic compare exchange (strong), returns if the operation succeeded and update *oldval with the previous value bool atomic_compare_exchange (volatile atomic_word* p, atomic_word* oldval, atomic_word newval); // atomic fetch then add, returns previous value atomic_word atomic_fetch_add (volatile atomic_word *p, atomic_word val); // atomic fetch then sub, returns previous value atomic_word atomic_fetch_sub (volatile atomic_word *p, atomic_word val); // explicit versions // memory fence with semantic void atomic_thread_fence (memory_order_t mo); // atomic load with semantic atomic_word atomic_load_explicit (const volatile atomic_word* p, memory_order_t mo); // atomic store with semantic void atomic_store_explicit (volatile atomic_word* p, atomic_word v, memory_order_t mo); // atomic exchange with semantic, returns previous value atomic_word atomic_exchange_explicit (volatile atomic_word* p, atomic_word v, memory_order_t mo); // on RISC platforms with LoadLinked-StoreConditional available: // atomic_compare_exchange_weak_explicit: can fail spuriously even if *p == *oldval // uses memory barrier when it succeeds, otherwize // returns the state of the operation and updates *oldval with the previous value bool atomic_compare_exchange_weak_explicit (volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_t success, memory_order_t failure); // atomic_compare_exchange_strong_explicit: can loop and only returns false if *p != *oldval // uses memory barrier when it succeeds, otherwise // returns the state of the operation and updates *oldval with the previous value bool atomic_compare_exchange_strong_explicit (volatile atomic_word* p, atomic_word *oldval, atomic_word newval, memory_order_t success, memory_order_t failure); // atomic fetch then add with semantic, returns previous value int atomic_fetch_add_explicit (volatile int* p, int val, memory_order_t mo); atomic_word atomic_fetch_add_explicit (volatile atomic_word* p, atomic_word val, memory_order_t mo); // atomic fetch then sub with semantic, returns previous value int atomic_fetch_sub_explicit (volatile int* p, int val, memory_order_t mo); atomic_word atomic_fetch_sub_explicit (volatile atomic_word* p, atomic_word val, memory_order_t mo); // extensions to the C++0x11 standard: // spinning hint for the processor void atomic_pause (); // atomic increment with relaxed semantic void atomic_retain (volatile int *p); // atomic decrement with acquire/release semantic, returns true if resulting value is zero, false otherwize bool atomic_release (volatile int *p); // on platforms with double word compare exchange (ABA safe atomic pointers): // atomic load atomic_word2 atomic_load_explicit (const volatile atomic_word2* p, memory_order_t mo); // atomic store void atomic_store_explicit (volatile atomic_word2* p, atomic_word2 v, memory_order_t mo); // atomic exchange atomic_word atomic_exchange_explicit (volatile atomic_word2* p, atomic_word2 newval, memory_order_t mo); // atomic compare exchange bool atomic_compare_exchange_strong_explicit (volatile atomic_word2* p, atomic_word2* oldval, atomic_word2 newval, memory_order_t success, memory_order_t failure); */ #if IL2CPP_TARGET_HAS_EXTENDED_ATOMICS # include "os/ExtendedAtomicOps.h" #elif defined(__x86_64__) || defined(_M_X64) # include "ExtendedAtomicOps-x86-64.h" # define UNITY_ATOMIC_INT_OVERLOAD #elif defined(__x86__) || defined(__i386__) || defined(_M_IX86) # include "ExtendedAtomicOps-x86.h" #elif defined(__arm64__) && (defined(__clang__) || defined(__GNUC__)) # include "ExtendedAtomicOps-arm64.h" # define UNITY_ATOMIC_INT_OVERLOAD #elif defined(_M_ARM) || (defined(__arm__) && (defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)) && (!UNITY_STV_API) && (defined(__clang__) || defined(__GNUC__))) # include "ExtendedAtomicOps-arm.h" #elif PLATFORM_WIIU # include "ExtendedAtomicOps-ppc.h" #elif PLATFORM_PSVITA # include "PlatformExtendedAtomicOps.h" #elif (defined(__ppc64__) || defined(_ARCH_PPC64)) && (defined(__clang__) || defined(__GNUC__)) # include "ExtendedAtomicOps-ppc64.h" # define UNITY_ATOMIC_INT_OVERLOAD //#elif defined (__ppc__) && (defined (__clang__) || defined (__GNUC__)) //# include "Runtime/Threads/ExtendedAtomicOps-ppc.h" #else #define UNITY_NO_ATOMIC_OPS static inline atomic_word atomic_load_explicit(const volatile atomic_word* p, memory_order_relaxed_t) { return *p; } static inline void atomic_store_explicit(volatile atomic_word* p, atomic_word v, memory_order_relaxed_t) { *p = v; } #endif #ifndef UNITY_NO_ATOMIC_OPS // non-explicit versions, use sequential consistency semantic static inline void atomic_thread_fence() { atomic_thread_fence(memory_order_seq_cst); } static inline atomic_word atomic_load(const volatile atomic_word* p) { return atomic_load_explicit(p, memory_order_seq_cst); } static inline void atomic_store(volatile atomic_word* p, atomic_word val) { atomic_store_explicit(p, val, memory_order_seq_cst); } static inline atomic_word atomic_exchange(volatile atomic_word* p, atomic_word val) { return atomic_exchange_explicit(p, val, memory_order_seq_cst); } static inline bool atomic_compare_exchange(volatile atomic_word* p, atomic_word* oldval, atomic_word newval) { return atomic_compare_exchange_strong_explicit(p, oldval, newval, memory_order_seq_cst, memory_order_seq_cst); } static inline atomic_word atomic_fetch_add(volatile atomic_word *p, atomic_word val) { return atomic_fetch_add_explicit(p, val, memory_order_seq_cst); } static inline atomic_word atomic_fetch_sub(volatile atomic_word *p, atomic_word val) { return atomic_fetch_sub_explicit(p, val, memory_order_seq_cst); } #if defined(UNITY_ATOMIC_INT_OVERLOAD) static inline int atomic_load(const volatile int* p) { return atomic_load_explicit(p, memory_order_seq_cst); } static inline void atomic_store(volatile int* p, int val) { atomic_store_explicit(p, val, memory_order_seq_cst); } static inline int atomic_fetch_add(volatile int *p, int val) { return static_cast(atomic_fetch_add_explicit(p, val, memory_order_seq_cst)); } static inline int atomic_fetch_sub(volatile int *p, int val) { return static_cast(atomic_fetch_sub_explicit(p, val, memory_order_seq_cst)); } #endif #endif UNITY_PLATFORM_END_NAMESPACE; ================================================ FILE: unity_decoder/libil2cpp/os/Unity/ExtendedAtomicTypes.h ================================================ #pragma once UNITY_PLATFORM_BEGIN_NAMESPACE; #if IL2CPP_TARGET_HAS_EXTENDED_ATOMICS # include "os/ExtendedAtomicTypes.h" #elif defined(__x86_64__) || defined(_M_X64) # include /// atomic_word must be 16 bytes aligned if you want to use it with atomic_* ops. # if defined(_MSC_VER) typedef __int64 atomic_word; # else typedef long long atomic_word; # endif /// atomic_word2 must be 16 bytes aligned if you want to use it with atomic_* ops. union atomic_word2 { __m128i v; struct { atomic_word lo, hi; }; }; #define ATOMIC_HAS_DCAS #elif defined(__x86__) || defined(__i386__) || defined(_M_IX86) /// atomic_word must be 8 bytes aligned if you want to use it with atomic_* ops. typedef int atomic_word; /// atomic_word2 must be 8 bytes aligned if you want to use it with atomic_* ops. union atomic_word2 { # if defined(_MSC_VER) __int64 v; # else long long v; # endif # if !defined(__SSE2__) double d; # endif struct { atomic_word lo, hi; }; }; #define ATOMIC_HAS_DCAS #elif defined(__arm64__) && (defined(__clang__) || defined(__GNUC__)) typedef long long atomic_word; struct atomic_word2 { atomic_word lo; atomic_word hi; }; # define ATOMIC_HAS_DCAS # define ATOMIC_HAS_LDR #elif defined(_M_ARM) || (defined(__arm__) && (defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)) && (!UNITY_STV_API) && (defined(__clang__) || defined(__GNUC__))) typedef int atomic_word; union atomic_word2 { # if defined(_MSC_VER) __int64 v; # else long long v; # endif struct { atomic_word lo; atomic_word hi; }; }; # define ATOMIC_HAS_DCAS # if !defined(_MSC_VER) # define ATOMIC_HAS_LDR # endif #elif PLATFORM_PSVITA typedef int32_t atomic_word; union atomic_word2 { int64_t v; struct { atomic_word lo; atomic_word hi; }; }; # define ATOMIC_HAS_DCAS # define ATOMIC_HAS_LDR #elif defined(__ppc64__) || defined(_ARCH_PPC64) typedef long atomic_word; # define ATOMIC_HAS_LDR #elif defined(__ppc__) typedef int atomic_word; # define ATOMIC_HAS_LDR #else # if defined(__LP64__) typedef long long atomic_word; # else typedef int atomic_word; # endif struct atomic_word2 { atomic_word lo; atomic_word hi; }; #endif UNITY_PLATFORM_END_NAMESPACE; ================================================ FILE: unity_decoder/libil2cpp/os/Unity/UnityPlatformConfigure.h ================================================ #pragma once // Stopgap measure to allow using some code from the Unity's own platform layer without having to adapt it exclusively // for il2cpp. #include "il2cpp-config.h" #if IL2CPP_TARGET_WINDOWS || IL2CPP_TARGET_XBOXONE #include #else #include #endif #include #define UNITY_PLATFORM_BEGIN_NAMESPACE namespace il2cpp { namespace os { #define UNITY_PLATFORM_END_NAMESPACE }} #define UNITY_PLATFORM_NEW(type, label) new type #define UNITY_PLATFORM_NEW_ALIGNED(type, label, alignment) new (alignment) type #define UNITY_PLATFORM_DELETE(ptr, label) delete ptr inline void* operator new(size_t size, int alignment) { void* result = NULL; #if IL2CPP_TARGET_WINDOWS || IL2CPP_TARGET_XBOXONE result = _aligned_malloc(size, alignment); #elif IL2CPP_TARGET_ANDROID || IL2CPP_TARGET_PSP2 result = memalign(alignment, size); #else if (posix_memalign(&result, size, alignment)) result = NULL; #endif if (!result) throw std::bad_alloc(); return result; } #if IL2CPP_TARGET_WINDOWS || IL2CPP_TARGET_XBOXONE // Visual C++ warns if new is overridden but delete is not. inline void operator delete(void* ptr, int alignment) throw () { free(ptr); } #endif ================================================ FILE: unity_decoder/libil2cpp/os/WaitStatus.h ================================================ #pragma once namespace il2cpp { namespace os { enum WaitStatus { kWaitStatusSuccess = 0, kWaitStatusFailure, kWaitStatusTimeout, }; } } ================================================ FILE: unity_decoder/libil2cpp/os/Win32/AtomicImpl.h ================================================ #pragma once #if IL2CPP_TARGET_WINDOWS #include "os/Win32/WindowsHeaders.h" namespace il2cpp { namespace os { inline int32_t Atomic::Add(volatile int32_t* location1, int32_t value) { return (InterlockedExchangeAdd((long volatile*)location1, value) + value); } inline int64_t Atomic::Add64(volatile int64_t* location1, int64_t value) { return (InterlockedExchangeAdd64((long long volatile*)location1, value) + value); } inline int32_t Atomic::Increment(volatile int32_t* value) { return InterlockedIncrement((long volatile*)value); } inline int64_t Atomic::Increment64(volatile int64_t* value) { return InterlockedIncrement64(value); } inline int32_t Atomic::Decrement(volatile int32_t* value) { return InterlockedDecrement((long volatile*)value); } inline int64_t Atomic::Decrement64(volatile int64_t* value) { return InterlockedDecrement64((long long volatile*)value); } inline int32_t Atomic::CompareExchange(volatile int32_t* dest, int32_t exchange, int32_t comparand) { return InterlockedCompareExchange((long volatile*)dest, exchange, comparand); } inline int64_t Atomic::CompareExchange64(volatile int64_t* dest, int64_t exchange, int64_t comparand) { return InterlockedCompareExchange64((long long volatile*)dest, exchange, comparand); } inline void* Atomic::CompareExchangePointer(void* volatile* dest, void* exchange, void* comparand) { return InterlockedCompareExchangePointer(dest, exchange, comparand); } inline int64_t Atomic::Exchange64(volatile int64_t* dest, int64_t exchange) { return InterlockedExchange64(dest, exchange); } inline int32_t Atomic::Exchange(volatile int32_t* dest, int32_t exchange) { return InterlockedExchange((long volatile*)dest, exchange); } inline void* Atomic::ExchangePointer(void* volatile* dest, void* exchange) { return InterlockedExchangePointer(dest, exchange); } int64_t Atomic::Read64(volatile int64_t* addr) { return InterlockedCompareExchange64((long long volatile*)addr, 0, 0); } // MemoryBarrier is defined as a macro on x64 and as a function on x86. #undef MemoryBarrier inline void Atomic::MemoryBarrier() { #if defined(_AMD64_) ::__faststorefence(); #elif defined(_M_IX86) ::MemoryBarrier(); #elif defined(_M_ARM) __dmb(_ARM_BARRIER_SY); #else #error Not implemented; #endif } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/COM.cpp ================================================ #include "il2cpp-config.h" #include "object-internals.h" #include "os/COM.h" #include "WindowsHeaders.h" #if !IL2CPP_USE_GENERIC_COM namespace il2cpp { namespace os { il2cpp_hresult_t COM::CreateInstance(const Il2CppGuid& clsid, Il2CppIUnknown** object) { return ::CoCreateInstance(reinterpret_cast(clsid), NULL, CLSCTX_ALL, __uuidof(IUnknown), reinterpret_cast(object)); } il2cpp_hresult_t COM::CreateFreeThreadedMarshaler(Il2CppIUnknown* outer, Il2CppIUnknown** marshal) { return ::CoCreateFreeThreadedMarshaler(reinterpret_cast(outer), reinterpret_cast(marshal)); } } } #endif #if !IL2CPP_USE_GENERIC_COM_SAFEARRAYS namespace il2cpp { namespace os { // variant void COM::VariantInit(Il2CppVariant* variant) { ::VariantInit(reinterpret_cast(variant)); } il2cpp_hresult_t COM::VariantClear(Il2CppVariant* variant) { return ::VariantClear(reinterpret_cast(variant)); } // safe array Il2CppSafeArray* COM::SafeArrayCreate(uint16_t type, uint32_t dimention_count, Il2CppSafeArrayBound* bounds) { return reinterpret_cast(::SafeArrayCreate(type, dimention_count, reinterpret_cast(bounds))); } il2cpp_hresult_t COM::SafeArrayDestroy(Il2CppSafeArray* safeArray) { return ::SafeArrayDestroy(reinterpret_cast(safeArray)); } il2cpp_hresult_t COM::SafeArrayAccessData(Il2CppSafeArray* safeArray, void** data) { return ::SafeArrayAccessData(reinterpret_cast(safeArray), data); } il2cpp_hresult_t COM::SafeArrayUnaccessData(Il2CppSafeArray* safeArray) { return ::SafeArrayUnaccessData(reinterpret_cast(safeArray)); } il2cpp_hresult_t COM::SafeArrayGetVartype(Il2CppSafeArray* safeArray, uint16_t* type) { return ::SafeArrayGetVartype(reinterpret_cast(safeArray), type); } uint32_t COM::SafeArrayGetDim(Il2CppSafeArray* safeArray) { return ::SafeArrayGetDim(reinterpret_cast(safeArray)); } il2cpp_hresult_t COM::SafeArrayGetLBound(Il2CppSafeArray* safeArray, uint32_t dimention, int32_t* bound) { return ::SafeArrayGetLBound(reinterpret_cast(safeArray), dimention, reinterpret_cast(bound)); } il2cpp_hresult_t COM::SafeArrayGetUBound(Il2CppSafeArray* safeArray, uint32_t dimention, int32_t* bound) { return ::SafeArrayGetUBound(reinterpret_cast(safeArray), dimention, reinterpret_cast(bound)); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/ConditionVariableImpl.cpp ================================================ #include "il2cpp-config.h" #if NET_4_0 #if IL2CPP_THREADS_WIN32 #include "MutexImpl.h" #include "ConditionVariableImpl.h" #include "WindowsHelpers.h" namespace il2cpp { namespace os { ConditionVariableImpl::ConditionVariableImpl() { ::InitializeConditionVariable(&m_ConditionVariable); } ConditionVariableImpl::~ConditionVariableImpl() { /* Beauty of win32 API: do not destroy it */ } int ConditionVariableImpl::Wait(FastMutexImpl* lock) { return ::SleepConditionVariableCS(&m_ConditionVariable, lock->GetOSHandle(), INFINITE) ? 0 : 1; } int ConditionVariableImpl::TimedWait(FastMutexImpl* lock, uint32_t timeout_ms) { return ::SleepConditionVariableCS(&m_ConditionVariable, lock->GetOSHandle(), timeout_ms) ? 0 : 1; } void ConditionVariableImpl::Broadcast() { ::WakeAllConditionVariable(&m_ConditionVariable); } void ConditionVariableImpl::Signal() { ::WakeConditionVariable(&m_ConditionVariable); } } } #endif #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/ConditionVariableImpl.h ================================================ #pragma once #if NET_4_0 #if IL2CPP_THREADS_WIN32 #include "utils/NonCopyable.h" #include "WindowsHeaders.h" class FastMutexImpl; namespace il2cpp { namespace os { class ConditionVariableImpl : public il2cpp::utils::NonCopyable { public: ConditionVariableImpl(); ~ConditionVariableImpl(); int Wait(FastMutexImpl* lock); int TimedWait(FastMutexImpl* lock, uint32_t timeout_ms); void Broadcast(); void Signal(); private: CONDITION_VARIABLE m_ConditionVariable; }; } } #endif #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/Console.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINDOWS #include "os/Console.h" namespace il2cpp { namespace os { namespace Console { int32_t InternalKeyAvailable(int32_t ms_timeout) { NOT_IMPLEMENTED_ICALL(Console::InternalKeyAvailable); return 0; } bool SetBreak(bool wantBreak) { NOT_IMPLEMENTED_ICALL(Console::SetBreak); return false; } bool SetEcho(bool wantEcho) { NOT_IMPLEMENTED_ICALL(Console::SetEcho); return false; } bool TtySetup(const std::string& keypadXmit, const std::string& teardown, uint8_t* control_characters, int32_t** size) { NOT_IMPLEMENTED_ICALL(Console::TtySetup); return false; } } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/CpuInfo.cpp ================================================ #if NET_4_0 #if IL2CPP_ENABLE_CPU_INFO #include "il2cpp-config.h" #if IL2CPP_PLATFORM_WIN32 #include "os/CpuInfo.h" #include "utils/Memory.h" #define WIN32_LEAN_AND_MEAN 1 #include struct Il2CppCpuUsageState { uint64_t kernel_time; uint64_t user_time; uint64_t idle_time; }; namespace il2cpp { namespace os { void* CpuInfo::Create() { return IL2CPP_MALLOC_ZERO(sizeof(Il2CppCpuUsageState)); } int32_t CpuInfo::Usage(void* previous) { Il2CppCpuUsageState* prev = (Il2CppCpuUsageState*)previous; int32_t cpu_usage = 0; int64_t cpu_total_time; int64_t cpu_busy_time; uint64_t idle_time; uint64_t kernel_time; uint64_t user_time; ::GetSystemTimes((FILETIME*)&idle_time, (FILETIME*)&kernel_time, (FILETIME*)&user_time); cpu_total_time = (int64_t)((user_time - (prev ? prev->user_time : 0)) + (kernel_time - (prev ? prev->kernel_time : 0))); cpu_busy_time = (int64_t)(cpu_total_time - (idle_time - (prev ? prev->idle_time : 0))); if (prev) { prev->idle_time = idle_time; prev->kernel_time = kernel_time; prev->user_time = user_time; } if (cpu_total_time > 0 && cpu_busy_time > 0) cpu_usage = (int32_t)(cpu_busy_time * 100 / cpu_total_time); return cpu_usage; } } } #endif #endif #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/Cryptography.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINDOWS_DESKTOP #include "os/Win32/WindowsHeaders.h" #include "os/Cryptography.h" #include namespace il2cpp { namespace os { void* Cryptography::GetCryptographyProvider() { HCRYPTPROV provider = 0; if (!CryptAcquireContext(&provider, NULL, NULL, PROV_INTEL_SEC, CRYPT_VERIFYCONTEXT)) { if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { provider = 0; } } return (void*)provider; } bool Cryptography::OpenCryptographyProvider() { return false; } void Cryptography::ReleaseCryptographyProvider(void* provider) { CryptReleaseContext((HCRYPTPROV)provider, 0); } bool Cryptography::FillBufferWithRandomBytes(void* provider, uint32_t length, unsigned char* data) { return CryptGenRandom((HCRYPTPROV)provider, length, data) == TRUE; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/Debug.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINDOWS #include "os/Debug.h" #include "os/Win32/WindowsHeaders.h" namespace il2cpp { namespace os { bool Debug::IsDebuggerPresent() { return ::IsDebuggerPresent() != FALSE; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/Directory.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINDOWS #include "WindowsHeaders.h" #undef FindFirstFile #undef FindNextFile #include "os/Directory.h" #include "os/ErrorCodes.h" #include "utils/StringUtils.h" #include "utils/PathUtils.h" static inline int Win32ErrorToErrorCode(DWORD win32ErrorCode) { return win32ErrorCode; } using namespace il2cpp::utils::PathUtils; namespace il2cpp { namespace os { std::string Directory::GetCurrent(int *error) { UTF16String buf; int len, res_len; len = MAX_PATH + 1; buf.resize(len, 0); *error = ERROR_SUCCESS; res_len = ::GetCurrentDirectory(len, (LPWSTR)buf.c_str()); if (res_len > len) /*buf is too small.*/ { int old_res_len = res_len; buf.resize(res_len, 0); res_len = ::GetCurrentDirectory(res_len, (LPWSTR)buf.c_str()) == old_res_len; } std::string directory; if (res_len) { len = 0; while (buf[len]) ++len; directory = il2cpp::utils::StringUtils::Utf16ToUtf8(buf.c_str()); } else { *error = Win32ErrorToErrorCode(::GetLastError()); } return directory; } bool Directory::SetCurrent(const std::string& path, int* error) { *error = kErrorCodeSuccess; const UTF16String utf16Path(il2cpp::utils::StringUtils::Utf8ToUtf16(path.c_str())); if (::SetCurrentDirectory((LPWSTR)utf16Path.c_str())) return true; *error = Win32ErrorToErrorCode(::GetLastError()); return false; } bool Directory::Create(const std::string& path, int *error) { *error = kErrorCodeSuccess; const UTF16String utf16Path(il2cpp::utils::StringUtils::Utf8ToUtf16(path.c_str())); if (::CreateDirectory((LPWSTR)utf16Path.c_str(), NULL)) return true; *error = Win32ErrorToErrorCode(::GetLastError()); return false; } bool Directory::Remove(const std::string& path, int *error) { *error = kErrorCodeSuccess; const UTF16String utf16Path(il2cpp::utils::StringUtils::Utf8ToUtf16(path.c_str())); if (::RemoveDirectory((LPWSTR)utf16Path.c_str())) return true; *error = Win32ErrorToErrorCode(::GetLastError()); return false; } std::set Directory::GetFileSystemEntries(const std::string& path, const std::string& pathWithPattern, int32_t attrs, int32_t mask, int* error) { *error = kErrorCodeSuccess; std::set files; WIN32_FIND_DATA ffd; const UTF16String utf16Path(il2cpp::utils::StringUtils::Utf8ToUtf16(pathWithPattern.c_str())); HANDLE handle = ::FindFirstFileExW((LPCWSTR)utf16Path.c_str(), FindExInfoStandard, &ffd, FindExSearchNameMatch, NULL, 0); if (INVALID_HANDLE_VALUE == handle) { // Following the Mono implementation, do not treat a directory with no files as an error. int errorCode = Win32ErrorToErrorCode(::GetLastError()); if (errorCode != ERROR_FILE_NOT_FOUND) *error = errorCode; return files; } do { const std::string fileName(il2cpp::utils::StringUtils::Utf16ToUtf8(ffd.cFileName)); if ((fileName.length() == 1 && fileName.at(0) == '.') || (fileName.length() == 2 && fileName.at(0) == '.' && fileName.at(1) == '.')) continue; if ((ffd.dwFileAttributes & mask) == attrs) { files.insert(Combine(path, fileName)); } } while (::FindNextFileW(handle, &ffd) != 0); ::FindClose(handle); return files; } Directory::FindHandle::FindHandle(const utils::StringView& searchPathWithPattern) : osHandle(INVALID_HANDLE_VALUE), directoryPath(il2cpp::utils::PathUtils::DirectoryName(searchPathWithPattern)), pattern(il2cpp::utils::PathUtils::Basename(searchPathWithPattern)) { } Directory::FindHandle::~FindHandle() { IL2CPP_ASSERT(osHandle == INVALID_HANDLE_VALUE); } int32_t Directory::FindHandle::CloseOSHandle() { int32_t result = os::kErrorCodeSuccess; if (osHandle != INVALID_HANDLE_VALUE) { result = ::FindClose(osHandle); osHandle = INVALID_HANDLE_VALUE; } return result; } os::ErrorCode Directory::FindFirstFile(FindHandle* findHandle, const utils::StringView& searchPathWithPattern, Il2CppNativeString* resultFileName, int32_t* resultAttributes) { WIN32_FIND_DATA findData; HANDLE handle = FindFirstFileExW(searchPathWithPattern.Str(), FindExInfoStandard, &findData, FindExSearchNameMatch, NULL, 0); if (handle != INVALID_HANDLE_VALUE) { findHandle->SetOSHandle(handle); *resultFileName = findData.cFileName; *resultAttributes = findData.dwFileAttributes; return os::kErrorCodeSuccess; } else { return static_cast(GetLastError()); } } os::ErrorCode Directory::FindNextFile(FindHandle* findHandle, Il2CppNativeString* resultFileName, int32_t* resultAttributes) { WIN32_FIND_DATA findData; if (FindNextFileW(findHandle->osHandle, &findData) == FALSE) return static_cast(GetLastError()); *resultFileName = findData.cFileName; *resultAttributes = findData.dwFileAttributes; return os::kErrorCodeSuccess; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/Encoding.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINDOWS #include "WindowsHelpers.H" #include "os/Encoding.h" namespace il2cpp { namespace os { namespace Encoding { std::string GetCharSet() { static char buf[14]; sprintf(buf, "CP%u", GetACP()); return std::string(buf); } } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/Environment.cpp ================================================ #include "il2cpp-config.h" #if !IL2CPP_USE_GENERIC_ENVIRONMENT && IL2CPP_TARGET_WINDOWS #include "WindowsHelpers.h" #if !IL2CPP_TARGET_XBOXONE #include #endif // Windows.h defines GetEnvironmentVariable as GetEnvironmentVariableW for unicode and this will // change the string "Environment::GetEnvironmentVariable" below to "Environment::GetEnvironmentVariableW" // in the preprocessor. So we undef to avoid this issue and use GetEnvironmentVariableW directly. // Same for SetEnvironmentVariable #undef GetEnvironmentVariable #undef SetEnvironmentVariable #include "os/Environment.h" #include "utils/StringUtils.h" #include #include #define BUFFER_SIZE 1024 namespace il2cpp { namespace os { std::string Environment::GetMachineName() { Il2CppChar computerName[MAX_COMPUTERNAME_LENGTH + 1]; DWORD size = sizeof(computerName) / sizeof(computerName[0]); if (!GetComputerNameW(computerName, &size)) return NULL; return utils::StringUtils::Utf16ToUtf8(computerName); } int32_t Environment::GetProcessorCount() { SYSTEM_INFO info; GetSystemInfo(&info); return info.dwNumberOfProcessors; } // GetVersionEx is deprecated on desktop in Windows SDK, and we shim it for WinRT #pragma warning( push ) #pragma warning( disable : 4996 ) std::string Environment::GetOsVersionString() { OSVERSIONINFO verinfo; verinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (GetVersionEx(&verinfo)) { char version[64]; /* maximum string length is 35 bytes 3 x 10 bytes per number, 1 byte for 0, 3 x 1 byte for dots, 1 for NULL */ sprintf(version, "%ld.%ld.%ld.0", verinfo.dwMajorVersion, verinfo.dwMinorVersion, verinfo.dwBuildNumber); return version; } return "0.0.0.0"; } #pragma warning( pop ) std::string Environment::GetOsUserName() { Il2CppChar user_name[256 + 1]; DWORD user_name_size = ARRAYSIZE(user_name); if (GetUserNameW(user_name, &user_name_size)) return utils::StringUtils::Utf16ToUtf8(user_name); return "Unknown"; } std::string Environment::GetEnvironmentVariable(const std::string& name) { Il2CppChar buffer[BUFFER_SIZE]; const UTF16String varName = utils::StringUtils::Utf8ToUtf16(name.c_str()); DWORD ret = GetEnvironmentVariableW(varName.c_str(), buffer, BUFFER_SIZE); if (ret == 0) // Not found return std::string(); if (ret < BUFFER_SIZE) // Found and fits into buffer return utils::StringUtils::Utf16ToUtf8(buffer); // Requires bigger buffer IL2CPP_ASSERT(ret >= BUFFER_SIZE); Il2CppChar* bigbuffer = new Il2CppChar[ret + 1]; ret = GetEnvironmentVariableW(varName.c_str(), bigbuffer, ret + 1); IL2CPP_ASSERT(ret != 0); std::string variableValue(utils::StringUtils::Utf16ToUtf8(bigbuffer)); delete bigbuffer; return variableValue; } void Environment::SetEnvironmentVariable(const std::string& name, const std::string& value) { const UTF16String varName = utils::StringUtils::Utf8ToUtf16(name.c_str()); if (value.empty()) SetEnvironmentVariableW((LPWSTR)varName.c_str(), NULL); else { const UTF16String varValue = utils::StringUtils::Utf8ToUtf16(value.c_str()); SetEnvironmentVariableW((LPWSTR)varName.c_str(), (LPWSTR)varValue.c_str()); } } std::vector Environment::GetEnvironmentVariableNames() { WCHAR* env_strings; WCHAR* env_string; WCHAR* equal_str; std::vector result; env_strings = GetEnvironmentStringsW(); if (env_strings) { env_string = env_strings; while (*env_string != '\0') { // Skip over environment variables starting with '=' if (*env_string != '=') { equal_str = wcschr(env_string, '='); result.push_back(utils::StringUtils::Utf16ToUtf8(env_string, (int)(equal_str - env_string))); } while (*env_string != '\0') env_string++; env_string++; } FreeEnvironmentStringsW(env_strings); } return result; } std::string Environment::GetHomeDirectory() { NOT_IMPLEMENTED_ICALL(Environment::GetHomeDirectory); return std::string(); } std::vector Environment::GetLogicalDrives() { NOT_IMPLEMENTED_ICALL(Environment::GetLogicalDrives); return std::vector(); } void Environment::Exit(int result) { NOT_IMPLEMENTED_ICALL(Environment::Exit); } NORETURN void Environment::Abort() { // __fastfail() is available since VS2012 #if _MSC_VER >= 1700 __fastfail(FAST_FAIL_FATAL_APP_EXIT); #else abort(); #endif } #if IL2CPP_TARGET_WINDOWS_DESKTOP std::string Environment::GetWindowsFolderPath(int32_t folder) { Il2CppChar path[MAX_PATH]; if (SUCCEEDED(SHGetFolderPathW(NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) return utils::StringUtils::Utf16ToUtf8(path); return std::string(); } #if NET_4_0 typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); bool Environment::Is64BitOs() { BOOL isWow64Process = false; // Supported on XP SP2 and higher //IsWow64Process is not available on all supported versions of Windows. //Use GetModuleHandle to get a handle to the DLL that contains the function //and GetProcAddress to get a pointer to the function if available. LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress( GetModuleHandle(TEXT("kernel32")), "IsWow64Process"); if (NULL != fnIsWow64Process) { if (fnIsWow64Process(GetCurrentProcess(), &isWow64Process)) { return isWow64Process == TRUE; } } return false; } #endif #endif } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/EventImpl.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_THREADS_WIN32 #include "EventImpl.h" #include "WindowsHelpers.h" namespace il2cpp { namespace os { EventImpl::EventImpl(bool manualReset, bool signaled) { m_Event = ::CreateEvent(NULL, manualReset ? TRUE : FALSE, signaled ? TRUE : FALSE, NULL); IL2CPP_ASSERT(m_Event); } EventImpl::~EventImpl() { IL2CPP_ASSERT(m_Event); ::CloseHandle(m_Event); } ErrorCode EventImpl::Set() { if (::SetEvent(m_Event)) return kErrorCodeSuccess; return kErrorCodeGenFailure; } ErrorCode EventImpl::Reset() { if (::ResetEvent(m_Event)) return kErrorCodeSuccess; return kErrorCodeGenFailure; } WaitStatus EventImpl::Wait(bool interruptible) { return Wait(INFINITE, interruptible); } WaitStatus EventImpl::Wait(uint32_t ms, bool interruptible) { return il2cpp::os::win::WaitForSingleObjectAndAccountForAPCs(m_Event, ms, interruptible); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/EventImpl.h ================================================ #pragma once #if IL2CPP_THREADS_WIN32 #include "os/ErrorCodes.h" #include "os/WaitStatus.h" #include "utils/NonCopyable.h" #include "WindowsHeaders.h" namespace il2cpp { namespace os { class EventImpl : public il2cpp::utils::NonCopyable { public: EventImpl(bool manualReset = false, bool signaled = false); ~EventImpl(); ErrorCode Set(); ErrorCode Reset(); WaitStatus Wait(bool interruptible); WaitStatus Wait(uint32_t ms, bool interruptible); private: HANDLE m_Event; }; } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/File.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINDOWS #include "WindowsHelpers.h" #undef CopyFile #undef DeleteFile #undef MoveFile #undef ReplaceFile #undef GetFileAttributes #undef SetFileAttributes #undef CreatePipe #include "os/File.h" #include "vm/Exception.h" #include "utils/StringUtils.h" #include "utils/PathUtils.h" #include static inline int Win32ErrorToErrorCode(DWORD win32ErrorCode) { return win32ErrorCode; } namespace il2cpp { namespace os { #if IL2CPP_TARGET_WINDOWS_DESKTOP bool File::Isatty(FileHandle* fileHandle) { DWORD mode; return GetConsoleMode((HANDLE)fileHandle, &mode) != 0; } FileHandle* File::GetStdInput() { return (FileHandle*)GetStdHandle(STD_INPUT_HANDLE); } FileHandle* File::GetStdError() { return (FileHandle*)GetStdHandle(STD_ERROR_HANDLE); } FileHandle* File::GetStdOutput() { return (FileHandle*)GetStdHandle(STD_OUTPUT_HANDLE); } #endif bool File::CreatePipe(FileHandle** read_handle, FileHandle** write_handle) { int error; return CreatePipe(read_handle, write_handle, &error); } bool File::CreatePipe(FileHandle** read_handle, FileHandle** write_handle, int* error) { #if IL2CPP_TARGET_WINDOWS_DESKTOP SECURITY_ATTRIBUTES attr; attr.nLength = sizeof(SECURITY_ATTRIBUTES); attr.bInheritHandle = TRUE; attr.lpSecurityDescriptor = NULL; bool ret = ::CreatePipe((PHANDLE)read_handle, (PHANDLE)write_handle, &attr, 0); if (ret == FALSE) { *error = GetLastError(); /* FIXME: throw an exception? */ return false; } return true; #else vm::Exception::Raise(vm::Exception::GetNotSupportedException("Pipes are not supported on WinRT based platforms.")); #endif } #if !IL2CPP_TARGET_XBOXONE UnityPalFileAttributes File::GetFileAttributes(const std::string& path, int *error) { const UTF16String utf16Path(utils::StringUtils::Utf8ToUtf16(path.c_str())); WIN32_FILE_ATTRIBUTE_DATA fileAttributes; BOOL result = ::GetFileAttributesExW((LPCWSTR)utf16Path.c_str(), GetFileExInfoStandard, &fileAttributes); if (result == FALSE) { *error = Win32ErrorToErrorCode(::GetLastError()); return static_cast(INVALID_FILE_ATTRIBUTES); } *error = kErrorCodeSuccess; return static_cast(fileAttributes.dwFileAttributes); } #endif bool File::SetFileAttributes(const std::string& path, UnityPalFileAttributes attributes, int* error) { const UTF16String utf16Path(utils::StringUtils::Utf8ToUtf16(path.c_str())); *error = kErrorCodeSuccess; if (::SetFileAttributesW((LPCWSTR)utf16Path.c_str(), attributes)) return true; *error = Win32ErrorToErrorCode(::GetLastError()); return false; } static inline int64_t HighAndLowToInt64(uint32_t high, uint32_t low) { return ((uint64_t)high << 32) + low; } static inline int64_t FileTimeToInt64(const FILETIME& fileTime) { return HighAndLowToInt64(fileTime.dwHighDateTime, fileTime.dwLowDateTime); } bool File::GetFileStat(const std::string& path, il2cpp::os::FileStat * stat, int* error) { *error = kErrorCodeSuccess; const UTF16String utf16Path(utils::StringUtils::Utf8ToUtf16(path.c_str())); WIN32_FILE_ATTRIBUTE_DATA data; if (!::GetFileAttributesExW((LPCWSTR)utf16Path.c_str(), GetFileExInfoStandard, &data)) { *error = Win32ErrorToErrorCode(::GetLastError()); return false; } stat->name = il2cpp::utils::PathUtils::Basename(path); stat->attributes = data.dwFileAttributes; stat->creation_time = FileTimeToInt64(data.ftCreationTime); stat->last_access_time = FileTimeToInt64(data.ftLastAccessTime); stat->last_write_time = FileTimeToInt64(data.ftLastWriteTime); stat->length = HighAndLowToInt64(data.nFileSizeHigh, data.nFileSizeLow); return true; } FileType File::GetFileType(FileHandle* handle) { int result = ::GetFileType((HANDLE)handle); /*if (result == FILE_TYPE_UNKNOWN) { *error = GetLastError(); }*/ return (FileType)result; } bool File::CopyFile(const std::string& src, const std::string& dest, bool overwrite, int* error) { const UTF16String utf16Src(utils::StringUtils::Utf8ToUtf16(src.c_str())); const UTF16String utf16Dest(utils::StringUtils::Utf8ToUtf16(dest.c_str())); *error = kErrorCodeSuccess; if (::CopyFileW((LPWSTR)utf16Src.c_str(), (LPWSTR)utf16Dest.c_str(), overwrite ? FALSE : TRUE)) return true; *error = Win32ErrorToErrorCode(::GetLastError()); return false; } bool File::MoveFile(const std::string& src, const std::string& dest, int* error) { const UTF16String utf16Src(utils::StringUtils::Utf8ToUtf16(src.c_str())); const UTF16String utf16Dest(utils::StringUtils::Utf8ToUtf16(dest.c_str())); *error = kErrorCodeSuccess; if (::MoveFileExW((LPWSTR)utf16Src.c_str(), (LPWSTR)utf16Dest.c_str(), MOVEFILE_COPY_ALLOWED)) return true; *error = Win32ErrorToErrorCode(::GetLastError()); return false; } bool File::DeleteFile(const std::string& path, int *error) { *error = kErrorCodeSuccess; const UTF16String utf16Path(utils::StringUtils::Utf8ToUtf16(path.c_str())); if (::DeleteFileW((LPWSTR)utf16Path.c_str())) return true; *error = Win32ErrorToErrorCode(::GetLastError()); return false; } bool File::ReplaceFile(const std::string& sourceFileName, const std::string& destinationFileName, const std::string& destinationBackupFileName, bool ignoreMetadataErrors, int* error) { const UTF16String utf16Src(utils::StringUtils::Utf8ToUtf16(sourceFileName.c_str())); const UTF16String utf16Dest(utils::StringUtils::Utf8ToUtf16(destinationFileName.c_str())); const UTF16String utf16Backup(utils::StringUtils::Utf8ToUtf16(destinationBackupFileName.c_str())); *error = kErrorCodeSuccess; DWORD flags = REPLACEFILE_WRITE_THROUGH; if (ignoreMetadataErrors) flags |= REPLACEFILE_IGNORE_MERGE_ERRORS; if (::ReplaceFileW((LPWSTR)utf16Dest.c_str(), (LPWSTR)utf16Src.c_str(), utf16Backup.empty() ? NULL : (LPWSTR)utf16Backup.c_str(), flags, NULL, NULL)) return true; *error = Win32ErrorToErrorCode(::GetLastError()); return false; } static inline int MonoToWindowsOpenMode(int monoOpenMode) { switch (monoOpenMode) { case kFileModeCreateNew: return CREATE_NEW; case kFileModeCreate: return CREATE_ALWAYS; case kFileModeOpen: return OPEN_EXISTING; case kFileModeOpenOrCreate: case kFileModeAppend: return OPEN_ALWAYS; case kFileModeTruncate: return TRUNCATE_EXISTING; default: Assert(false && "Unknown mono open mode"); IL2CPP_UNREACHABLE; } } static inline int MonoToWindowsAccessMode(int monoAccessMode) { switch (monoAccessMode) { case kFileAccessRead: return GENERIC_READ; case kFileAccessWrite: return GENERIC_WRITE; case kFileAccessReadWrite: return GENERIC_READ | GENERIC_WRITE; default: return 0; } } static inline DWORD MonoOptionsToWindowsFlagsAndAttributes(const std::string& path, int options) { DWORD flagsAndAttributes; if (options & kFileOptionsEncrypted) { flagsAndAttributes = FILE_ATTRIBUTE_ENCRYPTED; } else { flagsAndAttributes = FILE_ATTRIBUTE_NORMAL; } // Temporary flag does not mean temporary file. flagsAndAttributes |= options & ~(kFileOptionsEncrypted | kFileOptionsTemporary); int error; UnityPalFileAttributes currentAttributes = File::GetFileAttributes(path, &error); if (currentAttributes != INVALID_FILE_ATTRIBUTES && (currentAttributes & FILE_ATTRIBUTE_DIRECTORY)) flagsAndAttributes |= FILE_FLAG_BACKUP_SEMANTICS; // Required to open a directory return flagsAndAttributes; } FileHandle* File::Open(const std::string& path, int openMode, int accessMode, int shareMode, int options, int *error) { const UTF16String utf16Path(utils::StringUtils::Utf8ToUtf16(path.c_str())); openMode = MonoToWindowsOpenMode(openMode); accessMode = MonoToWindowsAccessMode(accessMode); DWORD flagsAndAttributes = MonoOptionsToWindowsFlagsAndAttributes(path, options); HANDLE handle = ::CreateFileW((LPCWSTR)utf16Path.c_str(), accessMode, shareMode, NULL, openMode, flagsAndAttributes, NULL); if (INVALID_HANDLE_VALUE == handle) { *error = Win32ErrorToErrorCode(::GetLastError()); return (FileHandle*)INVALID_HANDLE_VALUE; } *error = kErrorCodeSuccess; return (FileHandle*)handle; } bool File::Close(FileHandle* handle, int *error) { *error = kErrorCodeSuccess; if (CloseHandle((HANDLE)handle)) return true; *error = Win32ErrorToErrorCode(::GetLastError()); return false; } bool File::SetFileTime(FileHandle* handle, int64_t creation_time, int64_t last_access_time, int64_t last_write_time, int* error) { FILE_BASIC_INFO fileInfo; fileInfo.CreationTime.QuadPart = creation_time; fileInfo.LastAccessTime.QuadPart = last_access_time; fileInfo.LastWriteTime.QuadPart = last_write_time; fileInfo.ChangeTime.QuadPart = 0; // 0 means don't change anything fileInfo.FileAttributes = 0; // 0 means don't change anything if (SetFileInformationByHandle(handle, FileBasicInfo, &fileInfo, sizeof(FILE_BASIC_INFO)) == FALSE) { *error = GetLastError(); return false; } *error = kErrorCodeSuccess; return true; } int64_t File::GetLength(FileHandle* handle, int *error) { *error = kErrorCodeSuccess; LARGE_INTEGER size; if (!::GetFileSizeEx((HANDLE)handle, &size)) { *error = Win32ErrorToErrorCode(::GetLastError()); return 0; } return size.QuadPart; } bool File::SetLength(FileHandle* handle, int64_t length, int *error) { *error = kErrorCodeSuccess; LARGE_INTEGER zeroOffset = { 0 }; LARGE_INTEGER requestedOffset = { 0 }; requestedOffset.QuadPart = length; LARGE_INTEGER initialPosition = { 0 }; // set position to 0 from current to retrieve current position if (!::SetFilePointerEx((HANDLE)handle, zeroOffset, &initialPosition, FILE_CURRENT)) { *error = Win32ErrorToErrorCode(::GetLastError()); return false; } // seek to requested length if (!::SetFilePointerEx((HANDLE)handle, requestedOffset, NULL, FILE_BEGIN)) { *error = Win32ErrorToErrorCode(::GetLastError()); return false; } // set requested length if (!::SetEndOfFile((HANDLE)handle)) { *error = Win32ErrorToErrorCode(::GetLastError()); return false; } // restore original position if (!::SetFilePointerEx((HANDLE)handle, initialPosition, NULL, FILE_BEGIN)) { *error = Win32ErrorToErrorCode(::GetLastError()); return false; } return true; } int64_t File::Seek(FileHandle* handle, int64_t offset, int origin, int *error) { *error = kErrorCodeSuccess; LARGE_INTEGER distance; distance.QuadPart = offset; LARGE_INTEGER position = { 0 }; if (!::SetFilePointerEx((HANDLE)handle, distance, &position, origin)) *error = Win32ErrorToErrorCode(::GetLastError()); return position.QuadPart; } int File::Read(FileHandle* handle, char *dest, int count, int *error) { *error = kErrorCodeSuccess; DWORD bytesRead = 0; if (!::ReadFile(handle, dest, count, &bytesRead, NULL)) *error = Win32ErrorToErrorCode(::GetLastError()); return bytesRead; } int32_t File::Write(FileHandle* handle, const char* buffer, int count, int *error) { int32_t result; int32_t written; result = WriteFile((HANDLE)handle, buffer, count, (LPDWORD)&written, NULL); /*if (!result) { *error = GetLastError (); return -1; }*/ return written; } bool File::Flush(FileHandle* handle, int* error) { *error = kErrorCodeSuccess; if (FlushFileBuffers((HANDLE)handle)) return true; *error = Win32ErrorToErrorCode(::GetLastError()); return false; } void File::Lock(FileHandle* handle, int64_t position, int64_t length, int* error) { *error = kErrorCodeSuccess; OVERLAPPED overlapped; ZeroMemory(&overlapped, sizeof(overlapped)); overlapped.Offset = position & 0xFFFFFFFF; overlapped.OffsetHigh = position >> 32; LARGE_INTEGER lengthUnion; lengthUnion.QuadPart = length; if (!::LockFileEx((HANDLE)handle, LOCKFILE_FAIL_IMMEDIATELY, 0, lengthUnion.LowPart, lengthUnion.HighPart, &overlapped)) *error = Win32ErrorToErrorCode(::GetLastError()); } void File::Unlock(FileHandle* handle, int64_t position, int64_t length, int* error) { *error = kErrorCodeSuccess; OVERLAPPED overlapped; ZeroMemory(&overlapped, sizeof(overlapped)); overlapped.Offset = position & 0xFFFFFFFF; overlapped.OffsetHigh = position >> 32; LARGE_INTEGER lengthUnion; lengthUnion.QuadPart = length; if (!::UnlockFileEx((HANDLE)handle, 0, lengthUnion.LowPart, lengthUnion.HighPart, &overlapped)) *error = Win32ErrorToErrorCode(::GetLastError()); } bool File::DuplicateHandle(FileHandle* source_process_handle, FileHandle* source_handle, FileHandle* target_process_handle, FileHandle** target_handle, int access, int inherit, int options, int* error) { /* This is only used on Windows */ //MONO_PREPARE_BLOCKING; BOOL ret = ::DuplicateHandle((HANDLE)source_process_handle, (HANDLE)source_handle, (HANDLE)target_process_handle, (LPHANDLE)target_handle, access, inherit, options); //MONO_FINISH_BLOCKING; if (ret == FALSE) { *error = GetLastError(); /* FIXME: throw an exception? */ return false; } return true; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/FileSystemWatcher.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINDOWS #include #include "os/FileSystemWatcher.h" namespace il2cpp { namespace os { namespace FileSystemWatcher { int IsSupported() { NOT_IMPLEMENTED_ICALL(FileSystemWatcher::IsSupported); return 0; } } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/Image.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINDOWS #include "WindowsHeaders.h" EXTERN_C IMAGE_DOS_HEADER __ImageBase; namespace il2cpp { namespace os { namespace Image { void* GetImageBase() { return &__ImageBase; } } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/Initialize.cpp ================================================ #include "il2cpp-config.h" #include "os/Initialize.h" #if IL2CPP_TARGET_WINDOWS #include "os/Environment.h" #include "os/WindowsRuntime.h" #include void il2cpp::os::Initialize() { #if _DEBUG std::string buildMachine = il2cpp::os::Environment::GetEnvironmentVariable("UNITY_THISISABUILDMACHINE"); if (!buildMachine.empty()) { _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT); } #endif // This is needed so we could extract exception text from bad hresults os::WindowsRuntime::EnableErrorReporting(); } #if !IL2CPP_TARGET_WINRT && !IL2CPP_TARGET_XBOXONE void il2cpp::os::Uninitialize() { } #endif #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/LastError.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINDOWS #include "os/LastError.h" #include "WindowsHeaders.h" namespace il2cpp { namespace os { uint32_t LastError::GetLastError() { return ::GetLastError(); } } /* namespace os */ } /* namespace il2cpp*/ #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/LibraryLoader.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINDOWS #include "metadata.h" #include "os/Mutex.h" #include "os/LibraryLoader.h" #include "os/Image.h" #include "vm/PlatformInvoke.h" #include "utils/StringUtils.h" #include #include "WindowsHelpers.h" namespace il2cpp { namespace os { static std::vector > s_NativeDllCache; typedef std::vector >::const_iterator DllCacheIterator; os::FastMutex s_NativeDllCacheMutex; #define HARDCODED_DEPENDENCY_LIBRARY(libraryName, libraryFunctions) { libraryName, ARRAYSIZE(libraryFunctions), libraryFunctions } #define HARDCODED_DEPENDENCY_FUNCTION(function) { #function, reinterpret_cast(function) } struct HardcodedPInvokeDependencyFunction { const char* functionName; Il2CppMethodPointer functionPointer; }; struct HardcodedPInvokeDependencyLibrary { const wchar_t* libraryName; size_t functionCount; const HardcodedPInvokeDependencyFunction* functions; }; const HardcodedPInvokeDependencyFunction kKernel32Functions[] = { HARDCODED_DEPENDENCY_FUNCTION(GetTimeZoneInformation), HARDCODED_DEPENDENCY_FUNCTION(GetDynamicTimeZoneInformation), }; #if !IL2CPP_TARGET_WINDOWS_DESKTOP const HardcodedPInvokeDependencyFunction kTimezoneFunctions[] = { #if !IL2CPP_TARGET_XBOXONE HARDCODED_DEPENDENCY_FUNCTION(EnumDynamicTimeZoneInformation), #endif HARDCODED_DEPENDENCY_FUNCTION(GetDynamicTimeZoneInformation), #if !IL2CPP_TARGET_XBOXONE HARDCODED_DEPENDENCY_FUNCTION(GetDynamicTimeZoneInformationEffectiveYears), #endif HARDCODED_DEPENDENCY_FUNCTION(GetTimeZoneInformationForYear), }; #endif #if IL2CPP_TARGET_WINRT const HardcodedPInvokeDependencyFunction kWinTypesFunctions[] = { HARDCODED_DEPENDENCY_FUNCTION(RoGetBufferMarshaler) }; #endif // All these come without ".dll" extension! const HardcodedPInvokeDependencyLibrary kHardcodedPInvokeDependencies[] = { #if !IL2CPP_TARGET_WINDOWS_DESKTOP // These functions are win7+ HARDCODED_DEPENDENCY_LIBRARY(L"api-ms-win-core-timezone-l1-1-0", kTimezoneFunctions), #endif HARDCODED_DEPENDENCY_LIBRARY(L"kernel32", kKernel32Functions), #if IL2CPP_TARGET_WINRT // Win8+, plus needs to be looked up dynamically on Xbox One HARDCODED_DEPENDENCY_LIBRARY(L"wintypes", kWinTypesFunctions), #endif }; inline static wchar_t AsciiToLower(wchar_t c) { if (c >= 'A' && c <= 'Z') return c - 'A' + 'a'; return c; } static bool DoesNativeDynamicLibraryNameMatch(const il2cpp::utils::StringView& desiredLibraryName, const wchar_t* hardcodedLibraryName) { size_t desiredLibraryNameLength = desiredLibraryName.Length(); for (size_t i = 0; i < desiredLibraryNameLength; i++) { wchar_t desiredCharacter = AsciiToLower(desiredLibraryName[i]); wchar_t hardcodedCharacter = hardcodedLibraryName[i]; // Assume hardcodedLibraryName consists of only lower case ascii characters IL2CPP_ASSERT(hardcodedCharacter < 128 && (hardcodedCharacter<'A' || hardcodedCharacter> 'Z')); if (desiredCharacter != hardcodedCharacter) { // If we've reached end of our hardcoded dll name, it can still match if we've // reached end of desiredLibraryName file name and only the extension is left return hardcodedCharacter == 0 && i + 4 == desiredLibraryNameLength && desiredLibraryName[i] == '.' && AsciiToLower(desiredLibraryName[i + 1]) == 'd' && AsciiToLower(desiredLibraryName[i + 2]) == 'l' && AsciiToLower(desiredLibraryName[i + 3]) == 'l'; } else if (hardcodedCharacter == 0) { // We've reached the end of hardcoded library name // It's a match if we're at the end of desired library name too return i + 1 == desiredLibraryNameLength; } } // We've reached the end of desired library name, // but not the end of hardcoded library name. // It is not a match. return false; } Il2CppMethodPointer LibraryLoader::GetHardcodedPInvokeDependencyFunctionPointer(const il2cpp::utils::StringView& nativeDynamicLibrary, const il2cpp::utils::StringView& entryPoint) { for (int i = 0; i < ARRAYSIZE(kHardcodedPInvokeDependencies); i++) { const HardcodedPInvokeDependencyLibrary& library = kHardcodedPInvokeDependencies[i]; if (DoesNativeDynamicLibraryNameMatch(nativeDynamicLibrary, library.libraryName)) { size_t functionCount = library.functionCount; for (size_t j = 0; j < functionCount; j++) { const HardcodedPInvokeDependencyFunction function = library.functions[j]; if (strncmp(function.functionName, entryPoint.Str(), entryPoint.Length()) == 0) return function.functionPointer; } // We assume that kHardcodedPInvokeDependencies will not contain duplicates return NULL; } } return NULL; } void* LibraryLoader::LoadDynamicLibrary(const utils::StringView& nativeDynamicLibrary) { if (nativeDynamicLibrary.IsEmpty()) return (HMODULE)Image::GetImageBase(); { os::FastAutoLock lock(&s_NativeDllCacheMutex); for (DllCacheIterator it = s_NativeDllCache.begin(); it != s_NativeDllCache.end(); it++) { if (it->first.compare(0, std::string::npos, nativeDynamicLibrary.Str(), nativeDynamicLibrary.Length()) == 0) return it->second; } } std::wstring dllName(nativeDynamicLibrary.Str(), nativeDynamicLibrary.Length()); HMODULE module = ::LoadLibraryW(dllName.c_str()); if (module != NULL) { os::FastAutoLock lock(&s_NativeDllCacheMutex); s_NativeDllCache.push_back(std::make_pair(std::move(dllName), module)); } return module; } Il2CppMethodPointer LibraryLoader::GetFunctionPointer(void* dynamicLibrary, const PInvokeArguments& pinvokeArgs) { if (dynamicLibrary == NULL) return NULL; HMODULE module = (HMODULE)dynamicLibrary; StringViewAsNullTerminatedStringOf(char, pinvokeArgs.entryPoint, entryPoint); // If there's 'no mangle' flag set, just return directly what GetProcAddress returns if (pinvokeArgs.isNoMangle) return reinterpret_cast(GetProcAddress(module, entryPoint)); const size_t kBufferOverhead = 10; FARPROC functionPtr = NULL; size_t originalFuncNameLength = strlen(entryPoint) + 1; std::string functionName; functionName.resize(originalFuncNameLength + kBufferOverhead + 1); // Let's index the string from '1', because we might have to prepend an underscore in case of stdcall mangling memcpy(&functionName[1], entryPoint, originalFuncNameLength); ZeroMemory(&functionName[1] + originalFuncNameLength, kBufferOverhead); // If there's no 'dont mangle' flag set, 'W' function takes priority over original name, but 'A' function does not (yes, really) if (pinvokeArgs.charSet == CHARSET_UNICODE) { functionName[originalFuncNameLength] = 'W'; functionPtr = GetProcAddress(module, functionName.c_str() + 1); if (functionPtr != NULL) return reinterpret_cast(functionPtr); // If charset specific function lookup failed, try with original name functionPtr = GetProcAddress(module, entryPoint); } else { functionPtr = GetProcAddress(module, entryPoint); if (functionPtr != NULL) return reinterpret_cast(functionPtr); // If original name function lookup failed, try with mangled name functionName[originalFuncNameLength] = 'A'; functionPtr = GetProcAddress(module, functionName.c_str() + 1); } if (functionPtr != NULL) return reinterpret_cast(functionPtr); // If it's not cdecl, try mangling the name // THIS ONLY APPLIES TO 32-bit x86! #if !defined(__arm__) if (sizeof(void*) == 4 && pinvokeArgs.callingConvention != IL2CPP_CALL_C) { functionName[0] = '_'; sprintf(&functionName[0] + originalFuncNameLength, "@%ld", pinvokeArgs.parameterSize); functionPtr = GetProcAddress(module, functionName.c_str()); } #endif return reinterpret_cast(functionPtr); } Il2CppMethodPointer LibraryLoader::GetFunctionPointer(void* dynamicLibrary, const char* functionName) { return reinterpret_cast(GetProcAddress(static_cast(dynamicLibrary), functionName)); } void LibraryLoader::CleanupLoadedLibraries() { for (DllCacheIterator it = s_NativeDllCache.begin(); it != s_NativeDllCache.end(); it++) { FreeLibrary(it->second); } } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/Locale.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINDOWS #include "os/Locale.h" #include "WindowsHelpers.h" #include namespace il2cpp { namespace os { #if IL2CPP_TARGET_WINDOWS_DESKTOP std::string Locale::GetLocale() { LCID lcid = GetThreadLocale(); int number_of_characters = GetLocaleInfo(lcid, LOCALE_SNAME, NULL, 0); std::vector locale_name(number_of_characters); if (GetLocaleInfo(lcid, LOCALE_SNAME, &locale_name[0], number_of_characters) == 0) return std::string(); std::vector locale_name_char(number_of_characters); if (WideCharToMultiByte(CP_ACP, 0, &locale_name[0], number_of_characters, &locale_name_char[0], number_of_characters, NULL, NULL) == 0) return std::string(); return std::string(locale_name_char.begin(), locale_name_char.end()); } #endif #if IL2CPP_SUPPORT_LOCALE_INDEPENDENT_PARSING static _locale_t s_cLocale = NULL; #endif void Locale::Initialize() { #if IL2CPP_SUPPORT_LOCALE_INDEPENDENT_PARSING s_cLocale = _create_locale(LC_ALL, "C"); #endif } void Locale::UnInitialize() { #if IL2CPP_SUPPORT_LOCALE_INDEPENDENT_PARSING _free_locale(s_cLocale); s_cLocale = NULL; #endif } #if IL2CPP_SUPPORT_LOCALE_INDEPENDENT_PARSING double Locale::DoubleParseLocaleIndependentImpl(char *ptr, char** endptr) { return _strtod_l(ptr, endptr, s_cLocale); } #endif } /* namespace os */ } /* namespace il2cpp */ #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/MarshalAlloc.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINDOWS #include "os/MarshalAlloc.h" #include "WindowsHeaders.h" #include "Objbase.h" namespace il2cpp { namespace os { void* MarshalAlloc::Allocate(size_t size) { return ::CoTaskMemAlloc(size); } void* MarshalAlloc::ReAlloc(void* ptr, size_t size) { return ::CoTaskMemRealloc(ptr, size); } void MarshalAlloc::Free(void* ptr) { ::CoTaskMemFree(ptr); } } /* namespace os */ } /* namespace il2cpp*/ #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/MarshalStringAlloc.cpp ================================================ #include "il2cpp-config.h" #if !IL2CPP_USE_GENERIC_COM #include "os/MarshalStringAlloc.h" #include "WindowsHeaders.h" namespace il2cpp { namespace os { il2cpp_hresult_t MarshalStringAlloc::AllocateBStringLength(const Il2CppChar* text, int32_t length, Il2CppChar** bstr) { IL2CPP_ASSERT(bstr); *bstr = ::SysAllocStringLen(text, length); return *bstr ? IL2CPP_S_OK : IL2CPP_E_OUTOFMEMORY; } il2cpp_hresult_t MarshalStringAlloc::GetBStringLength(const Il2CppChar* bstr, int32_t* length) { IL2CPP_ASSERT(length); *length = ::SysStringLen((BSTR)bstr); return IL2CPP_S_OK; } il2cpp_hresult_t MarshalStringAlloc::FreeBString(Il2CppChar* bstr) { ::SysFreeString((BSTR)bstr); return IL2CPP_S_OK; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/Memory.cpp ================================================ #include "il2cpp-config.h" #include "os/Memory.h" #if IL2CPP_TARGET_WINDOWS namespace il2cpp { namespace os { namespace Memory { void* AlignedAlloc(size_t size, size_t alignment) { return _aligned_malloc(size, alignment); } void* AlignedReAlloc(void* memory, size_t newSize, size_t alignment) { return _aligned_realloc(memory, newSize, alignment); } void AlignedFree(void* memory) { return _aligned_free(memory); } } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/MemoryMappedFile.cpp ================================================ #include "il2cpp-config.h" #if !IL2CPP_USE_GENERIC_MEMORY_MAPPED_FILE && IL2CPP_TARGET_WINDOWS #include #include "WindowsHelpers.h" #include "os/MemoryMappedFile.h" #include "os/Mutex.h" #include namespace il2cpp { namespace os { static FastMutex s_Mutex; static std::map s_MappedAddressToMappedFileObject; void* MemoryMappedFile::Map(FileHandle* file, size_t length, size_t offset) { os::FastAutoLock lock(&s_Mutex); HANDLE mappedFile = CreateFileMapping((HANDLE)file, NULL, PAGE_READONLY, 0, 0, NULL); if (mappedFile == NULL) return NULL; IL2CPP_ASSERT(offset <= std::numeric_limits::max()); IL2CPP_ASSERT(length <= std::numeric_limits::max()); void* address = MapViewOfFile(mappedFile, FILE_MAP_READ, 0, static_cast(offset), static_cast(length)); if (address == NULL) { DWORD error = GetLastError(); CloseHandle(mappedFile); return NULL; } s_MappedAddressToMappedFileObject[address] = mappedFile; return address; } void MemoryMappedFile::Unmap(void* address, size_t length) { if (address != NULL) { os::FastAutoLock lock(&s_Mutex); BOOL error = UnmapViewOfFile(address); IL2CPP_ASSERT(error != 0); (void)error; // Avoid an unused variable warning std::map::iterator entry = s_MappedAddressToMappedFileObject.find(address); if (entry != s_MappedAddressToMappedFileObject.end()) { error = CloseHandle(entry->second); IL2CPP_ASSERT(error != 0); } } } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/MutexImpl.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_THREADS_WIN32 #include "MutexImpl.h" #include "WindowsHelpers.h" // Can't use critical sections as they don't allow for interruption by APCs. namespace il2cpp { namespace os { MutexImpl::MutexImpl() { #if IL2CPP_THREADS_ALL_ACCESS m_MutexHandle = ::CreateMutexEx(NULL, NULL, 0, MUTEX_ALL_ACCESS); #else m_MutexHandle = ::CreateMutex(NULL, FALSE, NULL); #endif IL2CPP_ASSERT(m_MutexHandle); } MutexImpl::~MutexImpl() { IL2CPP_ASSERT(m_MutexHandle); ::CloseHandle(m_MutexHandle); } void MutexImpl::Lock(bool interruptible) { TryLock(INFINITE, interruptible); } bool MutexImpl::TryLock(uint32_t milliseconds, bool interruptible) { return (il2cpp::os::win::WaitForSingleObjectAndAccountForAPCs(m_MutexHandle, milliseconds, interruptible) == kWaitStatusSuccess); } void MutexImpl::Unlock() { ReleaseMutex(m_MutexHandle); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/MutexImpl.h ================================================ #pragma once #if IL2CPP_THREADS_WIN32 #include "os/ErrorCodes.h" #include "os/WaitStatus.h" #include "utils/NonCopyable.h" #include "WindowsHeaders.h" namespace il2cpp { namespace os { class MutexImpl : public il2cpp::utils::NonCopyable { public: MutexImpl(); ~MutexImpl(); void Lock(bool interruptible); bool TryLock(uint32_t milliseconds, bool interruptible); void Unlock(); private: HANDLE m_MutexHandle; }; class FastMutexImpl { public: FastMutexImpl() { InitializeCriticalSection(&m_CritialSection); } ~FastMutexImpl() { DeleteCriticalSection(&m_CritialSection); } void Lock() { EnterCriticalSection(&m_CritialSection); } void Unlock() { LeaveCriticalSection(&m_CritialSection); } CRITICAL_SECTION* GetOSHandle() { return &m_CritialSection; } private: CRITICAL_SECTION m_CritialSection; }; } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/NativeMethods.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINDOWS #include "WindowsHelpers.h" #include "os/NativeMethods.h" #include "vm/Exception.h" namespace il2cpp { namespace os { bool NativeMethods::CloseProcess(ProcessHandle* handle) { return ::CloseHandle(handle) != FALSE; } bool NativeMethods::GetExitCodeProcess(ProcessHandle* handle, int32_t* exitCode) { #if IL2CPP_TARGET_WINDOWS_DESKTOP return ::GetExitCodeProcess((HANDLE)handle, (LPDWORD)exitCode); #else vm::Exception::Raise(vm::Exception::GetNotSupportedException("Getting process exit code is not supported on WinRT based platforms.")); #endif } int32_t NativeMethods::GetCurrentProcessId() { return ::GetCurrentProcessId(); } ProcessHandle* NativeMethods::GetCurrentProcess() { return (ProcessHandle*)::GetCurrentProcess(); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/Path.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINDOWS #include "WindowsHeaders.h" #undef GetTempPath #include "os/Environment.h" #include "os/Path.h" #include "utils/StringUtils.h" #include "WindowsHelpers.h" #include namespace il2cpp { namespace os { std::string Path::GetExecutablePath() { wchar_t buffer[MAX_PATH]; GetModuleFileNameW(NULL, buffer, MAX_PATH); return utils::StringUtils::Utf16ToUtf8(buffer); } std::string Path::GetTempPath() { WCHAR tempPath[MAX_PATH + 1]; ::GetTempPathW(sizeof(tempPath) / sizeof(tempPath[0]), tempPath); ::GetLongPathNameW(tempPath, tempPath, sizeof(tempPath) / sizeof(tempPath[0])); return utils::StringUtils::Utf16ToUtf8(tempPath); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/Process.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINDOWS_DESKTOP #include "WindowsHelpers.h" #include #include "os/Process.h" struct ProcessHandle { HANDLE handle; }; namespace il2cpp { namespace os { int Process::GetCurrentProcessId() { return ::GetCurrentProcessId(); } ProcessHandle* Process::GetProcess(int processId) { return (ProcessHandle*)OpenProcess(PROCESS_ALL_ACCESS, TRUE, processId); } void Process::FreeProcess(ProcessHandle* handle) { ::CloseHandle((HANDLE)handle); } std::string Process::GetProcessName(ProcessHandle* handle) { const size_t bufferLength = 256; WCHAR buf[bufferLength]; DWORD length = ::GetProcessImageFileName((HANDLE)handle, buf, bufferLength); if (length == 0) return std::string(); char multiByteStr[bufferLength]; size_t numConverted = wcstombs(multiByteStr, buf, bufferLength); if (numConverted <= 0) return std::string(); return std::string(multiByteStr, numConverted); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/SemaphoreImpl.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_THREADS_WIN32 #include "SemaphoreImpl.h" #include "WindowsHelpers.h" namespace il2cpp { namespace os { SemaphoreImpl::SemaphoreImpl(int32_t initialValue, int32_t maximumValue) { #if IL2CPP_THREADS_ALL_ACCESS m_Handle = ::CreateSemaphoreEx(NULL, initialValue, maximumValue, NULL, 0, SEMAPHORE_ALL_ACCESS); #else m_Handle = ::CreateSemaphore(NULL, initialValue, maximumValue, NULL); #endif IL2CPP_ASSERT(m_Handle); } SemaphoreImpl::~SemaphoreImpl() { IL2CPP_ASSERT(m_Handle); ::CloseHandle(m_Handle); } bool SemaphoreImpl::Post(int32_t releaseCount, int32_t* previousCount) { return ::ReleaseSemaphore(m_Handle, releaseCount, reinterpret_cast(previousCount)) != 0; } WaitStatus SemaphoreImpl::Wait(bool interruptible) { return Wait(INFINITE, interruptible); } WaitStatus SemaphoreImpl::Wait(uint32_t ms, bool interruptible) { return il2cpp::os::win::WaitForSingleObjectAndAccountForAPCs(m_Handle, ms, interruptible); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/SemaphoreImpl.h ================================================ #pragma once #if IL2CPP_THREADS_WIN32 #include "os/ErrorCodes.h" #include "os/WaitStatus.h" #include "utils/NonCopyable.h" #include "WindowsHeaders.h" namespace il2cpp { namespace os { class SemaphoreImpl : public il2cpp::utils::NonCopyable { public: SemaphoreImpl(int32_t initialValue, int32_t maximumValue); ~SemaphoreImpl(); bool Post(int32_t releaseCount, int32_t* previousCount = NULL); WaitStatus Wait(bool interruptible); WaitStatus Wait(uint32_t ms, bool interruptible); private: HANDLE m_Handle; }; } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/SocketImpl.cpp ================================================ #include "il2cpp-config.h" #if !IL2CPP_USE_GENERIC_SOCKET_IMPL && IL2CPP_TARGET_WINDOWS #include #include #include #include #include #include "WindowsHelpers.h" #include #include #if !IL2CPP_TARGET_XBOXONE #include #endif #include "os/Error.h" #include "os/Socket.h" #include "os/ErrorCodes.h" #include "os/Win32/SocketImpl.h" #include "utils/StringUtils.h" #include "il2cpp-vm-support.h" typedef int socklen_t; namespace il2cpp { namespace os { static bool is_loopback(int32_t family, uint8_t *addr) { return ((family) == AF_INET ? ((addr)[0] == 127) : false); } static struct in_addr *get_local_ips(int32_t family, int32_t *nips) { *nips = 0; return 0; } static bool hostent_get_info(struct hostent *he, std::string &name, std::vector &aliases, std::vector &addr_list) { if (he == NULL) return false; if (he->h_length != 4 || he->h_addrtype != AF_INET) return false; name.assign(he->h_name); for (int32_t i = 0; he->h_aliases[i] != NULL; ++i) aliases.push_back(he->h_aliases[i]); if (he->h_addrtype == AF_INET) { struct in_addr addr = {0}; for (int32_t i = 0; he->h_addr_list[i] != NULL; ++i) { addr.s_addr = *(u_long*)he->h_addr_list[i]; addr_list.push_back(inet_ntoa(addr)); } } // TODO(gab): add support for IPv6 //else if(he->h_addrtype == AF_INET6) return true; } static bool hostent_get_info_with_local_ips(struct hostent *he, std::string &name, std::vector &aliases, std::vector &addr_list) { int32_t i = 0; int32_t nlocal_in = 0; if (he != NULL) { if (he->h_length != 4 || he->h_addrtype != AF_INET) return false; name.assign(he->h_name); for (int32_t i = 0; he->h_aliases[i] != NULL; ++i) aliases.push_back(he->h_aliases[i]); } struct in_addr *local_in = get_local_ips(AF_INET, &nlocal_in); if (nlocal_in) { for (int32_t i = 0; i < nlocal_in; ++i) addr_list.push_back(inet_ntoa(local_in[i])); free(local_in); } else if (he == NULL) { // If requesting "" and there are no other interfaces up, MS returns 127.0.0.1 addr_list.push_back("127.0.0.1"); return true; } if (nlocal_in == 0 && he != NULL) { if (he->h_addrtype == AF_INET) { struct in_addr addr = {0}; for (int32_t i = 0; he->h_addr_list[i] != NULL; ++i) { addr.s_addr = *(u_long*)he->h_addr_list[i]; addr_list.push_back(inet_ntoa(addr)); } } // TODO(gab): add support for IPv6 //else if(he->h_addrtype == AF_INET6) } return true; } static int32_t convert_socket_flags(os::SocketFlags flags) { int32_t c_flags = 0; if (flags) { // Check if contains invalid flag values if (flags & ~(os::kSocketFlagsOutOfBand | os::kSocketFlagsMaxIOVectorLength | os::kSocketFlagsPeek | os::kSocketFlagsDontRoute | os::kSocketFlagsPartial)) { return -1; } if (flags & os::kSocketFlagsOutOfBand) c_flags |= MSG_OOB; if (flags & os::kSocketFlagsPeek) c_flags |= MSG_PEEK; if (flags & os::kSocketFlagsDontRoute) c_flags |= MSG_DONTROUTE; // Ignore Partial - see bug 349688. Don't return -1, because // according to the comment in that bug ms runtime doesn't for // UDP sockets (this means we will silently ignore it for TCP // too) #ifdef MSG_MORE if (flags & os::kSocketFlagsPartial) c_flags |= MSG_MORE; #endif } return c_flags; } WaitStatus SocketImpl::GetHostByAddr(const std::string &address, std::string &name, std::vector &aliases, std::vector &addr_list) { struct in_addr inaddr; if (inet_pton(AF_INET, address.c_str(), &inaddr) <= 0) return kWaitStatusFailure; struct hostent *he = gethostbyaddr((char*)&inaddr, sizeof(inaddr), AF_INET); if (he == NULL) { name = address; addr_list.push_back(name); return kWaitStatusSuccess; } return hostent_get_info(he, name, aliases, addr_list) ? kWaitStatusSuccess : kWaitStatusFailure; } WaitStatus SocketImpl::GetHostByName(const std::string &host, std::string &name, std::vector &aliases, std::vector &addr_list) { char this_hostname[256] = {0}; const char *hostname = host.c_str(); bool add_local_ips = (*hostname == '\0'); if (!add_local_ips && gethostname(this_hostname, sizeof(this_hostname)) != -1) { if (!strcmp(hostname, this_hostname)) add_local_ips = true; } struct hostent *he = NULL; if (*hostname) he = gethostbyname(hostname); if (*hostname && he == NULL) return kWaitStatusFailure; return (add_local_ips ? hostent_get_info_with_local_ips(he, name, aliases, addr_list) : hostent_get_info(he, name, aliases, addr_list)) ? kWaitStatusSuccess : kWaitStatusFailure; } void SocketImpl::Startup() { WSADATA wsadata; const int32_t ret = WSAStartup(MAKEWORD(2, 0), &wsadata); if (ret != 0) { exit(-1); } } void SocketImpl::Cleanup() { WSACleanup(); } WaitStatus SocketImpl::GetHostName(std::string &name) { char hostname[256]; int32_t ret = gethostname(hostname, sizeof(hostname)); if (ret == -1) return kWaitStatusFailure; name.assign(hostname); return kWaitStatusSuccess; } SocketImpl::SocketImpl(ThreadStatusCallback thread_status_callback) : _is_valid(false) , _fd(-1) , _domain(-1) , _type(-1) , _protocol(-1) , _saved_error(kErrorCodeSuccess) , _still_readable(0) , _thread_status_callback(thread_status_callback) { } SocketImpl::~SocketImpl() { } static int32_t convert_address_family(AddressFamily family) { switch (family) { case kAddressFamilyUnspecified: return AF_UNSPEC; // NOTE(gab): not supported on Windows //case kAddressFamilyUnix: // return AF_UNIX; case kAddressFamilyInterNetwork: return AF_INET; case kAddressFamilyIpx: return AF_IPX; case kAddressFamilySna: return AF_SNA; case kAddressFamilyDecNet: return AF_DECnet; case kAddressFamilyAppleTalk: return AF_APPLETALK; case kAddressFamilyInterNetworkV6: return AF_INET6; #ifdef AF_IRDA case kAddressFamilyIrda: return AF_IRDA; #endif default: break; } return -1; } static int32_t convert_socket_type(SocketType type) { switch (type) { case kSocketTypeStream: return SOCK_STREAM; case kSocketTypeDgram: return SOCK_DGRAM; case kSocketTypeRaw: return SOCK_RAW; case kSocketTypeRdm: return SOCK_RDM; case kSocketTypeSeqpacket: return SOCK_SEQPACKET; default: break; } return -1; } static int32_t convert_socket_protocol(ProtocolType protocol) { switch (protocol) { case kProtocolTypeIP: case kProtocolTypeIPv6: case kProtocolTypeIcmp: case kProtocolTypeIgmp: case kProtocolTypeGgp: case kProtocolTypeTcp: case kProtocolTypePup: case kProtocolTypeUdp: case kProtocolTypeIdp: // In this case the enum values map exactly. return (int32_t)protocol; default: break; } // Everything else in unsupported and unexpected return -1; } static int SocketExceptionFilter(unsigned int code) { // Sometimes, we call the socket functions and close the socket right after, // and in some rare cases, it throws EXCEPTION_INVALID_HANDLE SEH exception // rather than returning an error code. Although this is undocumented on MSDN, // it causes a crash just because it thinks we gave it an invalid handle. // We guard against it by wrapping every socket call with __try/__except if (code == EXCEPTION_INVALID_HANDLE) return EXCEPTION_CONTINUE_EXECUTION; return EXCEPTION_CONTINUE_SEARCH; } WaitStatus SocketImpl::Create(AddressFamily family, SocketType type, ProtocolType protocol) { _fd = -1; _is_valid = false; _still_readable = 1; _domain = convert_address_family(family); _type = convert_socket_type(type); _protocol = convert_socket_protocol(protocol); IL2CPP_ASSERT(_type != -1 && "Unsupported socket type"); IL2CPP_ASSERT(_domain != -1 && "Unsupported address family"); IL2CPP_ASSERT(_protocol != -1 && "Unsupported protocol type"); _fd = socket(_domain, _type, _protocol); if (_fd == -1 && _domain == AF_INET && _type == SOCK_RAW && _protocol == 0) { // Retry with protocol == 4 (see bug #54565) _protocol = 4; _fd = socket(AF_INET, SOCK_RAW, 4); } if (_fd == -1) { StoreLastError(); return kWaitStatusFailure; } // if (fd >= _wapi_fd_reserve) // { // WSASetLastError (WSASYSCALLFAILURE); // closesocket (fd); // return(INVALID_SOCKET); // } /* .net seems to set this by default for SOCK_STREAM, not for * SOCK_DGRAM (see bug #36322) * * It seems winsock has a rather different idea of what * SO_REUSEADDR means. If it's set, then a new socket can be * bound over an existing listening socket. There's a new * windows-specific option called SO_EXCLUSIVEADDRUSE but * using that means the socket MUST be closed properly, or a * denial of service can occur. Luckily for us, winsock * behaves as though any other system would when SO_REUSEADDR * is true, so we don't need to do anything else here. See * bug 53992. */ { int32_t v = 1; const int32_t ret = setsockopt((SOCKET)_fd, SOL_SOCKET, SO_REUSEADDR, (char*)&v, sizeof(v)); if (ret == -1) { if (closesocket((SOCKET)_fd) == -1) StoreLastError(); return kWaitStatusFailure; } } // mono_once (&socket_ops_once, socket_ops_init); // handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle); // if (handle == _WAPI_HANDLE_INVALID) { // g_warning ("%s: error creating socket handle", __func__); // WSASetLastError (WSASYSCALLFAILURE); // closesocket (fd); // return(INVALID_SOCKET); // } _is_valid = true; return kWaitStatusSuccess; } WaitStatus SocketImpl::Create(SocketDescriptor fd, int32_t family, int32_t type, int32_t protocol) { _fd = fd; _is_valid = (fd != -1); _still_readable = 1; _domain = family; _type = type; _protocol = protocol; IL2CPP_ASSERT(_type != -1 && "Unsupported socket type"); IL2CPP_ASSERT(_domain != -1 && "Unsupported address family"); IL2CPP_ASSERT(_protocol != -1 && "Unsupported protocol type"); return kWaitStatusSuccess; } WaitStatus SocketImpl::Close() { _saved_error = kErrorCodeSuccess; SOCKET fd = (SOCKET)_fd; if (_is_valid && fd != -1) { if (closesocket(fd) == -1) StoreLastError(); } _fd = -1; _is_valid = false; _still_readable = 0; _domain = -1; _type = -1; _protocol = -1; return kWaitStatusSuccess; } WaitStatus SocketImpl::SetBlocking(bool blocking) { /* * block == TRUE/FALSE means we will block/not block. * But the ioctlsocket call takes TRUE/FALSE for non-block/block */ u_long ioctl_socket_blocking = (u_long) !blocking; SOCKET fd = (SOCKET)_fd; if (fd == -1) { Error::SetLastError(il2cpp::os::kWSAeshutdown); return kWaitStatusFailure; } int32_t ret = -1; __try { ret = ioctlsocket(fd, FIONBIO, &ioctl_socket_blocking); } __except (SocketExceptionFilter(GetExceptionCode())) { } if (ret == SOCKET_ERROR) { StoreLastError(); return kWaitStatusFailure; } return kWaitStatusSuccess; } ErrorCode SocketImpl::GetLastError() const { return _saved_error; } void SocketImpl::StoreLastError() { const ErrorCode error = (ErrorCode)WSAGetLastError(); Error::SetLastError(error); _saved_error = error; } void SocketImpl::StoreLastError(int32_t error_no) { const ErrorCode error = (ErrorCode)error_no; Error::SetLastError(error); _saved_error = error; } static void sockaddr_from_address(uint32_t address, uint16_t port, struct sockaddr *sa, socklen_t *sa_size) { struct sockaddr_in sa_in = {0}; sa_in.sin_family = AF_INET; sa_in.sin_port = port; sa_in.sin_addr.s_addr = address; *sa_size = sizeof(struct sockaddr_in); *sa = *((struct sockaddr*)&sa_in); } static bool socketaddr_to_endpoint_info(const struct sockaddr *address, socklen_t address_len, EndPointInfo &info) { info.family = (os::AddressFamily)address->sa_family; if (info.family == os::kAddressFamilyInterNetwork) { const struct sockaddr_in *address_in = (const struct sockaddr_in *)address; info.data.inet.port = ntohs(address_in->sin_port); info.data.inet.address = ntohl(address_in->sin_addr.s_addr); return true; } // NOTE(gab): kAddressFamilyUnix not supported on Windows //if (info.family == os::kAddressFamilyUnix) //{ // for (int32_t i = 0; i < address_len; i++) // info.data.path[i] = address->sa_data[i]; // return true; //} return false; } WaitStatus SocketImpl::Bind(const char *path) { // NOTE(gab): not supported on Windows. return kWaitStatusFailure; } WaitStatus SocketImpl::Bind(const char *address, uint16_t port) { struct sockaddr sa = {0}; socklen_t sa_size = 0; sockaddr_from_address(inet_addr(address), htons(port), &sa, &sa_size); SOCKET fd = (SOCKET)_fd; if (fd == -1) { Error::SetLastError(il2cpp::os::kWSAeshutdown); return kWaitStatusFailure; } int bindResult = -1; __try { bindResult = bind(fd, &sa, sa_size); } __except (SocketExceptionFilter(GetExceptionCode())) { } if (bindResult == -1) { StoreLastError(); return kWaitStatusFailure; } return kWaitStatusSuccess; } WaitStatus SocketImpl::Bind(uint32_t address, uint16_t port) { struct sockaddr sa = {0}; socklen_t sa_size = 0; sockaddr_from_address(htonl(address), htons(port), &sa, &sa_size); SOCKET fd = (SOCKET)_fd; if (fd == -1) { Error::SetLastError(il2cpp::os::kWSAeshutdown); return kWaitStatusFailure; } int bindResult = -1; __try { bindResult = bind(fd, &sa, sa_size); } __except (SocketExceptionFilter(GetExceptionCode())) { } if (bindResult == -1) { StoreLastError(); return kWaitStatusFailure; } return kWaitStatusSuccess; } WaitStatus SocketImpl::Bind(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port) { IL2CPP_VM_NOT_SUPPORTED(SocketImpl::Bind, "We don't have IPv6 support on Windows yet."); return kWaitStatusFailure; } WaitStatus SocketImpl::ConnectInternal(struct sockaddr *sa, int32_t sa_size) { SOCKET fd = (SOCKET)_fd; if (fd == -1) { Error::SetLastError(il2cpp::os::kWSAeshutdown); return kWaitStatusFailure; } __try { if (connect(fd, sa, (socklen_t)sa_size) != -1) return kWaitStatusSuccess; if (errno != EINTR) { StoreLastError(); return kWaitStatusFailure; } struct pollfd fds = { 0 }; fds.fd = fd; fds.events = POLLOUT; while (WSAPoll(&fds, 1, -1) == -1) { if (errno != EINTR) { StoreLastError(); return kWaitStatusFailure; } } int32_t so_error = 0; socklen_t len = sizeof(so_error); if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*)&so_error, &len) == -1) { StoreLastError(); return kWaitStatusFailure; } if (so_error != 0) { StoreLastError(so_error); return kWaitStatusFailure; } } __except (SocketExceptionFilter(GetExceptionCode())) { SetLastError(kWSAeshutdown); return kWaitStatusFailure; } return kWaitStatusSuccess; } WaitStatus SocketImpl::Connect(const char *path) { // NOTE(gab): not supported on Windows. return kWaitStatusFailure; } WaitStatus SocketImpl::Connect(uint32_t address, uint16_t port) { struct sockaddr sa = {0}; socklen_t sa_size = 0; sockaddr_from_address(htonl(address), htons(port), &sa, &sa_size); return ConnectInternal((struct sockaddr *)&sa, sa_size); } WaitStatus SocketImpl::Connect(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port) { IL2CPP_VM_NOT_SUPPORTED(SocketImpl::Connect, "We don't have IPv6 support on Windows yet."); return kWaitStatusFailure; } WaitStatus SocketImpl::GetLocalEndPointInfo(EndPointInfo &info) { // Note: the size here could probably be smaller uint8_t buffer[END_POINT_MAX_PATH_LEN + 3] = {0}; socklen_t address_len = sizeof(buffer); SOCKET fd = (SOCKET)_fd; if (fd == -1) { Error::SetLastError(il2cpp::os::kWSAeshutdown); return kWaitStatusFailure; } int getsocknameResult = -1; __try { getsocknameResult = getsockname(fd, (struct sockaddr *)buffer, &address_len); } __except (SocketExceptionFilter(GetExceptionCode())) { SetLastError(kWSAeshutdown); return kWaitStatusFailure; } if (getsocknameResult == -1) { StoreLastError(); return kWaitStatusFailure; } if (!socketaddr_to_endpoint_info((struct sockaddr *)buffer, address_len, info)) { _saved_error = kWSAeafnosupport; return kWaitStatusFailure; } return kWaitStatusSuccess; } WaitStatus SocketImpl::GetRemoteEndPointInfo(EndPointInfo &info) { // Note: the size here could probably be smaller uint8_t buffer[END_POINT_MAX_PATH_LEN + 3] = {0}; socklen_t address_len = sizeof(buffer); SOCKET fd = (SOCKET)_fd; if (fd == -1) { Error::SetLastError(il2cpp::os::kWSAeshutdown); return kWaitStatusFailure; } int getpeernameResult = -1; __try { getpeernameResult = getpeername(fd, (struct sockaddr *)buffer, &address_len); } __except (SocketExceptionFilter(GetExceptionCode())) { } if (getpeernameResult == -1) { StoreLastError(); return kWaitStatusFailure; } if (!socketaddr_to_endpoint_info((struct sockaddr *)buffer, address_len, info)) { _saved_error = kWSAeafnosupport; return kWaitStatusFailure; } return kWaitStatusSuccess; } WaitStatus SocketImpl::Listen(int32_t backlog) { SOCKET fd = (SOCKET)_fd; if (fd == -1) { Error::SetLastError(il2cpp::os::kWSAeshutdown); return kWaitStatusFailure; } int listenResult = -1; __try { listenResult = listen(fd, backlog); } __except (SocketExceptionFilter(GetExceptionCode())) { } if (listenResult == -1) { StoreLastError(); return kWaitStatusFailure; } return kWaitStatusSuccess; } WaitStatus SocketImpl::Shutdown(int32_t how) { SOCKET fd = (SOCKET)_fd; if (fd == -1) { Error::SetLastError(il2cpp::os::kWSAeshutdown); return kWaitStatusFailure; } int shutdownResult = -1; __try { shutdownResult = shutdown(fd, how); } __except (SocketExceptionFilter(GetExceptionCode())) { } if (shutdownResult == -1) { StoreLastError(); return kWaitStatusFailure; } if (how == SD_RECEIVE || how == SD_BOTH) _still_readable = 0; return kWaitStatusSuccess; } static SOCKET AcceptProtected(SOCKET fd) { SOCKET new_fd; do { __try { new_fd = accept(fd, NULL, 0); } __except (SocketExceptionFilter(GetExceptionCode())) { new_fd = -1; break; } } while (new_fd == -1 && errno == EINTR); return new_fd; } WaitStatus SocketImpl::Accept(os::Socket **socket) { SocketDescriptor new_fd = 0; *socket = NULL; SOCKET fd = (SOCKET)_fd; if (fd == -1) { Error::SetLastError(il2cpp::os::kWSAeshutdown); return kWaitStatusFailure; } new_fd = AcceptProtected(fd); if (new_fd == -1) { StoreLastError(); return kWaitStatusFailure; } *socket = new os::Socket(_thread_status_callback); const WaitStatus status = (*socket)->Create(new_fd, _domain, _type, _protocol); if (status != kWaitStatusSuccess) { delete *socket; *socket = NULL; return status; } return kWaitStatusSuccess; } WaitStatus SocketImpl::Disconnect(bool reuse) { GUID GuidDisconnectEx = WSAID_DISCONNECTEX; LPFN_DISCONNECTEX disconnectEx; DWORD copied; SOCKET fd = (SOCKET)_fd; if (fd == -1) { Error::SetLastError(il2cpp::os::kWSAeshutdown); return kWaitStatusFailure; } __try { int32_t ret = WSAIoctl(fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &GuidDisconnectEx, sizeof(GuidDisconnectEx), &disconnectEx, sizeof(disconnectEx), &copied, 0, 0); if (ret == SOCKET_ERROR) { StoreLastError(); return kWaitStatusFailure; } if (!disconnectEx(fd, NULL, 0, NULL)) { StoreLastError(); return kWaitStatusFailure; } } __except (SocketExceptionFilter(GetExceptionCode())) { Error::SetLastError(il2cpp::os::kWSAeshutdown); return kWaitStatusFailure; } return kWaitStatusSuccess; } WaitStatus SocketImpl::Receive(const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len) { *len = 0; const int32_t c_flags = convert_socket_flags(flags); if (c_flags == -1) { _saved_error = kWSAeopnotsupp; return kWaitStatusFailure; } return ReceiveFromInternal(data, count, c_flags, len, NULL, 0); } WaitStatus SocketImpl::ReceiveFromInternal(const uint8_t *data, size_t count, int32_t flags, int32_t *len, struct sockaddr *from, int32_t *fromlen) { int32_t ret = 0; IL2CPP_ASSERT(count < static_cast(std::numeric_limits::max())); SOCKET fd = (SOCKET)_fd; if (fd == -1) { Error::SetLastError(il2cpp::os::kWSAeshutdown); return kWaitStatusFailure; } do { __try { ret = recvfrom(fd, (char*)data, static_cast(count), flags, from, (socklen_t*)fromlen); } __except (SocketExceptionFilter(GetExceptionCode())) { ret = -1; break; } } while (ret == -1 && errno == EINTR); if (ret == 0 && count > 0) { // According to the Linux man page, recvfrom only // returns 0 when the socket has been shut down // cleanly. Turn this into an EINTR to simulate win32 // behaviour of returning EINTR when a socket is // closed while the recvfrom is blocking (we use a // shutdown() in socket_close() to trigger this.) See // bug 75705. // Distinguish between the socket being shut down at // the local or remote ends, and reads that request 0 // bytes to be read // If this returns FALSE, it means the socket has been // closed locally. If it returns TRUE, but // still_readable != 1 then shutdown // (SHUT_RD|SHUT_RDWR) has been called locally. if (_still_readable != 1) { ret = -1; errno = EINTR; } } if (ret == -1) { StoreLastError(); return kWaitStatusFailure; } *len = ret; return kWaitStatusSuccess; } WaitStatus SocketImpl::Send(const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len) { *len = 0; const int32_t c_flags = convert_socket_flags(flags); if (c_flags == -1) { _saved_error = kWSAeopnotsupp; return kWaitStatusFailure; } SOCKET fd = (SOCKET)_fd; if (fd == -1) { Error::SetLastError(il2cpp::os::kWSAeshutdown); return kWaitStatusFailure; } int32_t ret = 0; do { __try { ret = send(fd, (char*)data, count, flags); } __except (SocketExceptionFilter(GetExceptionCode())) { ret = -1; break; } } while (ret == -1 && errno == EINTR); if (ret == -1) { StoreLastError(); return kWaitStatusFailure; } *len = ret; return kWaitStatusSuccess; } WaitStatus SocketImpl::SendArray(WSABuf *wsabufs, int32_t count, int32_t *sent, SocketFlags flags) { DWORD c_flags = convert_socket_flags(flags); if (c_flags == -1) { _saved_error = kWSAeopnotsupp; return kWaitStatusFailure; } SOCKET fd = (SOCKET)_fd; if (fd == -1) { Error::SetLastError(il2cpp::os::kWSAeshutdown); return kWaitStatusFailure; } DWORD bytes_sent; int32_t ret = -1; __try { ret = WSASend(fd, (WSABUF*)wsabufs, count, &bytes_sent, c_flags, NULL, NULL); } __except (SocketExceptionFilter(GetExceptionCode())) { } if (ret == SOCKET_ERROR) { *sent = 0; StoreLastError(); return kWaitStatusFailure; } *sent = bytes_sent; return kWaitStatusSuccess; } WaitStatus SocketImpl::ReceiveArray(WSABuf *wsabufs, int32_t count, int32_t *len, SocketFlags flags) { DWORD recv; DWORD c_flags = convert_socket_flags(flags); if (c_flags == -1) { _saved_error = kWSAeopnotsupp; return kWaitStatusFailure; } SOCKET fd = (SOCKET)_fd; if (fd == -1) { Error::SetLastError(il2cpp::os::kWSAeshutdown); return kWaitStatusFailure; } int32_t ret = -1; __try { // NOTE(gab): this cast is possible as long as WSABuf is binary compatible with WSABUF ret = WSARecv(fd, (WSABUF*)wsabufs, count, &recv, &c_flags, NULL, NULL); } __except (SocketExceptionFilter(GetExceptionCode())) { } if (ret == SOCKET_ERROR) { *len = 0; StoreLastError(); return kWaitStatusFailure; } *len = recv; return kWaitStatusSuccess; } WaitStatus SocketImpl::SendTo(uint32_t address, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len) { *len = 0; struct sockaddr sa = {0}; socklen_t sa_size = 0; sockaddr_from_address(htonl(address), htons(port), &sa, &sa_size); const int32_t c_flags = convert_socket_flags(flags); if (c_flags == -1) { _saved_error = kWSAeopnotsupp; return kWaitStatusFailure; } SOCKET fd = (SOCKET)_fd; if (fd == -1) { Error::SetLastError(il2cpp::os::kWSAeshutdown); return kWaitStatusFailure; } int32_t ret = 0; do { __try { ret = sendto(fd, (char*)data, count, c_flags, &sa, sa_size); } __except (SocketExceptionFilter(GetExceptionCode())) { ret = -1; break; } } while (ret == -1 && errno == EINTR); if (ret == -1) { StoreLastError(); return kWaitStatusFailure; } *len = ret; return kWaitStatusSuccess; } WaitStatus SocketImpl::SendTo(const char *path, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len) { // NOTE(gab): not supported on Windows. return kWaitStatusFailure; } WaitStatus SocketImpl::SendTo(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len) { IL2CPP_VM_NOT_SUPPORTED(SocketImpl::SendTo, "We don't have IPv6 support on Windows yet."); return kWaitStatusFailure; } WaitStatus SocketImpl::RecvFrom(uint32_t address, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep) { *len = 0; struct sockaddr sa = {0}; socklen_t sa_size = 0; sockaddr_from_address(htonl(address), htons(port), &sa, &sa_size); const int32_t c_flags = convert_socket_flags(flags); if (c_flags == -1) { _saved_error = kWSAeopnotsupp; return kWaitStatusFailure; } int32_t ret = 0; const WaitStatus status = ReceiveFromInternal(data, count, c_flags, len, &sa, (int32_t*)&sa_size); if (status != kWaitStatusSuccess) { ep.family = os::kAddressFamilyError; return status; } if (sa_size == 0) return kWaitStatusSuccess; if (!socketaddr_to_endpoint_info(&sa, sa_size, ep)) { ep.family = os::kAddressFamilyError; _saved_error = kWSAeafnosupport; return kWaitStatusFailure; } return kWaitStatusSuccess; } WaitStatus SocketImpl::RecvFrom(const char *path, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep) { // NOTE(gab): not supported on Windows. return kWaitStatusFailure; } WaitStatus SocketImpl::RecvFrom(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep) { IL2CPP_VM_NOT_SUPPORTED(SocketImpl::RecvFrom, "We don't have IPv6 support on Windows yet."); return kWaitStatusFailure; } WaitStatus SocketImpl::Available(int32_t *amount) { *amount = 0; u_long a = 0; SOCKET fd = (SOCKET)_fd; if (fd == -1) { Error::SetLastError(il2cpp::os::kWSAeshutdown); return kWaitStatusFailure; } int ioctlsocketResult = -1; __try { ioctlsocketResult = ioctlsocket(fd, FIONREAD, &a); } __except (SocketExceptionFilter(GetExceptionCode())) { } if (ioctlsocketResult == -1) { StoreLastError(); return kWaitStatusFailure; } *amount = a; return kWaitStatusSuccess; } WaitStatus SocketImpl::Ioctl(int32_t command, const uint8_t *in_data, int32_t in_len, uint8_t *out_data, int32_t out_len, int32_t *written) { IL2CPP_ASSERT(command != 0xC8000006 /* SIO_GET_EXTENSION_FUNCTION_POINTER */ && "SIO_GET_EXTENSION_FUNCTION_POINTER ioctl command not supported"); SOCKET fd = (SOCKET)_fd; if (fd == -1) { Error::SetLastError(il2cpp::os::kWSAeshutdown); return kWaitStatusFailure; } DWORD len = 0; int32_t ret = -1; __try { ret = WSAIoctl(fd, command, (void*)in_data, in_len, out_data, out_len, &len, NULL, NULL); } __except (SocketExceptionFilter(GetExceptionCode())) { } if (ret == SOCKET_ERROR) { StoreLastError(); return kWaitStatusFailure; } *written = len; return kWaitStatusSuccess; } #define SKIP_OPTION -2 #define INVALID_OPTION_NAME -1 static int32_t level_and_name_to_system(SocketOptionLevel level, SocketOptionName name, int32_t *system_level, int32_t *system_name) { switch (level) { case kSocketOptionLevelSocket: *system_level = SOL_SOCKET; switch (name) { // This is SO_LINGER, because the setsockopt // internal call maps DontLinger to SO_LINGER // with l_onoff=0 case kSocketOptionNameDontLinger: *system_name = SO_LINGER; break; case kSocketOptionNameDebug: *system_name = SO_DEBUG; break; // #ifdef SO_ACCEPTCONN case kSocketOptionNameAcceptConnection: *system_name = SO_ACCEPTCONN; break; // #endif case kSocketOptionNameReuseAddress: *system_name = SO_REUSEADDR; break; case kSocketOptionNameKeepAlive: *system_name = SO_KEEPALIVE; break; case kSocketOptionNameDontRoute: *system_name = SO_DONTROUTE; break; case kSocketOptionNameBroadcast: *system_name = SO_BROADCAST; break; case kSocketOptionNameLinger: *system_name = SO_LINGER; break; case kSocketOptionNameOutOfBandInline: *system_name = SO_OOBINLINE; break; case kSocketOptionNameSendBuffer: *system_name = SO_SNDBUF; break; case kSocketOptionNameReceiveBuffer: *system_name = SO_RCVBUF; break; case kSocketOptionNameSendLowWater: *system_name = SO_SNDLOWAT; break; case kSocketOptionNameReceiveLowWater: *system_name = SO_RCVLOWAT; break; case kSocketOptionNameSendTimeout: *system_name = SO_SNDTIMEO; break; case kSocketOptionNameReceiveTimeout: *system_name = SO_RCVTIMEO; break; case kSocketOptionNameError: *system_name = SO_ERROR; break; case kSocketOptionNameType: *system_name = SO_TYPE; break; case kSocketOptionNameExclusiveAddressUse: #ifdef SO_EXCLUSIVEADDRUSE *system_name = SO_EXCLUSIVEADDRUSE; break; #elif SO_REUSEADDR *system_name = SO_REUSEADDR; break; #endif case kSocketOptionNameUseLoopback: #ifdef SO_USELOOPBACK *system_name = SO_USELOOPBACK; break; #endif case kSocketOptionNameMaxConnections: #ifdef SO_MAXCONN *system_name = SO_MAXCONN; break; #elif defined(SOMAXCONN) *system_name = SOMAXCONN; break; #endif default: return INVALID_OPTION_NAME; } break; case kSocketOptionLevelIP: #ifdef SOL_IP *system_level = SOL_IP; #else *system_level = IPPROTO_IP; #endif switch (name) { case kSocketOptionNameIPOptions: *system_name = IP_OPTIONS; break; #ifdef IP_HDRINCL case kSocketOptionNameHeaderIncluded: *system_name = IP_HDRINCL; break; #endif #ifdef IP_TOS case kSocketOptionNameTypeOfService: *system_name = IP_TOS; break; #endif #ifdef IP_TTL case kSocketOptionNameIpTimeToLive: *system_name = IP_TTL; break; #endif case kSocketOptionNameMulticastInterface: *system_name = IP_MULTICAST_IF; break; case kSocketOptionNameMulticastTimeToLive: *system_name = IP_MULTICAST_TTL; break; case kSocketOptionNameMulticastLoopback: *system_name = IP_MULTICAST_LOOP; break; case kSocketOptionNameAddMembership: *system_name = IP_ADD_MEMBERSHIP; break; case kSocketOptionNameDropMembership: *system_name = IP_DROP_MEMBERSHIP; break; #ifdef HAVE_IP_PKTINFO case kSocketOptionNamePacketInformation: *system_name = IP_PKTINFO; break; #endif case kSocketOptionNameDontFragment: #ifdef IP_DONTFRAGMENT *system_name = IP_DONTFRAGMENT; #elif IP_MTU_DISCOVER *system_name = IP_MTU_DISCOVER; #elif IP_DONTFRAG *system_name = IP_DONTFRAG; #else return SKIP_OPTION; #endif break; case kSocketOptionNameAddSourceMembership: case kSocketOptionNameDropSourceMembership: case kSocketOptionNameBlockSource: case kSocketOptionNameUnblockSource: // Can't figure out how to map these, so fall // through default: return INVALID_OPTION_NAME; } break; case kSocketOptionLevelTcp: #ifdef SOL_TCP *system_level = SOL_TCP; #else *system_level = IPPROTO_TCP; #endif switch (name) { case kSocketOptionNameNoDelay: *system_name = TCP_NODELAY; break; default: return INVALID_OPTION_NAME; } break; case kSocketOptionLevelUdp: default: return INVALID_OPTION_NAME; } return 0; } WaitStatus SocketImpl::GetSocketOption(SocketOptionLevel level, SocketOptionName name, uint8_t *buffer, int32_t *length) { int32_t system_level = 0; int32_t system_name = 0; const int32_t o_res = level_and_name_to_system(level, name, &system_level, &system_name); if (o_res == SKIP_OPTION) { *((int32_t*)buffer) = 0; *length = sizeof(int32_t); return kWaitStatusSuccess; } if (o_res == INVALID_OPTION_NAME) { _saved_error = kWSAenoprotoopt; return kWaitStatusFailure; } SOCKET fd = (SOCKET)_fd; if (fd == -1) { Error::SetLastError(il2cpp::os::kWSAeshutdown); return kWaitStatusFailure; } uint8_t *tmp_val = buffer; int32_t ret = -1; __try { ret = getsockopt(fd, system_level, system_name, (char*)tmp_val, (socklen_t*)length); } __except (SocketExceptionFilter(GetExceptionCode())) { } if (ret == -1) { StoreLastError(); return kWaitStatusFailure; } if (system_name == SO_ERROR) { if (*((int32_t*)buffer) != 0) { StoreLastError(*((int32_t*)buffer)); } else { *((int32_t*)buffer) = _saved_error; } } return kWaitStatusSuccess; } WaitStatus SocketImpl::GetSocketOptionFull(SocketOptionLevel level, SocketOptionName name, int32_t *first, int32_t *second) { int32_t system_level = 0; int32_t system_name = 0; #if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR) if (level == kSocketOptionLevelSocket && name == kSocketOptionNameExclusiveAddressUse) { system_level = SOL_SOCKET; system_name = SO_REUSEADDR; } else #endif { const int32_t o_res = level_and_name_to_system(level, name, &system_level, &system_name); if (o_res == SKIP_OPTION) { *first = 0; *second = 0; return kWaitStatusSuccess; } if (o_res == INVALID_OPTION_NAME) { _saved_error = kWSAenoprotoopt; return kWaitStatusFailure; } } SOCKET fd = (SOCKET)_fd; if (fd == -1) { Error::SetLastError(il2cpp::os::kWSAeshutdown); return kWaitStatusFailure; } int32_t ret = -1; switch (name) { case kSocketOptionNameLinger: { struct linger linger; socklen_t lingersize = sizeof(linger); __try { ret = getsockopt(fd, system_level, system_name, (char*)&linger, &lingersize); *first = linger.l_onoff; *second = linger.l_linger; } __except (SocketExceptionFilter(GetExceptionCode())) { ret = -1; } } break; case kSocketOptionNameDontLinger: { struct linger linger; socklen_t lingersize = sizeof(linger); __try { ret = getsockopt(fd, system_level, system_name, (char*)&linger, &lingersize); *first = !linger.l_onoff; } __except (SocketExceptionFilter(GetExceptionCode())) { ret = -1; } } break; case kSocketOptionNameSendTimeout: case kSocketOptionNameReceiveTimeout: { socklen_t time_ms_size = sizeof(*first); __try { ret = getsockopt(fd, system_level, system_name, (char*)first, &time_ms_size); } __except (SocketExceptionFilter(GetExceptionCode())) { ret = -1; } } break; default: { socklen_t valsize = sizeof(*first); __try { ret = getsockopt(fd, system_level, system_name, (char*)first, &valsize); } __except (SocketExceptionFilter(GetExceptionCode())) { ret = -1; } } break; } if (ret == -1) { StoreLastError(); return kWaitStatusFailure; } #if !defined(SO_EXCLUSIVEADDRUSE) && defined(SO_REUSEADDR) if (level == kSocketOptionLevelSocket && name == kSocketOptionNameExclusiveAddressUse) *first = *first ? 0 : 1; #endif return kWaitStatusSuccess; } WaitStatus SocketImpl::Poll(std::vector &requests, int32_t count, int32_t timeout, int32_t *result, int32_t *error) { const size_t nfds = (size_t)count; fd_set rfds, wfds, efds; FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); for (size_t i = 0; i < nfds; i++) { SOCKET fd = static_cast(requests[i].fd); requests[i].revents = kPollFlagsNone; if (fd == -1) continue; if ((requests[i].events & kPollFlagsIn) != 0) FD_SET(fd, &rfds); if ((requests[i].events & kPollFlagsOut) != 0) FD_SET(fd, &wfds); FD_SET(fd, &efds); } timeval timevalTimeout; timeval* timeoutPtr = NULL; if (timeout != -1) { timevalTimeout.tv_sec = timeout / 1000; timevalTimeout.tv_usec = (timeout % 1000) * 1000; timeoutPtr = &timevalTimeout; } int32_t affected = -1; __try { affected = select(0, &rfds, &wfds, &efds, timeoutPtr); } __except (SocketExceptionFilter(GetExceptionCode())) { } if (affected == -1) { *error = WSAGetLastError(); // Mono does this as well and the threadpool-ms-io-poll code depends on this behavior if (*error == WSAENOTSOCK) { *error = os::SocketError::kInvalidHandle; } return kWaitStatusFailure; } int32_t resultCount = 0; for (size_t i = 0; i < nfds && affected > 0; i++) { SOCKET fd = static_cast(requests[i].fd); if (fd == -1) continue; if ((requests[i].events & kPollFlagsIn) != 0 && FD_ISSET(fd, &rfds)) { requests[i].revents |= kPollFlagsIn; affected--; } if ((requests[i].events & kPollFlagsOut) != 0 && FD_ISSET(fd, &wfds)) { requests[i].revents |= kPollFlagsOut; affected--; } if (FD_ISSET(fd, &efds)) { requests[i].revents |= kPollFlagsErr; affected--; } if (requests[i].revents != kPollFlagsNone) resultCount++; } *result = resultCount; return kWaitStatusSuccess; } WaitStatus SocketImpl::Poll(std::vector& requests, int32_t timeout, int32_t *result, int32_t *error) { return Poll(requests, (int32_t)requests.size(), timeout, result, error); } WaitStatus SocketImpl::Poll(PollRequest& request, int32_t timeout, int32_t *result, int32_t *error) { std::vector requests; requests.push_back(request); return Poll(requests, 1, timeout, result, error); } WaitStatus SocketImpl::SetSocketOption(SocketOptionLevel level, SocketOptionName name, int32_t value) { int32_t system_level = 0; int32_t system_name = 0; const int32_t o_res = level_and_name_to_system(level, name, &system_level, &system_name); if (o_res == SKIP_OPTION) { return kWaitStatusSuccess; } if (o_res == INVALID_OPTION_NAME) { _saved_error = kWSAenoprotoopt; return kWaitStatusFailure; } struct linger linger; WaitStatus ret = kWaitStatusFailure; switch (name) { case kSocketOptionNameDontLinger: linger.l_onoff = !value; linger.l_linger = 0; ret = SetSocketOptionInternal(system_level, system_name, &linger, sizeof(linger)); break; case kSocketOptionNameDontFragment: #ifdef IP_PMTUDISC_DO // Fiddle with the value slightly if we're turning DF on if (value == 1) value = IP_PMTUDISC_DO; #endif ret = SetSocketOptionInternal(system_level, system_name, (char*)&value, sizeof(value)); break; default: ret = SetSocketOptionInternal(system_level, system_name, (char*)&value, sizeof(value)); break; } return ret; } WaitStatus SocketImpl::SetSocketOptionLinger(SocketOptionLevel level, SocketOptionName name, bool enabled, int32_t seconds) { int32_t system_level = 0; int32_t system_name = 0; const int32_t o_res = level_and_name_to_system(level, name, &system_level, &system_name); if (o_res == SKIP_OPTION) { return kWaitStatusSuccess; } if (o_res == INVALID_OPTION_NAME) { _saved_error = kWSAenoprotoopt; return kWaitStatusFailure; } struct linger linger; linger.l_onoff = enabled; linger.l_linger = seconds; return SetSocketOptionInternal(system_level, system_name, &linger, sizeof(linger)); } WaitStatus SocketImpl::SetSocketOptionArray(SocketOptionLevel level, SocketOptionName name, const uint8_t *buffer, int32_t length) { int32_t system_level = 0; int32_t system_name = 0; const int32_t o_res = level_and_name_to_system(level, name, &system_level, &system_name); if (o_res == SKIP_OPTION) { return kWaitStatusSuccess; } if (o_res == INVALID_OPTION_NAME) { _saved_error = kWSAenoprotoopt; return kWaitStatusFailure; } struct linger linger; WaitStatus ret = kWaitStatusFailure; switch (name) { case kSocketOptionNameDontLinger: if (length == 1) { linger.l_linger = 0; linger.l_onoff = (*((char*)buffer)) ? 0 : 1; ret = SetSocketOptionInternal(system_level, system_name, &linger, sizeof(linger)); } else { _saved_error = kWSAeinval; return kWaitStatusFailure; } break; default: ret = SetSocketOptionInternal(system_level, system_name, buffer, length); break; } return ret; } WaitStatus SocketImpl::SetSocketOptionMembership(SocketOptionLevel level, SocketOptionName name, uint32_t group_address, uint32_t local_address) { int32_t system_level = 0; int32_t system_name = 0; const int32_t o_res = level_and_name_to_system(level, name, &system_level, &system_name); if (o_res == SKIP_OPTION) { return kWaitStatusSuccess; } if (o_res == INVALID_OPTION_NAME) { _saved_error = kWSAenoprotoopt; return kWaitStatusFailure; } IP_MREQ mreq = {{0}}; mreq.imr_multiaddr.s_addr = group_address; mreq.imr_interface.s_addr = local_address; return SetSocketOptionInternal(system_level, system_name, &mreq, sizeof(mreq)); return kWaitStatusFailure; } #if IL2CPP_SUPPORT_IPV6 WaitStatus SocketImpl::SetSocketOptionMembership(SocketOptionLevel level, SocketOptionName name, IPv6Address ipv6, uint64_t interfaceOffset) { IL2CPP_VM_NOT_SUPPORTED(SocketImpl::SetSocketOptionMembership, "We don't have IPv6 support on Windows yet."); return kWaitStatusFailure; } #endif WaitStatus SocketImpl::SetSocketOptionInternal(int32_t level, int32_t name, const void *value, int32_t len) { const void *real_val = value; SOCKET fd = (SOCKET)_fd; if (fd == -1) { Error::SetLastError(il2cpp::os::kWSAeshutdown); return kWaitStatusFailure; } int32_t ret = -1; __try { ret = setsockopt(fd, level, name, (const char*)real_val, (socklen_t)len); } __except (SocketExceptionFilter(GetExceptionCode())) { } if (ret == -1) { StoreLastError(); return kWaitStatusFailure; } return kWaitStatusSuccess; } int32_t WSAIoctlProtected(SOCKET s, DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPDWORD lpcbBytesReturned, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) { __try { return WSAIoctl(s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine); } __except (SocketExceptionFilter(GetExceptionCode())) { } return -1; } BOOL transmitFileProtected(LPFN_TRANSMITFILE transmitFile, SOCKET hSocket, HANDLE hFile, DWORD nNumberOfBytesToWrite, DWORD nNumberOfBytesPerSend, LPOVERLAPPED lpOverlapped, LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, DWORD dwReserved) { __try { return transmitFile(hSocket, hFile, nNumberOfBytesToWrite, nNumberOfBytesPerSend, lpOverlapped, lpTransmitBuffers, dwReserved); } __except (SocketExceptionFilter(GetExceptionCode())) { } return FALSE; } WaitStatus SocketImpl::SendFile(const char *filename, TransmitFileBuffers *buffers, TransmitFileOptions options) { if (filename == NULL) return kWaitStatusFailure; const UTF16String wideFilename = utils::StringUtils::Utf8ToUtf16(filename); HANDLE file = CreateFileW((LPCWSTR)wideFilename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (file == INVALID_HANDLE_VALUE) { StoreLastError(); return kWaitStatusFailure; } GUID transmitFileGuid = WSAID_TRANSMITFILE; LPFN_TRANSMITFILE transmitFile; DWORD copied; SOCKET fd = (SOCKET)_fd; if (fd == -1) { Error::SetLastError(il2cpp::os::kWSAeshutdown); return kWaitStatusFailure; } int32_t ret = WSAIoctlProtected(fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &transmitFileGuid, sizeof(transmitFileGuid), &transmitFile, sizeof(transmitFile), &copied, 0, 0); if (ret == SOCKET_ERROR) { StoreLastError(); return kWaitStatusFailure; } if (!transmitFileProtected(transmitFile, fd, file, 0, 0, NULL, (TRANSMIT_FILE_BUFFERS*)&buffers, options)) { StoreLastError(); CloseHandle(file); return kWaitStatusFailure; } CloseHandle(file); return kWaitStatusSuccess; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/SocketImpl.h ================================================ #pragma once #if IL2CPP_TARGET_WINDOWS #include #include #include #include "os/Socket.h" #include "os/ErrorCodes.h" #include "os/WaitStatus.h" #include "utils/NonCopyable.h" struct sockaddr; namespace il2cpp { namespace os { class SocketImpl : public il2cpp::utils::NonCopyable { public: /// Handle for socket. Must be large enough to hold a pointer. typedef uint64_t SocketDescriptor; SocketImpl(ThreadStatusCallback thread_status_callback); ~SocketImpl(); inline SocketDescriptor GetDescriptor() { return _fd; } ErrorCode GetLastError() const; WaitStatus Create(SocketDescriptor fd, int32_t family, int32_t type, int32_t protocol); WaitStatus Create(AddressFamily family, SocketType type, ProtocolType protocol); WaitStatus Close(); bool IsClosed() { return (_fd == -1); } WaitStatus SetBlocking(bool blocking); WaitStatus Listen(int32_t blacklog); WaitStatus Bind(const char *path); WaitStatus Bind(const char *address, uint16_t port); WaitStatus Bind(uint32_t address, uint16_t port); WaitStatus Bind(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port); WaitStatus Connect(const char *path); WaitStatus Connect(uint32_t address, uint16_t port); WaitStatus Connect(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port); WaitStatus Disconnect(bool reuse); WaitStatus Shutdown(int32_t how); WaitStatus GetLocalEndPointInfo(EndPointInfo &info); WaitStatus GetRemoteEndPointInfo(EndPointInfo &info); WaitStatus Receive(const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len); WaitStatus ReceiveFromInternal(const uint8_t *data, size_t count, int32_t flags, int32_t *len, struct sockaddr *from, int32_t *fromlen); WaitStatus Send(const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len); WaitStatus SendArray(WSABuf *wsabufs, int32_t count, int32_t *sent, SocketFlags c_flags); WaitStatus ReceiveArray(WSABuf *wsabufs, int32_t count, int32_t *len, SocketFlags c_flags); WaitStatus SendTo(uint32_t address, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len); WaitStatus SendTo(const char *path, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len); WaitStatus SendTo(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len); WaitStatus RecvFrom(uint32_t address, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep); WaitStatus RecvFrom(const char *path, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep); WaitStatus RecvFrom(uint8_t address[ipv6AddressSize], uint32_t scope, uint16_t port, const uint8_t *data, int32_t count, os::SocketFlags flags, int32_t *len, os::EndPointInfo &ep); WaitStatus Available(int32_t *amount); WaitStatus Accept(os::Socket **socket); WaitStatus Ioctl(int32_t command, const uint8_t *in_data, int32_t in_len, uint8_t *out_data, int32_t out_len, int32_t *written); WaitStatus GetSocketOption(SocketOptionLevel level, SocketOptionName name, uint8_t *buffer, int32_t *length); WaitStatus GetSocketOptionFull(SocketOptionLevel level, SocketOptionName name, int32_t *first, int32_t *second); WaitStatus SetSocketOption(SocketOptionLevel level, SocketOptionName name, int32_t value); WaitStatus SetSocketOptionLinger(SocketOptionLevel level, SocketOptionName name, bool enabled, int32_t seconds); WaitStatus SetSocketOptionArray(SocketOptionLevel level, SocketOptionName name, const uint8_t *buffer, int32_t length); WaitStatus SetSocketOptionMembership(SocketOptionLevel level, SocketOptionName name, uint32_t group_address, uint32_t local_address); #if IL2CPP_SUPPORT_IPV6 WaitStatus SetSocketOptionMembership(SocketOptionLevel level, SocketOptionName name, IPv6Address ipv6, uint64_t interfaceOffset); #endif WaitStatus SendFile(const char *filename, TransmitFileBuffers *buffers, TransmitFileOptions options); static WaitStatus Poll(std::vector &requests, int32_t count, int32_t timeout, int32_t *result, int32_t *error); static WaitStatus Poll(std::vector &requests, int32_t timeout, int32_t *result, int32_t *error); static WaitStatus Poll(PollRequest& request, int32_t timeout, int32_t *result, int32_t *error); static WaitStatus GetHostName(std::string &name); static WaitStatus GetHostByName(const std::string &host, std::string &name, std::vector &aliases, std::vector &addr_list); static WaitStatus GetHostByAddr(const std::string &address, std::string &name, std::vector &aliases, std::vector &addr_list); static void Startup(); static void Cleanup(); private: bool _is_valid; SocketDescriptor _fd; int32_t _domain; int32_t _type; int32_t _protocol; ErrorCode _saved_error; int32_t _still_readable; ThreadStatusCallback _thread_status_callback; void StoreLastError(); void StoreLastError(int32_t error_no); WaitStatus ConnectInternal(struct sockaddr *sa, int32_t sa_size); WaitStatus SetSocketOptionInternal(int32_t level, int32_t name, const void *value, int32_t len); }; } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/StackTrace.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINDOWS #include "WindowsHeaders.h" #include "os/Mutex.h" #include "os/StackTrace.h" namespace il2cpp { namespace os { void StackTrace::WalkStack(WalkStackCallback callback, void* context, WalkOrder walkOrder) { const uint32_t kMaxFrames = 128; void* stack[kMaxFrames]; size_t frames = CaptureStackBackTrace(0, kMaxFrames, stack, NULL); if (walkOrder == WalkOrder::kFirstCalledToLastCalled) { for (size_t i = frames; i--;) { if (!callback(reinterpret_cast(stack[i]), context)) break; } } else { for (size_t i = 0; i < frames; i++) { if (!callback(reinterpret_cast(stack[i]), context)) break; } } } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/ThreadImpl.cpp ================================================ #include "il2cpp-config.h" #if !IL2CPP_THREADS_STD && IL2CPP_THREADS_WIN32 #include "ThreadImpl.h" #include "os/Time.h" #include "WindowsHelpers.h" #include "il2cpp-vm-support.h" namespace il2cpp { namespace os { struct StartData { Thread::StartFunc m_StartFunc; void* m_StartArg; volatile DWORD* m_ThreadId; }; static DWORD WINAPI ThreadStartWrapper(LPVOID arg) { StartData startData = *(StartData*)arg; free(arg); *startData.m_ThreadId = GetCurrentThreadId(); startData.m_StartFunc(startData.m_StartArg); return 0; } ThreadImpl::ThreadImpl() : m_ThreadHandle(0), m_ThreadId(0), m_StackSize(IL2CPP_DEFAULT_STACK_SIZE), m_ApartmentState(kApartmentStateUnknown), m_Priority(kThreadPriorityNormal) { } ThreadImpl::~ThreadImpl() { if (m_ThreadHandle != NULL) CloseHandle(m_ThreadHandle); } uint64_t ThreadImpl::Id() { return m_ThreadId; } void ThreadImpl::SetName(const std::string& name) { // http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx const DWORD MS_VC_EXCEPTION = 0x406D1388; #pragma pack(push,8) typedef struct tagTHREADNAME_INFO { DWORD dwType; // Must be 0x1000. LPCSTR szName; // Pointer to name (in user addr space). DWORD dwThreadID; // Thread ID (-1=caller thread). DWORD dwFlags; // Reserved for future use, must be zero. } THREADNAME_INFO; #pragma pack(pop) THREADNAME_INFO info; info.dwType = 0x1000; info.szName = name.c_str(); info.dwThreadID = static_cast(Id()); info.dwFlags = 0; __try { RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); } __except (EXCEPTION_EXECUTE_HANDLER) { } } void ThreadImpl::SetPriority(ThreadPriority priority) { if (m_ThreadHandle == NULL) m_Priority = priority; else { int ret = ::SetThreadPriority(m_ThreadHandle, priority - 2); IL2CPP_ASSERT(ret); } } ThreadPriority ThreadImpl::GetPriority() { if (m_ThreadHandle == NULL) return m_Priority; int ret = ::GetThreadPriority(m_ThreadHandle) + 2; IL2CPP_ASSERT(ret != THREAD_PRIORITY_ERROR_RETURN); return (ThreadPriority)ret; } ErrorCode ThreadImpl::Run(Thread::StartFunc func, void* arg) { // It might happen that func will start executing and will try to access m_ThreadId before CreateThread gets a chance to assign it. // Therefore m_ThreadId is assigned both by this thread and from the newly created thread (race condition could go the other way too). StartData* startData = (StartData*)malloc(sizeof(StartData)); startData->m_StartFunc = func; startData->m_StartArg = arg; startData->m_ThreadId = &m_ThreadId; // Create thread. DWORD threadId; HANDLE threadHandle = ::CreateThread(NULL, m_StackSize, &ThreadStartWrapper, startData, STACK_SIZE_PARAM_IS_A_RESERVATION, &threadId); if (!threadHandle) return kErrorCodeGenFailure; m_ThreadHandle = threadHandle; m_ThreadId = threadId; return kErrorCodeSuccess; } void ThreadImpl::Sleep(uint32_t ms, bool interruptible) { uint32_t remainingWaitTime = ms; while (true) { uint32_t startWaitTime = os::Time::GetTicksMillisecondsMonotonic(); DWORD sleepResult = ::SleepEx(remainingWaitTime, interruptible); if (sleepResult == WAIT_IO_COMPLETION) { uint32_t waitedTime = os::Time::GetTicksMillisecondsMonotonic() - startWaitTime; if (waitedTime >= remainingWaitTime) return; remainingWaitTime -= waitedTime; continue; } break; } } void ThreadImpl::QueueUserAPC(Thread::APCFunc func, void* context) { ::QueueUserAPC(reinterpret_cast(func), m_ThreadHandle, reinterpret_cast(context)); } namespace { // It would be nice to always use CoGetApartmentType but it's only available on Windows 7 and later. // That's why we check for function at runtime and do a fallback on Windows XP. // CoGetApartmentType is always available in Windows Store Apps. typedef HRESULT (STDAPICALLTYPE * CoGetApartmentTypeFunc)(APTTYPE* type, APTTYPEQUALIFIER* qualifier); ApartmentState GetApartmentWindows7(CoGetApartmentTypeFunc coGetApartmentType, bool* implicit) { *implicit = false; APTTYPE type; APTTYPEQUALIFIER qualifier; const HRESULT hr = coGetApartmentType(&type, &qualifier); if (FAILED(hr)) { IL2CPP_ASSERT(CO_E_NOTINITIALIZED == hr); return kApartmentStateUnknown; } switch (type) { case APTTYPE_STA: case APTTYPE_MAINSTA: return kApartmentStateInSTA; case APTTYPE_MTA: *implicit = (APTTYPEQUALIFIER_IMPLICIT_MTA == qualifier); return kApartmentStateInMTA; case APTTYPE_NA: switch (qualifier) { case APTTYPEQUALIFIER_NA_ON_STA: case APTTYPEQUALIFIER_NA_ON_MAINSTA: return kApartmentStateInSTA; case APTTYPEQUALIFIER_NA_ON_MTA: return kApartmentStateInMTA; case APTTYPEQUALIFIER_NA_ON_IMPLICIT_MTA: *implicit = true; return kApartmentStateInMTA; } break; } IL2CPP_ASSERT(0 && "CoGetApartmentType returned unexpected value."); return kApartmentStateUnknown; } #if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) ApartmentState GetApartmentWindowsXp(bool* implicit) { *implicit = false; IUnknown* context = nullptr; HRESULT hr = CoGetContextToken(reinterpret_cast(&context)); if (SUCCEEDED(hr)) { IComThreadingInfo* info; hr = context->QueryInterface(&info); if (SUCCEEDED(hr)) { THDTYPE type; hr = info->GetCurrentThreadType(&type); if (SUCCEEDED(hr)) { // THDTYPE_PROCESSMESSAGES means that we are in STA thread. // Otherwise it's an MTA thread. We are not sure at this moment if CoInitializeEx has been called explicitly on this thread // or if it has been implicitly made MTA by a CoInitialize call on another thread. if (THDTYPE_PROCESSMESSAGES == type) return kApartmentStateInSTA; // Assume implicit. Even if it's explicit, we'll handle the case correctly by checking CoInitializeEx return value. *implicit = true; return kApartmentStateInMTA; } info->Release(); } // No need to release context. } return kApartmentStateUnknown; } class CoGetApartmentTypeHelper { private: HMODULE _library; CoGetApartmentTypeFunc _func; public: inline CoGetApartmentTypeHelper() { _library = LoadLibraryW(L"ole32.dll"); Assert(_library); _func = reinterpret_cast(GetProcAddress(_library, "CoGetApartmentType")); } inline ~CoGetApartmentTypeHelper() { FreeLibrary(_library); } inline CoGetApartmentTypeFunc GetFunc() const { return _func; } }; inline ApartmentState GetApartmentImpl(bool* implicit) { static CoGetApartmentTypeHelper coGetApartmentTypeHelper; const CoGetApartmentTypeFunc func = coGetApartmentTypeHelper.GetFunc(); return func ? GetApartmentWindows7(func, implicit) : GetApartmentWindowsXp(implicit); } #else inline ApartmentState GetApartmentImpl(bool* implicit) { return GetApartmentWindows7(CoGetApartmentType, implicit); } #endif } ApartmentState ThreadImpl::GetApartment() { Assert(GetCurrentThreadId() == m_ThreadId); ApartmentState state = static_cast(m_ApartmentState & ~kApartmentStateCoInitialized); if (kApartmentStateUnknown == state) { bool implicit; state = GetApartmentImpl(&implicit); if (!implicit) m_ApartmentState = state; } return state; } ApartmentState ThreadImpl::GetExplicitApartment() { return static_cast(m_ApartmentState & ~kApartmentStateCoInitialized); } ApartmentState ThreadImpl::SetApartment(ApartmentState state) { Assert(GetCurrentThreadId() == m_ThreadId); // Unknown state uninitializes COM. if (kApartmentStateUnknown == state) { if (m_ApartmentState & kApartmentStateCoInitialized) { CoUninitialize(); m_ApartmentState = kApartmentStateUnknown; } return GetApartment(); } // Initialize apartment state. Ignore result of this function because it will return MTA value for both implicit and explicit apartment. // On the other hand m_ApartmentState will only be set to MTA if it was initialized explicitly with CoInitializeEx. GetApartment(); ApartmentState currentState = static_cast(m_ApartmentState & ~kApartmentStateCoInitialized); if (kApartmentStateUnknown != currentState) { Assert(state == currentState); return currentState; } #if IL2CPP_TARGET_XBOXONE if (state == kApartmentStateInSTA) { // Only assert in debug.. we wouldn't want to bring down the application in Release config IL2CPP_ASSERT(false && "STA apartment state is not supported on Xbox One"); state = kApartmentStateInMTA; } #endif HRESULT hr = CoInitializeEx(nullptr, (kApartmentStateInSTA == state) ? COINIT_APARTMENTTHREADED : COINIT_MULTITHREADED); if (SUCCEEDED(hr)) { m_ApartmentState = state; if (S_OK == hr) m_ApartmentState = static_cast(m_ApartmentState | kApartmentStateCoInitialized); else CoUninitialize(); // Someone has already called correct CoInitialize. Don't leave incorrect reference count. } else if (RPC_E_CHANGED_MODE == hr) { // CoInitialize has already been called with a different apartment state. m_ApartmentState = (kApartmentStateInSTA == state) ? kApartmentStateInMTA : kApartmentStateInSTA; } else { IL2CPP_VM_RAISE_COM_EXCEPTION(hr, true); } return GetApartment(); } void ThreadImpl::SetExplicitApartment(ApartmentState state) { Assert(!(m_ApartmentState & kApartmentStateCoInitialized)); m_ApartmentState = state; } uint64_t ThreadImpl::CurrentThreadId() { return GetCurrentThreadId(); } ThreadImpl* ThreadImpl::CreateForCurrentThread() { ThreadImpl* thread = new ThreadImpl(); BOOL duplicateResult = DuplicateHandle(::GetCurrentProcess(), ::GetCurrentThread(), ::GetCurrentProcess(), &thread->m_ThreadHandle, 0, FALSE, DUPLICATE_SAME_ACCESS); Assert(duplicateResult && "DuplicateHandle failed."); thread->m_ThreadId = ::GetCurrentThreadId(); return thread; } #if NET_4_0 bool ThreadImpl::YieldInternal() { return SwitchToThread(); } #endif } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/ThreadImpl.h ================================================ #pragma once #if !IL2CPP_THREADS_STD && IL2CPP_THREADS_WIN32 #include "os/ErrorCodes.h" #include "os/Thread.h" #include "os/WaitStatus.h" #include "utils/NonCopyable.h" #include "WindowsHeaders.h" #define IL2CPP_DEFAULT_STACK_SIZE ( 1 * 1024 * 1024) // default .NET stacksize is 1mb namespace il2cpp { namespace os { class ThreadImpl : public il2cpp::utils::NonCopyable { public: ThreadImpl(); ~ThreadImpl(); uint64_t Id(); ErrorCode Run(Thread::StartFunc func, void* arg); void SetName(const std::string& name); void SetPriority(ThreadPriority priority); ThreadPriority GetPriority(); void SetStackSize(size_t newsize) { // only makes sense if it's called BEFORE the thread has been created IL2CPP_ASSERT(m_ThreadHandle == NULL); // if newsize is zero we use the per-platform default value for size of stack if (newsize == 0) { newsize = IL2CPP_DEFAULT_STACK_SIZE; } m_StackSize = newsize; } void QueueUserAPC(Thread::APCFunc func, void* context); ApartmentState GetApartment(); ApartmentState GetExplicitApartment(); ApartmentState SetApartment(ApartmentState state); void SetExplicitApartment(ApartmentState state); static void Sleep(uint32_t ms, bool interruptible); static uint64_t CurrentThreadId(); static ThreadImpl* CreateForCurrentThread(); #if NET_4_0 static bool YieldInternal(); #endif private: HANDLE m_ThreadHandle; volatile DWORD m_ThreadId; SIZE_T m_StackSize; ApartmentState m_ApartmentState; ThreadPriority m_Priority; }; } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/ThreadLocalValueImpl.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_THREADS_WIN32 #include "ThreadLocalValueImpl.h" namespace il2cpp { namespace os { ThreadLocalValueImpl::ThreadLocalValueImpl() { m_Index = TlsAlloc(); IL2CPP_ASSERT(m_Index != TLS_OUT_OF_INDEXES); } ThreadLocalValueImpl::~ThreadLocalValueImpl() { IL2CPP_ASSERT(TlsFree(m_Index)); } ErrorCode ThreadLocalValueImpl::SetValue(void* value) { if (TlsSetValue(m_Index, value) == FALSE) return static_cast(GetLastError()); return kErrorCodeSuccess; } ErrorCode ThreadLocalValueImpl::GetValue(void** value) { *value = TlsGetValue(m_Index); if (*value) return kErrorCodeSuccess; DWORD lastError = GetLastError(); if (lastError == ERROR_SUCCESS) return kErrorCodeSuccess; return static_cast(lastError); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/ThreadLocalValueImpl.h ================================================ #pragma once #if IL2CPP_THREADS_WIN32 #include "os/ErrorCodes.h" #include "utils/NonCopyable.h" #include "WindowsHelpers.h" namespace il2cpp { namespace os { class ThreadLocalValueImpl : public il2cpp::utils::NonCopyable { public: ThreadLocalValueImpl(); ~ThreadLocalValueImpl(); ErrorCode SetValue(void* value); ErrorCode GetValue(void** value); private: DWORD m_Index; }; } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/Time.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINDOWS #include "os/Time.h" #include "os/Win32/WindowsHeaders.h" #include "utils/MathUtils.h" #define MTICKS_PER_SEC 10000000LL namespace il2cpp { namespace os { static LARGE_INTEGER s_PerformanceCounterFrequency; static inline void InitializePerformanceCounterFrequency() { if (!s_PerformanceCounterFrequency.QuadPart) { // From MSDN: On systems that run Windows XP or later, the function will always succeed and will thus never return zero. // so I'll just assume we never run on older than XP BOOL qpfResult = QueryPerformanceFrequency(&s_PerformanceCounterFrequency); IL2CPP_ASSERT(qpfResult != FALSE); } } uint32_t Time::GetTicksMillisecondsMonotonic() { InitializePerformanceCounterFrequency(); LARGE_INTEGER value; QueryPerformanceCounter(&value); return static_cast(value.QuadPart * 1000 / s_PerformanceCounterFrequency.QuadPart); } int64_t Time::GetTicks100NanosecondsMonotonic() { InitializePerformanceCounterFrequency(); LARGE_INTEGER value; QueryPerformanceCounter(&value); return utils::MathUtils::A_Times_B_DividedBy_C(value.QuadPart, MTICKS_PER_SEC, s_PerformanceCounterFrequency.QuadPart); } /* * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001 */ const uint64_t FILETIME_ADJUST = ((uint64_t)504911232000000000LL); int64_t Time::GetTicks100NanosecondsDateTime() { ULARGE_INTEGER ft; IL2CPP_ASSERT(sizeof(ft) == sizeof(FILETIME)); ::GetSystemTimeAsFileTime((FILETIME*)&ft); return FILETIME_ADJUST + ft.QuadPart; } int64_t Time::GetSystemTimeAsFileTime() { int64_t fileTime; ::GetSystemTimeAsFileTime(reinterpret_cast(&fileTime)); return fileTime; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/TimeZone.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINDOWS #include "os/TimeZone.h" #include "os/Win32/WindowsHeaders.h" /* * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001 */ const uint64_t FILETIME_ADJUST = ((uint64_t)504911232000000000LL); namespace il2cpp { namespace os { static void convert_to_absolute_date(SYSTEMTIME *date) { #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0)) static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; /* from the calendar FAQ */ int a = (14 - date->wMonth) / 12; int y = date->wYear - a; int m = date->wMonth + 12 * a - 2; int d = (1 + y + y / 4 - y / 100 + y / 400 + (31 * m) / 12) % 7; /* d is now the day of the week for the first of the month (0 == Sunday) */ int day_of_week = date->wDayOfWeek; /* set day_in_month to the first day in the month which falls on day_of_week */ int day_in_month = 1 + (day_of_week - d); if (day_in_month <= 0) day_in_month += 7; /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */ date->wDay = day_in_month + (date->wDay - 1) * 7; if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1])) date->wDay -= 7; } // names[0] - standardName // names[1] - daylightName bool TimeZone::GetTimeZoneData(int32_t year, int64_t data[4], std::string names[2]) { TIME_ZONE_INFORMATION tz_info; FILETIME ft; int err, tz_id; // TODO: Get proper unicode conversion routines char daylightName[33] = {0}; char standardName[33] = {0}; tz_id = GetTimeZoneInformation(&tz_info); if (tz_id == TIME_ZONE_ID_INVALID) return 0; const int kMaxUtf8NameLength = 64; names[0].resize(kMaxUtf8NameLength); names[1].resize(kMaxUtf8NameLength); // WideCharToMultiByte returns the number of bytes written to the buffer pointed to by lpMultiByteStr if successful. // WideCharToMultiByte does not null-terminate an output string if the input string length is explicitly specified without a terminating null character. // In our case, input string is null terminated int standardNameLength = WideCharToMultiByte(CP_UTF8, 0, tz_info.StandardName, -1, &names[0][0], kMaxUtf8NameLength, NULL, NULL); names[0].resize(standardNameLength - 1); int daylightNameLength = WideCharToMultiByte(CP_UTF8, 0, tz_info.DaylightName, -1, &names[1][0], kMaxUtf8NameLength, NULL, NULL); names[1].resize(daylightNameLength - 1); if ((year <= 1601) || (year > 30827)) { /* * According to MSDN, the MS time functions can't handle dates outside * this interval. */ return 1; } /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */ if (tz_id != TIME_ZONE_ID_UNKNOWN) { tz_info.StandardDate.wYear = year; convert_to_absolute_date(&tz_info.StandardDate); err = SystemTimeToFileTime(&tz_info.StandardDate, &ft); //g_IL2CPP_ASSERT(err); if (err == 0) return 0; data[1] = FILETIME_ADJUST + (((uint64_t)ft.dwHighDateTime << 32) | ft.dwLowDateTime); tz_info.DaylightDate.wYear = year; convert_to_absolute_date(&tz_info.DaylightDate); err = SystemTimeToFileTime(&tz_info.DaylightDate, &ft); if (err == 0) return 0; data[0] = FILETIME_ADJUST + (((uint64_t)ft.dwHighDateTime << 32) | ft.dwLowDateTime); } data[2] = (tz_info.Bias + tz_info.StandardBias) * -600000000LL; data[3] = (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL; return 1; } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/WindowsHeaders.h ================================================ #pragma once #if IL2CPP_TARGET_WINDOWS #define NOMINMAX #define WIN32_LEAN_AND_MEAN 1 #define INC_OLE2 1 #include #if !IL2CPP_TARGET_WINDOWS_DESKTOP #include #include #include #include #endif #define LINK_TO_WINDOWSRUNTIME_LIBS (!IL2CPP_TARGET_WINDOWS_DESKTOP) #endif ================================================ FILE: unity_decoder/libil2cpp/os/Win32/WindowsHelpers.cpp ================================================ #include "il2cpp-config.h" #include "WindowsHelpers.h" #include "os/Time.h" #if IL2CPP_TARGET_WINDOWS namespace il2cpp { namespace os { namespace win { WaitStatus WaitForSingleObjectAndAccountForAPCs(HANDLE handle, uint32_t ms, bool interruptible) { uint32_t remainingWaitTimeMS = ms; while (true) { uint32_t waitStartTime = os::Time::GetTicksMillisecondsMonotonic(); DWORD result = ::WaitForSingleObjectEx(handle, remainingWaitTimeMS, interruptible); if (result == WAIT_OBJECT_0) return kWaitStatusSuccess; if (result == WAIT_TIMEOUT) return kWaitStatusTimeout; if (result == WAIT_IO_COMPLETION) { if (ms != INFINITE) { uint32_t haveWaitedTimeMS = os::Time::GetTicksMillisecondsMonotonic() - waitStartTime; if (haveWaitedTimeMS >= remainingWaitTimeMS) return kWaitStatusTimeout; remainingWaitTimeMS -= haveWaitedTimeMS; } continue; } break; } return kWaitStatusFailure; } } } } #endif // IL2CPP_TARGET_WINDOWS ================================================ FILE: unity_decoder/libil2cpp/os/Win32/WindowsHelpers.h ================================================ #pragma once #if IL2CPP_TARGET_WINDOWS #include "WindowsHeaders.h" #include "os/WaitStatus.h" #if IL2CPP_TARGET_WINRT #include "os/WinRT/Win32ApiWinRTEmulation.h" #endif #if IL2CPP_TARGET_XBOXONE #include "os/XboxOne/Win32ApiXboxEmulation.h" #endif #if IL2CPP_TARGET_WINRT || IL2CPP_TARGET_XBOXONE #include "os/WinRT/Win32ApiSharedEmulation.h" #endif namespace il2cpp { namespace os { namespace win { // Wait for a release of the given handle in way that can be interrupted by APCs. WaitStatus WaitForSingleObjectAndAccountForAPCs(HANDLE handle, uint32_t ms, bool interruptible); } } } #endif // IL2CPP_TARGET_WINDOWS ================================================ FILE: unity_decoder/libil2cpp/os/Win32/WindowsRuntime.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "il2cpp-string-types.h" #include "il2cpp-vm-support.h" #include "os/WindowsRuntime.h" #include "utils/Il2CppHStringReference.h" #include "utils/StringUtils.h" #include "vm/Array.h" #include "vm/CCW.h" #include "vm/Exception.h" #include "vm/String.h" #include "WindowsHeaders.h" #if IL2CPP_TARGET_WINDOWS && !IL2CPP_USE_GENERIC_WINDOWSRUNTIME #if LINK_TO_WINDOWSRUNTIME_LIBS #include #else typedef enum { RO_ERROR_REPORTING_NONE = 0x00000000, RO_ERROR_REPORTING_SUPPRESSEXCEPTIONS = 0x00000001, RO_ERROR_REPORTING_FORCEEXCEPTIONS = 0x00000002, RO_ERROR_REPORTING_USESETERRORINFO = 0x00000004, RO_ERROR_REPORTING_SUPPRESSSETERRORINFO = 0x00000008, } RO_ERROR_REPORTING_FLAGS; #endif namespace il2cpp { namespace os { #if !LINK_TO_WINDOWSRUNTIME_LIBS template FunctionType ResolveAPI(const wchar_t* moduleName, const char* functionName) { HMODULE module = GetModuleHandleW(moduleName); if (module == NULL) return NULL; return reinterpret_cast(GetProcAddress(module, functionName)); } #endif il2cpp_hresult_t WindowsRuntime::GetActivationFactory(Il2CppHString className, Il2CppIActivationFactory** activationFactory) { IL2CPP_ASSERT(className != NULL); IL2CPP_ASSERT(activationFactory != NULL); #if LINK_TO_WINDOWSRUNTIME_LIBS return RoGetActivationFactory(reinterpret_cast(className), reinterpret_cast(Il2CppIActivationFactory::IID), reinterpret_cast(activationFactory)); #else typedef HRESULT(WINAPI* RoGetActivationFactoryFunc)(void* activatableClassId, const Il2CppGuid& iid, Il2CppIActivationFactory** factory); static RoGetActivationFactoryFunc RoGetActivationFactory = NULL; if (RoGetActivationFactory == NULL) { RoGetActivationFactory = ResolveAPI(L"api-ms-win-core-winrt-l1-1-0.dll", "RoGetActivationFactory"); if (RoGetActivationFactory == NULL) return IL2CPP_REGDB_E_CLASSNOTREG; } return RoGetActivationFactory(className, Il2CppIActivationFactory::IID, activationFactory); #endif } il2cpp_hresult_t WindowsRuntime::CreateHStringReference(const utils::StringView& str, Il2CppHStringHeader* header, Il2CppHString* hstring) { IL2CPP_ASSERT(header != NULL); IL2CPP_ASSERT(hstring != NULL); if (str.Length() == 0) { *hstring = NULL; return S_OK; } #if LINK_TO_WINDOWSRUNTIME_LIBS return WindowsCreateStringReference(str.Str(), static_cast(str.Length()), reinterpret_cast(header), reinterpret_cast(hstring)); #else typedef HRESULT(STDAPICALLTYPE * WindowsCreateStringReferenceFunc)(const wchar_t* sourceString, uint32_t length, Il2CppHStringHeader* hstringHeader, Il2CppHString* hstring); static WindowsCreateStringReferenceFunc WindowsCreateStringReference = NULL; if (WindowsCreateStringReference == NULL) { WindowsCreateStringReference = ResolveAPI(L"api-ms-win-core-winrt-string-l1-1-0.dll", "WindowsCreateStringReference"); if (WindowsCreateStringReference == NULL) return IL2CPP_COR_E_PLATFORMNOTSUPPORTED; } return WindowsCreateStringReference(str.Str(), static_cast(str.Length()), header, hstring); #endif } il2cpp_hresult_t WindowsRuntime::CreateHString(const utils::StringView& str, Il2CppHString* hstring) { IL2CPP_ASSERT(str.Str() != NULL || str.Length() == 0); if (str.Length() == 0) { *hstring = NULL; return S_OK; } #if LINK_TO_WINDOWSRUNTIME_LIBS return WindowsCreateString(str.Str(), static_cast(str.Length()), reinterpret_cast(hstring)); #else typedef il2cpp_hresult_t (STDAPICALLTYPE * WindowsCreateStringFunc)(const wchar_t* sourceString, uint32_t length, Il2CppHString* hstring); static WindowsCreateStringFunc WindowsCreateString = NULL; if (WindowsCreateString == NULL) { WindowsCreateString = ResolveAPI(L"api-ms-win-core-winrt-string-l1-1-0.dll", "WindowsCreateString"); if (WindowsCreateString == NULL) return IL2CPP_COR_E_PLATFORMNOTSUPPORTED; } return WindowsCreateString(str.Str(), static_cast(str.Length()), hstring); #endif } il2cpp_hresult_t WindowsRuntime::DeleteHString(Il2CppHString hstring) { if (hstring == NULL) return IL2CPP_S_OK; #if LINK_TO_WINDOWSRUNTIME_LIBS return WindowsDeleteString(reinterpret_cast(hstring)); #else typedef il2cpp_hresult_t (STDAPICALLTYPE * WindowsDeleteStringFunc)(Il2CppHString hstring); static WindowsDeleteStringFunc WindowsDeleteString = NULL; if (WindowsDeleteString == NULL) { WindowsDeleteString = ResolveAPI(L"api-ms-win-core-winrt-string-l1-1-0.dll", "WindowsDeleteString"); if (WindowsDeleteString == NULL) return IL2CPP_COR_E_PLATFORMNOTSUPPORTED; } return WindowsDeleteString(hstring); #endif } const Il2CppChar* WindowsRuntime::GetHStringBuffer(Il2CppHString hstring, uint32_t* length) { #if LINK_TO_WINDOWSRUNTIME_LIBS return WindowsGetStringRawBuffer(reinterpret_cast(hstring), length); #else typedef const wchar_t* (STDAPICALLTYPE * WindowsGetStringRawBufferFunc)(Il2CppHString hstring, uint32_t* length); static WindowsGetStringRawBufferFunc WindowsGetStringRawBuffer = NULL; if (WindowsGetStringRawBuffer == NULL) { WindowsGetStringRawBuffer = ResolveAPI(L"api-ms-win-core-winrt-string-l1-1-0.dll", "WindowsGetStringRawBuffer"); if (WindowsGetStringRawBuffer == NULL) IL2CPP_VM_NOT_SUPPORTED(GetHStringBuffer, "Marshaling HSTRINGs is not supported on current platform."); } return WindowsGetStringRawBuffer(hstring, length); #endif } Il2CppString* WindowsRuntime::HStringToManagedString(Il2CppHString hstring) { if (hstring == NULL) return IL2CPP_VM_STRING_EMPTY(); uint32_t length; const wchar_t* ptr = GetHStringBuffer(hstring, &length); return IL2CPP_VM_STRING_NEW_UTF16(ptr, length); } Il2CppIRestrictedErrorInfo* WindowsRuntime::GetRestrictedErrorInfo() { Il2CppIRestrictedErrorInfo* errorInfo; HRESULT hr; #if LINK_TO_WINDOWSRUNTIME_LIBS hr = ::GetRestrictedErrorInfo(reinterpret_cast(&errorInfo)); #else typedef HRESULT (STDAPICALLTYPE * GetRestrictedErrorInfoFunc)(Il2CppIRestrictedErrorInfo** ppRestrictedErrorInfo); static GetRestrictedErrorInfoFunc getRestrictedErrorInfo = NULL; if (getRestrictedErrorInfo == NULL) { getRestrictedErrorInfo = ResolveAPI(L"api-ms-win-core-winrt-error-l1-1-1.dll", "GetRestrictedErrorInfo"); if (getRestrictedErrorInfo == NULL) return NULL; } hr = getRestrictedErrorInfo(&errorInfo); #endif if (FAILED(hr)) return NULL; return errorInfo; } // Fallback path for desktop in case we're running on below Windows 8.1 // Also used for Xbox One as it has no RoOriginateLanguageException static inline void OriginateErrorNoLanguageException(Il2CppException* ex, Il2CppHString message) { #if !LINK_TO_WINDOWSRUNTIME_LIBS typedef BOOL(STDAPICALLTYPE * RoOriginateErrorFunc)(il2cpp_hresult_t error, Il2CppHString message); static RoOriginateErrorFunc RoOriginateError = NULL; if (RoOriginateError == NULL) { RoOriginateError = ResolveAPI(L"api-ms-win-core-winrt-error-l1-1-0.dll", "RoOriginateError"); if (RoOriginateError == NULL) { // We're running on Win7 or below. Give up. return; } } RoOriginateError(ex->hresult, message); #else RoOriginateError(ex->hresult, reinterpret_cast(message)); #endif } #if !IL2CPP_TARGET_XBOXONE inline void OriginateLanguageExceptionWithFallback(Il2CppException* ex, Il2CppHString message) { #if !LINK_TO_WINDOWSRUNTIME_LIBS typedef BOOL(STDAPICALLTYPE * RoOriginateLanguageExceptionFunc)(il2cpp_hresult_t error, Il2CppHString message, Il2CppIUnknown* languageException); static RoOriginateLanguageExceptionFunc RoOriginateLanguageException = NULL; if (RoOriginateLanguageException == NULL) { RoOriginateLanguageException = ResolveAPI(L"api-ms-win-core-winrt-error-l1-1-1.dll", "RoOriginateLanguageException"); if (RoOriginateLanguageException == NULL) { // We're running on Win8 or below. Fallback to RoOriginateError OriginateErrorNoLanguageException(ex, message); return; } } #endif Il2CppIUnknown* exceptionCCW = IL2CPP_VM_GET_CREATE_CCW_EXCEPTION(ex); #if LINK_TO_WINDOWSRUNTIME_LIBS RoOriginateLanguageException(ex->hresult, reinterpret_cast(static_cast(message)), reinterpret_cast(exceptionCCW)); #else RoOriginateLanguageException(ex->hresult, message, exceptionCCW); #endif exceptionCCW->Release(); } #endif // !IL2CPP_TARGET_XBOXONE void WindowsRuntime::OriginateLanguageException(Il2CppException* ex, Il2CppString* exceptionString) { utils::StringView message(utils::StringUtils::GetChars(exceptionString), utils::StringUtils::GetLength(exceptionString)); utils::Il2CppHStringReference messageHString(message); #if IL2CPP_TARGET_XBOXONE OriginateErrorNoLanguageException(ex, messageHString); #else OriginateLanguageExceptionWithFallback(ex, messageHString); #endif } void WindowsRuntime::EnableErrorReporting() { #if !LINK_TO_WINDOWSRUNTIME_LIBS typedef il2cpp_hresult_t (STDCALL * RoSetErrorReportingFlagsFunc)(uint32_t flags); static RoSetErrorReportingFlagsFunc RoSetErrorReportingFlags = NULL; if (RoSetErrorReportingFlags == NULL) { RoSetErrorReportingFlags = ResolveAPI(L"api-ms-win-core-winrt-error-l1-1-0.dll", "RoSetErrorReportingFlags"); // We're running on Win7 or below. Do nothing if (RoSetErrorReportingFlags == NULL) return; } #endif il2cpp_hresult_t hr = RoSetErrorReportingFlags(RO_ERROR_REPORTING_USESETERRORINFO); IL2CPP_ASSERT(IL2CPP_HR_SUCCEEDED(hr) && "RoSetErrorReportingFlags failed"); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/WinRT/Cryptography.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINRT || IL2CPP_TARGET_XBOXONE #include "os/Win32/WindowsHeaders.h" #include "os/Cryptography.h" namespace il2cpp { namespace os { // This has to be non-null value because the return value of NULL from GetCryptographyProvider means it failed void* const kCryptographyProvider = reinterpret_cast(0x12345678); void* Cryptography::GetCryptographyProvider() { return kCryptographyProvider; } bool Cryptography::OpenCryptographyProvider() { return true; } void Cryptography::ReleaseCryptographyProvider(void* provider) { // Do nothing, since we never allocated it } bool Cryptography::FillBufferWithRandomBytes(void* provider, uint32_t length, unsigned char* data) { NO_UNUSED_WARNING(provider); return SUCCEEDED(BCryptGenRandom(NULL, data, length, BCRYPT_USE_SYSTEM_PREFERRED_RNG)); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/WinRT/Environment.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINRT || IL2CPP_TARGET_XBOXONE #include "il2cpp-vm-support.h" #include "os\Environment.h" #include "os\Win32\WindowsHelpers.h" #include "utils\StringUtils.h" #include "vm\Exception.h" #include #include using namespace ABI::Windows::Storage; using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; namespace il2cpp { using namespace vm; namespace os { #define CSIDL_DESKTOP 0x0000 // #define CSIDL_PROGRAMS 0x0002 // Start Menu\Programs #define CSIDL_PERSONAL 0x0005 // My Documents #define CSIDL_FAVORITES 0x0006 // \Favorites #define CSIDL_STARTUP 0x0007 // Start Menu\Programs\Startup #define CSIDL_RECENT 0x0008 // \Recent #define CSIDL_SENDTO 0x0009 // \SendTo #define CSIDL_STARTMENU 0x000b // \Start Menu #define CSIDL_MYMUSIC 0x000d // "My Music" folder #define CSIDL_MYVIDEO 0x000e // "My Videos" folder #define CSIDL_DESKTOPDIRECTORY 0x0010 // \Desktop #define CSIDL_DRIVES 0x0011 // My Computer #define CSIDL_NETWORK 0x0012 // Network Neighborhood (My Network Places) #define CSIDL_NETHOOD 0x0013 // \nethood #define CSIDL_FONTS 0x0014 // windows\fonts #define CSIDL_TEMPLATES 0x0015 #define CSIDL_COMMON_STARTMENU 0x0016 // All Users\Start Menu #define CSIDL_COMMON_PROGRAMS 0X0017 // All Users\Start Menu\Programs #define CSIDL_COMMON_STARTUP 0x0018 // All Users\Startup #define CSIDL_COMMON_DESKTOPDIRECTORY 0x0019 // All Users\Desktop #define CSIDL_APPDATA 0x001a // \Application Data #define CSIDL_PRINTHOOD 0x001b // \PrintHood #define CSIDL_LOCAL_APPDATA 0x001c // \Local Settings\Applicaiton Data (non roaming) #define CSIDL_ALTSTARTUP 0x001d // non localized startup #define CSIDL_COMMON_ALTSTARTUP 0x001e // non localized common startup #define CSIDL_COMMON_FAVORITES 0x001f #define CSIDL_INTERNET_CACHE 0x0020 #define CSIDL_COOKIES 0x0021 #define CSIDL_HISTORY 0x0022 #define CSIDL_COMMON_APPDATA 0x0023 // All Users\Application Data #define CSIDL_WINDOWS 0x0024 // GetWindowsDirectory() #define CSIDL_SYSTEM 0x0025 // GetSystemDirectory() #define CSIDL_PROGRAM_FILES 0x0026 // C:\Program Files #define CSIDL_MYPICTURES 0x0027 // C:\Program Files\My Pictures #define CSIDL_PROFILE 0x0028 // USERPROFILE #define CSIDL_SYSTEMX86 0x0029 // x86 system directory on RISC #define CSIDL_PROGRAM_FILESX86 0x002a // x86 C:\Program Files on RISC #define CSIDL_PROGRAM_FILES_COMMON 0x002b // C:\Program Files\Common #define CSIDL_PROGRAM_FILES_COMMONX86 0x002c // x86 Program Files\Common on RISC #define CSIDL_COMMON_TEMPLATES 0x002d // All Users\Templates #define CSIDL_COMMON_DOCUMENTS 0x002e // All Users\Documents #define CSIDL_COMMON_ADMINTOOLS 0x002f // All Users\Start Menu\Programs\Administrative Tools #define CSIDL_ADMINTOOLS 0x0030 // \Start Menu\Programs\Administrative Tools #define CSIDL_CONNECTIONS 0x0031 // Network and Dial-up Connections #define CSIDL_COMMON_MUSIC 0x0035 // All Users\My Music #define CSIDL_COMMON_PICTURES 0x0036 // All Users\My Pictures #define CSIDL_COMMON_VIDEO 0x0037 // All Users\My Video #define CSIDL_RESOURCES 0x0038 // Resource Direcotry #define CSIDL_RESOURCES_LOCALIZED 0x0039 // Localized Resource Direcotry #define CSIDL_COMMON_OEM_LINKS 0x003a // Links to All Users OEM specific apps #define CSIDL_CDBURN_AREA 0x003b // USERPROFILE\Local Settings\Application Data\Microsoft\CD Burning #define CSIDL_COMPUTERSNEARME 0x003d // Computers Near Me (computered from Workgroup membership) template static inline std::string GetAppFolder(T appDataToStorageFolder) { ComPtr appDataStatics; ComPtr appData; ComPtr appDataFolder; ComPtr appDataFolderItem; HString appDataPath; auto hr = RoGetActivationFactory(HStringReference(RuntimeClass_Windows_Storage_ApplicationData).Get(), __uuidof(IApplicationDataStatics), &appDataStatics); IL2CPP_VM_RAISE_IF_FAILED(hr, false); hr = appDataStatics->get_Current(&appData); IL2CPP_VM_RAISE_IF_FAILED(hr, false); hr = appDataToStorageFolder(appData.Get(), &appDataFolder); IL2CPP_VM_RAISE_IF_FAILED(hr, false); hr = appDataFolder.As(&appDataFolderItem); IL2CPP_VM_RAISE_IF_FAILED(hr, false); hr = appDataFolderItem->get_Path(appDataPath.GetAddressOf()); IL2CPP_VM_RAISE_IF_FAILED(hr, false); unsigned int dummy; return utils::StringUtils::Utf16ToUtf8(appDataPath.GetRawBuffer(&dummy)); } static inline std::string GetLocalAppDataFolder() { return GetAppFolder([](IApplicationData* appData, IStorageFolder** folder) { return appData->get_LocalFolder(folder); }); } #if !IL2CPP_TARGET_XBOXONE static inline std::string GetRoamingAppDataFolder() { return GetAppFolder([](IApplicationData* appData, IStorageFolder** folder) { return appData->get_RoamingFolder(folder); }); } #endif std::string Environment::GetWindowsFolderPath(int32_t folder) { switch (folder) { #if !IL2CPP_TARGET_XBOXONE case CSIDL_APPDATA: return GetRoamingAppDataFolder(); #endif case CSIDL_LOCAL_APPDATA: return GetLocalAppDataFolder(); default: Exception::Raise(Exception::GetUnauthorizedAccessException(L"Failed getting the path of a special folder: Access Denied.")); } } #if NET_4_0 bool Environment::Is64BitOs() { #if IL2CPP_TARGET_WINRT vm::Exception::Raise(vm::Exception::GetPlatformNotSupportedException(L"It is not possible to check if the OS is a 64bit OS on the current platform.")); #endif return true; } #endif } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/WinRT/File.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINRT || IL2CPP_TARGET_XBOXONE #include #include "os/File.h" #include "os/Win32/WindowsHeaders.h" namespace il2cpp { namespace os { static inline std::wstring GetDirectoryForStandardOutput() { #if IL2CPP_TARGET_XBOXONE return L"D:\\"; #elif IL2CPP_TARGET_WINRT wchar_t buffer[MAX_PATH + 2]; uint32_t tempPathLength = GetTempPathW(MAX_PATH + 2, buffer); return std::wstring(buffer, tempPathLength); #else #error Unknown platform #endif } static FileHandle* GetOrCreateRedirectedHandle(FILE* stdFile, const wchar_t* fileNameOnDisk) { #if IL2CPP_DEBUG || IL2CPP_DEVELOPMENT auto stdFd = _fileno(stdFile); auto stdHandle = reinterpret_cast(_get_osfhandle(stdFd)); if (stdHandle != INVALID_HANDLE_VALUE && !_isatty(stdFd)) return stdHandle; std::wstring pathOnDisk = GetDirectoryForStandardOutput() + fileNameOnDisk; auto redirectedFile = _wfreopen(pathOnDisk.c_str(), L"w+", stdFile); return reinterpret_cast(_get_osfhandle(_fileno(redirectedFile))); #else return NULL; #endif } bool File::Isatty(FileHandle* fileHandle) { NOT_IMPLEMENTED_ICALL(File::IsAtty); return false; } FileHandle* File::GetStdInput() { return GetOrCreateRedirectedHandle(stdin, L"stdin.txt"); } FileHandle* File::GetStdError() { return GetOrCreateRedirectedHandle(stderr, L"stderr.txt"); } FileHandle* File::GetStdOutput() { return GetOrCreateRedirectedHandle(stdout, L"stdout.txt"); } } //os } //il2cpp #endif ================================================ FILE: unity_decoder/libil2cpp/os/WinRT/Initialize.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINRT || IL2CPP_TARGET_XBOXONE #include "os/Initialize.h" #include "os/Win32/WindowsHelpers.h" #include void il2cpp::os::Uninitialize() { HANDLE stdoutHandle = reinterpret_cast(_get_osfhandle(_fileno(stdout))); HANDLE stderrHandle = reinterpret_cast(_get_osfhandle(_fileno(stderr))); if (stdoutHandle != INVALID_HANDLE_VALUE) FlushFileBuffers(stdoutHandle); if (stderrHandle != INVALID_HANDLE_VALUE) FlushFileBuffers(stderrHandle); } #endif ================================================ FILE: unity_decoder/libil2cpp/os/WinRT/Locale.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINRT || IL2CPP_TARGET_XBOXONE #include "os/Locale.h" #include "os/Win32/WindowsHeaders.h" #include namespace il2cpp { namespace os { std::string Locale::GetLocale() { WCHAR wideLocaleName[LOCALE_NAME_MAX_LENGTH]; if (GetUserDefaultLocaleName(wideLocaleName, LOCALE_NAME_MAX_LENGTH) == 0) return std::string(); int length = static_cast(wcslen(wideLocaleName)); std::string multiLocaleName; multiLocaleName.resize(2 * length); int narrowLength = WideCharToMultiByte(CP_ACP, 0, &wideLocaleName[0], length, &multiLocaleName[0], 2 * length, NULL, NULL); multiLocaleName.resize(narrowLength); return multiLocaleName; } } /* namespace os */ } /* namespace il2cpp */ #endif ================================================ FILE: unity_decoder/libil2cpp/os/WinRT/Process.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINRT || IL2CPP_TARGET_XBOXONE #include "os/Win32/WindowsHeaders.h" #include "os/Process.h" #include "utils/StringUtils.h" #include "vm/Exception.h" struct ProcessHandle { HANDLE handle; }; namespace il2cpp { namespace os { int Process::GetCurrentProcessId() { return ::GetCurrentProcessId(); } ProcessHandle* Process::GetProcess(int processId) { if (processId == GetCurrentProcessId()) return (ProcessHandle*)::GetCurrentProcess(); vm::Exception::Raise(vm::Exception::GetPlatformNotSupportedException(L"It is not possible to interact with other system processes on current platform.")); } void Process::FreeProcess(ProcessHandle* handle) { // We have nothing to do here. } std::string Process::GetProcessName(ProcessHandle* handle) { if (handle == ::GetCurrentProcess()) { wchar_t path[MAX_PATH + 1]; SetLastError(ERROR_SUCCESS); DWORD pathLength = GetModuleFileNameW(NULL, path, MAX_PATH + 1); return utils::StringUtils::Utf16ToUtf8(path, static_cast(pathLength)); } vm::Exception::Raise(vm::Exception::GetPlatformNotSupportedException(L"It is not possible to interact with other system processes on current platform.")); } } } #endif ================================================ FILE: unity_decoder/libil2cpp/os/WinRT/SynchronousOperation.h ================================================ #pragma once #include "os/Win32/WindowsHeaders.h" #include #include namespace il2cpp { namespace winrt { template class SynchronousOperation : Microsoft::WRL::RuntimeClass, ABI::Windows::Foundation::IAsyncOperationCompletedHandler > { private: HANDLE m_Event; HRESULT m_HR; T m_Result; public: inline SynchronousOperation(ABI::Windows::Foundation::IAsyncOperation* op) { m_Event = CreateEventExW(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); Assert(m_Event); auto hr = op->put_Completed(this); Assert(SUCCEEDED(hr)); } inline ~SynchronousOperation() { CloseHandle(m_Event); } HRESULT GetResults(T* result) { auto waitResult = WaitForSingleObjectEx(m_Event, INFINITE, FALSE); if (waitResult != WAIT_OBJECT_0) return E_FAIL; if (FAILED(m_HR)) return m_HR; *result = m_Result; return S_OK; } private: virtual HRESULT STDMETHODCALLTYPE Invoke(ABI::Windows::Foundation::IAsyncOperation* asyncInfo, ABI::Windows::Foundation::AsyncStatus status) override { m_HR = asyncInfo->GetResults(&m_Result); SetEvent(m_Event); return S_OK; } }; } } ================================================ FILE: unity_decoder/libil2cpp/os/WinRT/Win32ApiSharedEmulation.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINRT || IL2CPP_TARGET_XBOXONE #include "os/Win32/WindowsHeaders.h" #include "Win32ApiSharedEmulation.h" #include #include #include using namespace il2cpp::winrt; using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::Windows::Foundation; using namespace ABI::Windows::Foundation::Collections; using namespace ABI::Windows::Networking; using namespace ABI::Windows::Networking::Connectivity; using namespace ABI::Windows::Storage; extern "C" { BOOL WINAPI GetComputerNameW(LPWSTR lpBuffer, LPDWORD nSize) { #define ERROR_CHECK(hr) do { if (FAILED(hr)) { SetLastError(WIN32_FROM_HRESULT(hr)); return FALSE; } } while (false) ComPtr info; auto hr = RoGetActivationFactory(HStringReference(RuntimeClass_Windows_Networking_Connectivity_NetworkInformation).Get(), __uuidof(info), &info); ERROR_CHECK(hr); ComPtr > names; hr = info->GetHostNames(&names); ERROR_CHECK(hr); unsigned int size; hr = names->get_Size(&size); if (FAILED(hr) || !size) { SetLastError(WIN32_FROM_HRESULT(hr)); return FALSE; } ComPtr name; hr = names->GetAt(0, &name); ERROR_CHECK(hr); HString displayName; hr = name->get_DisplayName(displayName.GetAddressOf()); ERROR_CHECK(hr); #undef ERROR_CHECK return CopyHStringToBuffer(displayName, lpBuffer, nSize); } } // extern "C" #endif ================================================ FILE: unity_decoder/libil2cpp/os/WinRT/Win32ApiSharedEmulation.h ================================================ #pragma once #if IL2CPP_TARGET_WINRT || IL2CPP_TARGET_XBOXONE #include "os/Win32/WindowsHeaders.h" #include #define MAX_COMPUTERNAME_LENGTH 31 namespace il2cpp { namespace winrt { inline DWORD WIN32_FROM_HRESULT(HRESULT hr) { if ((hr & 0xFFFF0000) == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, 0)) return HRESULT_CODE(hr); if (hr == S_OK) return HRESULT_CODE(hr); return ERROR_SUCCESS; } inline static BOOL CopyHStringToBuffer(Microsoft::WRL::Wrappers::HString& source, LPWSTR target, LPDWORD targetSize) { unsigned int sourceLength; auto sourceBuffer = source.GetRawBuffer(&sourceLength); if (sourceLength > *targetSize - 1) { SetLastError(ERROR_BUFFER_OVERFLOW); *targetSize = sourceLength + 1; return FALSE; } memcpy(target, sourceBuffer, sourceLength * sizeof(wchar_t)); target[sourceLength] = L'\0'; *targetSize = sourceLength; return TRUE; } } } extern "C" { #define GetComputerName GetComputerNameW inline BOOL WINAPI CopyFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, BOOL bFailIfExists) { COPYFILE2_EXTENDED_PARAMETERS params; params.dwSize = sizeof(params); params.dwCopyFlags = bFailIfExists ? COPY_FILE_FAIL_IF_EXISTS : 0; params.pfCancel = FALSE; params.pProgressRoutine = nullptr; params.pvCallbackContext = nullptr; auto hr = CopyFile2(lpExistingFileName, lpNewFileName, ¶ms); if (FAILED(hr)) { SetLastError(il2cpp::winrt::WIN32_FROM_HRESULT(hr)); return FALSE; } return TRUE; } inline UINT WINAPI GetACP() { return CP_ACP; } BOOL WINAPI GetComputerNameW(LPWSTR lpBuffer, LPDWORD nSize); } // extern "C" #endif ================================================ FILE: unity_decoder/libil2cpp/os/WinRT/Win32ApiWinRTEmulation.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_TARGET_WINRT #include "os/Win32/WindowsHeaders.h" #include #include #include #include "os/Mutex.h" #include "SynchronousOperation.h" #include "utils/Il2CppHashMap.h" #include "utils/Memory.h" #include "utils/StringUtils.h" #include "Win32ApiSharedEmulation.h" #include "Win32ApiWinRTEmulation.h" using namespace ABI::Windows::Foundation; using namespace ABI::Windows::System::Profile; using namespace ABI::Windows::System::UserProfile; using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace il2cpp::winrt; struct WideStringHash { public: size_t operator()(const std::wstring& str) const { return Hash(str); } static size_t Hash(const std::wstring& str) { return il2cpp::utils::StringUtils::Hash((const char*)str.c_str(), sizeof(std::wstring::value_type) * str.length()); } }; typedef Il2CppHashMap EnvironmentVariableMap; static EnvironmentVariableMap s_EnvironmentVariables; static il2cpp::os::FastMutex s_EnvironmentVariablesMutex; extern "C" { BOOL WINAPI FreeEnvironmentStringsW(LPWCH strings) { IL2CPP_FREE(strings); return TRUE; } LPWCH WINAPI GetEnvironmentStringsW() { il2cpp::os::FastAutoLock lock(&s_EnvironmentVariablesMutex); // Two iterations // 1) Figure out length // 2) Make result string size_t length = 0; for (EnvironmentVariableMap::const_iterator it = s_EnvironmentVariables.begin(); it != s_EnvironmentVariables.end(); it++) { // Key + value + '=' + '\0' length += it->first.key.length() + it->second.length() + 2; } // Terminating '\0' length++; LPWCH result = static_cast(IL2CPP_MALLOC(length * sizeof(WCHAR))); size_t index = 0; for (EnvironmentVariableMap::const_iterator it = s_EnvironmentVariables.begin(); it != s_EnvironmentVariables.end(); it++) { const size_t keyLength = it->first.key.length(); const size_t valueLength = it->second.length(); memcpy(result + index, it->first.key.c_str(), keyLength * sizeof(WCHAR)); index += keyLength; result[index++] = L'='; memcpy(result + index, it->second.c_str(), valueLength * sizeof(WCHAR)); index += valueLength; result[index++] = '\0'; } result[index++] = '\0'; IL2CPP_ASSERT(index == length); return result; } DWORD WINAPI GetEnvironmentVariableW(LPCWSTR lpName, LPWSTR lpBuffer, DWORD nSize) { il2cpp::os::FastAutoLock lock(&s_EnvironmentVariablesMutex); std::wstring key(lpName); auto it = s_EnvironmentVariables.find(key); if (it == s_EnvironmentVariables.end()) return 0; DWORD sizeNeeded = static_cast(it->second.length()); if (nSize < sizeNeeded) { SetLastError(ERROR_BUFFER_OVERFLOW); } else { memcpy(lpBuffer, it->second.data(), (sizeNeeded + 1) * sizeof(wchar_t)); } return sizeNeeded; } BOOL WINAPI GetVersionExW(LPOSVERSIONINFOW lpVersionInformation) { Assert(lpVersionInformation->dwOSVersionInfoSize == sizeof(OSVERSIONINFOW)); #define ERROR_CHECK(hr) do { if (FAILED(hr)) { SetLastError(WIN32_FROM_HRESULT(hr)); return FALSE; } } while (false) ComPtr analytics; auto hr = RoGetActivationFactory(HStringReference(RuntimeClass_Windows_System_Profile_AnalyticsInfo).Get(), __uuidof(IAnalyticsInfoStatics), &analytics); ERROR_CHECK(hr); ComPtr versionInfo; hr = analytics->get_VersionInfo(&versionInfo); ERROR_CHECK(hr); HString versionString; hr = versionInfo->get_DeviceFamilyVersion(versionString.GetAddressOf()); ERROR_CHECK(hr); #undef ERROR_CHECK unsigned int dummy; int64_t versionNumber = _wtoi64(versionString.GetRawBuffer(&dummy)); if (versionNumber == 0) { SetLastError(ERROR_VERSION_PARSE_ERROR); return FALSE; } lpVersionInformation->dwMajorVersion = versionNumber >> 48; lpVersionInformation->dwMinorVersion = (versionNumber >> 32) & 0xFFFF; lpVersionInformation->dwBuildNumber = (versionNumber >> 16) & 0xFFFF; lpVersionInformation->dwPlatformId = VER_PLATFORM_WIN32_NT; ZeroMemory(lpVersionInformation->szCSDVersion, sizeof(lpVersionInformation->szCSDVersion)); return TRUE; } BOOL WINAPI SetEnvironmentVariableW(LPCWSTR lpName, LPCWSTR lpValue) { il2cpp::os::FastAutoLock lock(&s_EnvironmentVariablesMutex); if (lpValue != NULL) { s_EnvironmentVariables[std::wstring(lpName)] = lpValue; } else { s_EnvironmentVariables.erase(std::wstring(lpName)); } return TRUE; } BOOL WINAPI GetUserNameW(LPWSTR lpBuffer, LPDWORD pcbBuffer) { #define ERROR_CHECK(hr) do { if (FAILED(hr)) { SetLastError(WIN32_FROM_HRESULT(hr)); return FALSE; } } while (false) ComPtr info; auto hr = RoGetActivationFactory(HStringReference(RuntimeClass_Windows_System_UserProfile_UserInformation).Get(), __uuidof(info), &info); ERROR_CHECK(hr); boolean isAccessAllowed; hr = info->get_NameAccessAllowed(&isAccessAllowed); ERROR_CHECK(hr); if (!isAccessAllowed) { SetLastError(ERROR_ACCESS_DENIED); return FALSE; } ComPtr > op; hr = info->GetDisplayNameAsync(&op); ERROR_CHECK(hr); HString name; hr = SynchronousOperation(op.Get()).GetResults(name.GetAddressOf()); ERROR_CHECK(hr); #undef ERROR_CHECK return CopyHStringToBuffer(name, lpBuffer, pcbBuffer); } } // extern "C" #endif ================================================ FILE: unity_decoder/libil2cpp/os/WinRT/Win32ApiWinRTEmulation.h ================================================ #pragma once #if IL2CPP_TARGET_WINRT extern "C" { #define CreateEvent CreateEventW #define FreeEnvironmentStrings FreeEnvironmentStringsW #define GetEnvironmentStrings GetEnvironmentStringsW #define GetEnvironmentVariable GetEnvironmentVariableW #define GetVersionEx GetVersionExW #define GetUserName GetUserNameW #define SetEnvironmentVariable SetEnvironmentVariableW inline HANDLE WINAPI CreateEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCWSTR lpName) { DWORD flags = 0; if (bManualReset) flags |= CREATE_EVENT_MANUAL_RESET; if (bInitialState) flags |= CREATE_EVENT_INITIAL_SET; return CreateEventExW(lpEventAttributes, lpName, flags, EVENT_ALL_ACCESS); } inline HANDLE WINAPI CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { const DWORD kFileAttributeMask = 0x0000FFFF; const DWORD kFileFlagMask = 0xFFFF0000; CREATEFILE2_EXTENDED_PARAMETERS extendedParameters; extendedParameters.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); extendedParameters.dwFileAttributes = dwFlagsAndAttributes & kFileAttributeMask; extendedParameters.dwFileFlags = dwFlagsAndAttributes & kFileFlagMask; extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS; extendedParameters.lpSecurityAttributes = lpSecurityAttributes; extendedParameters.hTemplateFile = hTemplateFile; return CreateFile2(lpFileName, dwDesiredAccess, dwShareMode, dwCreationDisposition, &extendedParameters); } BOOL WINAPI FreeEnvironmentStringsW(LPWCH strings); LPWCH WINAPI GetEnvironmentStringsW(); DWORD WINAPI GetEnvironmentVariableW(LPCWSTR lpName, LPWSTR lpBuffer, DWORD nSize); BOOL WINAPI GetUserNameW(LPWSTR lpBuffer, LPDWORD pcbBuffer); BOOL WINAPI GetVersionExW(LPOSVERSIONINFOW lpVersionInformation); inline HMODULE WINAPI LoadLibraryW(LPCWSTR lpLibFileName) { return LoadPackagedLibrary(lpLibFileName, 0); } BOOL WINAPI SetEnvironmentVariableW(LPCWSTR lpName, LPCWSTR lpValue); #define CreateFileMappingW(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName) \ CreateFileMappingFromApp(hFile, lpFileMappingAttributes, flProtect, (static_cast(dwMaximumSizeHigh) << 32) | dwMaximumSizeLow, lpName); #define MapViewOfFile(hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap) \ MapViewOfFileFromApp(hFileMappingObject, dwDesiredAccess, (static_cast(dwFileOffsetHigh) << 32) | dwFileOffsetLow, dwNumberOfBytesToMap); #define TlsAlloc() FlsAlloc(NULL) #define TlsGetValue FlsGetValue #define TlsSetValue FlsSetValue #define TlsFree FlsFree } // extern "C" #endif ================================================ FILE: unity_decoder/libil2cpp/os/WindowsRuntime.h ================================================ #pragma once #include "object-internals.h" #include "utils/StringView.h" namespace il2cpp { namespace os { class LIBIL2CPP_CODEGEN_API WindowsRuntime { public: static il2cpp_hresult_t GetActivationFactory(Il2CppHString className, Il2CppIActivationFactory** activationFactory); static il2cpp_hresult_t CreateHStringReference(const utils::StringView& str, Il2CppHStringHeader* header, Il2CppHString* hstring); static il2cpp_hresult_t CreateHString(const utils::StringView& str, Il2CppHString* hstring); static il2cpp_hresult_t DeleteHString(Il2CppHString hstring); static const Il2CppChar* GetHStringBuffer(Il2CppHString hstring, uint32_t* length); static Il2CppString* HStringToManagedString(Il2CppHString hstring); static Il2CppIRestrictedErrorInfo* GetRestrictedErrorInfo(); static void OriginateLanguageException(Il2CppException* ex, Il2CppString* exceptionString); static void EnableErrorReporting(); }; } } ================================================ FILE: unity_decoder/libil2cpp/os/c-api/Allocator.cpp ================================================ #include "Allocator.h" static allocate_func s_Allocator; extern "C" { void register_allocator(allocate_func allocator) { s_Allocator = allocator; } } void* Allocator::Allocate(size_t size) { IL2CPP_ASSERT(s_Allocator); return s_Allocator(size); } char* Allocator::CopyToAllocatedStringBuffer(const std::string& input) { size_t size = input.size(); char* buffer = (char*)Allocator::Allocate(size + 1); input.copy(buffer, size); buffer[size] = '\0'; return buffer; } ================================================ FILE: unity_decoder/libil2cpp/os/c-api/Allocator.h ================================================ #pragma once #include "il2cpp-config.h" typedef void* (*allocate_func)(size_t size); #if defined(__cplusplus) extern "C" { #endif void register_allocator(allocate_func allocator); #if defined(__cplusplus) } #endif #if defined(__cplusplus) #include class Allocator { public: static void* Allocate(size_t size); static char* CopyToAllocatedStringBuffer(const std::string& input); }; #endif ================================================ FILE: unity_decoder/libil2cpp/os/c-api/File-c-api.h ================================================ #pragma once #include "os/OSGlobalEnums.h" #if defined(__cplusplus) #include "os/ErrorCodes.h" #include "os/File.h" typedef il2cpp::os::FileHandle UnityPalFileHandle; typedef il2cpp::os::FileStat UnityPalFileStat; #else typedef struct UnityPalFileHandle UnityPalFileHandle; struct UnityPalFileStat { char* name; int32_t attributes; int64_t length; int64_t creation_time; int64_t last_access_time; int64_t last_write_time; } UnityPalFileStat; #endif //__cplusplus #if defined(__cplusplus) extern "C" { #endif bool UnityPalIsatty(UnityPalFileHandle* fileHandle); UnityPalFileHandle* UnityPalGetStdInput(); UnityPalFileHandle* UnityPalGetStdOutput(); UnityPalFileHandle* UnityPalGetStdError(); bool UnityPalCreatePipe(UnityPalFileHandle** read_handle, UnityPalFileHandle** write_handle); bool UnityPalCreatePipe_with_error(UnityPalFileHandle** read_handle, UnityPalFileHandle** write_handle, int* error); FileType UnityPalGetFileType(UnityPalFileHandle* handle); UnityPalFileAttributes UnityPalGetFileAttributes(const char* path, int* error); bool UnityPalSetFileAttributes(const char* path, UnityPalFileAttributes attributes, int* error); bool UnityPalGetFileStat(const char* path, UnityPalFileStat * stat, int* error); bool UnityPalCopyFile(const char* src, const char* dest, bool overwrite, int* error); bool UnityPalMoveFile(const char* src, const char* dest, int* error); bool UnityPalDeleteFile(const char* path, int *error); bool UnityPalReplaceFile(const char* sourceFileName, const char* destinationFileName, const char* destinationBackupFileName, bool ignoreMetadataErrors, int* error); UnityPalFileHandle* UnityPalOpen(const char* path, int openMode, int accessMode, int shareMode, int options, int *error); bool UnityPalClose(UnityPalFileHandle* handle, int *error); bool UnityPalSetFileTime(UnityPalFileHandle* handle, int64_t creation_time, int64_t last_access_time, int64_t last_write_time, int* error); int64_t UnityPalGetLength(UnityPalFileHandle* handle, int *error); bool UnityPalSetLength(UnityPalFileHandle* handle, int64_t length, int *error); int64_t UnityPalSeek(UnityPalFileHandle* handle, int64_t offset, int origin, int *error); int UnityPalRead(UnityPalFileHandle* handle, char *dest, int count, int *error); int32_t UnityPalWrite(UnityPalFileHandle* handle, const char* buffer, int count, int *error); bool UnityPalFlush(UnityPalFileHandle* handle, int* error); void UnityPalLock(UnityPalFileHandle* handle, int64_t position, int64_t length, int* error); void UnityPalUnlock(UnityPalFileHandle* handle, int64_t position, int64_t length, int* error); bool UnityPalDuplicateHandle(UnityPalFileHandle* source_process_handle, UnityPalFileHandle* source_handle, UnityPalFileHandle* target_process_handle, UnityPalFileHandle** target_handle, int access, int inherit, int options, int* error); #if defined(__cplusplus) } #endif ================================================ FILE: unity_decoder/libil2cpp/os/c-api/File.cpp ================================================ #include "os/File.h" #include "os/c-api/File-c-api.h" extern "C" { bool UnityPalIsatty(UnityPalFileHandle* fileHandle) { return il2cpp::os::File::Isatty(fileHandle); } UnityPalFileHandle* UnityPalGetStdInput() { return il2cpp::os::File::GetStdInput(); } UnityPalFileHandle* UnityPalGetStdOutput() { return il2cpp::os::File::GetStdOutput(); } UnityPalFileHandle* UnityPalGetStdError() { return il2cpp::os::File::GetStdError(); } bool UnityPalCreatePipe(UnityPalFileHandle** read_handle, UnityPalFileHandle** write_handle) { return il2cpp::os::File::CreatePipe(read_handle, write_handle); } bool UnityPalCreatePipe_With_Error(UnityPalFileHandle** read_handle, UnityPalFileHandle** write_handle, int* error) { return il2cpp::os::File::CreatePipe(read_handle, write_handle, error); } FileType UnityPalGetFileType(UnityPalFileHandle* handle) { return il2cpp::os::File::GetFileType(handle); } UnityPalFileAttributes UnityPalGetFileAttributes(const char* path, int* error) { return il2cpp::os::File::GetFileAttributes(path, error); } bool UnityPalSetFileAttributes(const char* path, UnityPalFileAttributes attributes, int* error) { return il2cpp::os::File::SetFileAttributes(path, attributes, error); } bool UnityPalGetFileStat(const char* path, UnityPalFileStat * stat, int* error) { return il2cpp::os::File::GetFileStat(path, stat, error); } bool UnityPalCopyFile(const char* src, const char* dest, bool overwrite, int* error) { return il2cpp::os::File::CopyFile(src, dest, overwrite, error); } bool UnityPalMoveFile(const char* src, const char* dest, int* error) { return il2cpp::os::File::MoveFile(src, dest, error); } bool UnityPalDeleteFile(const char* path, int *error) { return il2cpp::os::File::DeleteFile(path, error); } bool UnityPalReplaceFile(const char* sourceFileName, const char* destinationFileName, const char* destinationBackupFileName, bool ignoreMetadataErrors, int* error) { return il2cpp::os::File::ReplaceFile(sourceFileName, destinationFileName, destinationBackupFileName, ignoreMetadataErrors, error); } UnityPalFileHandle* UnityPalOpen(const char* path, int openMode, int accessMode, int shareMode, int options, int *error) { return il2cpp::os::File::Open(path, openMode, accessMode, shareMode, options, error); } bool UnityPalClose(UnityPalFileHandle* handle, int *error) { return il2cpp::os::File::Close(handle, error); } bool UnityPalSetFileTime(UnityPalFileHandle* handle, int64_t creation_time, int64_t last_access_time, int64_t last_write_time, int* error) { return il2cpp::os::File::SetFileTime(handle, creation_time, last_access_time, last_write_time, error); } int64_t UnityPalGetLength(UnityPalFileHandle* handle, int *error) { return il2cpp::os::File::GetLength(handle, error); } bool UnityPalSetLength(UnityPalFileHandle* handle, int64_t length, int *error) { return il2cpp::os::File::SetLength(handle, length, error); } int64_t UnityPalSeek(UnityPalFileHandle* handle, int64_t offset, int origin, int *error) { return il2cpp::os::File::Seek(handle, offset, origin, error); } int UnityPalRead(UnityPalFileHandle* handle, char *dest, int count, int *error) { return il2cpp::os::File::Read(handle, dest, count, error); } int32_t UnityPalWrite(UnityPalFileHandle* handle, const char* buffer, int count, int *error) { return il2cpp::os::File::Write(handle, buffer, count, error); } bool UnityPalFlush(UnityPalFileHandle* handle, int* error) { return il2cpp::os::File::Flush(handle, error); } void UnityPalLock(UnityPalFileHandle* handle, int64_t position, int64_t length, int* error) { return il2cpp::os::File::Lock(handle, position, length, error); } void UnityPalUnlock(UnityPalFileHandle* handle, int64_t position, int64_t length, int* error) { return il2cpp::os::File::Unlock(handle, position, length, error); } bool UnityPalDuplicateHandle(UnityPalFileHandle* source_process_handle, UnityPalFileHandle* source_handle, UnityPalFileHandle* target_process_handle, UnityPalFileHandle** target_handle, int access, int inherit, int options, int* error) { return il2cpp::os::File::DuplicateHandle(source_process_handle, source_handle, target_process_handle, target_handle, access, inherit, options, error); } } ================================================ FILE: unity_decoder/libil2cpp/os/c-api/NativeMethods-c-api.h ================================================ #pragma once #include #include "os/c-api/Process_c_api.h" #if defined(__cplusplus) extern "C" { #endif bool UnityPalNativeCloseProcess(UnityPalProcessHandle* handle); bool UnityPalNativeGetExitCodeProcess(UnityPalProcessHandle* handle, int32_t* exitCode); int32_t UnityPalNativeGetCurrentProcessId(); UnityPalProcessHandle* UnityPalNativeGetCurrentProcess(); #if defined(__cplusplus) } #endif ================================================ FILE: unity_decoder/libil2cpp/os/c-api/NativeMethods.cpp ================================================ #include "os/NativeMethods.h" #include "os/c-api/Process-c-api.h" extern "C" { bool UnityPalNativeCloseProcess(UnityPalProcessHandle* handle) { return il2cpp::os::NativeMethods::CloseProcess(handle); } bool UnityPalNativeGetExitCodeProcess(UnityPalProcessHandle* handle, int32_t* exitCode) { return il2cpp::os::NativeMethods::GetExitCodeProcess(handle, exitCode); } int32_t UnityPalNativeGetCurrentProcessId() { return il2cpp::os::NativeMethods::GetCurrentProcessId(); } UnityPalProcessHandle* UnityPalNativeGetCurrentProcess() { return il2cpp::os::NativeMethods::GetCurrentProcess(); } } ================================================ FILE: unity_decoder/libil2cpp/os/c-api/Path-c-api.h ================================================ #pragma once #if defined(__cplusplus) extern "C" { #endif char* UnityPalGetExecutablePath(); char* UnityPalGetTempPath(); #if defined(__cplusplus) } #endif ================================================ FILE: unity_decoder/libil2cpp/os/c-api/Path.cpp ================================================ #include "os/Path.h" #include "Allocator.h" #include extern "C" { const char* UnityPalGetTempPath() { return Allocator::CopyToAllocatedStringBuffer(il2cpp::os::Path::GetTempPath()); } const char* UnityPalGetExecutablePath() { return Allocator::CopyToAllocatedStringBuffer(il2cpp::os::Path::GetExecutablePath()); } } ================================================ FILE: unity_decoder/libil2cpp/os/c-api/Process-c-api.h ================================================ #pragma once #if defined(__cplusplus) typedef il2cpp::os::ProcessHandle UnityPalProcessHandle; #else typedef struct UnityPalProcessHandle UnityPalProcessHandle; #endif //__cplusplus #if defined(__cplusplus) extern "C" { #endif int UnityPalGetCurrentProcessId(); UnityPalProcessHandle* UnityPalGetProcess(int processId); void UnityPalFreeProcess(UnityPalProcessHandle* handle); const char* UnityPalGetProcessName(UnityPalProcessHandle* handle); #if defined(__cplusplus) } #endif ================================================ FILE: unity_decoder/libil2cpp/os/c-api/Process.cpp ================================================ #include "os/Process.h" #include "os/c-api/Process-c-api.h" #include "Allocator.h" #include extern "C" { int UnityPalGetCurrentProcessId() { return il2cpp::os::Process::GetCurrentProcessId(); } UnityPalProcessHandle* UnityPalGetProcess(int processId) { return il2cpp::os::Process::GetProcess(processId); } void UnityPalFreeProcess(UnityPalProcessHandle* handle) { return il2cpp::os::Process::FreeProcess(handle); } const char* UnityPalGetProcessName(UnityPalProcessHandle* handle) { return Allocator::CopyToAllocatedStringBuffer(il2cpp::os::Process::GetProcessName(handle)); } } ================================================ FILE: unity_decoder/libil2cpp/os/c-api/Time-c-api.h ================================================ #pragma once #include #if defined(__cplusplus) extern "C" { #endif uint32_t UnityPalGetTicksMillisecondsMonotonic(); int64_t UnityPalGetTicks100NanosecondsMonotonic(); int64_t UnityPalGetTicks100NanosecondsDateTime(); int64_t UnityPalGetSystemTimeAsFileTime(); #if defined(__cplusplus) } #endif ================================================ FILE: unity_decoder/libil2cpp/os/c-api/Time.cpp ================================================ #include "os/Time.h" #include extern "C" { uint32_t UnityPalGetTicksMillisecondsMonotonic() { return il2cpp::os::Time::GetTicksMillisecondsMonotonic(); } int64_t UnityPalGetTicks100NanosecondsMonotonic() { return il2cpp::os::Time::GetTicks100NanosecondsMonotonic(); } int64_t UnityPalGetTicks100NanosecondsDateTime() { return il2cpp::os::Time::GetTicks100NanosecondsDateTime(); } int64_t UnityPalGetSystemTimeAsFileTime() { return il2cpp::os::Time::GetSystemTimeAsFileTime(); } } ================================================ FILE: unity_decoder/libil2cpp/os/c-api/TimeZone-c-api.h ================================================ #pragma once #include #if defined(__cplusplus) extern "C" { #endif bool UnityPalGetTimeZoneData(int32_t year, int64_t data[4], const char* names[2]); #if defined(__cplusplus) } #endif ================================================ FILE: unity_decoder/libil2cpp/os/c-api/TimeZone.cpp ================================================ #include "os/TimeZone.h" #include "Allocator.h" #include extern "C" { bool UnityPalGetTimeZoneData(int32_t year, int64_t data[4], const char* names[2]) { std::string namesBuffer[2]; bool result = il2cpp::os::TimeZone::GetTimeZoneData(year, data, namesBuffer); names[0] = Allocator::CopyToAllocatedStringBuffer(namesBuffer[0]); names[1] = Allocator::CopyToAllocatedStringBuffer(namesBuffer[1]); return result; } } ================================================ FILE: unity_decoder/libil2cpp/os/c-api/tests/FileTests.cpp ================================================ #if ENABLE_UNIT_TESTS #include "UnitTest++.h" #include "../../File.h" #include "../../Process.h" #include "../File-c-api.h" static const char* TEST_FILE_NAME = "TESTFILE2"; static const char* DUPLICATE_TEST_FILE_NAME = "DUP_TESTFILE2"; static const char* BACKUP_TEST_FILE_NAME = "BACKUP_TESTFILE2"; static const int64_t TEST_FILE_LENGTH = 1234567891L; static il2cpp::os::FileHandle* PrepareTestFile() { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, 1, 0, 0, 0, &error); return handle; } static void CleanupTestFile(il2cpp::os::FileHandle* handle) { int error; il2cpp::os::File::Close(handle, &error); il2cpp::os::File::DeleteFile(TEST_FILE_NAME, &error); } static void WriteSomeCharactersToTestFile(il2cpp::os::FileHandle* handle) { static const char* buffer = "THIS IS A TEST\0"; int error; il2cpp::os::File::Write(handle, buffer, (int)strlen(buffer), &error); } SUITE(FileTests) { TEST(FileIsAttyWithValidButNoTTY) { il2cpp::os::FileHandle* handle = PrepareTestFile(); bool result = UnityPalIsatty(handle); CleanupTestFile(handle); CHECK_MSG(!result, "A normal is a TTY, which is not expected."); } TEST(FileIsAttyMatchesClass) { il2cpp::os::FileHandle* handle = il2cpp::os::File::GetStdInput(); bool result = UnityPalIsatty(handle); CHECK_EQUAL(il2cpp::os::File::Isatty(handle), UnityPalIsatty(handle)); } TEST(FileIsAttyWithValidButNoTTYMatchesClass) { il2cpp::os::FileHandle* handle = PrepareTestFile(); bool result = UnityPalIsatty(handle); CHECK_EQUAL(il2cpp::os::File::Isatty(handle), UnityPalIsatty(handle)); CleanupTestFile(handle); } TEST(FileOpenTestNoError) { const char* FILE_NAME = "TESTFILE2"; int error; UnityPalFileHandle* handle = NULL; handle = UnityPalOpen(FILE_NAME, 1, 0, 0, 0, &error); CHECK_NOT_NULL(handle); il2cpp::os::File::Close(handle, &error); il2cpp::os::File::DeleteFile(FILE_NAME, &error); } TEST(FileOpenTestWithError) { int error = 0; UnityPalFileHandle* handle = NULL; handle = UnityPalOpen("", 1, 0, 0, 0, &error); CHECK_EQUAL(il2cpp::os::kErrorCodePathNotFound, error); } TEST(FileOpenWithErrorMatchesClassTest) { int api_error = 0; UnityPalFileHandle* api_handle = NULL; int class_error = 0; UnityPalFileHandle* class_handle = NULL; api_handle = UnityPalOpen("", 1, 0, 0, 0, &api_error); class_handle = il2cpp::os::File::Open("", 1, 0, 0, 0, &class_error); CHECK_EQUAL(class_error, api_error); } TEST(GetStdInputTest) { CHECK_NOT_NULL(UnityPalGetStdInput()); } TEST(GetStdOutputTest) { CHECK_NOT_NULL(UnityPalGetStdOutput()); } TEST(GetStdErrorTest) { CHECK_NOT_NULL(UnityPalGetStdError()); } TEST(GetFileTypeNormalTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); FileType testFileType = UnityPalGetFileType(handle); CleanupTestFile(handle); CHECK_EQUAL(kFileTypeDisk, testFileType); } TEST(GetFileTypeMatchesClass) { CHECK_EQUAL(il2cpp::os::File::GetFileType(UnityPalGetStdError()), UnityPalGetFileType(UnityPalGetStdError())); } TEST(GetFileTypeErrorEqualsClass) { il2cpp::os::FileHandle* handle = PrepareTestFile(); CleanupTestFile(handle); CHECK_EQUAL(il2cpp::os::File::GetFileType(handle), UnityPalGetFileType(handle)); } TEST(GetFileAttributesCleanErrorTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; UnityPalFileAttributes attributes = UnityPalGetFileAttributes(TEST_FILE_NAME, &error); CHECK_EQUAL(il2cpp::os::kErrorCodeSuccess, error); CleanupTestFile(handle); } TEST(GetFileAttributesCleanErrorMatchesClassTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int api_error; int class_error; UnityPalGetFileAttributes(TEST_FILE_NAME, &api_error); il2cpp::os::File::GetFileAttributes(TEST_FILE_NAME, &class_error); CHECK_EQUAL(class_error, api_error); CleanupTestFile(handle); } TEST(GetFileAttributesMatchesClassTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int api_error; int class_error; UnityPalFileAttributes api_attributes = UnityPalGetFileAttributes(TEST_FILE_NAME, &api_error); UnityPalFileAttributes class_attributes = il2cpp::os::File::GetFileAttributes(TEST_FILE_NAME, &class_error); CHECK_EQUAL(class_attributes, api_attributes); CleanupTestFile(handle); } TEST(GetFileAttributesWithBadPath) { int error; UnityPalFileAttributes attributes = UnityPalGetFileAttributes("sf&236732q#", &error); CHECK_EQUAL(-1, attributes); } TEST(GetFileAttributesWithBadPathMatchesClass) { int api_error; int class_error; UnityPalFileAttributes api_attributes = UnityPalGetFileAttributes("#23sfs#", &api_error); UnityPalFileAttributes class_attributes = il2cpp::os::File::GetFileAttributes("#23sfs#", &class_error); CHECK_EQUAL(class_attributes, api_attributes); } TEST(SetFileAttributesNormalResultTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; bool result = UnityPalSetFileAttributes(TEST_FILE_NAME, kFileAttributeTemporary, &error); CleanupTestFile(handle); CHECK(result); } TEST(SetFileAttributesNormalErrorTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); UnityPalSetFileAttributes(TEST_FILE_NAME, kFileAttributeNormal, &error); CleanupTestFile(handle); CHECK_EQUAL(il2cpp::os::kErrorCodeSuccess, error); } TEST(SetFileAttributesBadResultTest) { int error; bool result = UnityPalSetFileAttributes("234232345$$", kFileAttributeTemporary, &error); CHECK(!result); } TEST(SetFileAttributesBadErrorTest) { int error; UnityPalSetFileAttributes("234232345$$", kFileAttributeTemporary, &error); CHECK_NOT_EQUAL(il2cpp::os::kErrorCodeSuccess, error); } TEST(SetFileAttributesNormalResultMatchesClassTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; CHECK_EQUAL(il2cpp::os::File::SetFileAttributes(TEST_FILE_NAME, kFileAttributeTemporary, &error), UnityPalSetFileAttributes(TEST_FILE_NAME, kFileAttributeTemporary, &error)); CleanupTestFile(handle); } TEST(SetFileAttributesNormalAttributeReadMatchesClassTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; UnityPalSetFileAttributes(TEST_FILE_NAME, kFileAttributeTemporary, &error); UnityPalFileAttributes api_attributes = UnityPalGetFileAttributes(TEST_FILE_NAME, &error); CleanupTestFile(handle); handle = PrepareTestFile(); il2cpp::os::File::SetFileAttributes(TEST_FILE_NAME, kFileAttributeTemporary, &error); UnityPalFileAttributes class_attributes = il2cpp::os::File::GetFileAttributes(TEST_FILE_NAME, &error); CleanupTestFile(handle); CHECK_EQUAL(api_attributes, class_attributes); } TEST(SetFileAttributesBadResultMatchesClassTest) { int error; CHECK_EQUAL(il2cpp::os::File::SetFileAttributes("234232345$$", kFileAttributeTemporary, &error), UnityPalSetFileAttributes("234232345$$", kFileAttributeTemporary, &error)); } TEST(SetFileAttributesBadErrorMatchesClassTest) { int api_error; int class_error; UnityPalSetFileAttributes("234232345$$", kFileAttributeTemporary, &api_error); il2cpp::os::File::SetFileAttributes("234232345$$", kFileAttributeTemporary, &class_error); CHECK_EQUAL(class_error, api_error); } TEST(GetFileStatNormalResultTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; UnityPalFileStat fileStat; bool result = UnityPalGetFileStat(TEST_FILE_NAME, &fileStat, &error); CleanupTestFile(handle); CHECK(result); } TEST(GetFileStatNormalErrorTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; UnityPalFileStat fileStat; UnityPalGetFileStat(TEST_FILE_NAME, &fileStat, &error); CleanupTestFile(handle); CHECK_EQUAL(il2cpp::os::kErrorCodeSuccess, error); } TEST(GetFileStatBadResultTest) { int error; UnityPalFileStat fileStat; bool result = UnityPalGetFileStat("#Q23423", &fileStat, &error); CHECK(!result); } TEST(GetFileStatBadErrorTest) { int error; UnityPalFileStat fileStat; UnityPalGetFileStat("#Q23423", &fileStat, &error); CHECK_NOT_EQUAL(il2cpp::os::kErrorCodeSuccess, error); } TEST(GetFileStatNormalNameTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; UnityPalFileStat fileStat; UnityPalGetFileStat(TEST_FILE_NAME, &fileStat, &error); CleanupTestFile(handle); CHECK_EQUAL(0, strcmp(fileStat.name.c_str(), TEST_FILE_NAME)); } TEST(GetFileStatNormalLengthTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; UnityPalFileStat fileStat; UnityPalGetFileStat(TEST_FILE_NAME, &fileStat, &error); CleanupTestFile(handle); CHECK_EQUAL(0, fileStat.length); } TEST(GetFileStatNormalCreationTimeTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; UnityPalFileStat fileStat; UnityPalGetFileStat(TEST_FILE_NAME, &fileStat, &error); CleanupTestFile(handle); CHECK(fileStat.creation_time > 100000000); } TEST(GetFileStatNormalLastAccessTimeTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; UnityPalFileStat fileStat; UnityPalGetFileStat(TEST_FILE_NAME, &fileStat, &error); CleanupTestFile(handle); CHECK(fileStat.last_access_time > 100000000); } TEST(GetFileStatNormalLastWriteTimeTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; UnityPalFileStat fileStat; UnityPalGetFileStat(TEST_FILE_NAME, &fileStat, &error); CleanupTestFile(handle); CHECK(fileStat.last_write_time > 100000000); } TEST(GetFileStatNormalResultMatchesClassTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; UnityPalFileStat fileStat; CHECK_EQUAL(il2cpp::os::File::GetFileStat(TEST_FILE_NAME, &fileStat, &error), UnityPalGetFileStat(TEST_FILE_NAME, &fileStat, &error)); CleanupTestFile(handle); } TEST(GetFileStatNormalErrorMatchesClassTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int api_error; int class_error; UnityPalFileStat fileStat; UnityPalGetFileStat(TEST_FILE_NAME, &fileStat, &api_error); il2cpp::os::File::GetFileStat(TEST_FILE_NAME, &fileStat, &class_error); CleanupTestFile(handle); CHECK_EQUAL(class_error, api_error); } TEST(GetFileStatBadResultMatchesClassTest) { int error; UnityPalFileStat fileStat; CHECK_EQUAL(il2cpp::os::File::GetFileStat("#Q23423", &fileStat, &error), UnityPalGetFileStat("#Q23423", &fileStat, &error)); } TEST(GetFileStatBadErrorMatchesClassTest) { int api_error; int class_error; UnityPalFileStat fileStat; UnityPalGetFileStat("#Q23423", &fileStat, &api_error); il2cpp::os::File::GetFileStat("#Q23423", &fileStat, &class_error); CHECK_EQUAL(class_error, api_error); } TEST(GetFileStatNormalNameMatchesClassTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; UnityPalFileStat fileStat; UnityPalGetFileStat(TEST_FILE_NAME, &fileStat, &error); CleanupTestFile(handle); CHECK_EQUAL(0, strcmp(fileStat.name.c_str(), TEST_FILE_NAME)); } TEST(GetFileStatNormalAttributesMatchesClassTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; UnityPalFileStat apiFileStat; il2cpp::os::FileStat classFileStat; UnityPalGetFileStat(TEST_FILE_NAME, &apiFileStat, &error); il2cpp::os::File::GetFileStat(TEST_FILE_NAME, &classFileStat, &error); CleanupTestFile(handle); CHECK_EQUAL(classFileStat.attributes, apiFileStat.attributes); } TEST(GetFileStatNormalLengthMatchesClassTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; UnityPalFileStat apiFileStat; il2cpp::os::FileStat classFileStat; UnityPalGetFileStat(TEST_FILE_NAME, &apiFileStat, &error); il2cpp::os::File::GetFileStat(TEST_FILE_NAME, &classFileStat, &error); CleanupTestFile(handle); CHECK_EQUAL(classFileStat.length, apiFileStat.length); } TEST(GetFileStatNormalCreationTimeMatchesClassTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; UnityPalFileStat apiFileStat; il2cpp::os::FileStat classFileStat; UnityPalGetFileStat(TEST_FILE_NAME, &apiFileStat, &error); il2cpp::os::File::GetFileStat(TEST_FILE_NAME, &classFileStat, &error); CleanupTestFile(handle); CHECK_EQUAL(classFileStat.creation_time, apiFileStat.creation_time); } TEST(GetFileStatNormalLastAccessTimeMatchesClassTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; UnityPalFileStat apiFileStat; il2cpp::os::FileStat classFileStat; UnityPalGetFileStat(TEST_FILE_NAME, &apiFileStat, &error); il2cpp::os::File::GetFileStat(TEST_FILE_NAME, &classFileStat, &error); CleanupTestFile(handle); CHECK_EQUAL(classFileStat.last_access_time, apiFileStat.last_access_time); } TEST(GetFileStatNormalLastWriteTimeMatchesClassTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; UnityPalFileStat apiFileStat; il2cpp::os::FileStat classFileStat; UnityPalGetFileStat(TEST_FILE_NAME, &apiFileStat, &error); il2cpp::os::File::GetFileStat(TEST_FILE_NAME, &classFileStat, &error); CleanupTestFile(handle); CHECK_EQUAL(classFileStat.last_write_time, apiFileStat.last_write_time); } TEST(CopyFileNormalResultTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; bool result = UnityPalCopyFile(TEST_FILE_NAME, DUPLICATE_TEST_FILE_NAME, true, &error); UnityPalDeleteFile(DUPLICATE_TEST_FILE_NAME, &error); CleanupTestFile(handle); CHECK(result); } TEST(CopyFileNormalErrorTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; UnityPalCopyFile(TEST_FILE_NAME, DUPLICATE_TEST_FILE_NAME, true, &error); UnityPalDeleteFile(DUPLICATE_TEST_FILE_NAME, &error); CleanupTestFile(handle); CHECK_EQUAL(il2cpp::os::kErrorCodeSuccess, error); } TEST(CopyFileBadResultTest) { int error; bool result = UnityPalCopyFile("#453453", "#sdfsdw3", true, &error); CHECK(!result); } TEST(CopyFileBadErrorTest) { int error; UnityPalCopyFile("#453453", "#sdfsdw3", true, &error); CHECK_NOT_EQUAL(il2cpp::os::kErrorCodeSuccess, error); } TEST(CopyFileNormalStatTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; UnityPalFileStat fileStat; UnityPalCopyFile(TEST_FILE_NAME, DUPLICATE_TEST_FILE_NAME, true, &error); UnityPalGetFileStat(DUPLICATE_TEST_FILE_NAME, &fileStat, &error); UnityPalDeleteFile(DUPLICATE_TEST_FILE_NAME, &error); CleanupTestFile(handle); CHECK(fileStat.last_write_time > 100000000); } TEST(CopyFileNormalResultMatchesClassTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; bool api_result = UnityPalCopyFile(TEST_FILE_NAME, DUPLICATE_TEST_FILE_NAME, true, &error); UnityPalDeleteFile(DUPLICATE_TEST_FILE_NAME, &error); bool class_result = il2cpp::os::File::CopyFile(TEST_FILE_NAME, DUPLICATE_TEST_FILE_NAME, true, &error); il2cpp::os::File::DeleteFile(DUPLICATE_TEST_FILE_NAME, &error); CleanupTestFile(handle); CHECK_EQUAL(class_result, api_result); } TEST(CopyFileNormalErrorMatchesClassTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int api_error; int class_error; UnityPalCopyFile(TEST_FILE_NAME, DUPLICATE_TEST_FILE_NAME, true, &api_error); UnityPalDeleteFile(DUPLICATE_TEST_FILE_NAME, &api_error); il2cpp::os::File::CopyFile(TEST_FILE_NAME, DUPLICATE_TEST_FILE_NAME, true, &class_error); il2cpp::os::File::DeleteFile(DUPLICATE_TEST_FILE_NAME, &class_error); CleanupTestFile(handle); CHECK_EQUAL(class_error, api_error); } TEST(CopyFileBadResultMatchesClassTest) { int error; CHECK_EQUAL(il2cpp::os::File::CopyFile("#453453", "#sdfsdw3", true, &error), UnityPalCopyFile("#453453", "#sdfsdw3", true, &error)); } TEST(CopyFileBadErrorMatchesClassTest) { int api_error; int class_error; UnityPalCopyFile("#453453", "#sdfsdw3", true, &api_error); il2cpp::os::File::CopyFile("#453453", "#sdfsdw3", true, &class_error); CHECK_EQUAL(class_error, api_error); } TEST(MoveFileBadResultTest) { int error; bool result = UnityPalMoveFile("#453453", "#sdfsdw3", &error); CHECK(!result); } TEST(MoveFileBadErrorTest) { int error; UnityPalMoveFile("#453453", "#sdfsdw3", &error); CHECK_NOT_EQUAL(il2cpp::os::kErrorCodeSuccess, error); } TEST(MoveFileNormalResultMatchesClassTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; bool api_result = UnityPalMoveFile(TEST_FILE_NAME, DUPLICATE_TEST_FILE_NAME, &error); UnityPalDeleteFile(DUPLICATE_TEST_FILE_NAME, &error); CleanupTestFile(handle); handle = PrepareTestFile(); bool class_result = il2cpp::os::File::MoveFile(TEST_FILE_NAME, DUPLICATE_TEST_FILE_NAME, &error); il2cpp::os::File::DeleteFile(DUPLICATE_TEST_FILE_NAME, &error); CleanupTestFile(handle); CHECK_EQUAL(class_result, api_result); } TEST(MoveFileNormalErrorMatchesClassTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int api_error; int class_error; UnityPalMoveFile(TEST_FILE_NAME, DUPLICATE_TEST_FILE_NAME, &api_error); UnityPalDeleteFile(DUPLICATE_TEST_FILE_NAME, &api_error); CleanupTestFile(handle); handle = PrepareTestFile(); il2cpp::os::File::MoveFile(TEST_FILE_NAME, DUPLICATE_TEST_FILE_NAME, &class_error); il2cpp::os::File::DeleteFile(DUPLICATE_TEST_FILE_NAME, &class_error); CleanupTestFile(handle); CHECK_EQUAL(class_error, api_error); } TEST(MoveFileBadResultMatchesClassTest) { int error; CHECK_EQUAL(il2cpp::os::File::MoveFile("#453453", "#sdfsdw3", &error), UnityPalMoveFile("#453453", "#sdfsdw3", &error)); } TEST(MoveFileBadErrorMatchesClassTest) { int api_error; int class_error; UnityPalMoveFile("#453453", "#sdfsdw3", &api_error); il2cpp::os::File::MoveFile("#453453", "#sdfsdw3", &class_error); CHECK_EQUAL(class_error, api_error); } TEST(DeleteFileNormalResultTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; bool result = UnityPalDeleteFile(TEST_FILE_NAME, &error); CleanupTestFile(handle); CHECK(result); } TEST(DeleteFileNormalErrorTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; UnityPalDeleteFile(TEST_FILE_NAME, &error); CleanupTestFile(handle); CHECK_EQUAL(il2cpp::os::kErrorCodeSuccess, error); } TEST(DeleteFileBadResultTest) { int error; bool result = UnityPalDeleteFile("#453453", &error); CHECK(!result); } TEST(DeleteFileBadErrorTest) { int error; UnityPalDeleteFile("#453453", &error); CHECK_NOT_EQUAL(il2cpp::os::kErrorCodeSuccess, error); } TEST(DeleteFileNormalStatTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; UnityPalFileStat fileStat; UnityPalDeleteFile(TEST_FILE_NAME, &error); UnityPalGetFileStat(TEST_FILE_NAME, &fileStat, &error); CleanupTestFile(handle); CHECK(fileStat.last_write_time < 1); } TEST(DeleteFileNormalResultMatchesClassTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int error; bool api_result = UnityPalDeleteFile(TEST_FILE_NAME, &error); CleanupTestFile(handle); handle = PrepareTestFile(); bool class_result = il2cpp::os::File::DeleteFile(TEST_FILE_NAME, &error); CleanupTestFile(handle); CHECK_EQUAL(class_result, api_result); } TEST(DeleteFileNormalErrorMatchesClassTest) { il2cpp::os::FileHandle* handle = PrepareTestFile(); int api_error; int class_error; UnityPalDeleteFile(TEST_FILE_NAME, &api_error); CleanupTestFile(handle); handle = PrepareTestFile(); il2cpp::os::File::DeleteFile(TEST_FILE_NAME, &class_error); CleanupTestFile(handle); CHECK_EQUAL(class_error, api_error); } TEST(DeleteFileBadResultMatchesClassTest) { int error; CHECK_EQUAL(il2cpp::os::File::DeleteFile("#453453", &error), UnityPalDeleteFile("#453453", &error)); } TEST(DeleteFileBadErrorMatchesClassTest) { int api_error; int class_error; UnityPalDeleteFile("#453453", &api_error); il2cpp::os::File::DeleteFile("#453453", &class_error); CHECK_EQUAL(class_error, api_error); } TEST(ReplaceFileTest) { // TODO Figure out how to test // Replace File does not seem to work in libil2cpp } TEST(OpenFileNormalResultTest) { int error; UnityPalFileHandle* handle = NULL; handle = UnityPalOpen(TEST_FILE_NAME, 1, 0, 0, 0, &error); CHECK_NOT_NULL(handle); il2cpp::os::File::Close(handle, &error); il2cpp::os::File::DeleteFile(TEST_FILE_NAME, &error); } TEST(OpenFileNormalErrorTest) { int error; UnityPalFileHandle* handle = NULL; handle = UnityPalOpen(TEST_FILE_NAME, 1, 0, 0, 0, &error); CHECK_EQUAL(il2cpp::os::kErrorCodeSuccess, error); il2cpp::os::File::Close(handle, &error); il2cpp::os::File::DeleteFile(TEST_FILE_NAME, &error); } TEST(OpenFileNormalStatTest) { int error; UnityPalFileStat fileStat; UnityPalFileHandle* handle = NULL; handle = UnityPalOpen(TEST_FILE_NAME, 1, 0, 0, 0, &error); UnityPalGetFileStat(TEST_FILE_NAME, &fileStat, &error); il2cpp::os::File::Close(handle, &error); il2cpp::os::File::DeleteFile(TEST_FILE_NAME, &error); CHECK(fileStat.last_write_time > 1); } TEST(OpenFileNormalErrorMatchesClassTest) { int error; int api_error; int class_error; UnityPalFileHandle* handle = NULL; handle = UnityPalOpen(TEST_FILE_NAME, 1, 0, 0, 0, &api_error); il2cpp::os::File::Close(handle, &error); il2cpp::os::File::DeleteFile(TEST_FILE_NAME, &error); handle = il2cpp::os::File::Open(TEST_FILE_NAME, 1, 0, 0, 0, &class_error); il2cpp::os::File::Close(handle, &error); il2cpp::os::File::DeleteFile(TEST_FILE_NAME, &error); CHECK_EQUAL(class_error, api_error); } TEST(OpenFileNormalStatMatchesClassTest) { int error; UnityPalFileStat api_fileStat; il2cpp::os::FileStat class_fileStat; UnityPalFileHandle* handle = NULL; handle = UnityPalOpen(TEST_FILE_NAME, 1, 0, 0, 0, &error); UnityPalGetFileStat(TEST_FILE_NAME, &api_fileStat, &error); il2cpp::os::File::Close(handle, &error); il2cpp::os::File::DeleteFile(TEST_FILE_NAME, &error); handle = il2cpp::os::File::Open(TEST_FILE_NAME, 1, 0, 0, 0, &error); il2cpp::os::File::GetFileStat(TEST_FILE_NAME, &class_fileStat, &error); il2cpp::os::File::Close(handle, &error); // Tthey dont have to be exact, just in the ballpark CHECK_EQUAL(class_fileStat.last_write_time / 1000000L, api_fileStat.last_write_time / 1000000L); } TEST(SetFileTimeNormalTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); UnityPalFileStat fileStat; bool result = UnityPalSetFileTime(handle, 131360602701336952, 131360602701336952, 131360602701336952, &error); UnityPalGetFileStat(TEST_FILE_NAME, &fileStat, &error); CleanupTestFile(handle); CHECK(result); } /* TEST(SetFileTimeNormalStatTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); UnityPalFileStat fileStat; bool result = UnityPalSetFileTime(handle, 131360602701336952, 131360602701336952, 131360602701336952, &error); UnityPalGetFileStat(TEST_FILE_NAME, &fileStat, &error); CleanupTestFile(handle); CHECK(fileStat.creation_time == 131360602701336952 && fileStat.last_write_time == 131360602701336952 && fileStat.last_access_time == 131360602701336952); } */ TEST(SetFileTimeNormalErrorTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); bool result = UnityPalSetFileTime(handle, 131360602701336952, 131360602701336952, 131360602701336952, &error); CleanupTestFile(handle); CHECK_EQUAL(il2cpp::os::kErrorCodeSuccess, error); } TEST(SetFileTimeNormalMatchesClassTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); UnityPalFileStat fileStat; bool api_result = UnityPalSetFileTime(handle, 131360602701336952, 131360602701336952, 131360602701336952, &error); bool class_result = il2cpp::os::File::SetFileTime(handle, 131360602701336952, 131360602701336952, 131360602701336952, &error); CleanupTestFile(handle); CHECK_EQUAL(class_result, api_result); } TEST(SetFileTimeNormalStatMatchesClassTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); UnityPalFileStat api_fileStat; UnityPalFileStat class_fileStat; UnityPalSetFileTime(handle, 131360602701336952, 131360602701336952, 131360602701336952, &error); UnityPalGetFileStat(TEST_FILE_NAME, &api_fileStat, &error); il2cpp::os::File::SetFileTime(handle, 131360602701336952, 131360602701336952, 131360602701336952, &error); il2cpp::os::File::GetFileStat(TEST_FILE_NAME, &class_fileStat, &error); CleanupTestFile(handle); CHECK(api_fileStat.creation_time == class_fileStat.creation_time && api_fileStat.last_write_time == class_fileStat.last_write_time && api_fileStat.last_access_time == class_fileStat.last_access_time); } TEST(SetFileTimeNormalErrorMatchesClassTest) { int error; int api_error; int class_error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); UnityPalSetFileTime(handle, 131360602701336952, 131360602701336952, 131360602701336952, &api_error); il2cpp::os::File::SetFileTime(handle, 131360602701336952, 131360602701336952, 131360602701336952, &class_error); CleanupTestFile(handle); CHECK_EQUAL(class_error, api_error); } TEST(GetLengthNormalTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); WriteSomeCharactersToTestFile(handle); int64_t length = UnityPalGetLength(handle, &error); CleanupTestFile(handle); CHECK_EQUAL(14, length); } TEST(GetLengthZeroTest) { int error; il2cpp::os::FileHandle* handle = PrepareTestFile(); int64_t length = UnityPalGetLength(handle, &error); CleanupTestFile(handle); CHECK_EQUAL(0, length); } TEST(GetLengthBadFileErrorTest) { int error; il2cpp::os::FileHandle* handle = PrepareTestFile(); CleanupTestFile(handle); UnityPalGetLength(handle, &error); CHECK_NOT_EQUAL(il2cpp::os::kErrorCodeSuccess, error); } TEST(GetLengthNormalMatchesClassTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); WriteSomeCharactersToTestFile(handle); int64_t api_length = UnityPalGetLength(handle, &error); int64_t class_length = il2cpp::os::File::GetLength(handle, &error); CleanupTestFile(handle); CHECK_EQUAL(class_length, api_length); } TEST(GetLengthZeroMatchesClassTest) { int error; il2cpp::os::FileHandle* handle = PrepareTestFile(); int64_t api_length = UnityPalGetLength(handle, &error); int64_t class_length = il2cpp::os::File::GetLength(handle, &error); CleanupTestFile(handle); CHECK_EQUAL(class_length, api_length); } TEST(GetLengthBadFileErrorMatchesClassTest) { int api_error; int class_error; il2cpp::os::FileHandle* handle = PrepareTestFile(); CleanupTestFile(handle); UnityPalGetLength(handle, &api_error); il2cpp::os::File::GetLength(handle, &class_error); CHECK_EQUAL(class_error, api_error); } TEST(SetLengthNormalResultTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); bool result = UnityPalSetLength(handle, TEST_FILE_LENGTH, &error); CleanupTestFile(handle); CHECK(result); } TEST(SetLengthNormalGetLengthTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); bool result = UnityPalSetLength(handle, TEST_FILE_LENGTH, &error); int64_t length = il2cpp::os::File::GetLength(handle, &error); CleanupTestFile(handle); CHECK_EQUAL(TEST_FILE_LENGTH, length); } TEST(SetLengthBadResultTest) { int error; il2cpp::os::FileHandle* handle = PrepareTestFile(); CleanupTestFile(handle); bool result = UnityPalSetLength(handle, TEST_FILE_LENGTH, &error); CHECK(!result); } TEST(SetLengthBadErrorTest) { int error; il2cpp::os::FileHandle* handle = PrepareTestFile(); CleanupTestFile(handle); UnityPalSetLength(handle, TEST_FILE_LENGTH, &error); CHECK_NOT_EQUAL(il2cpp::os::kErrorCodeSuccess, error); } TEST(SetLengthNormalResultMatchesClassTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); bool api_result = UnityPalSetLength(handle, TEST_FILE_LENGTH, &error); CleanupTestFile(handle); handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); bool class_result = il2cpp::os::File::SetLength(handle, TEST_FILE_LENGTH, &error); CleanupTestFile(handle); CHECK_EQUAL(class_result, api_result); } TEST(SetLengthNormalGetLengthMatchesClassTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); UnityPalSetLength(handle, TEST_FILE_LENGTH, &error); int64_t api_length = il2cpp::os::File::GetLength(handle, &error); CleanupTestFile(handle); handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); il2cpp::os::File::SetLength(handle, TEST_FILE_LENGTH, &error); int64_t class_length = il2cpp::os::File::GetLength(handle, &error); CleanupTestFile(handle); CHECK_EQUAL(class_length, api_length); } TEST(SetLengthBadResultMatchesClassTest) { int error; il2cpp::os::FileHandle* handle = PrepareTestFile(); CleanupTestFile(handle); bool api_result = UnityPalSetLength(handle, TEST_FILE_LENGTH, &error); bool class_result = il2cpp::os::File::SetLength(handle, TEST_FILE_LENGTH, &error); CHECK_EQUAL(class_result, api_result); } TEST(SetLengthBadErrorMatchesClassTest) { int api_error; int class_error; il2cpp::os::FileHandle* handle = PrepareTestFile(); CleanupTestFile(handle); UnityPalSetLength(handle, TEST_FILE_LENGTH, &api_error); il2cpp::os::File::SetLength(handle, TEST_FILE_LENGTH, &class_error); CHECK_EQUAL(class_error, api_error); } TEST(SeekNormalResultTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); WriteSomeCharactersToTestFile(handle); int64_t result = UnityPalSeek(handle, 10, 0, &error); CleanupTestFile(handle); CHECK_EQUAL(10, result); } TEST(SeekNormalBufferTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); WriteSomeCharactersToTestFile(handle); int64_t result = UnityPalSeek(handle, 10, 0, &error); char buffer[15]; il2cpp::os::File::Read(handle, buffer, 4, &error); CleanupTestFile(handle); CHECK_EQUAL(0, strncmp("TEST", buffer, 4)); } TEST(SeekBadErrorTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); CleanupTestFile(handle); UnityPalSeek(handle, 10, 0, &error); CHECK_NOT_EQUAL(il2cpp::os::kErrorCodeSuccess, error); } TEST(SeekNormalResultMatchesClassTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); WriteSomeCharactersToTestFile(handle); int64_t api_result = UnityPalSeek(handle, 10, 0, &error); CleanupTestFile(handle); handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); WriteSomeCharactersToTestFile(handle); int64_t class_result = il2cpp::os::File::Seek(handle, 10, 0, &error); CleanupTestFile(handle); CHECK_EQUAL(class_result, api_result); } TEST(SeekNormalBufferMatchesClassTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); WriteSomeCharactersToTestFile(handle); UnityPalSeek(handle, 10, 0, &error); char api_buffer[15]; char class_buffer[15]; il2cpp::os::File::Read(handle, api_buffer, 4, &error); CleanupTestFile(handle); handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); WriteSomeCharactersToTestFile(handle); il2cpp::os::File::Seek(handle, 10, 0, &error); il2cpp::os::File::Read(handle, class_buffer, 4, &error); CleanupTestFile(handle); CHECK_EQUAL(0, strncmp(class_buffer, api_buffer, 4)); } TEST(SeekBadErrorMatchesClassTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); CleanupTestFile(handle); UnityPalSeek(handle, 10, 0, &error); CHECK_NOT_EQUAL(il2cpp::os::kErrorCodeSuccess, error); } TEST(ReadNormalResultTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); WriteSomeCharactersToTestFile(handle); char buffer[16]; UnityPalSeek(handle, 0, 0, &error); int result = UnityPalRead(handle, buffer, 16, &error); CleanupTestFile(handle); CHECK_EQUAL(14, result); } TEST(ReadNormalBufferTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); WriteSomeCharactersToTestFile(handle); char buffer[16]; UnityPalSeek(handle, 0, 0, &error); UnityPalRead(handle, buffer, 16, &error); CleanupTestFile(handle); CHECK_EQUAL(0, strncmp("THIS IS A TEST", buffer, 14)); } TEST(ReadBadResultTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); CleanupTestFile(handle); char buffer[16]; int64_t result = UnityPalRead(handle, buffer, 16, &error); CHECK(!result); } TEST(ReadBadErrorTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); CleanupTestFile(handle); char buffer[16]; UnityPalRead(handle, buffer, 16, &error); CHECK_NOT_EQUAL(il2cpp::os::kErrorCodeSuccess, error); } TEST(ReadNormalResultMatchesClassTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); WriteSomeCharactersToTestFile(handle); UnityPalSeek(handle, 0, 0, &error); char buffer[16]; int api_result = UnityPalRead(handle, buffer, 14, &error); CleanupTestFile(handle); handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); WriteSomeCharactersToTestFile(handle); il2cpp::os::File::Seek(handle, 0, 0, &error); int class_result = il2cpp::os::File::Read(handle, buffer, 14, &error); CleanupTestFile(handle); CHECK_EQUAL(class_result, api_result); } TEST(ReadNormalBufferMatchesClassTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); WriteSomeCharactersToTestFile(handle); UnityPalSeek(handle, 0, 0, &error); char api_buffer[16]; char class_buffer[16]; UnityPalRead(handle, api_buffer, 14, &error); CleanupTestFile(handle); handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); WriteSomeCharactersToTestFile(handle); il2cpp::os::File::Seek(handle, 0, 0, &error); il2cpp::os::File::Read(handle, class_buffer, 14, &error); CleanupTestFile(handle); CHECK_EQUAL(0, strncmp(class_buffer, api_buffer, 14)); } TEST(ReadBadResultMatchesClassTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); CleanupTestFile(handle); char buffer[16]; int64_t api_result = UnityPalRead(handle, buffer, 14, &error); int64_t class_result = il2cpp::os::File::Read(handle, buffer, 14, &error); CHECK_EQUAL(class_result, api_result); } TEST(ReadBadErrorMatchesClassTest) { int error; int api_error; int class_error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); CleanupTestFile(handle); char buffer[16]; UnityPalRead(handle, buffer, 14, &api_error); il2cpp::os::File::Read(handle, buffer, 14, &class_error); CHECK_EQUAL(class_error, api_error); } TEST(WriteNormalResultTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); static const char* buffer = "THIS IS A TEST\0"; int32_t result = UnityPalWrite(handle, buffer, 14, &error); CleanupTestFile(handle); CHECK_EQUAL(14, result); } TEST(WriteNormalErrorTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); static const char* buffer = "THIS IS A TEST\0"; UnityPalWrite(handle, buffer, 14, &error); CleanupTestFile(handle); CHECK_EQUAL(il2cpp::os::kErrorCodeSuccess, error); } TEST(WriteNormalBufferCheckTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); static const char* buffer = "THIS IS A TEST\0"; UnityPalWrite(handle, buffer, 14, &error); char read_buffer[16]; il2cpp::os::File::Seek(handle, 0, 0, &error); il2cpp::os::File::Read(handle, read_buffer, 16, &error); CleanupTestFile(handle); CHECK_EQUAL(0, strncmp("THIS IS A TEST", buffer, 14)); } TEST(WriteBadResultTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); CleanupTestFile(handle); static const char* buffer = "THIS IS A TEST\0"; int32_t result = UnityPalWrite(handle, buffer, 14, &error); CHECK_EQUAL(0, result); } TEST(WriteNormalResultMatchesClassTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); static const char* buffer = "THIS IS A TEST\0"; int32_t api_result = UnityPalWrite(handle, buffer, 14, &error); int32_t class_result = il2cpp::os::File::Write(handle, buffer, 14, &error); CleanupTestFile(handle); CHECK_EQUAL(class_result, api_result); } TEST(WriteNormalBufferCheckMatchesClassTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); static const char* buffer = "THIS IS A TEST\0"; UnityPalWrite(handle, buffer, 14, &error); char api_read_buffer[16]; il2cpp::os::File::Seek(handle, 0, 0, &error); il2cpp::os::File::Read(handle, api_read_buffer, 16, &error); CleanupTestFile(handle); handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); il2cpp::os::File::Write(handle, buffer, 14, &error); char class_read_buffer[16]; il2cpp::os::File::Seek(handle, 0, 0, &error); il2cpp::os::File::Read(handle, class_read_buffer, 16, &error); CleanupTestFile(handle); CHECK_EQUAL(0, strncmp(class_read_buffer, api_read_buffer, 14)); } TEST(WriteBadResultMatchesClassTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); CleanupTestFile(handle); static const char* buffer = "THIS IS A TEST\0"; int32_t api_result = UnityPalWrite(handle, buffer, 14, &error); int32_t class_result = il2cpp::os::File::Write(handle, buffer, 14, &error); CHECK_EQUAL(class_result, api_result); } TEST(WriteBadErrorMatchesClassTest) { int error; int api_error; int class_error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, 1, 1, 0, 0, &error); CleanupTestFile(handle); static const char* buffer = "THIS IS A TEST\0"; UnityPalWrite(handle, buffer, 14, &api_error); il2cpp::os::File::Write(handle, buffer, 14, &class_error); CHECK_EQUAL(api_error, class_error); } TEST(FlushNormalResultTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); WriteSomeCharactersToTestFile(handle); bool result = UnityPalFlush(handle, &error); CleanupTestFile(handle); CHECK(result); } TEST(FlushNormalErrorTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); WriteSomeCharactersToTestFile(handle); UnityPalFlush(handle, &error); CleanupTestFile(handle); CHECK_EQUAL(il2cpp::os::kErrorCodeSuccess, error); } TEST(FlushBadResultTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); WriteSomeCharactersToTestFile(handle); CleanupTestFile(handle); bool result = UnityPalFlush(handle, &error); CHECK(!result); } TEST(FlushBadErrorTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); WriteSomeCharactersToTestFile(handle); CleanupTestFile(handle); UnityPalFlush(handle, &error); CHECK_NOT_EQUAL(il2cpp::os::kErrorCodeSuccess, error); } TEST(FlushNormalResultMatchesClassTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); WriteSomeCharactersToTestFile(handle); bool api_result = UnityPalFlush(handle, &error); WriteSomeCharactersToTestFile(handle); bool class_result = il2cpp::os::File::Flush(handle, &error); CleanupTestFile(handle); CHECK_EQUAL(class_result, api_result); } TEST(FlushNormalErrorMatchesClassTest) { int error; int api_error; int class_error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); WriteSomeCharactersToTestFile(handle); UnityPalFlush(handle, &api_error); WriteSomeCharactersToTestFile(handle); il2cpp::os::File::Flush(handle, &class_error); CleanupTestFile(handle); CHECK_EQUAL(class_error, api_error); } TEST(FlushBadResultMatchesClassTest) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); WriteSomeCharactersToTestFile(handle); CleanupTestFile(handle); bool api_result = UnityPalFlush(handle, &error); bool class_result = il2cpp::os::File::Flush(handle, &error); CHECK_EQUAL(api_result, class_result); } TEST(FlushBadErrorMatchesClassTest) { int error; int api_error; int class_error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(TEST_FILE_NAME, kFileModeOpenOrCreate, kFileAccessReadWrite, 0, 0, &error); WriteSomeCharactersToTestFile(handle); CleanupTestFile(handle); UnityPalFlush(handle, &api_error); il2cpp::os::File::Flush(handle, &class_error); CHECK_EQUAL(class_error, api_error); } TEST(CreatePipeNormalResultTest) { int error; il2cpp::os::FileHandle* read_handle; il2cpp::os::FileHandle* write_handle; bool result = UnityPalCreatePipe(&read_handle, &write_handle); il2cpp::os::File::Close(read_handle, &error); il2cpp::os::File::Close(write_handle, &error); CHECK(result); } TEST(CreatePipeNormalBufferTest) { int error; il2cpp::os::FileHandle* read_handle; il2cpp::os::FileHandle* write_handle; UnityPalCreatePipe(&read_handle, &write_handle); WriteSomeCharactersToTestFile(write_handle); char buffer[16]; il2cpp::os::File::Read(read_handle, buffer, 4, &error); il2cpp::os::File::Close(read_handle, &error); il2cpp::os::File::Close(write_handle, &error); CHECK_EQUAL(0, strncmp("THIS", buffer, 4)); } TEST(CreatePipeNormalResultMatchesClassTest) { int error; il2cpp::os::FileHandle* read_handle; il2cpp::os::FileHandle* write_handle; bool api_result = UnityPalCreatePipe(&read_handle, &write_handle); il2cpp::os::File::Close(read_handle, &error); il2cpp::os::File::Close(write_handle, &error); bool class_result = il2cpp::os::File::CreatePipe(&read_handle, &write_handle); il2cpp::os::File::Close(read_handle, &error); il2cpp::os::File::Close(write_handle, &error); CHECK_EQUAL(class_result, api_result); } TEST(CreatePipeNormalBufferMatchesClassTest) { int error; il2cpp::os::FileHandle* api_read_handle; il2cpp::os::FileHandle* api_write_handle; il2cpp::os::FileHandle* class_read_handle; il2cpp::os::FileHandle* class_write_handle; UnityPalCreatePipe(&api_read_handle, &api_write_handle); WriteSomeCharactersToTestFile(api_write_handle); char api_buffer[16]; il2cpp::os::File::Read(api_read_handle, api_buffer, 4, &error); il2cpp::os::File::Close(api_read_handle, &error); il2cpp::os::File::Close(api_write_handle, &error); il2cpp::os::File::CreatePipe(&class_read_handle, &class_write_handle); WriteSomeCharactersToTestFile(class_write_handle); char class_buffer[16]; il2cpp::os::File::Read(class_read_handle, class_buffer, 4, &error); il2cpp::os::File::Close(class_read_handle, &error); il2cpp::os::File::Close(class_write_handle, &error); CHECK_EQUAL(0, strncmp(class_buffer, api_buffer, 4)); } } #endif // ENABLE_UNIT_TESTS ================================================ FILE: unity_decoder/libil2cpp/os/c-api/tests/MainTestRunner.cpp ================================================ #if ENABLE_UNIT_TESTS #include "UnitTest++.h" #include "il2cpp-config.h" #include "../Allocator.h" // Have to define this due to Unity's customized // version of UNitTest++ that integrates into the Unity // editor. extern "C" { void printf_console_log(const char* log, va_list list) {} } // We can't use Il2CppNativeChar here due to an old bug in clang handling typdefs in main. #if _MSC_VER int main(int argc, const wchar_t* const argv[]) #else int main(int argc, const char* const argv[]) #endif { register_allocator(malloc); return UnitTest::RunAllTests(); } #if IL2CPP_TARGET_WINDOWS #if IL2CPP_TARGET_WINDOWS_DESKTOP #include #else #include "ActivateApp.h" #endif int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd) { #if IL2CPP_TARGET_WINDOWS_DESKTOP int argc; wchar_t** argv = CommandLineToArgvW(GetCommandLineW(), &argc); int returnValue = main(argc, argv); LocalFree(argv); return returnValue; #else return WinRT::Activate(main); #endif } #endif #endif // ENABLE_UNIT_TESTS ================================================ FILE: unity_decoder/libil2cpp/os/c-api/tests/NativeMethodsTests.cpp ================================================ #if ENABLE_UNIT_TESTS #include "UnitTest++.h" SUITE(NativeMethodsTests) { TEST(FirstNativeMethodTest) { } } #endif // ENABLE_UNIT_TESTS ================================================ FILE: unity_decoder/libil2cpp/os/c-api/tests/PathTests.cpp ================================================ #if ENABLE_UNIT_TESTS #include "UnitTest++.h" #include "../Path-c-api.h" #include "../../Path.h" SUITE(PathTests) { TEST(GetTempPathNotNullTest) { CHECK_NOT_NULL(UnityPalGetTempPath()); } TEST(GetTempPathSanityTest) { // Path will never be the same depeding on user, platform,machine etc. Check if the string is // at least a few chars long CHECK(strlen(UnityPalGetTempPath()) > 5); } TEST(GetTempPathTestMatchesClassTest) { CHECK_EQUAL(il2cpp::os::Path::GetTempPath().c_str(), UnityPalGetTempPath()); } TEST(GetExecutablePathNotNullTest) { CHECK_NOT_NULL(UnityPalGetExecutablePath()); } TEST(GetExecutablePathSanityTest) { // Path will never be the same depeding on user, platform,machine etc. Check if the string is // at least a few chars long CHECK(strlen(UnityPalGetExecutablePath()) > 5); } TEST(GetExecutablePathMatchesClassTest) { CHECK_EQUAL(il2cpp::os::Path::GetExecutablePath().c_str(), UnityPalGetExecutablePath()); } } #endif // ENABLE_UNIT_TESTS ================================================ FILE: unity_decoder/libil2cpp/os/c-api/tests/ProcessTests.cpp ================================================ #if ENABLE_UNIT_TESTS #include "UnitTest++.h" #include "../../Process.h" #include "../Process-c-api.h" SUITE(ProcessTests) { TEST(GetProcessIDTest) { CHECK(UnityPalGetCurrentProcessId() > 0); } TEST(GetProcessIDMatchesClassTest) { CHECK_EQUAL(il2cpp::os::Process::GetCurrentProcessId(), UnityPalGetCurrentProcessId()); } TEST(GetProcessHandleValidTest) { UnityPalProcessHandle* handle = NULL; handle = UnityPalGetProcess(UnityPalGetCurrentProcessId()); CHECK_NOT_NULL(handle); } TEST(GetProcessHandleMatchesClassTest) { int processId = il2cpp::os::Process::GetCurrentProcessId(); UnityPalProcessHandle* api_handle = UnityPalGetProcess(processId); il2cpp::os::ProcessHandle* class_handle = il2cpp::os::Process::GetProcess(processId); std::string api_name = il2cpp::os::Process::GetProcessName(api_handle); std::string class_name = il2cpp::os::Process::GetProcessName(class_handle); CHECK_EQUAL(class_name, api_name); } TEST(GetProcessNameNotNullTest) { int processId = il2cpp::os::Process::GetCurrentProcessId(); UnityPalProcessHandle* processHandle = UnityPalGetProcess(processId); const char* processName = UnityPalGetProcessName(processHandle); CHECK_NOT_NULL(processName); } TEST(GetProcessNameValidTest) { int processId = il2cpp::os::Process::GetCurrentProcessId(); UnityPalProcessHandle* processHandle = UnityPalGetProcess(processId); const char* processName = UnityPalGetProcessName(processHandle); CHECK(strlen(processName) > 0); } TEST(GetProcessNameMatchesClassTest) { int processId = il2cpp::os::Process::GetCurrentProcessId(); UnityPalProcessHandle* api_handle = UnityPalGetProcess(processId); il2cpp::os::ProcessHandle* class_handle = il2cpp::os::Process::GetProcess(processId); const char* api_name = UnityPalGetProcessName(api_handle); std::string class_name = il2cpp::os::Process::GetProcessName(class_handle); CHECK_EQUAL(class_name.c_str(), api_name); } TEST(GetProcessNameWithInvalidIdTest) { const char* processName = NULL; // First check the staticness, grab a real string processName = UnityPalGetProcessName(UnityPalGetProcess(UnityPalGetCurrentProcessId())); // Now test that it goes blank processName = UnityPalGetProcessName(UnityPalGetProcess(-9999999)); CHECK_EQUAL("", processName); } } #endif // ENABLE_UNIT_TESTS ================================================ FILE: unity_decoder/libil2cpp/os/c-api/tests/TimeTests.cpp ================================================ #if ENABLE_UNIT_TESTS #include "UnitTest++.h" #include "../Time-c-api.h" #include "../../Time.h" SUITE(TimeTests) { TEST(TicksMillisecondsMonotonicTestValid) { CHECK(UnityPalGetTicksMillisecondsMonotonic() > 0); } TEST(TicksMillisecondsMonotonicEqualsClassTest) { CHECK_EQUAL(il2cpp::os::Time::GetTicksMillisecondsMonotonic(), UnityPalGetTicksMillisecondsMonotonic()); } TEST(Ticks100NanosecondsMonotonicTestValid) { CHECK(UnityPalGetTicks100NanosecondsMonotonic() > 0); } TEST(Ticks100NanosecondsMonotonicEqualsClassTest) { // This number is fairly sensitive to time between calls, check to see if they are close enough, chop off the last few digits CHECK_EQUAL(il2cpp::os::Time::GetTicks100NanosecondsMonotonic() / 1000L, UnityPalGetTicks100NanosecondsMonotonic() / 1000L); } TEST(GetTicks100NanosecondsDateTimeTest) { CHECK(UnityPalGetTicks100NanosecondsDateTime() > 0); } TEST(GetTicks100NanosecondsDateTimeEqualsClassTest) { CHECK_EQUAL(il2cpp::os::Time::GetTicks100NanosecondsDateTime() / 1000L, UnityPalGetTicks100NanosecondsDateTime() / 1000L); } TEST(GetSystemTimeAsFileTimeTest) { CHECK(UnityPalGetSystemTimeAsFileTime() > 0); } TEST(GetSystemTimeAsFileTimeEqualsClassTest) { CHECK_EQUAL(il2cpp::os::Time::GetSystemTimeAsFileTime(), UnityPalGetSystemTimeAsFileTime()); } } #endif // ENABLE_UNIT_TESTS ================================================ FILE: unity_decoder/libil2cpp/os/c-api/tests/TimeZoneTests.cpp ================================================ #if ENABLE_UNIT_TESTS #include "UnitTest++.h" #include "../TimeZone-c-api.h" #include "../../TimeZone.h" SUITE(TimeZoneTests) { static const int32_t INVALID_YEAR = -45; static const int32_t VALID_YEAR = 2015; TEST(TimeZoneResultMatchesClassResultValidYear) { int64_t data_c_api[4]; const char* names_c_api[2]; bool result_c_api; int64_t data_class[4]; std::string names_class[2]; bool result_class; result_c_api = UnityPalGetTimeZoneData(VALID_YEAR, data_c_api, names_c_api); result_class = il2cpp::os::TimeZone::GetTimeZoneData(VALID_YEAR, data_class, names_class); CHECK_EQUAL(result_class, result_c_api); } TEST(TimeZoneResultMatchesClassResultInValidYear) { int64_t data_c_api[4]; const char* names_c_api[2]; bool result_c_api; int64_t data_class[4]; std::string names_class[2]; bool result_class; result_c_api = UnityPalGetTimeZoneData(INVALID_YEAR, data_c_api, names_c_api); result_class = il2cpp::os::TimeZone::GetTimeZoneData(INVALID_YEAR, data_class, names_class); CHECK_EQUAL(result_class, result_c_api); } TEST(TimeZoneStartOfDayLightSavingsValidYearMatchesClass) { int64_t data_c_api[4]; const char* names_c_api[2]; bool result_c_api; int64_t data_class[4]; std::string names_class[2]; bool result_class; result_c_api = UnityPalGetTimeZoneData(VALID_YEAR, data_c_api, names_c_api); result_class = il2cpp::os::TimeZone::GetTimeZoneData(VALID_YEAR, data_class, names_class); CHECK_EQUAL(data_class[0], data_c_api[0]); } TEST(TimeZoneEndOfDayLightSavingsValidYearMatchesClass) { int64_t data_c_api[4]; const char* names_c_api[2]; bool result_c_api; int64_t data_class[4]; std::string names_class[2]; bool result_class; result_c_api = UnityPalGetTimeZoneData(VALID_YEAR, data_c_api, names_c_api); result_class = il2cpp::os::TimeZone::GetTimeZoneData(VALID_YEAR, data_class, names_class); CHECK_EQUAL(data_class[1], data_c_api[1]); } TEST(TimeZoneUTFOffsetValidYear) { int64_t data_c_api[4]; const char* names_c_api[2]; bool result_c_api; result_c_api = UnityPalGetTimeZoneData(VALID_YEAR, data_c_api, names_c_api); CHECK(data_c_api[2] < 1L); } TEST(TimeZoneUTFOffSetValidYearMatchesClass) { int64_t data_c_api[4]; const char* names_c_api[2]; bool result_c_api; int64_t data_class[4]; std::string names_class[2]; bool result_class; result_c_api = UnityPalGetTimeZoneData(VALID_YEAR, data_c_api, names_c_api); result_class = il2cpp::os::TimeZone::GetTimeZoneData(VALID_YEAR, data_class, names_class); CHECK_EQUAL(data_class[2], data_c_api[2]); } TEST(TimeZoneAdditionalOffSetValidYearMatchesClass) { int64_t data_c_api[4]; const char* names_c_api[2]; bool result_c_api; int64_t data_class[4]; std::string names_class[2]; bool result_class; result_c_api = UnityPalGetTimeZoneData(VALID_YEAR, data_c_api, names_c_api); result_class = il2cpp::os::TimeZone::GetTimeZoneData(VALID_YEAR, data_class, names_class); CHECK_EQUAL(data_class[3], data_c_api[3]); } TEST(TimeZoneNameNotDayLighttValidYear) { int64_t data_c_api[4]; const char* names_c_api[2]; bool result_c_api; result_c_api = UnityPalGetTimeZoneData(VALID_YEAR, data_c_api, names_c_api); CHECK(strlen(names_c_api[0]) > 1); } TEST(TimeZoneNameNotDayLightValidYearMatchesClass) { int64_t data_c_api[4]; const char* names_c_api[2]; bool result_c_api; int64_t data_class[4]; std::string names_class[2]; bool result_class; result_c_api = UnityPalGetTimeZoneData(VALID_YEAR, data_c_api, names_c_api); result_class = il2cpp::os::TimeZone::GetTimeZoneData(VALID_YEAR, data_class, names_class); CHECK_EQUAL(names_class[0].c_str(), names_c_api[0]); } TEST(TimeZoneNameDayLighttValidYear) { int64_t data_c_api[4]; const char* names_c_api[2]; bool result_c_api; result_c_api = UnityPalGetTimeZoneData(VALID_YEAR, data_c_api, names_c_api); CHECK(strlen(names_c_api[1]) > 1); } TEST(TimeZoneNameDayLightValidYearMatchesClass) { int64_t data_c_api[4]; const char* names_c_api[2]; bool result_c_api; int64_t data_class[4]; std::string names_class[2]; bool result_class; result_c_api = UnityPalGetTimeZoneData(VALID_YEAR, data_c_api, names_c_api); result_class = il2cpp::os::TimeZone::GetTimeZoneData(VALID_YEAR, data_class, names_class); CHECK_EQUAL(names_class[1].c_str(), names_c_api[1]); } } #endif // ENABLE_UNIT_TESTS ================================================ FILE: unity_decoder/libil2cpp/os/c-api/tests/libil2cpp-c-api-tests.vcxproj ================================================  Debug Win32 Release Win32 Debug x64 Release x64 15.0 {78826D45-2742-4AAA-A738-CD47C8775876} libil2cppcapitests 10.0.14393.0 Application true v141 MultiByte Application false v141 true MultiByte Application true v100 MultiByte Application false v141 true MultiByte $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ $(SolutionDir)build\$(Configuration)\$(Platform)\ build\$(Configuration)\$(Platform)\ Level3 Disabled true ../../../;../../../../../il2cpp-dependencies/UnitTest++;%(AdditionalIncludeDirectories) MultiThreadedDebug ENABLE_UNIT_TESTS;%(PreprocessorDefinitions) ../../../../build/$(Configuration)/$(Platform)/libil2cpp.lib;psapi.lib;Shell32.lib;Advapi32.lib;ole32.lib;oleaut32.lib Console wWinMainCRTStartup true Level3 Disabled true ../../../;../../../../../il2cpp-dependencies/UnitTest++;%(AdditionalIncludeDirectories) ENABLE_UNIT_TESTS;%(PreprocessorDefinitions) ../../../../build/$(Configuration)/$(Platform)/libil2cpp.lib;psapi.lib;Shell32.lib;Advapi32.lib;ole32.lib;oleaut32.lib Console wWinMainCRTStartup true Level3 MaxSpeed true true true ../../../;../../../../../il2cpp-dependencies/UnitTest++;%(AdditionalIncludeDirectories) ENABLE_UNIT_TESTS;%(PreprocessorDefinitions) true true ../../../../build/$(Configuration)/$(Platform)/libil2cpp.lib;psapi.lib;Shell32.lib;Advapi32.lib;ole32.lib;oleaut32.lib Console wWinMainCRTStartup Level3 MaxSpeed true true true ../../../;../../../../../il2cpp-dependencies/UnitTest++;%(AdditionalIncludeDirectories) ENABLE_UNIT_TESTS;%(PreprocessorDefinitions) true true ../../../../build/$(Configuration)/$(Platform)/libil2cpp.lib;psapi.lib;Shell32.lib;Advapi32.lib;ole32.lib;oleaut32.lib Console wWinMainCRTStartup ================================================ FILE: unity_decoder/libil2cpp/os/c-api/tests/libil2cpp-c-api-tests.vcxproj.filters ================================================  {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms {a90afd27-d348-410a-80f0-8e370ca5a1f0} Source Files Source Files Source Files Source Files Source Files Source Files UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ Source Files UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ UnitTest++ ================================================ FILE: unity_decoder/libil2cpp/tabledefs.h ================================================ #pragma once /* * Field Attributes (21.1.5). */ #define FIELD_ATTRIBUTE_FIELD_ACCESS_MASK 0x0007 #define FIELD_ATTRIBUTE_COMPILER_CONTROLLED 0x0000 #define FIELD_ATTRIBUTE_PRIVATE 0x0001 #define FIELD_ATTRIBUTE_FAM_AND_ASSEM 0x0002 #define FIELD_ATTRIBUTE_ASSEMBLY 0x0003 #define FIELD_ATTRIBUTE_FAMILY 0x0004 #define FIELD_ATTRIBUTE_FAM_OR_ASSEM 0x0005 #define FIELD_ATTRIBUTE_PUBLIC 0x0006 #define FIELD_ATTRIBUTE_STATIC 0x0010 #define FIELD_ATTRIBUTE_INIT_ONLY 0x0020 #define FIELD_ATTRIBUTE_LITERAL 0x0040 #define FIELD_ATTRIBUTE_NOT_SERIALIZED 0x0080 #define FIELD_ATTRIBUTE_SPECIAL_NAME 0x0200 #define FIELD_ATTRIBUTE_PINVOKE_IMPL 0x2000 /* For runtime use only */ #define FIELD_ATTRIBUTE_RESERVED_MASK 0x9500 #define FIELD_ATTRIBUTE_RT_SPECIAL_NAME 0x0400 #define FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL 0x1000 #define FIELD_ATTRIBUTE_HAS_DEFAULT 0x8000 #define FIELD_ATTRIBUTE_HAS_FIELD_RVA 0x0100 /* * Method Attributes (22.1.9) */ #define METHOD_IMPL_ATTRIBUTE_CODE_TYPE_MASK 0x0003 #define METHOD_IMPL_ATTRIBUTE_IL 0x0000 #define METHOD_IMPL_ATTRIBUTE_NATIVE 0x0001 #define METHOD_IMPL_ATTRIBUTE_OPTIL 0x0002 #define METHOD_IMPL_ATTRIBUTE_RUNTIME 0x0003 #define METHOD_IMPL_ATTRIBUTE_MANAGED_MASK 0x0004 #define METHOD_IMPL_ATTRIBUTE_UNMANAGED 0x0004 #define METHOD_IMPL_ATTRIBUTE_MANAGED 0x0000 #define METHOD_IMPL_ATTRIBUTE_FORWARD_REF 0x0010 #define METHOD_IMPL_ATTRIBUTE_PRESERVE_SIG 0x0080 #define METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL 0x1000 #define METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED 0x0020 #define METHOD_IMPL_ATTRIBUTE_NOINLINING 0x0008 #define METHOD_IMPL_ATTRIBUTE_MAX_METHOD_IMPL_VAL 0xffff #define METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK 0x0007 #define METHOD_ATTRIBUTE_COMPILER_CONTROLLED 0x0000 #define METHOD_ATTRIBUTE_PRIVATE 0x0001 #define METHOD_ATTRIBUTE_FAM_AND_ASSEM 0x0002 #define METHOD_ATTRIBUTE_ASSEM 0x0003 #define METHOD_ATTRIBUTE_FAMILY 0x0004 #define METHOD_ATTRIBUTE_FAM_OR_ASSEM 0x0005 #define METHOD_ATTRIBUTE_PUBLIC 0x0006 #define METHOD_ATTRIBUTE_STATIC 0x0010 #define METHOD_ATTRIBUTE_FINAL 0x0020 #define METHOD_ATTRIBUTE_VIRTUAL 0x0040 #define METHOD_ATTRIBUTE_HIDE_BY_SIG 0x0080 #define METHOD_ATTRIBUTE_VTABLE_LAYOUT_MASK 0x0100 #define METHOD_ATTRIBUTE_REUSE_SLOT 0x0000 #define METHOD_ATTRIBUTE_NEW_SLOT 0x0100 #define METHOD_ATTRIBUTE_STRICT 0x0200 #define METHOD_ATTRIBUTE_ABSTRACT 0x0400 #define METHOD_ATTRIBUTE_SPECIAL_NAME 0x0800 #define METHOD_ATTRIBUTE_PINVOKE_IMPL 0x2000 #define METHOD_ATTRIBUTE_UNMANAGED_EXPORT 0x0008 /* * For runtime use only */ #define METHOD_ATTRIBUTE_RESERVED_MASK 0xd000 #define METHOD_ATTRIBUTE_RT_SPECIAL_NAME 0x1000 #define METHOD_ATTRIBUTE_HAS_SECURITY 0x4000 #define METHOD_ATTRIBUTE_REQUIRE_SEC_OBJECT 0x8000 /* * Type Attributes (21.1.13). */ #define TYPE_ATTRIBUTE_VISIBILITY_MASK 0x00000007 #define TYPE_ATTRIBUTE_NOT_PUBLIC 0x00000000 #define TYPE_ATTRIBUTE_PUBLIC 0x00000001 #define TYPE_ATTRIBUTE_NESTED_PUBLIC 0x00000002 #define TYPE_ATTRIBUTE_NESTED_PRIVATE 0x00000003 #define TYPE_ATTRIBUTE_NESTED_FAMILY 0x00000004 #define TYPE_ATTRIBUTE_NESTED_ASSEMBLY 0x00000005 #define TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM 0x00000006 #define TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM 0x00000007 #define TYPE_ATTRIBUTE_LAYOUT_MASK 0x00000018 #define TYPE_ATTRIBUTE_AUTO_LAYOUT 0x00000000 #define TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT 0x00000008 #define TYPE_ATTRIBUTE_EXPLICIT_LAYOUT 0x00000010 #define TYPE_ATTRIBUTE_CLASS_SEMANTIC_MASK 0x00000020 #define TYPE_ATTRIBUTE_CLASS 0x00000000 #define TYPE_ATTRIBUTE_INTERFACE 0x00000020 #define TYPE_ATTRIBUTE_ABSTRACT 0x00000080 #define TYPE_ATTRIBUTE_SEALED 0x00000100 #define TYPE_ATTRIBUTE_SPECIAL_NAME 0x00000400 #define TYPE_ATTRIBUTE_IMPORT 0x00001000 #define TYPE_ATTRIBUTE_SERIALIZABLE 0x00002000 #define TYPE_ATTRIBUTE_STRING_FORMAT_MASK 0x00030000 #define TYPE_ATTRIBUTE_ANSI_CLASS 0x00000000 #define TYPE_ATTRIBUTE_UNICODE_CLASS 0x00010000 #define TYPE_ATTRIBUTE_AUTO_CLASS 0x00020000 #define TYPE_ATTRIBUTE_BEFORE_FIELD_INIT 0x00100000 #define TYPE_ATTRIBUTE_FORWARDER 0x00200000 #define TYPE_ATTRIBUTE_RESERVED_MASK 0x00040800 #define TYPE_ATTRIBUTE_RT_SPECIAL_NAME 0x00000800 #define TYPE_ATTRIBUTE_HAS_SECURITY 0x00040000 /* * Flags for Params (22.1.12) */ #define PARAM_ATTRIBUTE_IN 0x0001 #define PARAM_ATTRIBUTE_OUT 0x0002 #define PARAM_ATTRIBUTE_OPTIONAL 0x0010 #define PARAM_ATTRIBUTE_RESERVED_MASK 0xf000 #define PARAM_ATTRIBUTE_HAS_DEFAULT 0x1000 #define PARAM_ATTRIBUTE_HAS_FIELD_MARSHAL 0x2000 #define PARAM_ATTRIBUTE_UNUSED 0xcfe0 // Flags for Generic Parameters (II.23.1.7) #define GENERIC_PARAMETER_ATTRIBUTE_NON_VARIANT 0x00 #define GENERIC_PARAMETER_ATTRIBUTE_COVARIANT 0x01 #define GENERIC_PARAMETER_ATTRIBUTE_CONTRAVARIANT 0x02 #define GENERIC_PARAMETER_ATTRIBUTE_VARIANCE_MASK 0x03 #define GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT 0x04 #define GENERIC_PARAMETER_ATTRIBUTE_NOT_NULLABLE_VALUE_TYPE_CONSTRAINT 0x08 #define GENERIC_PARAMETER_ATTRIBUTE_DEFAULT_CONSTRUCTOR_CONSTRAINT 0x10 #define GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINT_MASK 0x1C /** * 21.5 AssemblyRefs */ #define ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG 0x00000001 #define ASSEMBLYREF_RETARGETABLE_FLAG 0x00000100 #define ASSEMBLYREF_ENABLEJITCOMPILE_TRACKING_FLAG 0x00008000 #define ASSEMBLYREF_DISABLEJITCOMPILE_OPTIMIZER_FLAG 0x00004000 ================================================ FILE: unity_decoder/libil2cpp/utils/CallOnce.h ================================================ #pragma once #include "NonCopyable.h" #include "../os/Atomic.h" #include "../os/Mutex.h" namespace il2cpp { namespace utils { typedef void (*CallOnceFunc) (void* arg); struct OnceFlag : NonCopyable { OnceFlag() : m_Flag(NULL) { } friend void CallOnce(OnceFlag& flag, CallOnceFunc func, void* arg); bool IsSet() { return il2cpp::os::Atomic::ReadPointer(&m_Flag) ? true : false; } private: void* m_Flag; il2cpp::os::FastMutex m_Mutex; }; inline void CallOnce(OnceFlag& flag, CallOnceFunc func, void* arg) { if (!il2cpp::os::Atomic::ReadPointer(&flag.m_Flag)) { os::FastAutoLock lock(&flag.m_Mutex); if (!il2cpp::os::Atomic::ReadPointer(&flag.m_Flag)) { func(arg); il2cpp::os::Atomic::ExchangePointer(&flag.m_Flag, (void*)1); } } } } } ================================================ FILE: unity_decoder/libil2cpp/utils/Collections.h ================================================ #pragma once #include #include #include #include "NonCopyable.h" namespace il2cpp { namespace utils { namespace collections { // Memory compact, map-like data structure that stores values and // is a able to compute the key from the value with the provided converter // This data structure is perfect to storing values that will not be changed // for the duration of program (like type metadata) and need fast querying // // It is able to store multiple values associated with a single key, and query them through find() // find_first() is a special case find() which improves performance for cases where we don't store multiple values for each key template, typename TKeyEquals = std::equal_to > class ArrayValueMap : NonCopyable { public: typedef ArrayValueMap map_type; typedef const TValue* iterator; private: const TValue* m_Values; const size_t m_ValueCount; bool m_OwnStorage; const TValueToKeyConverter m_ValueToKeyConverter; const TKeyLess m_KeyLessComparer; const TKeyEquals m_KeyEqualsComparer; struct SortComparer { private: const TValueToKeyConverter m_ValueToKeyConverter; const TKeyLess m_KeyComparer; public: SortComparer(TValueToKeyConverter valueToKeyConverter, TKeyLess keyComparer) : m_ValueToKeyConverter(valueToKeyConverter), m_KeyComparer(keyComparer) { } inline bool operator()(const TValue& left, const TValue& right) const { return m_KeyComparer(m_ValueToKeyConverter(left), m_ValueToKeyConverter(right)); } }; struct LowerBoundFindComparer { private: const TValueToKeyConverter m_ValueToKeyConverter; const TKeyLess m_KeyComparer; public: LowerBoundFindComparer(TValueToKeyConverter valueToKeyConverter, TKeyLess keyComparer) : m_ValueToKeyConverter(valueToKeyConverter), m_KeyComparer(keyComparer) { } inline bool operator()(const TValue& left, const TKey& right) const { return m_KeyComparer(m_ValueToKeyConverter(left), right); } }; struct UpperBoundFindComparer { private: const TValueToKeyConverter m_ValueToKeyConverter; const TKeyLess m_KeyComparer; public: UpperBoundFindComparer(TValueToKeyConverter valueToKeyConverter, TKeyLess keyComparer) : m_ValueToKeyConverter(valueToKeyConverter), m_KeyComparer(keyComparer) { } inline bool operator()(const TKey& left, const TValue& right) const { return m_KeyComparer(left, m_ValueToKeyConverter(right)); } }; inline static TValue* InitializeInPlace(TValue* values, size_t valueCount, TValueToKeyConverter valueToKeyConverter, TKeyLess keyLessComparer) { std::sort(values, values + valueCount, SortComparer(valueToKeyConverter, keyLessComparer)); return values; } inline static TValue* AllocateAndInitialize(const TValue* originalValues, size_t valueCount, TValueToKeyConverter valueToKeyConverter, TKeyLess keyLessComparer) { TValue* values = new TValue[valueCount]; memcpy(values, originalValues, valueCount * sizeof(TValue)); return InitializeInPlace(values, valueCount, valueToKeyConverter, keyLessComparer); } public: inline ArrayValueMap() : m_Values(NULL), m_ValueCount(0), m_OwnStorage(false), m_ValueToKeyConverter(TValueToKeyConverter()), m_KeyLessComparer(TKeyLess()), m_KeyEqualsComparer(TKeyEquals()) { } // Non-allocating constructor. It will take a pointer and will not allocate any storage // It WILL sort existing values inline ArrayValueMap(TValue* values, size_t valueCount, TValueToKeyConverter valueToKeyConverter = TValueToKeyConverter(), TKeyLess keyLessComparer = TKeyLess(), TKeyEquals keyEqualsComparer = TKeyEquals()) : m_Values(InitializeInPlace(values, valueCount, valueToKeyConverter, keyLessComparer)), m_ValueCount(valueCount), m_ValueToKeyConverter(valueToKeyConverter), m_KeyLessComparer(keyLessComparer), m_KeyEqualsComparer(keyEqualsComparer), m_OwnStorage(false) { } // Allocating constructor // Will copy values to newly allocated storage inline ArrayValueMap(const std::vector& values, TValueToKeyConverter valueToKeyConverter = TValueToKeyConverter(), TKeyLess keyLessComparer = TKeyLess(), TKeyEquals keyEqualsComparer = TKeyEquals()) : m_Values(AllocateAndInitialize(values.data(), values.size(), valueToKeyConverter, keyLessComparer)), m_ValueCount(values.size()), m_ValueToKeyConverter(valueToKeyConverter), m_KeyLessComparer(keyLessComparer), m_KeyEqualsComparer(keyEqualsComparer), m_OwnStorage(true) { } ~ArrayValueMap() { if (m_OwnStorage) { delete[] m_Values; } } inline void assign_external(TValue* values, size_t valueCount, TValueToKeyConverter valueToKeyConverter = TValueToKeyConverter(), TKeyLess keyLessComparer = TKeyLess(), TKeyEquals keyEqualsComparer = TKeyEquals()) { this->~ArrayValueMap(); new(this)map_type(values, valueCount, valueToKeyConverter, keyLessComparer, keyEqualsComparer); } // Constructs map that contains pointers to original array inline void assign_addresses(const TValue& valueArray, size_t valueCount, TValueToKeyConverter valueToKeyConverter = TValueToKeyConverter(), TKeyLess keyLessComparer = TKeyLess(), TKeyEquals keyEqualsComparer = TKeyEquals()) { this->~ArrayValueMap(); TValue* storage = NULL; if (valueCount > 0) { storage = new TValue[valueCount]; for (size_t i = 0; i < valueCount; i++) { storage[i] = &valueArray[i]; } } new(this)map_type(storage, valueCount, valueToKeyConverter, keyLessComparer, keyEqualsComparer); m_OwnStorage = true; } inline void assign(const std::vector& values, TValueToKeyConverter valueToKeyConverter = TValueToKeyConverter(), TKeyLess keyLessComparer = TKeyLess(), TKeyEquals keyEqualsComparer = TKeyEquals()) { this->~ArrayValueMap(); new(this)map_type(values, valueToKeyConverter, keyLessComparer, keyEqualsComparer); } inline iterator begin() const { return m_Values; } inline iterator end() const { return m_Values + m_ValueCount; } template inline iterator find(const TKey& key, const EqualsPredicate& equalsPredicate) const { iterator dataStart = begin(); iterator dataEnd = end(); iterator ptr = std::lower_bound(dataStart, dataEnd, key, LowerBoundFindComparer(m_ValueToKeyConverter, m_KeyLessComparer)); for (; ptr != dataEnd && m_KeyEqualsComparer(m_ValueToKeyConverter(*ptr), key); ptr++) { if (equalsPredicate(*ptr)) return ptr; } return dataEnd; } inline iterator find_first(const TKey& key) const { iterator dataStart = begin(); iterator dataEnd = end(); iterator ptr = std::lower_bound(dataStart, dataEnd, key, LowerBoundFindComparer(m_ValueToKeyConverter, m_KeyLessComparer)); if (ptr != dataEnd && m_KeyEqualsComparer(m_ValueToKeyConverter(*ptr), key)) return ptr; return dataEnd; } inline iterator lower_bound(const TKey& key) const { return std::lower_bound(begin(), end(), key, LowerBoundFindComparer(m_ValueToKeyConverter, m_KeyLessComparer)); } inline iterator upper_bound(const TKey& key) const { return std::upper_bound(begin(), end(), key, UpperBoundFindComparer(m_ValueToKeyConverter, m_KeyLessComparer)); } inline size_t size() const { return m_ValueCount; } inline const TValue& operator[](size_t i) const { return m_Values[i]; } }; } } // namespace utils } // namespace il2cpp ================================================ FILE: unity_decoder/libil2cpp/utils/DirectoryUtils.cpp ================================================ /* Directory utility functions that are common to all posix and posix-like platforms. */ #include "il2cpp-config.h" #include "StringUtils.h" #include "DirectoryUtils.h" namespace il2cpp { namespace utils { bool Match(const std::string name, size_t nameIndex, const std::string& pattern, const size_t patternIndex) { const size_t nameLength = name.length(); for (size_t i = patternIndex, patternLength = pattern.length(); i < patternLength; ++i) { const char c = pattern[i]; if (c == '*') { if (i + 1 == patternLength) // Star is last character, match everything. return true; do { // Check that we match the rest of the pattern against name. if (Match(name, nameIndex, pattern, i + 1)) return true; } while (nameIndex++ < nameLength); return false; } else if (c == '?') { if (nameIndex == nameLength) return false; nameIndex++; } else { if (nameIndex == nameLength || name[nameIndex] != c) return false; nameIndex++; } } // All characters matched return nameIndex == nameLength; } bool Match(const std::string name, const std::string& pattern) { return Match(name, 0, pattern, 0); } std::string CollapseAdjacentStars(const std::string& pattern) { std::string matchPattern; matchPattern.reserve(pattern.length()); // Collapse adjacent stars into one for (size_t i = 0, length = pattern.length(); i < length; ++i) { if (i > 0 && pattern[i] == '*' && pattern[i - 1] == '*') continue; matchPattern.append(1, pattern[i]); } return matchPattern; } } } ================================================ FILE: unity_decoder/libil2cpp/utils/DirectoryUtils.h ================================================ #pragma once #include namespace il2cpp { namespace utils { bool Match(const std::string name, size_t nameIndex, const std::string& pattern, const size_t patternIndex); bool Match(const std::string name, const std::string& pattern); std::string CollapseAdjacentStars(const std::string& pattern); } } ================================================ FILE: unity_decoder/libil2cpp/utils/Environment.cpp ================================================ #include "il2cpp-config.h" #include "utils/StringUtils.h" #include "utils/Environment.h" namespace il2cpp { namespace utils { static int s_ArgCount = 0; static std::vector s_Args; void Environment::SetMainArgs(const char* const* args, int num_args) { s_ArgCount = num_args; s_Args.resize(num_args); for (int i = 0; i < num_args; i++) s_Args[i] = utils::StringUtils::Utf8ToUtf16(args[i]); } void Environment::SetMainArgs(const Il2CppChar* const* args, int num_args) { s_ArgCount = num_args; s_Args.resize(num_args); for (int i = 0; i < num_args; i++) s_Args[i] = args[i]; } const std::vector& Environment::GetMainArgs() { return s_Args; } int Environment::GetNumMainArgs() { return s_ArgCount; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/utils/Environment.h ================================================ #pragma once #include #include #include "il2cpp-config.h" #include "il2cpp-string-types.h" struct Il2CppDomain; namespace il2cpp { namespace utils { class LIBIL2CPP_CODEGEN_API Environment { public: static const std::vector& GetMainArgs(); static int GetNumMainArgs(); static void SetMainArgs(const char* const* args, int num_args); static void SetMainArgs(const Il2CppChar* const* args, int num_args); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/utils/Exception.cpp ================================================ #include "utils/Exception.h" #include "utils/StringUtils.h" #include "object-internals.h" namespace il2cpp { namespace utils { std::string Exception::FormatException(const Il2CppException* ex) { std::string exception_namespace = ex->klass->namespaze; std::string exception_type = ex->klass->name; if (ex->message) return exception_namespace + "." + exception_type + ": " + il2cpp::utils::StringUtils::Utf16ToUtf8(il2cpp::utils::StringUtils::GetChars(ex->message)); else return exception_namespace + "." + exception_type; } std::string Exception::FormatInvalidCastException(const Il2CppClass* fromType, const Il2CppClass* toType) { std::string message; if (fromType != NULL && toType != NULL) { message += "Unable to cast object of type '"; message += fromType->name; message += "' to type '"; message += toType->name; message += "'."; } return message; } std::string Exception::FormatStackTrace(const Il2CppException* ex) { if (ex->stack_trace) return il2cpp::utils::StringUtils::Utf16ToUtf8(il2cpp::utils::StringUtils::GetChars(ex->stack_trace)); return ""; } } // utils } // il2cpp ================================================ FILE: unity_decoder/libil2cpp/utils/Exception.h ================================================ #pragma once #include "il2cpp-config.h" #include struct Il2CppException; namespace il2cpp { namespace utils { class LIBIL2CPP_CODEGEN_API Exception { public: static std::string FormatException(const Il2CppException* ex); static std::string FormatStackTrace(const Il2CppException* ex); static std::string FormatInvalidCastException(const Il2CppClass* fromType, const Il2CppClass* toType); }; } // utils } // utils ================================================ FILE: unity_decoder/libil2cpp/utils/Functional.h ================================================ #pragma once #include "utils/NonCopyable.h" namespace il2cpp { namespace utils { namespace functional { struct TrueFilter { template inline bool operator()(const T& item) const { return true; } }; template struct Filter : NonCopyable { private: ItemType m_Item; Comparer m_Comparer; public: Filter(ItemType item, Comparer comparer = Comparer()) : m_Item(item), m_Comparer(comparer) { } template inline bool operator()(const T& item) const { return m_Comparer(m_Item, item); } }; } // functional } // utils } // il2cpp ================================================ FILE: unity_decoder/libil2cpp/utils/HashUtils.h ================================================ #pragma once namespace il2cpp { namespace utils { class HashUtils { static const size_t Seed = 486187739; public: static inline size_t Combine(size_t hash1, size_t hash2) { return hash1 * Seed + hash2; } }; template struct PointerHash { size_t operator()(const T* value) const { return (size_t)value; } }; template struct PassThroughHash { size_t operator()(T value) const { return (size_t)value; } }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/utils/Il2CppHStringReference.h ================================================ #pragma once #include #include "StringView.h" #include "vm/Exception.h" #include "vm/WindowsRuntime.h" namespace il2cpp { namespace utils { class Il2CppHStringReference { private: Il2CppHString m_String; Il2CppHStringHeader m_Header; public: inline Il2CppHStringReference(const StringView& str) { il2cpp::vm::WindowsRuntime::CreateHStringReference(str, &m_Header, &m_String); } inline operator Il2CppHString() const { return m_String; } }; } } ================================================ FILE: unity_decoder/libil2cpp/utils/Il2CppHashMap.h ================================================ #pragma once #include "../external/google/sparsehash/dense_hash_map.h" #include "KeyWrapper.h" template, class Alloc = std::allocator, T> > > class Il2CppHashMap : public dense_hash_map, T, HashFcn, typename KeyWrapper::template EqualsComparer, Alloc> { private: typedef dense_hash_map, T, HashFcn, typename KeyWrapper::template EqualsComparer, Alloc> Base; public: typedef typename Base::size_type size_type; typedef typename Base::hasher hasher; typedef typename Base::key_equal key_equal; typedef typename Base::key_type key_type; explicit Il2CppHashMap(size_type n = 0, const hasher& hf = hasher(), const EqualKey& eql = EqualKey()) : Base(n, hf, key_equal(eql)) { Base::set_empty_key(key_type(key_type::KeyType_Empty)); Base::set_deleted_key(key_type(key_type::KeyType_Deleted)); } template Il2CppHashMap(InputIterator f, InputIterator l, size_type n = 0, const hasher& hf = hasher(), const EqualKey& eql = EqualKey()) : Base(f, l, n, hf, key_equal(eql)) { Base::set_empty_key(key_type(key_type::KeyType_Empty)); Base::set_deleted_key(key_type(key_type::KeyType_Deleted)); } void add(const key_type& key, const T& value) { Base::insert(std::make_pair(key, value)); } }; ================================================ FILE: unity_decoder/libil2cpp/utils/Il2CppHashSet.h ================================================ #pragma once #include "../external/google/sparsehash/dense_hash_set.h" #include "KeyWrapper.h" template, class Alloc = std::allocator > > class Il2CppHashSet : public dense_hash_set, HashFcn, typename KeyWrapper::template EqualsComparer, Alloc> { private: typedef dense_hash_set, HashFcn, typename KeyWrapper::template EqualsComparer, Alloc> Base; public: typedef typename Base::size_type size_type; typedef typename Base::hasher hasher; typedef typename Base::key_equal key_equal; typedef typename Base::key_type key_type; explicit Il2CppHashSet(size_type n = 0, const hasher& hf = hasher(), const EqualKey& eql = EqualKey()) : Base(n, hf, key_equal(eql)) { Base::set_empty_key(key_type(key_type::KeyType_Empty)); Base::set_deleted_key(key_type(key_type::KeyType_Deleted)); } template Il2CppHashSet(InputIterator f, InputIterator l, size_type n = 0, const hasher& hf = hasher(), const EqualKey& eql = EqualKey()) : Base(f, l, n, hf, key_equal(eql)) { Base::set_empty_key(key_type(key_type::KeyType_Empty)); Base::set_deleted_key(key_type(key_type::KeyType_Deleted)); } }; ================================================ FILE: unity_decoder/libil2cpp/utils/KeyWrapper.h ================================================ #pragma once template struct KeyWrapper { typedef T wrapped_type; typedef KeyWrapper self_type; enum KeyTypeEnum { KeyType_Normal, KeyType_Empty, KeyType_Deleted }; KeyTypeEnum type; T key; KeyWrapper() : type(KeyType_Normal), key(T()) {} KeyWrapper(KeyTypeEnum type_) : type(type_), key(T()) {} KeyWrapper(const T& key_) : key(key_), type(KeyType_Normal) {} KeyWrapper(const self_type& other) : type(other.type), key(other.key) {} operator const T&() const { return key; } bool isNormal() const { return (type == KeyType_Normal); } template struct EqualsComparer { EqualsComparer(KeyComparer keyComparer) : m_KeyComparer(keyComparer) { } bool operator()(const KeyWrapper& left, const KeyWrapper& right) const { if (left.type != right.type) return false; if (!left.isNormal()) return true; return m_KeyComparer(left.key, right.key); } private: KeyComparer m_KeyComparer; }; }; ================================================ FILE: unity_decoder/libil2cpp/utils/Logging.cpp ================================================ #include #include #include "Logging.h" #include "Output.h" using namespace il2cpp::utils; static void DefaultLogCallback(const char* message) { Output::WriteToStdout(message); Output::WriteToStdout("\n"); } Il2CppLogCallback Logging::s_Callback = DefaultLogCallback; void Logging::Write(const char* format, ...) { assert(s_Callback != NULL); va_list va; va_start(va, format); const char* prefix = "[libil2cpp] "; const int bufferSize = 1024 * 5; char buffer[bufferSize]; memcpy(buffer, prefix, 12); vsnprintf(buffer + 12, bufferSize - 12, format, va); s_Callback(buffer); va_end(va); } void Logging::SetLogCallback(Il2CppLogCallback method) { assert(method != NULL); s_Callback = method; } ================================================ FILE: unity_decoder/libil2cpp/utils/Logging.h ================================================ #pragma once #include "il2cpp-config.h" namespace il2cpp { namespace utils { class LIBIL2CPP_CODEGEN_API Logging { public: static void Write(const char* format, ...); static void SetLogCallback(Il2CppLogCallback method); private: static Il2CppLogCallback s_Callback; }; } } ================================================ FILE: unity_decoder/libil2cpp/utils/MarshalingUtils.cpp ================================================ #include "MarshalingUtils.h" namespace il2cpp { namespace utils { void MarshalingUtils::MarshalStructToNative(void* managedStructure, void* marshaledStructure, const Il2CppInteropData* interopData) { IL2CPP_ASSERT(interopData); IL2CPP_ASSERT(interopData->pinvokeMarshalToNativeFunction); interopData->pinvokeMarshalToNativeFunction(managedStructure, marshaledStructure); } void MarshalingUtils::MarshalStructFromNative(void* marshaledStructure, void* managedStructure, const Il2CppInteropData* interopData) { IL2CPP_ASSERT(interopData); IL2CPP_ASSERT(interopData->pinvokeMarshalFromNativeFunction); interopData->pinvokeMarshalFromNativeFunction(marshaledStructure, managedStructure); } bool MarshalingUtils::MarshalFreeStruct(void* marshaledStructure, const Il2CppInteropData* interopData) { if (interopData == NULL) return false; PInvokeMarshalCleanupFunc cleanup = interopData->pinvokeMarshalCleanupFunction; if (cleanup == NULL) return false; cleanup(marshaledStructure); return true; } } // namespace utils } // namespace il2cpp ================================================ FILE: unity_decoder/libil2cpp/utils/MarshalingUtils.h ================================================ #pragma once #include "il2cpp-config.h" #include "class-internals.h" namespace il2cpp { namespace utils { class MarshalingUtils { public: static void MarshalStructToNative(void* managedStructure, void* marshaledStructure, const Il2CppInteropData* interopData); static void MarshalStructFromNative(void* marshaledStructure, void* managedStructure, const Il2CppInteropData* interopData); static bool MarshalFreeStruct(void* marshaledStructure, const Il2CppInteropData* interopData); }; } // namespace utils } // namespace il2cpp ================================================ FILE: unity_decoder/libil2cpp/utils/MathUtils.h ================================================ #pragma once #include "il2cpp-config.h" #include #include #include #include namespace il2cpp { namespace utils { namespace MathUtils { // Do math on low/high part separately as 64-bit integers because otherwise // we might easily overflow during initial multiplication inline int64_t A_Times_B_DividedBy_C(int64_t multiplicand, int64_t multiplier, int64_t divisor) { IL2CPP_ASSERT((llabs(divisor) & (1LL << 62)) == 0 && "Can't divide by numbers with absolute value larger than 2^62 - 1."); bool resultIsNegative = static_cast(multiplicand ^ multiplier ^ divisor) >> 63; // Result is negative if odd number of operands are negative multiplicand = llabs(multiplicand); IL2CPP_ASSERT(multiplicand > 0 && "Can't multiply by -2^63."); multiplier = llabs(multiplier); IL2CPP_ASSERT(multiplier > 0 && "Can't multiply by -2^63."); divisor = llabs(divisor); // We already asserted on divisor size uint64_t multiplicand_low = multiplicand & 0xFFFFFFFF; uint64_t multiplicand_high = multiplicand >> 32; uint64_t multiplier_low = multiplier & 0xFFFFFFFF; uint64_t multiplier_high = multiplier >> 32; // We're gonna assume our multiplicated value is 128-bit integer // so we're gonna compose it of two uint64_t's // a * b = // (a_high * 2^32 + a_low) * (b_high * 2^32 + b_low) = // a_high * b_high * 2^64 + (a_high * b_low + a_low * b_high) * 2^32 + a_low * b_low uint64_t dividends[2] = { multiplicand_low * multiplier_low, // low part, bits [0, 63] multiplicand_high * multiplier_high // high part, bits [64, 127] }; uint64_t resultMid1 = multiplicand_high * multiplier_low + multiplicand_low * multiplier_high; // mid part, bits [32, 95] dividends[1] += resultMid1 >> 32; // add the higher bits of mid part ([64, 95]) to high part resultMid1 = (resultMid1 & 0xFFFFFFFF) << 32; // Now this contains the lower bits of mid part ([32, 63]) // Check for lower part overflow below adding the lower bits of mid part to it // Add carry to high part if overflow occurs if (dividends[0] > std::numeric_limits::max() - resultMid1) dividends[1]++; dividends[0] += resultMid1; // add the lower bits of mid part to low part // At this point, we got our whole divident 128-bit value inside 'dividends' uint64_t workValue = 0; // Value that we're gonna be dividing uint64_t result = 0; // The final result const uint64_t kOne = 1; int bitIndex = 127; // Current bit that we're gonna be add to the workValue // Let's find the starting point for our division // We'll keep adding bits from our divident to the workValue until it's higher than the divisor // We did divisor = llabs(divisor) earlier, so cast to unsigned is safe while (workValue < static_cast(divisor)) { workValue <<= 1; if (bitIndex > -1) { workValue |= (dividends[bitIndex / 64] & (kOne << (bitIndex % 64))) != 0; } else { return 0; } bitIndex--; } // Main division loop for (; bitIndex > -2 || workValue >= static_cast(divisor); bitIndex--) { result <<= 1; // Shift result left // Since it's binary, the division result can be only 0 and 1 // It's 1 if workValue is higher or equal to divisor if (workValue >= static_cast(divisor)) { workValue -= static_cast(divisor); result++; } // Shift work value to the left and append the next bit of our dividend IL2CPP_ASSERT((workValue & (1LL << 63)) == 0 && "overflow!"); if (bitIndex > -1) { workValue <<= 1; workValue |= (dividends[bitIndex / 64] & (kOne << (bitIndex % 64))) != 0; } } // Negate result if it's supposed to be negative if (resultIsNegative) return -static_cast(result); return result; } } } } ================================================ FILE: unity_decoder/libil2cpp/utils/Memory.cpp ================================================ #include "il2cpp-config.h" #include "os/Memory.h" #include "utils/Memory.h" #include namespace il2cpp { namespace utils { static Il2CppMemoryCallbacks s_Callbacks = { malloc, os::Memory::AlignedAlloc, free, os::Memory::AlignedFree, calloc, realloc, os::Memory::AlignedReAlloc }; void Memory::SetMemoryCallbacks(Il2CppMemoryCallbacks* callbacks) { memcpy(&s_Callbacks, callbacks, sizeof(Il2CppMemoryCallbacks)); } void* Memory::Malloc(size_t size) { return s_Callbacks.malloc_func(size); } void* Memory::AlignedMalloc(size_t size, size_t alignment) { return s_Callbacks.aligned_malloc_func(size, alignment); } void Memory::Free(void* memory) { return s_Callbacks.free_func(memory); } void Memory::AlignedFree(void* memory) { return s_Callbacks.aligned_free_func(memory); } void* Memory::Calloc(size_t count, size_t size) { return s_Callbacks.calloc_func(count, size); } void* Memory::Realloc(void* memory, size_t newSize) { return s_Callbacks.realloc_func(memory, newSize); } void* Memory::AlignedRealloc(void* memory, size_t newSize, size_t alignment) { return s_Callbacks.aligned_realloc_func(memory, newSize, alignment); } } /* namespace utils */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/utils/Memory.h ================================================ #pragma once namespace il2cpp { namespace utils { struct LIBIL2CPP_CODEGEN_API Memory { static void SetMemoryCallbacks(Il2CppMemoryCallbacks* callbacks); static void* Malloc(size_t size); static void* AlignedMalloc(size_t size, size_t alignment); static void Free(void* memory); static void AlignedFree(void* memory); static void* Calloc(size_t count, size_t size); static void* Realloc(void* memory, size_t newSize); static void* AlignedRealloc(void* memory, size_t newSize, size_t alignment); }; } /* namespace utils */ } /* namespace il2cpp */ #define IL2CPP_MALLOC(size) il2cpp::utils::Memory::Malloc(size) #define IL2CPP_MALLOC_ALIGNED(size, alignment) il2cpp::utils::Memory::AlignedMalloc(size, alignment) #define IL2CPP_MALLOC_ZERO(size) il2cpp::utils::Memory::Calloc(1,size) #define IL2CPP_FREE(memory) il2cpp::utils::Memory::Free(memory) #define IL2CPP_FREE_ALIGNED(memory) il2cpp::utils::Memory::AlignedFree(memory) #define IL2CPP_CALLOC(count, size) il2cpp::utils::Memory::Calloc(count,size) #define IL2CPP_REALLOC(memory, newSize) il2cpp::utils::Memory::Realloc(memory,newSize) #define IL2CPP_REALLOC_ALIGNED(memory, newSize, alignment) il2cpp::utils::Memory::AlignedRealloc(memory, newSize, alignment) ================================================ FILE: unity_decoder/libil2cpp/utils/MemoryPool.cpp ================================================ #include "il2cpp-config.h" #include "utils/MemoryPool.h" #include "utils/Memory.h" #include #include namespace il2cpp { namespace utils { const size_t kPageSize = IL2CPP_PAGE_SIZE; const size_t kDefaultRegionSize = 16 * 1024; // by making all allocations a multiple of this value, we ensure the next // allocation will always be aligned to this value const size_t kMemoryAlignment = 8; static inline size_t MakeMultipleOf(size_t size, size_t alignment) { return (size + alignment - 1) & ~(alignment - 1); } struct MemoryPool::Region { char* start; char* current; size_t size; size_t free; }; MemoryPool::MemoryPool() { AddRegion(kDefaultRegionSize); } MemoryPool::MemoryPool(size_t initialSize) { AddRegion(initialSize); } MemoryPool::~MemoryPool() { for (RegionList::iterator iter = m_Regions.begin(); iter != m_Regions.end(); ++iter) { IL2CPP_FREE((*iter)->start); IL2CPP_FREE(*iter); } m_Regions.clear(); } void* MemoryPool::Malloc(size_t size) { size = MakeMultipleOf(size, kMemoryAlignment); Region* region = m_Regions.back(); if (region->free < size) region = AddRegion(size); IL2CPP_ASSERT(region->free >= size); void* value = region->current; region->current += size; region->free -= size; return value; } void* MemoryPool::Calloc(size_t count, size_t size) { void* ret = Malloc(count * size); return memset(ret, 0, count * size); } MemoryPool::Region* MemoryPool::AddRegion(size_t size) { Region* region = (Region*)IL2CPP_MALLOC(sizeof(Region)); size_t allocationSize = std::max(kDefaultRegionSize, MakeMultipleOf(size, kPageSize)); region->start = region->current = (char*)IL2CPP_MALLOC(allocationSize); region->size = region->free = allocationSize; m_Regions.push_back(region); return region; } } } ================================================ FILE: unity_decoder/libil2cpp/utils/MemoryPool.h ================================================ #pragma once #include namespace il2cpp { namespace utils { class MemoryPool { public: MemoryPool(); MemoryPool(size_t initialSize); ~MemoryPool(); void* Malloc(size_t size); void* Calloc(size_t count, size_t size); private: struct Region; typedef std::list RegionList; Region* AddRegion(size_t size); RegionList m_Regions; }; } /* namespace utils */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/utils/MemoryRead.h ================================================ #pragma once #include #include // unaligned safe reading namespace il2cpp { namespace utils { static inline Il2CppChar ReadChar(const char* p) { Il2CppChar val; memcpy(&val, p, sizeof(Il2CppChar)); return val; } static inline uint16_t Read16(const char* p) { uint16_t val; memcpy(&val, p, sizeof(uint16_t)); return val; } static inline uint32_t Read32(const char* p) { uint32_t val; memcpy(&val, p, sizeof(uint32_t)); return val; } static inline uint64_t Read64(const char* p) { uint64_t val; memcpy(&val, p, sizeof(uint64_t)); return val; } static inline float ReadFloat(const char* p) { float val; memcpy(&val, p, sizeof(float)); return val; } static inline double ReadDouble(const char* p) { double val; memcpy(&val, p, sizeof(double)); return val; } } /* utils */ } /* il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/utils/NonCopyable.h ================================================ #pragma once namespace il2cpp { namespace utils { class NonCopyable { public: NonCopyable() {} private: NonCopyable(const NonCopyable&); NonCopyable& operator=(const NonCopyable&); }; } } ================================================ FILE: unity_decoder/libil2cpp/utils/Output.cpp ================================================ #include "il2cpp-config.h" #include "object-internals.h" #include "Output.h" #include "os/ErrorCodes.h" #include "os/File.h" #include "StringUtils.h" using namespace il2cpp::utils; static inline void WriteToHandle(il2cpp::os::FileHandle* handle, const char* message) { int error = il2cpp::os::kErrorCodeSuccess; il2cpp::os::File::Write(handle, message, static_cast(strlen(message)), &error); IL2CPP_ASSERT(error == il2cpp::os::kErrorCodeSuccess); } void Output::WriteToStdout(const char* message) { WriteToHandle(os::File::GetStdOutput(), message); } void Output::WriteToStderr(const char* message) { WriteToHandle(os::File::GetStdError(), message); } ================================================ FILE: unity_decoder/libil2cpp/utils/Output.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppString; namespace il2cpp { namespace utils { class LIBIL2CPP_CODEGEN_API Output { public: static void WriteToStdout(const char* message); static void WriteToStderr(const char* message); }; } } ================================================ FILE: unity_decoder/libil2cpp/utils/PathUtils.cpp ================================================ #include "il2cpp-config.h" #include "utils/PathUtils.h" #include namespace il2cpp { namespace utils { namespace PathUtils { std::string BasenameNoExtension(const std::string& path) { if (path.empty()) return "."; std::string base = Basename(path); const size_t pos = base.rfind('.'); // No extension. if (pos == std::string::npos) return base; return base.substr(0, pos); } std::string PathNoExtension(const std::string& path) { const size_t pos = path.rfind('.'); // No extension. if (pos == std::string::npos) return path; return path.substr(0, pos); } } } /* utils */ } /* il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/utils/PathUtils.h ================================================ #pragma once #include #include "StringView.h" namespace il2cpp { namespace utils { namespace PathUtils { std::string BasenameNoExtension(const std::string& path); std::string PathNoExtension(const std::string& path); template std::basic_string Basename(const utils::StringView& path) { if (path.IsEmpty()) return std::basic_string(1, static_cast('.')); const size_t pos = path.RFind(IL2CPP_DIR_SEPARATOR); // No seperators. Path is filename if (pos == utils::StringView::NPos()) return std::basic_string(path.Str(), path.Length()); return std::basic_string(path.Str() + pos + 1, path.Length() - pos - 1); } template std::basic_string Basename(const std::basic_string& path) { return Basename(utils::StringView(path)); } template std::basic_string DirectoryName(const utils::StringView& path) { if (path.IsEmpty()) return std::basic_string(); const size_t pos = path.RFind(IL2CPP_DIR_SEPARATOR); if (pos == utils::StringView::NPos()) return std::basic_string(1, static_cast('.')); if (pos == 0) return std::basic_string(1, static_cast('/')); return std::basic_string(path.Str(), pos); } template std::basic_string Combine(const utils::StringView& path1, const utils::StringView& path2) { std::basic_string result; result.reserve(path1.Length() + path2.Length() + 1); result.append(path1.Str(), path1.Length()); result.append(1, static_cast(IL2CPP_DIR_SEPARATOR)); result.append(path2.Str(), path2.Length()); return result; } template std::basic_string DirectoryName(const std::basic_string& path) { return DirectoryName(utils::StringView(path)); } template std::basic_string Combine(const std::basic_string& path1, const std::basic_string& path2) { return Combine(utils::StringView(path1), utils::StringView(path2)); } template std::basic_string Combine(const std::basic_string& path1, const utils::StringView& path2) { return Combine(utils::StringView(path1), path2); } template std::basic_string Combine(const utils::StringView& path1, const std::basic_string& path2) { return Combine(path1, utils::StringView(path2)); } } } /* utils */ } /* il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/utils/RegisterRuntimeInitializeAndCleanup.cpp ================================================ #include "RegisterRuntimeInitializeAndCleanup.h" #include #include namespace il2cpp { namespace utils { typedef std::set RegistrationCallbackSet; static RegistrationCallbackSet* _registrationCallbacks = NULL; RegisterRuntimeInitializeAndCleanup::RegisterRuntimeInitializeAndCleanup(CallbackFunction Initialize, CallbackFunction Cleanup, int order) { if (!_registrationCallbacks) _registrationCallbacks = new RegistrationCallbackSet(); (*_registrationCallbacks).insert(Initialize); } void RegisterRuntimeInitializeAndCleanup::ExecuteInitializations() { if (_registrationCallbacks == NULL) return; for (RegistrationCallbackSet::iterator iter = (*_registrationCallbacks).begin(); iter != (*_registrationCallbacks).end(); ++iter) { (*iter)(); } } void RegisterRuntimeInitializeAndCleanup::ExecuteCleanup() { IL2CPP_ASSERT(0); } } /* namespace vm */ } /* namespace utils */ ================================================ FILE: unity_decoder/libil2cpp/utils/RegisterRuntimeInitializeAndCleanup.h ================================================ #pragma once #include "il2cpp-config.h" namespace il2cpp { namespace utils { class LIBIL2CPP_CODEGEN_API RegisterRuntimeInitializeAndCleanup { public: typedef void (*CallbackFunction) (); RegisterRuntimeInitializeAndCleanup(CallbackFunction Initialize, CallbackFunction Cleanup, int order = 0); static void ExecuteInitializations(); static void ExecuteCleanup(); }; } /* namespace vm */ } /* namespace utils */ ================================================ FILE: unity_decoder/libil2cpp/utils/Runtime.cpp ================================================ #include "il2cpp-config.h" #include "os/Path.h" #include "os/Environment.h" #include "utils/Runtime.h" #include "utils/PathUtils.h" #include "utils/StringUtils.h" #include "utils/Environment.h" namespace il2cpp { namespace utils { NORETURN void Runtime::Abort() { os::Environment::Abort(); } static std::string s_DataDirFallback; #if !defined(RUNTIME_MONO) static std::string s_DataDir; void Runtime::SetDataDir(const char *path) { s_DataDir = path; } #endif std::string Runtime::GetDataDir() { #if defined(RUNTIME_MONO) // use explicit value if set char* dataDirCS = mono_unity_get_data_dir(); if (dataDirCS) { std::string dataDir(dataDirCS, strlen(dataDirCS)); if (dataDir.size() > 0) return dataDir; } #else // use explicit value if set if (s_DataDir.size() > 0) return s_DataDir; #endif std::string executablePath = os::Path::GetExecutablePath(); if (!executablePath.empty()) return PathUtils::Combine(PathUtils::DirectoryName(executablePath), StringView("Data")); if (s_DataDirFallback.size() == 0 && Environment::GetNumMainArgs() > 0) { std::string main = StringUtils::Utf16ToUtf8(Environment::GetMainArgs()[0]); s_DataDirFallback = PathUtils::DirectoryName(main); } return s_DataDirFallback; } } // utils } // il2cpp ================================================ FILE: unity_decoder/libil2cpp/utils/Runtime.h ================================================ #pragma once #include namespace il2cpp { namespace utils { class LIBIL2CPP_CODEGEN_API Runtime { public: static NORETURN void Abort(); #if !defined(RUNTIME_MONO) static void SetDataDir(const char *path); #endif static std::string GetDataDir(); }; } // utils } // il2cpp ================================================ FILE: unity_decoder/libil2cpp/utils/StringUtils.cpp ================================================ #include "il2cpp-config.h" #include "../char-conversions.h" #include "../object-internals.h" #include "utils/Functional.h" #include "utils/Memory.h" #include "utils/StringUtils.h" #include "utils/utf8-cpp/source/utf8/unchecked.h" #include namespace il2cpp { namespace utils { std::string StringUtils::Printf(const char* format, ...) { va_list argsToCheckSize; int n; std::string ret; va_start(argsToCheckSize, format); #if IL2CPP_COMPILER_MSVC // MS vsnprintf always returns -1 if string doesn't fit, rather than // the needed size. Used their 'special' function instead to get required size n = _vscprintf_p(format, argsToCheckSize); #else // use a temporary buffer as some docs indicate we cannot pass NULL to vsnprintf char buf[1]; n = vsnprintf(buf, 0, format, argsToCheckSize); #endif if (n == -1) return NULL; ret.resize(n + 1, 0); va_end(argsToCheckSize); va_list argsToFormat; va_start(argsToFormat, format); n = vsnprintf(&ret[0], ret.size(), format, argsToFormat); va_end(argsToFormat); IL2CPP_ASSERT(n < (int)ret.size()); if (n == -1) return NULL; return ret; } std::string StringUtils::NPrintf(const char* format, size_t max_n, ...) { va_list argsToCheckSize; size_t n; std::string ret; va_start(argsToCheckSize, max_n); #if IL2CPP_COMPILER_MSVC // MS vsnprintf always returns -1 if string doesn't fit, rather than // the needed size. Used their 'special' function instead to get required size n = _vscprintf_p(format, argsToCheckSize); #else // use a temporary buffer as some docs indicate we cannot pass NULL to vsnprintf char buf[1]; n = vsnprintf(buf, 0, format, argsToCheckSize); #endif if (n == -1) return NULL; n = (max_n < ++n) ? max_n : n; ret.resize(n, 0); va_end(argsToCheckSize); va_list argsToFormat; va_start(argsToFormat, max_n); n = vsnprintf(&ret[0], n, format, argsToFormat); va_end(argsToFormat); IL2CPP_ASSERT(n < ret.size()); if (n == -1) return NULL; return ret; } std::string StringUtils::Utf16ToUtf8(const Il2CppChar* utf16String) { return Utf16ToUtf8(utf16String, -1); } std::string StringUtils::Utf16ToUtf8(const Il2CppChar* utf16String, int maximumSize) { const Il2CppChar* ptr = utf16String; size_t length = 0; while (*ptr) { ptr++; length++; if (maximumSize != -1 && length == maximumSize) break; } std::string utf8String; utf8String.reserve(length); utf8::unchecked::utf16to8(utf16String, ptr, std::back_inserter(utf8String)); return utf8String; } std::string StringUtils::Utf16ToUtf8(const UTF16String& utf16String) { return Utf16ToUtf8(utf16String.c_str(), static_cast(utf16String.length())); } UTF16String StringUtils::Utf8ToUtf16(const char* utf8String) { return Utf8ToUtf16(utf8String, strlen(utf8String)); } UTF16String StringUtils::Utf8ToUtf16(const char* utf8String, size_t length) { UTF16String utf16String; if (utf8::is_valid(utf8String, utf8String + length)) { utf16String.reserve(length); utf8::unchecked::utf8to16(utf8String, utf8String + length, std::back_inserter(utf16String)); } return utf16String; } UTF16String StringUtils::Utf8ToUtf16(const std::string& utf8String) { return Utf8ToUtf16(utf8String.c_str(), utf8String.length()); } char* StringUtils::StringDuplicate(const char *strSource) { char* result = NULL; if (!strSource) return NULL; size_t length = strlen(strSource) + 1; if ((result = (char*)IL2CPP_MALLOC(length))) #if IL2CPP_COMPILER_MSVC strcpy_s(result, length, strSource); #elif IL2CPP_TARGET_LINUX || IL2CPP_TARGET_TIZEN strncpy(result, strSource, length); #else strlcpy(result, strSource, length); #endif return result; } Il2CppChar* StringUtils::StringDuplicate(const Il2CppChar* strSource, size_t length) { size_t byteLengthWithNullTerminator = sizeof(Il2CppChar) * (length + 1); Il2CppChar* utf16name = (Il2CppChar*)IL2CPP_MALLOC(byteLengthWithNullTerminator); memcpy(utf16name, strSource, byteLengthWithNullTerminator); return utf16name; } bool StringUtils::EndsWith(const std::string& string, const std::string& suffix) { const size_t stringLength = string.length(); const size_t suffixLength = suffix.length(); if (suffixLength > stringLength) return false; return string.rfind(suffix.c_str(), stringLength - suffixLength, suffixLength) != std::string::npos; } Il2CppChar* StringUtils::GetChars(Il2CppString* str) { return str->chars; } int32_t StringUtils::GetLength(Il2CppString* str) { return str->length; } } /* utils */ } /* il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/utils/StringUtils.h ================================================ // The MIT License (MIT) // // Copyright(c) Unity Technologies, Microsoft Corporation // // 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. #pragma once #include "il2cpp-string-types.h" #include #include #include #include #include "il2cpp-config.h" namespace il2cpp { namespace utils { class LIBIL2CPP_CODEGEN_API StringUtils { public: static std::string Printf (const char* format, ...); static std::string NPrintf (const char* format, size_t max_n, ...); static std::string Utf16ToUtf8 (const Il2CppChar* utf16String); static std::string Utf16ToUtf8(const Il2CppChar* utf16String, int maximumSize); static std::string Utf16ToUtf8(const UTF16String& utf16String); static UTF16String Utf8ToUtf16(const char* utf8String); static UTF16String Utf8ToUtf16(const char* utf8String, size_t length); static UTF16String Utf8ToUtf16(const std::string& utf8String); static char* StringDuplicate (const char *strSource); static Il2CppChar* StringDuplicate (const Il2CppChar* strSource, size_t length); static bool EndsWith(const std::string& string, const std::string& suffix); static Il2CppChar* GetChars(Il2CppString* str); static int32_t GetLength(Il2CppString* str); #if IL2CPP_TARGET_WINDOWS static inline std::string NativeStringToUtf8(const Il2CppNativeString& nativeStr) { IL2CPP_ASSERT(nativeStr.length() < static_cast(std::numeric_limits::max())); return Utf16ToUtf8(nativeStr.c_str(), static_cast(nativeStr.length())); } static inline Il2CppNativeString Utf8ToNativeString(const std::string str) { IL2CPP_ASSERT(str.length() < static_cast(std::numeric_limits::max())); return Utf8ToUtf16(str.c_str(), str.length()); } #else static inline std::string NativeStringToUtf8(Il2CppNativeString nativeStr) { return nativeStr; } static inline Il2CppNativeString Utf8ToNativeString(const std::string str) { return str; } #endif template static inline size_t LiteralLength(const CharType (&str)[N]) { return N - 1; } template static size_t StrLen(const CharType* str) { size_t length = 0; while (*str) { str++; length++; } return length; } // Taken from github.com/Microsoft/referencesource/blob/master/mscorlib/system/string.cs template static inline size_t Hash (const CharType *str, size_t length) { IL2CPP_ASSERT(length <= static_cast(std::numeric_limits::max())); size_t hash1 = 5381; size_t hash2 = hash1; size_t i = 0; CharType c; const CharType* s = str; while (true) { if (i++ >= length) break; c = s[0]; hash1 = ((hash1 << 5) + hash1) ^ c; if (i++ >= length) break; c = s[1]; hash2 = ((hash2 << 5) + hash2) ^ c; s += 2; } return hash1 + (hash2 * 1566083941); } template static inline size_t Hash (const CharType *str) { size_t hash1 = 5381; size_t hash2 = hash1; CharType c; const CharType* s = str; while ((c = s[0]) != 0) { hash1 = ((hash1 << 5) + hash1) ^ c; c = s[1]; if (c == 0) break; hash2 = ((hash2 << 5) + hash2) ^ c; s += 2; } return hash1 + (hash2 * 1566083941); } template struct StringHasher { typedef typename StringType::value_type CharType; size_t operator()(const StringType& value) const { return Hash(value.c_str(), value.length()); } }; template struct StringHasher { size_t operator()(const CharType* value) const { return Hash(value); } }; }; } /* utils */ } /* il2cpp */ // Assumes str is not NULL #if defined(_MSC_VER) #define DECLARE_IL2CPP_STRING_AS_STRING_VIEW_OF_NATIVE_CHARS(variableName, str) \ il2cpp::utils::StringView variableName(reinterpret_cast(str)->chars, reinterpret_cast(str)->length); #define DECLARE_NATIVE_C_STRING_AS_STRING_VIEW_OF_IL2CPP_CHARS(variableName, str) \ il2cpp::utils::StringView variableName(str, wcslen(str)); #define DECLARE_NATIVE_STRING_AS_STRING_VIEW_OF_IL2CPP_CHARS(variableName, str) \ il2cpp::utils::StringView variableName(str); #else #define DECLARE_IL2CPP_STRING_AS_STRING_VIEW_OF_NATIVE_CHARS(variableName, str) \ Il2CppNativeString variableName##_native_string_storage = il2cpp::utils::StringUtils::Utf16ToUtf8(reinterpret_cast(str)->chars, reinterpret_cast(str)->length); \ il2cpp::utils::StringView variableName(variableName##_native_string_storage.c_str(), variableName##_native_string_storage.length()); #define DECLARE_NATIVE_C_STRING_AS_STRING_VIEW_OF_IL2CPP_CHARS(variableName, str) \ UTF16String variableName##_utf16String = il2cpp::utils::StringUtils::Utf8ToUtf16(str); \ il2cpp::utils::StringView variableName(variableName##_utf16String); #define DECLARE_NATIVE_STRING_AS_STRING_VIEW_OF_IL2CPP_CHARS DECLARE_NATIVE_C_STRING_AS_STRING_VIEW_OF_IL2CPP_CHARS #endif ================================================ FILE: unity_decoder/libil2cpp/utils/StringView.h ================================================ #pragma once #include namespace il2cpp { namespace utils { template class StringView { private: const CharType* m_String; size_t m_Length; // Intended to only be used by Empty() inline StringView() : m_String(NULL), m_Length(0) { } public: template inline StringView(const CharType(&str)[Length]) : m_String(str), m_Length(Length - 1) { } inline StringView(const CharType* str, size_t length) : m_String(str), m_Length(length) { IL2CPP_ASSERT(str != NULL); } inline StringView(const StringView& str, size_t startIndex, size_t length) : m_String(str.Str() + startIndex), m_Length(length) { IL2CPP_ASSERT(startIndex + length <= str.Length()); } template inline StringView(const std::basic_string& str) : m_String(str.c_str()), m_Length(str.length()) { } // This will prevent accidentally assigning temporary values (like function return values) // to a string view. While this protection will only be enabled on C++11 compiles, even those // are enough to catch the bug in our runtime #if IL2CPP_HAS_DELETED_FUNCTIONS template StringView(std::basic_string&&) = delete; #endif inline const CharType* Str() const { return m_String; } inline size_t Length() const { return m_Length; } inline CharType operator[](size_t index) const { return m_String[index]; } inline bool IsNullTerminated() const { return m_String[m_Length] == 0; } inline bool IsEmpty() const { return Length() == 0; } static inline StringView Empty() { return StringView(); } inline size_t RFind(CharType c) const { for (const CharType* ptr = m_String + m_Length - 1; ptr >= m_String; ptr--) { if (*ptr == c) return ptr - m_String; } return NPos(); } inline static size_t NPos() { return static_cast(-1); } }; #define StringViewAsNullTerminatedStringOf(CharType, stringView, variableName) \ const CharType* variableName; \ do \ { \ if (stringView.IsNullTerminated()) \ { \ variableName = stringView.Str(); \ } \ else \ { \ CharType* buffer = static_cast(alloca((stringView.Length() + 1) * sizeof(CharType))); \ memcpy(buffer, stringView.Str(), stringView.Length() * sizeof(CharType)); \ buffer[stringView.Length()] = 0; \ variableName = buffer; \ } \ } \ while (false) } } ================================================ FILE: unity_decoder/libil2cpp/utils/StringViewStream.h ================================================ #pragma once #include #include "StringView.h" // This function is in a separate header file because we include StringView into generated code // and we definitely don't want to include ostream into generated code template inline std::basic_ostream& operator<<(std::basic_ostream& ostream, const il2cpp::utils::StringView& stringView) { StringViewAsNullTerminatedStringOf(CharType, stringView, str); ostream << str; return ostream; } ================================================ FILE: unity_decoder/libil2cpp/utils/TemplateUtils.h ================================================ #pragma once #include namespace il2cpp { namespace utils { namespace TemplateUtils { template struct IsSame { static const bool value = false; }; template struct IsSame { static const bool value = true; }; template struct IsBaseOf { private: template struct Converter { operator BT*() const; operator DT*(); }; typedef int16_t Derived; typedef int8_t NotDerived; template static Derived IsDerived(D*, T); static NotDerived IsDerived(B*, int); public: static const bool value = IsSame::value || sizeof(IsDerived(Converter(), int())) == sizeof(Derived); }; } } } ================================================ FILE: unity_decoder/libil2cpp/utils/ThreadSafeFreeList.h ================================================ #pragma once #include "os/Unity/AtomicQueue.h" namespace il2cpp { namespace utils { struct ThreadSafeFreeListNode { ThreadSafeFreeListNode* nextFreeListNode; ThreadSafeFreeListNode() : nextFreeListNode(NULL) {} }; /// Lockless allocator that keeps instances of T on a free list. /// /// T must be derived from ThreadSafeFreeListNode. /// /// NOTE: T must have sizeof(T) >= sizeof(void*). template struct ThreadSafeFreeList { T* Allocate() { T* instance = reinterpret_cast(m_FreeList.Pop()); if (!instance) instance = new T(); return instance; } void Release(T* instance) { ThreadSafeFreeListNode* node = static_cast(instance); m_FreeList.Push(reinterpret_cast(node)); } ~ThreadSafeFreeList() { T* instance; while ((instance = reinterpret_cast(m_FreeList.Pop())) != NULL) delete instance; } private: ALIGN_TYPE(64) il2cpp::os::AtomicStack m_FreeList; }; } /* utils */ } /* il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/utils/dynamic_array.h ================================================ #pragma once #include "Memory.h" #include // std::max #include // std::uninitialized_fill // dynamic_array - simplified version of std::vector // // features: // . always uses memcpy for copying elements. Your data structures must be simple and can't have internal pointers / rely on copy constructor. // . EASTL like push_back(void) implementation // Existing std STL implementations implement insertion operations by copying from an element. // For example, resize(size() + 1) creates a throw-away temporary object. // There is no way in existing std STL implementations to add an element to a container without implicitly or // explicitly providing one to copy from (aside from some existing POD optimizations). // For expensive-to-construct objects this creates a potentially serious performance problem. // . grows X2 on reallocation // . small code footprint // . clear actually deallocates memory // . resize does NOT initialize members! // // Changelog: // Added pop_back() // Added assign() // Added clear() - frees the data, use resize(0) to clear w/o freeing // zero allocation for empty array // namespace il2cpp { namespace utils { template struct AlignOfType { enum { align = ALIGN_OF(T) }; }; template::align> struct dynamic_array { public: enum { align = ALIGN }; typedef T *iterator; typedef const T *const_iterator; typedef T value_type; typedef size_t size_type; typedef size_t difference_type; typedef T &reference; typedef const T &const_reference; public: dynamic_array() : m_data(NULL), m_size(0), m_capacity(0) { } explicit dynamic_array(size_t size) : m_size(size), m_capacity(size) { m_data = allocate(size); } dynamic_array(size_t size, T const &init_value) : m_size(size), m_capacity(size) { m_data = allocate(size); std::uninitialized_fill(m_data, m_data + size, init_value); } ~dynamic_array() { if (owns_data()) m_data = deallocate(m_data); } dynamic_array(const dynamic_array &other) : m_size(0), m_capacity(0) { m_data = NULL; assign(other.begin(), other.end()); } dynamic_array &operator=(const dynamic_array &other) { // should not allocate memory unless we have to if (&other != this) assign(other.begin(), other.end()); return *this; } void clear() { if (owns_data()) m_data = deallocate(m_data); m_size = 0; m_capacity = 0; } void assign(const_iterator begin, const_iterator end) { Assert(begin <= end); resize_uninitialized(end - begin); memcpy(m_data, begin, m_size * sizeof(T)); } iterator erase(iterator input_begin, iterator input_end) { Assert(input_begin <= input_end); Assert(input_begin >= begin()); Assert(input_end <= end()); size_t leftOverSize = end() - input_end; memmove(input_begin, input_end, leftOverSize * sizeof(T)); m_size -= input_end - input_begin; return input_begin; } iterator erase(iterator it) { return erase(it, it + 1); } iterator erase_swap_back(iterator it) { m_size--; memcpy(it, end(), sizeof(T)); return it; } iterator insert(iterator insert_before, const_iterator input_begin, const_iterator input_end) { Assert(input_begin <= input_end); Assert(insert_before >= begin()); Assert(insert_before <= end()); // resize (make sure that insertBefore does not get invalid in the meantime because of a reallocation) size_t insert_before_index = insert_before - begin(); size_t elements_to_be_moved = size() - insert_before_index; resize_uninitialized((input_end - input_begin) + size(), true); insert_before = begin() + insert_before_index; size_t insertsize = input_end - input_begin; // move to the end of where the inserted data will be memmove(insert_before + insertsize, insert_before, elements_to_be_moved * sizeof(T)); // inject input data in the hole we just created memcpy(insert_before, input_begin, insertsize * sizeof(T)); return insert_before; } iterator insert(iterator insertBefore, const T &t) { return insert(insertBefore, &t, &t + 1); } void swap(dynamic_array &other) throw () { std::swap(m_data, other.m_data); std::swap(m_size, other.m_size); std::swap(m_capacity, other.m_capacity); } // Returns the memory to the object. // This does not call the constructor for the newly added element. // You are expected to initialize all member variables of the returned data. T &push_back() { if (++m_size > capacity()) reserve(std::max(capacity() * 2, 1)); return back(); } // push_back but it also calls the constructor for the newly added element. T &push_back_construct() { if (++m_size > capacity()) reserve(std::max(capacity() * 2, 1)); // construct T *ptr = &back(); new(ptr)T; return *ptr; } // push_back but assigns /t/ to the newly added element. void push_back(const T &t) { push_back() = t; } void pop_back() { Assert(m_size >= 1); m_size--; } void resize_uninitialized(size_t size, bool double_on_resize = false) { m_size = size; if (m_size <= capacity()) return; if (double_on_resize && size < capacity() * 2) size = capacity() * 2; reserve(size); } void resize_initialized(size_t size, const T &t = T(), bool double_on_resize = false) { if (size > capacity()) { size_t requested_size = size; if (double_on_resize && size < capacity() * 2) requested_size = capacity() * 2; reserve(requested_size); } if (size > m_size) std::uninitialized_fill(m_data + m_size, m_data + size, t); m_size = size; } void reserve(size_t inCapacity) { if (capacity() >= inCapacity) return; if (owns_data()) { Assert((inCapacity & k_reference_bit) == 0 && "Dynamic array capacity overflow"); m_capacity = inCapacity; m_data = reallocate(m_data, inCapacity); } else { T *newData = allocate(inCapacity); memcpy(newData, m_data, m_size * sizeof(T)); // Invalidate old non-owned data, since using the data from two places is most likely a really really bad idea. #if IL2CPP_DEBUG memset(m_data, 0xCD, capacity() * sizeof(T)); #endif m_capacity = inCapacity; // and clear reference bit m_data = newData; } } void assign_external(T *begin, T *end) { if (owns_data()) m_data = deallocate(m_data); m_size = m_capacity = reinterpret_cast(end) - reinterpret_cast(begin); Assert(m_size < k_reference_bit); m_capacity |= k_reference_bit; m_data = begin; } void set_owns_data(bool ownsData) { if (ownsData) m_capacity &= ~k_reference_bit; else m_capacity |= k_reference_bit; } void shrink_to_fit() { if (owns_data()) { m_capacity = m_size; m_data = reallocate(m_data, m_size); } } const T &back() const { Assert(m_size != 0); return m_data[m_size - 1]; } const T &front() const { Assert(m_size != 0); return m_data[0]; } T &back() { Assert(m_size != 0); return m_data[m_size - 1]; } T &front() { Assert(m_size != 0); return m_data[0]; } T *data() { return m_data; } T const *data() const { return m_data; } bool empty() const { return m_size == 0; } size_t size() const { return m_size; } size_t capacity() const { return m_capacity & ~k_reference_bit; } T const &operator[](size_t index) const { Assert(index < m_size); return m_data[index]; } T &operator[](size_t index) { Assert(index < m_size); return m_data[index]; } T const *begin() const { return m_data; } T *begin() { return m_data; } T const *end() const { return m_data + m_size; } T *end() { return m_data + m_size; } bool owns_data() { return (m_capacity & k_reference_bit) == 0; } bool equals(const dynamic_array &other) const { if (m_size != other.m_size) return false; for (int i = 0; i < m_size; i++) { if (!(m_data[i] == other.m_data[i])) return false; } return true; } private: static const size_t k_reference_bit = (size_t)1 << (sizeof(size_t) * 8 - 1); T *allocate(size_t size) { return static_cast(IL2CPP_MALLOC_ALIGNED(size * sizeof(T), align)); } T *deallocate(T *data) { Assert(owns_data()); IL2CPP_FREE_ALIGNED(data); return NULL; } T *reallocate(T *data, size_t size) { Assert(owns_data()); return static_cast(IL2CPP_REALLOC_ALIGNED(data, size * sizeof(T), align)); } T *m_data; size_t m_size; size_t m_capacity; }; } //namespace il2cpp } //namespace utils ================================================ FILE: unity_decoder/libil2cpp/utils/utf8-cpp/source/utf8/checked.h ================================================ // Copyright 2006 Nemanja Trifunovic /* Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 #define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 #include "core.h" #include namespace utf8 { // Base for the exceptions that may be thrown from the library class exception : public ::std::exception { }; // Exceptions that may be thrown from the library functions. class invalid_code_point : public exception { uint32_t cp; public: invalid_code_point(uint32_t cp) : cp(cp) {} virtual const char* what() const throw() { return "Invalid code point"; } uint32_t code_point() const {return cp;} }; class invalid_utf8 : public exception { uint8_t u8; public: invalid_utf8 (uint8_t u) : u8(u) {} virtual const char* what() const throw() { return "Invalid UTF-8"; } uint8_t utf8_octet() const {return u8;} }; class invalid_utf16 : public exception { uint16_t u16; public: invalid_utf16 (uint16_t u) : u16(u) {} virtual const char* what() const throw() { return "Invalid UTF-16"; } uint16_t utf16_word() const {return u16;} }; class not_enough_room : public exception { public: virtual const char* what() const throw() { return "Not enough space"; } }; /// The library API - functions intended to be called by the users template octet_iterator append(uint32_t cp, octet_iterator result) { if (!utf8::internal::is_code_point_valid(cp)) throw invalid_code_point(cp); if (cp < 0x80) // one octet *(result++) = static_cast(cp); else if (cp < 0x800) { // two octets *(result++) = static_cast((cp >> 6) | 0xc0); *(result++) = static_cast((cp & 0x3f) | 0x80); } else if (cp < 0x10000) { // three octets *(result++) = static_cast((cp >> 12) | 0xe0); *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); *(result++) = static_cast((cp & 0x3f) | 0x80); } else { // four octets *(result++) = static_cast((cp >> 18) | 0xf0); *(result++) = static_cast(((cp >> 12) & 0x3f) | 0x80); *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); *(result++) = static_cast((cp & 0x3f) | 0x80); } return result; } template output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement) { while (start != end) { octet_iterator sequence_start = start; internal::utf_error err_code = utf8::internal::validate_next(start, end); switch (err_code) { case internal::UTF8_OK : for (octet_iterator it = sequence_start; it != start; ++it) *out++ = *it; break; case internal::NOT_ENOUGH_ROOM: throw not_enough_room(); case internal::INVALID_LEAD: out = utf8::append (replacement, out); ++start; break; case internal::INCOMPLETE_SEQUENCE: case internal::OVERLONG_SEQUENCE: case internal::INVALID_CODE_POINT: out = utf8::append (replacement, out); ++start; // just one replacement mark for the sequence while (start != end && utf8::internal::is_trail(*start)) ++start; break; } } return out; } template inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out) { static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd); return utf8::replace_invalid(start, end, out, replacement_marker); } template uint32_t next(octet_iterator& it, octet_iterator end) { uint32_t cp = 0; internal::utf_error err_code = utf8::internal::validate_next(it, end, cp); switch (err_code) { case internal::UTF8_OK : break; case internal::NOT_ENOUGH_ROOM : throw not_enough_room(); case internal::INVALID_LEAD : case internal::INCOMPLETE_SEQUENCE : case internal::OVERLONG_SEQUENCE : throw invalid_utf8(*it); case internal::INVALID_CODE_POINT : throw invalid_code_point(cp); } return cp; } template uint32_t peek_next(octet_iterator it, octet_iterator end) { return utf8::next(it, end); } template uint32_t prior(octet_iterator& it, octet_iterator start) { // can't do much if it == start if (it == start) throw not_enough_room(); octet_iterator end = it; // Go back until we hit either a lead octet or start while (utf8::internal::is_trail(*(--it))) if (it == start) throw invalid_utf8(*it); // error - no lead byte in the sequence return utf8::peek_next(it, end); } /// Deprecated in versions that include "prior" template uint32_t previous(octet_iterator& it, octet_iterator pass_start) { octet_iterator end = it; while (utf8::internal::is_trail(*(--it))) if (it == pass_start) throw invalid_utf8(*it); // error - no lead byte in the sequence octet_iterator temp = it; return utf8::next(temp, end); } template void advance (octet_iterator& it, distance_type n, octet_iterator end) { for (distance_type i = 0; i < n; ++i) utf8::next(it, end); } template typename std::iterator_traits::difference_type distance (octet_iterator first, octet_iterator last) { typename std::iterator_traits::difference_type dist; for (dist = 0; first < last; ++dist) utf8::next(first, last); return dist; } template octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) { while (start != end) { uint32_t cp = utf8::internal::mask16(*start++); // Take care of surrogate pairs first if (utf8::internal::is_lead_surrogate(cp)) { if (start != end) { uint32_t trail_surrogate = utf8::internal::mask16(*start++); if (utf8::internal::is_trail_surrogate(trail_surrogate)) cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; else throw invalid_utf16(static_cast(trail_surrogate)); } else throw invalid_utf16(static_cast(cp)); } // Lone trail surrogate else if (utf8::internal::is_trail_surrogate(cp)) throw invalid_utf16(static_cast(cp)); result = utf8::append(cp, result); } return result; } template u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) { while (start != end) { uint32_t cp = utf8::next(start, end); if (cp > 0xffff) { //make a surrogate pair *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); } else *result++ = static_cast(cp); } return result; } template octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) { while (start != end) result = utf8::append(*(start++), result); return result; } template u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) { while (start != end) (*result++) = utf8::next(start, end); return result; } // The iterator class template class iterator : public std::iterator { octet_iterator it; octet_iterator range_start; octet_iterator range_end; public: iterator () {} explicit iterator (const octet_iterator& octet_it, const octet_iterator& range_start, const octet_iterator& range_end) : it(octet_it), range_start(range_start), range_end(range_end) { if (it < range_start || it > range_end) throw std::out_of_range("Invalid utf-8 iterator position"); } // the default "big three" are OK octet_iterator base () const { return it; } uint32_t operator * () const { octet_iterator temp = it; return utf8::next(temp, range_end); } bool operator == (const iterator& rhs) const { if (range_start != rhs.range_start || range_end != rhs.range_end) throw std::logic_error("Comparing utf-8 iterators defined with different ranges"); return (it == rhs.it); } bool operator != (const iterator& rhs) const { return !(operator == (rhs)); } iterator& operator ++ () { utf8::next(it, range_end); return *this; } iterator operator ++ (int) { iterator temp = *this; utf8::next(it, range_end); return temp; } iterator& operator -- () { utf8::prior(it, range_start); return *this; } iterator operator -- (int) { iterator temp = *this; utf8::prior(it, range_start); return temp; } }; // class iterator } // namespace utf8 #endif //header guard ================================================ FILE: unity_decoder/libil2cpp/utils/utf8-cpp/source/utf8/core.h ================================================ // Copyright 2006 Nemanja Trifunovic /* Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 #define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 #include namespace utf8 { // The typedefs for 8-bit, 16-bit and 32-bit unsigned integers // You may need to change them to match your system. // These typedefs have the same names as ones from cstdint, or boost/cstdint typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; // Helper code - not intended to be directly called by the library users. May be changed at any time namespace internal { // Unicode constants // Leading (high) surrogates: 0xd800 - 0xdbff // Trailing (low) surrogates: 0xdc00 - 0xdfff const uint16_t LEAD_SURROGATE_MIN = 0xd800u; const uint16_t LEAD_SURROGATE_MAX = 0xdbffu; const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u; const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu; const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10); const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN; // Maximum valid value for a Unicode code point const uint32_t CODE_POINT_MAX = 0x0010ffffu; template inline uint8_t mask8(octet_type oc) { return static_cast(0xff & oc); } template inline uint16_t mask16(u16_type oc) { return static_cast(0xffff & oc); } template inline bool is_trail(octet_type oc) { return ((utf8::internal::mask8(oc) >> 6) == 0x2); } template inline bool is_lead_surrogate(u16 cp) { return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX); } template inline bool is_trail_surrogate(u16 cp) { return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); } template inline bool is_surrogate(u16 cp) { return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); } template inline bool is_code_point_valid(u32 cp) { return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp)); } template inline typename std::iterator_traits::difference_type sequence_length(octet_iterator lead_it) { uint8_t lead = utf8::internal::mask8(*lead_it); if (lead < 0x80) return 1; else if ((lead >> 5) == 0x6) return 2; else if ((lead >> 4) == 0xe) return 3; else if ((lead >> 3) == 0x1e) return 4; else return 0; } template inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length) { if (cp < 0x80) { if (length != 1) return true; } else if (cp < 0x800) { if (length != 2) return true; } else if (cp < 0x10000) { if (length != 3) return true; } return false; } enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT}; /// Helper for get_sequence_x template utf_error increase_safely(octet_iterator& it, octet_iterator end) { if (++it == end) return NOT_ENOUGH_ROOM; if (!utf8::internal::is_trail(*it)) return INCOMPLETE_SEQUENCE; return UTF8_OK; } #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;} /// get_sequence_x functions decode utf-8 sequences of the length x template utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point) { if (it == end) return NOT_ENOUGH_ROOM; code_point = utf8::internal::mask8(*it); return UTF8_OK; } template utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point) { if (it == end) return NOT_ENOUGH_ROOM; code_point = utf8::internal::mask8(*it); UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f); return UTF8_OK; } template utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point) { if (it == end) return NOT_ENOUGH_ROOM; code_point = utf8::internal::mask8(*it); UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) code_point += (*it) & 0x3f; return UTF8_OK; } template utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point) { if (it == end) return NOT_ENOUGH_ROOM; code_point = utf8::internal::mask8(*it); UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) code_point += (utf8::internal::mask8(*it) << 6) & 0xfff; UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) code_point += (*it) & 0x3f; return UTF8_OK; } #undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR template utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point) { // Save the original value of it so we can go back in case of failure // Of course, it does not make much sense with i.e. stream iterators octet_iterator original_it = it; uint32_t cp = 0; // Determine the sequence length based on the lead octet typedef typename std::iterator_traits::difference_type octet_difference_type; const octet_difference_type length = utf8::internal::sequence_length(it); // Get trail octets and calculate the code point utf_error err = UTF8_OK; switch (length) { case 0: return INVALID_LEAD; case 1: err = utf8::internal::get_sequence_1(it, end, cp); break; case 2: err = utf8::internal::get_sequence_2(it, end, cp); break; case 3: err = utf8::internal::get_sequence_3(it, end, cp); break; case 4: err = utf8::internal::get_sequence_4(it, end, cp); break; } if (err == UTF8_OK) { // Decoding succeeded. Now, security checks... if (utf8::internal::is_code_point_valid(cp)) { if (!utf8::internal::is_overlong_sequence(cp, length)){ // Passed! Return here. code_point = cp; ++it; return UTF8_OK; } else err = OVERLONG_SEQUENCE; } else err = INVALID_CODE_POINT; } // Failure branch - restore the original value of the iterator it = original_it; return err; } template inline utf_error validate_next(octet_iterator& it, octet_iterator end) { uint32_t ignored; return utf8::internal::validate_next(it, end, ignored); } } // namespace internal /// The library API - functions intended to be called by the users // Byte order mark const uint8_t bom[] = {0xef, 0xbb, 0xbf}; template octet_iterator find_invalid(octet_iterator start, octet_iterator end) { octet_iterator result = start; while (result != end) { utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end); if (err_code != internal::UTF8_OK) return result; } return result; } template inline bool is_valid(octet_iterator start, octet_iterator end) { return (utf8::find_invalid(start, end) == end); } template inline bool starts_with_bom (octet_iterator it, octet_iterator end) { return ( ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) && ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) && ((it != end) && (utf8::internal::mask8(*it)) == bom[2]) ); } //Deprecated in release 2.3 template inline bool is_bom (octet_iterator it) { return ( (utf8::internal::mask8(*it++)) == bom[0] && (utf8::internal::mask8(*it++)) == bom[1] && (utf8::internal::mask8(*it)) == bom[2] ); } } // namespace utf8 #endif // header guard ================================================ FILE: unity_decoder/libil2cpp/utils/utf8-cpp/source/utf8/unchecked.h ================================================ // Copyright 2006 Nemanja Trifunovic /* Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 #define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 #include "core.h" namespace utf8 { namespace unchecked { template octet_iterator append(uint32_t cp, octet_iterator result) { if (cp < 0x80) // one octet *(result++) = static_cast(cp); else if (cp < 0x800) { // two octets *(result++) = static_cast((cp >> 6) | 0xc0); *(result++) = static_cast((cp & 0x3f) | 0x80); } else if (cp < 0x10000) { // three octets *(result++) = static_cast((cp >> 12) | 0xe0); *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); *(result++) = static_cast((cp & 0x3f) | 0x80); } else { // four octets *(result++) = static_cast((cp >> 18) | 0xf0); *(result++) = static_cast(((cp >> 12) & 0x3f)| 0x80); *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); *(result++) = static_cast((cp & 0x3f) | 0x80); } return result; } template uint32_t next(octet_iterator& it) { uint32_t cp = utf8::internal::mask8(*it); typename std::iterator_traits::difference_type length = utf8::internal::sequence_length(it); switch (length) { case 1: break; case 2: it++; cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f); break; case 3: ++it; cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); ++it; cp += (*it) & 0x3f; break; case 4: ++it; cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); ++it; cp += (utf8::internal::mask8(*it) << 6) & 0xfff; ++it; cp += (*it) & 0x3f; break; } ++it; return cp; } template uint32_t peek_next(octet_iterator it) { return utf8::unchecked::next(it); } template uint32_t prior(octet_iterator& it) { while (utf8::internal::is_trail(*(--it))) ; octet_iterator temp = it; return utf8::unchecked::next(temp); } // Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous) template inline uint32_t previous(octet_iterator& it) { return utf8::unchecked::prior(it); } template void advance (octet_iterator& it, distance_type n) { for (distance_type i = 0; i < n; ++i) utf8::unchecked::next(it); } template typename std::iterator_traits::difference_type distance (octet_iterator first, octet_iterator last) { typename std::iterator_traits::difference_type dist; for (dist = 0; first < last; ++dist) utf8::unchecked::next(first); return dist; } template octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) { while (start != end) { uint32_t cp = utf8::internal::mask16(*start++); // Take care of surrogate pairs first if (utf8::internal::is_lead_surrogate(cp)) { uint32_t trail_surrogate = utf8::internal::mask16(*start++); cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; } result = utf8::unchecked::append(cp, result); } return result; } template u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) { while (start < end) { uint32_t cp = utf8::unchecked::next(start); if (cp > 0xffff) { //make a surrogate pair *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); } else *result++ = static_cast(cp); } return result; } template octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) { while (start != end) result = utf8::unchecked::append(*(start++), result); return result; } template u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) { while (start < end) (*result++) = utf8::unchecked::next(start); return result; } // The iterator class template class iterator : public std::iterator { octet_iterator it; public: iterator () {} explicit iterator (const octet_iterator& octet_it): it(octet_it) {} // the default "big three" are OK octet_iterator base () const { return it; } uint32_t operator * () const { octet_iterator temp = it; return utf8::unchecked::next(temp); } bool operator == (const iterator& rhs) const { return (it == rhs.it); } bool operator != (const iterator& rhs) const { return !(operator == (rhs)); } iterator& operator ++ () { ::std::advance(it, utf8::internal::sequence_length(it)); return *this; } iterator operator ++ (int) { iterator temp = *this; ::std::advance(it, utf8::internal::sequence_length(it)); return temp; } iterator& operator -- () { utf8::unchecked::prior(it); return *this; } iterator operator -- (int) { iterator temp = *this; utf8::unchecked::prior(it); return temp; } }; // class iterator } // namespace utf8::unchecked } // namespace utf8 #endif // header guard ================================================ FILE: unity_decoder/libil2cpp/utils/utf8-cpp/source/utf8.h ================================================ // Copyright 2006 Nemanja Trifunovic /* Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 #define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 #include "utf8/checked.h" #include "utf8/unchecked.h" #endif // header guard ================================================ FILE: unity_decoder/libil2cpp/vm/Array.cpp ================================================ #include "il2cpp-config.h" #include "gc/gc_wrapper.h" #include "vm/Array.h" #include "vm/Class.h" #include "vm/Exception.h" #include "vm/Object.h" #include "vm/Profiler.h" #include "class-internals.h" #include "object-internals.h" #include #include namespace il2cpp { namespace vm { int32_t Array::GetElementSize(const Il2CppClass *klass) { IL2CPP_ASSERT(klass->rank); return klass->element_size; } uint32_t Array::GetLength(Il2CppArray* array) { return array->max_length; } uint32_t Array::GetByteLength(Il2CppArray* array) { Il2CppClass *klass; int length; int i; klass = array->klass; if (array->bounds == NULL) length = array->max_length; else { length = 1; for (i = 0; i < klass->rank; ++i) length *= array->bounds[i].length; } return length * GetElementSize(klass); } Il2CppArray* Array::New(Il2CppClass *elementTypeInfo, il2cpp_array_size_t length) { return NewSpecific(Class::GetArrayClass(elementTypeInfo, 1), length); } static void RaiseOverflowException() { vm::Exception::Raise(vm::Exception::GetOverflowException("Arithmetic operation resulted in an overflow.")); } Il2CppArray* Array::NewSpecific(Il2CppClass *klass, il2cpp_array_size_t n) { Il2CppObject *o; Il2CppArray *ao; uint32_t byte_len, elem_size; Class::Init(klass); IL2CPP_ASSERT(klass->rank); IL2CPP_ASSERT(klass->initialized); IL2CPP_ASSERT(klass->element_class->initialized); NOT_IMPLEMENTED_NO_ASSERT(Array::NewSpecific, "Not checking for overflow"); NOT_IMPLEMENTED_NO_ASSERT(Array::NewSpecific, "Handle allocations with a GC descriptor"); if (n < 0) RaiseOverflowException(); //if (G_UNLIKELY (n > MONO_ARRAY_MAX_INDEX)) { // arith_overflow (); // return NULL; //} elem_size = il2cpp_array_element_size(klass); //if (CHECK_MUL_OVERFLOW_UN (n, elem_size)) { // mono_gc_out_of_memory (MONO_ARRAY_MAX_SIZE); // return NULL; //} byte_len = n * elem_size; //if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray))) { // mono_gc_out_of_memory (MONO_ARRAY_MAX_SIZE); // return NULL; //} byte_len += kIl2CppSizeOfArray; if (!klass->has_references) { o = Object::AllocatePtrFree(byte_len, klass); #if NEED_TO_ZERO_PTRFREE ((Il2CppArray*)o)->bounds = NULL; memset((char*)o + sizeof(Il2CppObject), 0, byte_len - sizeof(Il2CppObject)); #endif } #if IL2CPP_HAS_GC_DESCRIPTORS else if (klass->gc_desc != GC_NO_DESCRIPTOR) { o = Object::AllocateSpec(byte_len, klass); } #endif else { o = Object::Allocate(byte_len, klass); } ao = (Il2CppArray*)o; ao->max_length = n; #if IL2CPP_ENABLE_PROFILER if (Profiler::ProfileAllocations()) Profiler::Allocation(o, klass); #endif return ao; } Il2CppArray* Array::NewFull(Il2CppClass *array_class, il2cpp_array_size_t *lengths, il2cpp_array_size_t *lower_bounds) { il2cpp_array_size_t byte_len, len, bounds_size; Il2CppObject *o; Il2CppArray *array; int i; Class::Init(array_class); IL2CPP_ASSERT(array_class->rank); IL2CPP_ASSERT(array_class->initialized); IL2CPP_ASSERT(array_class->element_class->initialized); NOT_IMPLEMENTED_NO_ASSERT(Array::NewFull, "IGNORING non-zero based arrays!"); NOT_IMPLEMENTED_NO_ASSERT(Array::NewFull, "Handle allocations with a GC descriptor"); for (i = 0; i < array_class->rank; ++i) { if (lengths[i] < 0) RaiseOverflowException(); } byte_len = il2cpp_array_element_size(array_class); len = 1; /* A single dimensional array with a 0 lower bound is the same as an szarray */ if (array_class->rank == 1 && ((array_class->byval_arg->type == IL2CPP_TYPE_SZARRAY) || (lower_bounds && lower_bounds[0] == 0))) { len = lengths[0]; if (len > IL2CPP_ARRAY_MAX_INDEX) //MONO_ARRAY_MAX_INDEX RaiseOverflowException(); bounds_size = 0; } else { bounds_size = sizeof(Il2CppArrayBounds) * array_class->rank; for (i = 0; i < array_class->rank; ++i) { //if (lengths [i] > IL2CPP_ARRAY_MAX_INDEX) //MONO_ARRAY_MAX_INDEX // arith_overflow (); //if (CHECK_MUL_OVERFLOW_UN (len, lengths [i])) // mono_gc_out_of_memory (MONO_ARRAY_MAX_SIZE); len *= lengths[i]; } } //if (CHECK_MUL_OVERFLOW_UN (byte_len, len)) // mono_gc_out_of_memory (MONO_ARRAY_MAX_SIZE); byte_len *= len; //if (CHECK_ADD_OVERFLOW_UN (byte_len, sizeof (MonoArray))) // mono_gc_out_of_memory (MONO_ARRAY_MAX_SIZE); byte_len += kIl2CppSizeOfArray; if (bounds_size) { /* align */ //if (CHECK_ADD_OVERFLOW_UN (byte_len, 3)) // mono_gc_out_of_memory (MONO_ARRAY_MAX_SIZE); byte_len = (byte_len + 3) & ~3; //if (CHECK_ADD_OVERFLOW_UN (byte_len, bounds_size)) // mono_gc_out_of_memory (MONO_ARRAY_MAX_SIZE); byte_len += bounds_size; } /* * Following three lines almost taken from mono_object_new (): * they need to be kept in sync. */ if (!array_class->has_references) { o = Object::AllocatePtrFree(byte_len, array_class); #if NEED_TO_ZERO_PTRFREE memset((char*)o + sizeof(Il2CppObject), 0, byte_len - sizeof(Il2CppObject)); #endif } #if IL2CPP_HAS_GC_DESCRIPTORS else if (array_class->gc_desc != GC_NO_DESCRIPTOR) { o = Object::AllocateSpec(byte_len, array_class); } #endif else { o = Object::Allocate(byte_len, array_class); } array = (Il2CppArray*)o; array->max_length = len; if (bounds_size) { Il2CppArrayBounds *bounds = (Il2CppArrayBounds*)((char*)array + byte_len - bounds_size); array->bounds = bounds; for (i = 0; i < array_class->rank; ++i) { bounds[i].length = lengths[i]; if (lower_bounds) bounds[i].lower_bound = lower_bounds[i]; } } #if IL2CPP_ENABLE_PROFILER if (Profiler::ProfileAllocations()) Profiler::Allocation(o, array_class); #endif return array; } char* Array::GetFirstElementAddress(Il2CppArray *array) { return reinterpret_cast(array) + kIl2CppSizeOfArray; } } /* namespace vm */ } /* namespace il2cpp */ LIBIL2CPP_CODEGEN_API char* il2cpp_array_addr_with_size(Il2CppArray *array, int32_t size, uintptr_t idx) { return ((char*)array) + kIl2CppSizeOfArray + size * idx; } LIBIL2CPP_CODEGEN_API int32_t il2cpp_array_element_size(Il2CppClass *ac) { return il2cpp::vm::Array::GetElementSize(ac); } ================================================ FILE: unity_decoder/libil2cpp/vm/Array.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppArray; struct Il2CppObject; struct Il2CppString; struct Il2CppClass; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API Array { public: static int32_t GetElementSize(const Il2CppClass *klass); static uint32_t GetLength(Il2CppArray* array); static uint32_t GetByteLength(Il2CppArray* array); static Il2CppArray* New(Il2CppClass *elementTypeInfo, il2cpp_array_size_t length); static Il2CppArray* NewSpecific(Il2CppClass *arrayTypeInfo, il2cpp_array_size_t length); static Il2CppArray* NewFull(Il2CppClass *array_class, il2cpp_array_size_t *lengths, il2cpp_array_size_t *lower_bounds); public: // internal static Il2CppArray* NewCached(Il2CppClass *elementTypeInfo, il2cpp_array_size_t length) { return New(elementTypeInfo, length); } static char* GetFirstElementAddress(Il2CppArray *array); }; } /* namespace vm */ } /* namespace il2cpp */ LIBIL2CPP_CODEGEN_API char* il2cpp_array_addr_with_size(Il2CppArray *array, int32_t size, uintptr_t idx); extern "C" { IL2CPP_EXPORT int il2cpp_array_element_size(const Il2CppClass *ac); } #define load_array_elema(arr, idx, size) ((((uint8_t*)(arr)) + kIl2CppSizeOfArray) + ((size) * (idx))) #define il2cpp_array_setwithsize(array, elementSize, index, value) \ do { \ void*__p = (void*) il2cpp_array_addr_with_size ((array), elementSize, (index)); \ memcpy(__p, &(value), elementSize); \ } while (0) #define il2cpp_array_setrefwithsize(array, elementSize, index, value) \ do { \ void*__p = (void*) il2cpp_array_addr_with_size ((array), elementSize, (index)); \ memcpy(__p, value, elementSize); \ } while (0) #define il2cpp_array_addr(array, type, index) ((type*)(void*) il2cpp_array_addr_with_size (array, sizeof (type), index)) #define il2cpp_array_get(array, type, index) ( *(type*)il2cpp_array_addr ((array), type, (index)) ) #define il2cpp_array_set(array, type, index, value) \ do { \ type *__p = (type *) il2cpp_array_addr ((array), type, (index)); \ *__p = (value); \ } while (0) #define il2cpp_array_setref(array, index, value) \ do { \ void* *__p = (void* *) il2cpp_array_addr ((array), void*, (index)); \ /* il2cpp_gc_wbarrier_set_arrayref ((array), __p, (MonoObject*)(value)); */\ *__p = (value); \ } while (0) ================================================ FILE: unity_decoder/libil2cpp/vm/Assembly.cpp ================================================ #include "il2cpp-config.h" #include "vm/Assembly.h" #include "vm/AssemblyName.h" #include "vm/MetadataCache.h" #include "vm/Runtime.h" #include "tabledefs.h" #include "class-internals.h" #if IL2CPP_DEBUGGER_ENABLED #include "il2cpp-debugger.h" #endif #include #include namespace il2cpp { namespace vm { static AssemblyVector s_Assemblies; AssemblyVector* Assembly::GetAllAssemblies() { return &s_Assemblies; } const Il2CppAssembly* Assembly::GetLoadedAssembly(const char* name) { for (AssemblyVector::const_iterator assembly = s_Assemblies.begin(); assembly != s_Assemblies.end(); ++assembly) { if (strcmp(MetadataCache::GetStringFromIndex((*assembly)->aname.nameIndex), name) == 0) return *assembly; } return NULL; } Il2CppImage* Assembly::GetImage(const Il2CppAssembly* assembly) { return MetadataCache::GetImageFromIndex(assembly->imageIndex); } void Assembly::GetReferencedAssemblies(const Il2CppAssembly* assembly, AssemblyNameVector* target) { for (int32_t sourceIndex = 0; sourceIndex < assembly->referencedAssemblyCount; sourceIndex++) { int32_t indexIntoMainAssemblyTable = MetadataCache::GetReferenceAssemblyIndexIntoAssemblyTable(assembly->referencedAssemblyStart + sourceIndex); const Il2CppAssembly* refAssembly = MetadataCache::GetAssemblyFromIndex(indexIntoMainAssemblyTable); target->push_back(&refAssembly->aname); } } static bool ends_with(const char *str, const char *suffix) { if (!str || !suffix) return false; const size_t lenstr = strlen(str); const size_t lensuffix = strlen(suffix); if (lensuffix > lenstr) return false; return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0; } const Il2CppAssembly* Assembly::Load(const char* name) { const size_t len = strlen(name); for (AssemblyVector::const_iterator assembly = s_Assemblies.begin(); assembly != s_Assemblies.end(); ++assembly) { if (strcmp(name, MetadataCache::GetStringFromIndex((*assembly)->aname.nameIndex)) == 0) return *assembly; } if (!ends_with(name, ".dll") && !ends_with(name, ".exe")) { char *tmp = new char[len + 5]; memset(tmp, 0, len + 5); memcpy(tmp, name, len); memcpy(tmp + len, ".dll", 4); const Il2CppAssembly* result = Load(tmp); if (!result) { memcpy(tmp + len, ".exe", 4); result = Load(tmp); } delete[] tmp; return result; } else { for (AssemblyVector::const_iterator assembly = s_Assemblies.begin(); assembly != s_Assemblies.end(); ++assembly) { if (!strcmp(name, MetadataCache::GetImageFromIndex((*assembly)->imageIndex)->name)) return *assembly; } return NULL; } } void Assembly::Register(const Il2CppAssembly* assembly) { s_Assemblies.push_back(assembly); } void Assembly::Initialize() { for (AssemblyVector::const_iterator assembly = s_Assemblies.begin(); assembly != s_Assemblies.end(); ++assembly) { #if IL2CPP_DEBUGGER_ENABLED il2cpp_debugger_notify_assembly_load(*assembly); #endif } } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Assembly.h ================================================ #pragma once #include #include #include #include "il2cpp-config.h" struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppImage; struct Il2CppArray; namespace il2cpp { namespace vm { typedef std::vector AssemblyVector; typedef std::vector AssemblyNameVector; class LIBIL2CPP_CODEGEN_API Assembly { // exported public: static Il2CppImage* GetImage(const Il2CppAssembly* assembly); static void GetReferencedAssemblies(const Il2CppAssembly* assembly, AssemblyNameVector* target); public: static AssemblyVector* GetAllAssemblies(); static const Il2CppAssembly* GetLoadedAssembly(const char* name); static const Il2CppAssembly* Load(const char* name); static void Register(const Il2CppAssembly* assembly); static void Initialize(); private: }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/AssemblyName.cpp ================================================ #include "il2cpp-config.h" #include "vm/AssemblyName.h" #include "vm/MetadataCache.h" #include "vm/Runtime.h" #include "tabledefs.h" #include "class-internals.h" #include "vm/Array.h" #include "object-internals.h" #include "vm/Reflection.h" #include "vm/Type.h" #include "vm/Object.h" #include "utils/StringUtils.h" #include "vm/String.h" #include "vm/Class.h" #include #include namespace il2cpp { namespace vm { static Il2CppObject* CreateVersion(uint32_t major, uint32_t minor, uint32_t build, uint32_t revision) { static const MethodInfo* versionContructor = NULL; if (!versionContructor) versionContructor = Class::GetMethodFromName(il2cpp_defaults.version, ".ctor", 4); Il2CppObject* version = Object::New(il2cpp_defaults.version); void* args[4] = { &major, &minor, &build, &revision }; Runtime::Invoke(versionContructor, version, args, NULL); return version; } static Il2CppObject* CreateCulture(const char* cultureName) { static const MethodInfo* createCultureMethod = NULL; if (!createCultureMethod) createCultureMethod = Class::GetMethodFromName(il2cpp_defaults.culture_info, "CreateCulture", 2); bool reference = false; void* args[2]; if (cultureName != NULL) args[0] = String::New(cultureName); else args[0] = String::New("neutral"); args[1] = &reference; return Runtime::Invoke(createCultureMethod, NULL, args, NULL); } bool AssemblyName::ParseName(Il2CppReflectionAssemblyName* aname, std::string assemblyName) { il2cpp::vm::TypeNameParseInfo info; il2cpp::vm::TypeNameParser parser(assemblyName, info, false); if (!parser.ParseAssembly()) return false; const il2cpp::vm::TypeNameParseInfo::AssemblyName& parsedName = info.assembly_name(); IL2CPP_OBJECT_SETREF(aname, name, String::New(parsedName.name.c_str())); aname->major = parsedName.major; aname->minor = parsedName.minor; aname->build = parsedName.build; aname->revision = parsedName.revision; aname->flags = parsedName.flags; aname->hashalg = parsedName.hash_alg; IL2CPP_OBJECT_SETREF(aname, version, CreateVersion(parsedName.major, parsedName.minor, parsedName.build, parsedName.revision)); IL2CPP_OBJECT_SETREF(aname, cultureInfo, CreateCulture(parsedName.culture.c_str())); if (parsedName.public_key_token[0]) { IL2CPP_OBJECT_SETREF(aname, keyToken, Array::New(il2cpp_defaults.byte_class, kPublicKeyByteLength)); char* p = il2cpp_array_addr(aname->keyToken, char, 0); char buf[2] = { 0 }; for (int i = 0, j = 0; i < kPublicKeyByteLength; i++) { buf[0] = parsedName.public_key_token[j++]; *p = (char)(strtol(buf, NULL, 16) << 4); buf[0] = parsedName.public_key_token[j++]; *p |= (char)strtol(buf, NULL, 16); p++; } } else IL2CPP_OBJECT_SETREF(aname, keyToken, Array::New(il2cpp_defaults.byte_class, 0)); return true; } static char HexValueToLowercaseAscii(uint8_t hexValue) { if (hexValue < 10) return char(hexValue + 48); return char(hexValue + 87); } static std::string PublicKeyTokenToString(const uint8_t* publicKeyToken) { std::string result(kPublicKeyByteLength * 2, '0'); for (int i = 0; i < kPublicKeyByteLength; ++i) { uint8_t hi = (publicKeyToken[i] & 0xF0) >> 4; uint8_t lo = publicKeyToken[i] & 0x0F; result[i * 2] = HexValueToLowercaseAscii(hi); result[i * 2 + 1] = HexValueToLowercaseAscii(lo); } return result; } std::string AssemblyName::AssemblyNameToString(const Il2CppAssemblyName& aname) { std::string name; char buffer[1024]; name += MetadataCache::GetStringFromIndex(aname.nameIndex); name += ", Version="; sprintf(buffer, "%d", aname.major); name += buffer; name += "."; sprintf(buffer, "%d", aname.minor); name += buffer; name += "."; sprintf(buffer, "%d", aname.build); name += buffer; name += "."; sprintf(buffer, "%d", aname.revision); name += buffer; name += ", Culture="; name += (aname.cultureIndex != kStringLiteralIndexInvalid ? MetadataCache::GetStringFromIndex(aname.cultureIndex) : "neutral"); name += ", PublicKeyToken="; name += (aname.publicKeyToken[0] ? PublicKeyTokenToString(aname.publicKeyToken) : "null"); name += ((aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : ""); return name; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/AssemblyName.h ================================================ #pragma once #include #include #include #include "il2cpp-config.h" struct Il2CppAssemblyName; struct Il2CppReflectionAssemblyName; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API AssemblyName { // exported public: static std::string AssemblyNameToString(const Il2CppAssemblyName& aname); static bool ParseName(Il2CppReflectionAssemblyName* aname, std::string assemblyName); public: private: }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Atomic.cpp ================================================ #include "il2cpp-config.h" #include "vm/Atomic.h" #include "os/Atomic.h" namespace il2cpp { namespace vm { int32_t Atomic::Add(volatile int32_t* location1, int32_t value) { return os::Atomic::Add(location1, value); } int64_t Atomic::Add64(volatile int64_t* location1, int64_t value) { return os::Atomic::Add64(location1, value); } int32_t Atomic::Increment(volatile int32_t* value) { return os::Atomic::Increment(value); } int64_t Atomic::Increment64(volatile int64_t* value) { return os::Atomic::Increment64(value); } int32_t Atomic::Decrement(volatile int32_t* value) { return os::Atomic::Decrement(value); } int64_t Atomic::Decrement64(volatile int64_t* value) { return os::Atomic::Decrement64(value); } int32_t Atomic::CompareExchange(volatile int32_t* dest, int32_t exchange, int32_t comparand) { return os::Atomic::CompareExchange(dest, exchange, comparand); } int64_t Atomic::CompareExchange64(volatile int64_t* dest, int64_t exchange, int64_t comparand) { return os::Atomic::CompareExchange64(dest, exchange, comparand); } void* Atomic::CompareExchangePointer(void* volatile* dest, void* exchange, void* comparand) { return os::Atomic::CompareExchangePointer(dest, exchange, comparand); } int32_t Atomic::Exchange(volatile int32_t* dest, int32_t exchange) { return os::Atomic::Exchange(dest, exchange); } int64_t Atomic::Exchange64(volatile int64_t* dest, int64_t exchange) { return os::Atomic::Exchange64(dest, exchange); } void* Atomic::ExchangePointer(void* volatile* dest, void* exchange) { return os::Atomic::ExchangePointer(dest, exchange); } int64_t Atomic::Read64(volatile int64_t* addr) { return os::Atomic::Read64(addr); } void Atomic::MemoryBarrier() { os::Atomic::MemoryBarrier(); } } /* namespace vm */ } /* namespace il2pp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Atomic.h ================================================ #pragma once #include #include "il2cpp-config.h" namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API Atomic { public: static int32_t Add(volatile int32_t* location1, int32_t value); static int64_t Add64(volatile int64_t* location1, int64_t value); static int32_t Increment(volatile int32_t* value); static int64_t Increment64(volatile int64_t* value); static int32_t Decrement(volatile int32_t* value); static int64_t Decrement64(volatile int64_t* value); static int32_t CompareExchange(volatile int32_t* dest, int32_t exchange, int32_t comparand); static int64_t CompareExchange64(volatile int64_t* dest, int64_t exchange, int64_t comparand); static void* CompareExchangePointer(void* volatile* dest, void* exchange, void* comparand); static int32_t Exchange(volatile int32_t* dest, int32_t exchange); static int64_t Exchange64(volatile int64_t* dest, int64_t exchange); static void* ExchangePointer(void* volatile* dest, void* exchange); static int64_t Read64(volatile int64_t* addr); static void MemoryBarrier(); static inline uint32_t Add(volatile uint32_t* location1, uint32_t value) { return static_cast(Add((volatile int32_t*)location1, (int32_t)value)); } template static inline T* CompareExchangePointer(T* volatile* dest, T* newValue, T* oldValue) { return static_cast(CompareExchangePointer((void*volatile*)dest, newValue, oldValue)); } template static inline T* ExchangePointer(T* volatile* dest, T* newValue) { return static_cast(ExchangePointer((void*volatile*)dest, newValue)); } static inline uint64_t Read64(volatile uint64_t* addr) { return static_cast(Read64((volatile int64_t*)addr)); } template static inline T* ReadPointer(T* volatile* pointer) { #if IL2CPP_SIZEOF_VOID_P == 4 return reinterpret_cast(Add(reinterpret_cast(pointer), 0)); #else return reinterpret_cast(Add64(reinterpret_cast(pointer), 0)); #endif } static inline uint32_t Increment(volatile uint32_t* value) { return static_cast(Increment(reinterpret_cast(value))); } static inline uint64_t Increment64(volatile uint64_t* value) { return static_cast(Increment64(reinterpret_cast(value))); } static inline uint32_t Decrement(volatile uint32_t* value) { return static_cast(Decrement(reinterpret_cast(value))); } static inline uint64_t Decrement64(volatile uint64_t* value) { return static_cast(Decrement64(reinterpret_cast(value))); } static inline uint32_t CompareExchange(volatile uint32_t* value, uint32_t newValue, uint32_t oldValue) { return static_cast(CompareExchange(reinterpret_cast(value), newValue, oldValue)); } static inline uint64_t CompareExchange64(volatile uint64_t* value, uint64_t newValue, uint64_t oldValue) { return static_cast(CompareExchange64(reinterpret_cast(value), newValue, oldValue)); } static inline uint32_t Exchange(volatile uint32_t* value, uint32_t newValue) { return static_cast(Exchange(reinterpret_cast(value), newValue)); } static inline uint64_t Exchange64(volatile uint64_t* value, uint64_t newValue) { return static_cast(Exchange64(reinterpret_cast(value), newValue)); } }; } /* namesapce vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/CCW.cpp ================================================ #include "il2cpp-config.h" #include "object-internals.h" #include "class-internals.h" #include "vm/Object.h" #include "vm/CCW.h" #include "vm/Class.h" #include "vm/CachedCCWBase.h" #include "vm/Exception.h" #include "vm/MetadataCache.h" #include "vm/RCW.h" #include "vm/Runtime.h" #include "vm/String.h" namespace il2cpp { namespace vm { struct ManagedObject : CachedCCWBase { inline ManagedObject(Il2CppObject* obj) : CachedCCWBase(obj) { } virtual il2cpp_hresult_t STDCALL QueryInterface(const Il2CppGuid& iid, void** object) IL2CPP_OVERRIDE { if (::memcmp(&iid, &Il2CppIUnknown::IID, sizeof(Il2CppGuid)) == 0 || ::memcmp(&iid, &Il2CppIInspectable::IID, sizeof(Il2CppGuid)) == 0 || ::memcmp(&iid, &Il2CppIAgileObject::IID, sizeof(Il2CppGuid)) == 0) { *object = GetIdentity(); AddRefImpl(); return IL2CPP_S_OK; } if (::memcmp(&iid, &Il2CppIManagedObjectHolder::IID, sizeof(Il2CppGuid)) == 0) { *object = static_cast(this); AddRefImpl(); return IL2CPP_S_OK; } if (::memcmp(&iid, &Il2CppIMarshal::IID, sizeof(Il2CppGuid)) == 0) { *object = static_cast(this); AddRefImpl(); return IL2CPP_S_OK; } *object = NULL; return IL2CPP_E_NOINTERFACE; } virtual il2cpp_hresult_t STDCALL GetIids(uint32_t* iidCount, Il2CppGuid** iids) IL2CPP_OVERRIDE { *iidCount = 0; *iids = NULL; return IL2CPP_S_OK; } }; Il2CppIUnknown* CCW::CreateCCW(Il2CppObject* obj) { // check for ccw create function, which is implemented by objects that implement COM or Windows Runtime interfaces const Il2CppInteropData* interopData = obj->klass->interopData; if (interopData != NULL) { const CreateCCWFunc createCcw = interopData->createCCWFunction; if (createCcw != NULL) return createCcw(obj); } // otherwise create generic ccw object that "only" implements IUnknown, IMarshal, IInspectable, IAgileObject and IManagedObjectHolder interfaces void* memory = utils::Memory::Malloc(sizeof(ManagedObject)); if (memory == NULL) Exception::RaiseOutOfMemoryException(); return static_cast(new(memory)ManagedObject(obj)); } Il2CppException* CCW::GetIPropertyValueInvalidCast(Il2CppObject* value, const char* from, const char* to) { Il2CppClass* klass = il2cpp::vm::Object::GetClass(value); const MethodInfo* toString = il2cpp::vm::Class::GetMethodFromName(klass, "ToString", 0); Il2CppString* valueString = (Il2CppString*)il2cpp::vm::Runtime::Invoke(toString, value, NULL, NULL); std::string utf8Value = il2cpp::utils::StringUtils::Utf16ToUtf8(il2cpp::utils::StringUtils::GetChars(valueString)); std::string message = il2cpp::utils::StringUtils::Printf( "Object in an IPropertyValue is of type '%s' with value '%s', which cannot be converted to a '%s'.", from, utf8Value.c_str(), to); return il2cpp::vm::Exception::GetInvalidCastException(message.c_str()); } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/CCW.h ================================================ #pragma once #include "gc/GarbageCollector.h" struct Il2CppIUnknown; struct Il2CppObject; struct Il2CppException; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API CCW { public: // CreateCCW returns upcasted Il2CppIManagedObjectHolder if the CCW is cachable! static Il2CppIUnknown* CreateCCW(Il2CppObject* obj); static inline Il2CppIUnknown* GetOrCreate(Il2CppObject* obj, const Il2CppGuid& iid) { return gc::GarbageCollector::GetOrCreateCCW(obj, iid); } static Il2CppException* GetIPropertyValueInvalidCast(Il2CppObject* value, const char* from, const char* to); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/COM.cpp ================================================ #include "il2cpp-config.h" #include "object-internals.h" #include "il2cpp-vm-support.h" #include "vm/Array.h" #include "vm/COM.h" #include "vm/Exception.h" #include "vm/PlatformInvoke.h" #include "vm/Reflection.h" #include "os/COM.h" namespace il2cpp { namespace vm { void COM::MarshalVariant(Il2CppObject* obj, Il2CppVariant* variant) { IL2CPP_ASSERT(variant); os::COM::VariantInit(variant); if (!obj) return; if (obj->klass == il2cpp_defaults.sbyte_class) { variant->n1.n2.type = IL2CPP_VT_I1; variant->n1.n2.n3.cVal = *static_cast(Object::Unbox(obj)); } else if (obj->klass == il2cpp_defaults.byte_class) { variant->n1.n2.type = IL2CPP_VT_UI1; variant->n1.n2.n3.bVal = *static_cast(Object::Unbox(obj)); } else if (obj->klass == il2cpp_defaults.int16_class) { variant->n1.n2.type = IL2CPP_VT_I2; variant->n1.n2.n3.iVal = *static_cast(Object::Unbox(obj)); } else if (obj->klass == il2cpp_defaults.uint16_class) { variant->n1.n2.type = IL2CPP_VT_UI2; variant->n1.n2.n3.uiVal = *static_cast(Object::Unbox(obj)); } else if (obj->klass == il2cpp_defaults.int32_class) { variant->n1.n2.type = IL2CPP_VT_I4; variant->n1.n2.n3.lVal = *static_cast(Object::Unbox(obj)); } else if (obj->klass == il2cpp_defaults.uint32_class) { variant->n1.n2.type = IL2CPP_VT_UI4; variant->n1.n2.n3.ulVal = *static_cast(Object::Unbox(obj)); } else if (obj->klass == il2cpp_defaults.int64_class) { variant->n1.n2.type = IL2CPP_VT_I8; variant->n1.n2.n3.llVal = *static_cast(Object::Unbox(obj)); } else if (obj->klass == il2cpp_defaults.uint64_class) { variant->n1.n2.type = IL2CPP_VT_UI8; variant->n1.n2.n3.ullVal = *static_cast(Object::Unbox(obj)); } else if (obj->klass == il2cpp_defaults.single_class) { variant->n1.n2.type = IL2CPP_VT_R4; variant->n1.n2.n3.fltVal = *static_cast(Object::Unbox(obj)); } else if (obj->klass == il2cpp_defaults.double_class) { variant->n1.n2.type = IL2CPP_VT_R8; variant->n1.n2.n3.dblVal = *static_cast(Object::Unbox(obj)); } else if (obj->klass == il2cpp_defaults.boolean_class) { variant->n1.n2.type = IL2CPP_VT_BOOL; variant->n1.n2.n3.boolVal = *static_cast(Object::Unbox(obj)) ? IL2CPP_VARIANT_TRUE : IL2CPP_VARIANT_FALSE; } else if (obj->klass == il2cpp_defaults.string_class) { variant->n1.n2.type = IL2CPP_VT_BSTR; variant->n1.n2.n3.bstrVal = PlatformInvoke::MarshalCSharpStringToCppBString(reinterpret_cast(obj)); } else if (obj->klass == il2cpp_defaults.dbnull_class) { variant->n1.n2.type = IL2CPP_VT_NULL; } else if (obj->klass == il2cpp_defaults.error_wrapper_class) { variant->n1.n2.type = IL2CPP_VT_ERROR; variant->n1.n2.n3.scode = reinterpret_cast(obj)->errorCode; } else if (obj->klass == il2cpp_defaults.missing_class) { variant->n1.n2.type = IL2CPP_VT_ERROR; variant->n1.n2.n3.scode = IL2CPP_DISP_E_PARAMNOTFOUND; } else { Exception::Raise(IL2CPP_E_INVALIDARG, true); } } Il2CppObject* COM::MarshalVariantResult(const Il2CppVariant* variant) { IL2CPP_ASSERT(variant); switch (variant->n1.n2.type) { case IL2CPP_VT_EMPTY: return NULL; case IL2CPP_VT_NULL: return Reflection::GetDBNullObject(); case IL2CPP_VT_ERROR: { int32_t val = variant->n1.n2.n3.scode; return Object::Box(il2cpp_defaults.int32_class, &val); } case IL2CPP_VT_I1: { char val = variant->n1.n2.n3.cVal; return Object::Box(il2cpp_defaults.sbyte_class, &val); } case IL2CPP_VT_UI1: { uint8_t val = variant->n1.n2.n3.bVal; return Object::Box(il2cpp_defaults.byte_class, &val); } case IL2CPP_VT_I2: { int16_t val = variant->n1.n2.n3.iVal; return Object::Box(il2cpp_defaults.int16_class, &val); } case IL2CPP_VT_UI2: { uint16_t val = variant->n1.n2.n3.uiVal; return Object::Box(il2cpp_defaults.uint16_class, &val); } case IL2CPP_VT_I4: { int32_t val = variant->n1.n2.n3.lVal; return Object::Box(il2cpp_defaults.int32_class, &val); } case IL2CPP_VT_UI4: { uint32_t val = variant->n1.n2.n3.ulVal; return Object::Box(il2cpp_defaults.uint32_class, &val); } case IL2CPP_VT_I8: { int64_t val = variant->n1.n2.n3.llVal; return Object::Box(il2cpp_defaults.int64_class, &val); } case IL2CPP_VT_UI8: { uint64_t val = variant->n1.n2.n3.ullVal; return Object::Box(il2cpp_defaults.uint64_class, &val); } case IL2CPP_VT_R4: { float val = variant->n1.n2.n3.fltVal; return Object::Box(il2cpp_defaults.single_class, &val); } case IL2CPP_VT_R8: { double val = variant->n1.n2.n3.dblVal; return Object::Box(il2cpp_defaults.double_class, &val); } case IL2CPP_VT_BOOL: { IL2CPP_ASSERT(variant->n1.n2.n3.boolVal == IL2CPP_VARIANT_FALSE || variant->n1.n2.n3.boolVal == IL2CPP_VARIANT_TRUE); bool value = variant->n1.n2.n3.boolVal != IL2CPP_VARIANT_FALSE; return Object::Box(il2cpp_defaults.boolean_class, &value); } case IL2CPP_VT_BSTR: return reinterpret_cast(PlatformInvoke::MarshalCppBStringToCSharpStringResult(variant->n1.n2.n3.bstrVal)); default: Exception::Raise(IL2CPP_E_INVALIDARG, true); return NULL; } } void COM::DestroyVariant(Il2CppVariant* variant) { const il2cpp_hresult_t hr = os::COM::VariantClear(variant); IL2CPP_VM_RAISE_IF_FAILED(hr, true); } Il2CppSafeArray* COM::MarshalSafeArray(uint16_t variantType, Il2CppArray* managedArray) { if (!managedArray) return NULL; Il2CppSafeArrayBound bounds[1]; bounds[0].element_count = Array::GetLength(managedArray); bounds[0].lower_bound = 0; Il2CppSafeArray* safeArray = os::COM::SafeArrayCreate(variantType, 1, bounds); if (!safeArray) Exception::Raise(IL2CPP_E_OUTOFMEMORY, true); void* data; il2cpp_hresult_t hr = os::COM::SafeArrayAccessData(safeArray, &data); if (IL2CPP_HR_FAILED(hr)) { os::COM::SafeArrayDestroy(safeArray); Exception::Raise(hr, true); } ::memcpy(data, Array::GetFirstElementAddress(managedArray), Array::GetByteLength(managedArray)); hr = os::COM::SafeArrayUnaccessData(safeArray); if (IL2CPP_HR_FAILED(hr)) { os::COM::SafeArrayDestroy(safeArray); Exception::Raise(hr, true); } return safeArray; } Il2CppArray* COM::MarshalSafeArrayResult(uint16_t variantType, Il2CppClass* type, Il2CppSafeArray* safeArray) { if (!safeArray) return NULL; uint16_t actualVariantType; il2cpp_hresult_t hr = os::COM::SafeArrayGetVartype(safeArray, &actualVariantType); IL2CPP_VM_RAISE_IF_FAILED(hr, true); if (actualVariantType != variantType) Exception::Raise(IL2CPP_E_INVALIDARG, true); const uint32_t actualDimentionCount = os::COM::SafeArrayGetDim(safeArray); if (actualDimentionCount != 1) Exception::Raise(IL2CPP_E_INVALIDARG, true); int32_t lowerBound; hr = os::COM::SafeArrayGetLBound(safeArray, 1, &lowerBound); IL2CPP_VM_RAISE_IF_FAILED(hr, true); int32_t upperBound; hr = os::COM::SafeArrayGetUBound(safeArray, 1, &upperBound); IL2CPP_VM_RAISE_IF_FAILED(hr, true); const il2cpp_array_size_t size = static_cast(upperBound - lowerBound + 1); Il2CppArray* managedArray = Array::New(type, size); void* data; hr = os::COM::SafeArrayAccessData(safeArray, &data); IL2CPP_VM_RAISE_IF_FAILED(hr, true); ::memcpy(Array::GetFirstElementAddress(managedArray), data, Array::GetByteLength(managedArray)); hr = os::COM::SafeArrayUnaccessData(safeArray); IL2CPP_VM_RAISE_IF_FAILED(hr, true); return managedArray; } Il2CppSafeArray* COM::MarshalSafeArrayBString(Il2CppArray* managedArray) { if (!managedArray) return NULL; const uint32_t size = Array::GetLength(managedArray); Il2CppSafeArrayBound bounds[1]; bounds[0].element_count = size; bounds[0].lower_bound = 0; Il2CppSafeArray* safeArray = os::COM::SafeArrayCreate(IL2CPP_VT_BSTR, 1, bounds); if (!safeArray) Exception::Raise(IL2CPP_E_OUTOFMEMORY, true); Il2CppChar** data; il2cpp_hresult_t hr = os::COM::SafeArrayAccessData(safeArray, reinterpret_cast(&data)); if (IL2CPP_HR_FAILED(hr)) { os::COM::SafeArrayDestroy(safeArray); Exception::Raise(hr, true); } for (uint32_t i = 0; i < size; ++i) { Il2CppString* managedString = il2cpp_array_get(managedArray, Il2CppString*, i); hr = PlatformInvoke::MarshalCSharpStringToCppBStringNoThrow(managedString, data + i); if (IL2CPP_HR_FAILED(hr)) { os::COM::SafeArrayUnaccessData(safeArray); os::COM::SafeArrayDestroy(safeArray); Exception::Raise(hr, true); } } hr = os::COM::SafeArrayUnaccessData(safeArray); if (IL2CPP_HR_FAILED(hr)) { os::COM::SafeArrayDestroy(safeArray); Exception::Raise(hr, true); } return safeArray; } Il2CppArray* COM::MarshalSafeArrayBStringResult(Il2CppClass* type, Il2CppSafeArray* safeArray) { if (!safeArray) return NULL; uint16_t actualVariantType; il2cpp_hresult_t hr = os::COM::SafeArrayGetVartype(safeArray, &actualVariantType); IL2CPP_VM_RAISE_IF_FAILED(hr, true); if (actualVariantType != IL2CPP_VT_BSTR) Exception::Raise(IL2CPP_E_INVALIDARG, true); const uint32_t actualDimentionCount = os::COM::SafeArrayGetDim(safeArray); if (actualDimentionCount != 1) Exception::Raise(IL2CPP_E_INVALIDARG, true); int32_t lowerBound; hr = os::COM::SafeArrayGetLBound(safeArray, 1, &lowerBound); IL2CPP_VM_RAISE_IF_FAILED(hr, true); int32_t upperBound; hr = os::COM::SafeArrayGetUBound(safeArray, 1, &upperBound); IL2CPP_VM_RAISE_IF_FAILED(hr, true); const il2cpp_array_size_t size = static_cast(upperBound - lowerBound + 1); Il2CppArray* managedArray = Array::New(il2cpp_defaults.string_class, size); Il2CppChar** data; hr = os::COM::SafeArrayAccessData(safeArray, reinterpret_cast(&data)); IL2CPP_VM_RAISE_IF_FAILED(hr, true); for (il2cpp_array_size_t i = 0; i < size; ++i) il2cpp_array_setref(managedArray, i, PlatformInvoke::MarshalCppBStringToCSharpStringResult(data[i])); hr = os::COM::SafeArrayUnaccessData(safeArray); IL2CPP_VM_RAISE_IF_FAILED(hr, true); return managedArray; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/COM.h ================================================ #pragma once #include "class-internals.h" #include "il2cpp-vm-support.h" #include "os/COM.h" #include "vm/Exception.h" struct Il2CppGuid; struct Il2CppSafeArrayBound; struct Il2CppSafeArray; struct Il2CppIUnknown; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API COM { public: static inline void CreateInstance(const Il2CppGuid& clsid, Il2CppIUnknown** object) { const il2cpp_hresult_t hr = os::COM::CreateInstance(clsid, object); IL2CPP_VM_RAISE_IF_FAILED(hr, true); } static inline il2cpp_hresult_t CreateFreeThreadedMarshaler(Il2CppIUnknown* outer, Il2CppIUnknown** marshal) { return os::COM::CreateFreeThreadedMarshaler(outer, marshal); } static void MarshalVariant(Il2CppObject* obj, Il2CppVariant* variant); static Il2CppObject* MarshalVariantResult(const Il2CppVariant* variant); static void DestroyVariant(Il2CppVariant* variant); static Il2CppSafeArray* MarshalSafeArray(uint16_t variantType, Il2CppArray* managedArray); static Il2CppArray* MarshalSafeArrayResult(uint16_t variantType, Il2CppClass* type, Il2CppSafeArray* safeArray); static Il2CppSafeArray* MarshalSafeArrayBString(Il2CppArray* managedArray); static Il2CppArray* MarshalSafeArrayBStringResult(Il2CppClass* type, Il2CppSafeArray* safeArray); static inline void DestroySafeArray(Il2CppSafeArray* safeArray) { const il2cpp_hresult_t hr = os::COM::SafeArrayDestroy(safeArray); IL2CPP_VM_RAISE_IF_FAILED(hr, true); } }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/CachedCCWBase.h ================================================ #pragma once #include "gc/GCHandle.h" #include "vm/ComObjectBase.h" #include "utils/TemplateUtils.h" namespace il2cpp { namespace vm { // Alright, so the lifetime of this guy is pretty weird // For a single managed object, the IUnknown of its COM Callable Wrapper must always be the same // That means that we have to keep the same COM Callable Wrapper alive for an object once we create it // They are cached in il2cpp::vm::g_CCWCache, which is managed by il2cpp::vm::CCW class // // Here comes the tricky part: when a native object has a reference to the COM Callable Wrapper, // the managed object is not supposed to be garbage collected. However, when no native objects are referencing // it, it should not prevent the GC from collecting the managed object. We implement this by keeping a GC handle // on the managed object if our reference count is 1 or more. We acquire it when it gets increased from 0 (this // is safe because such AddRef can only come when this object is retrieved from CCW Cache) and release the GC // handle when our reference count gets decreased to 0. Here's a kicker: we don't destroy the COM Callable Wrapper // when the reference count reaches 0; we instead rely on GC finalizer of the managed object to both remove it from // CCW cache and also destroy it. template struct NOVTABLE CachedCCWBase : ComObjectBase { private: volatile uint32_t m_RefCount; uint32_t m_GCHandle; public: inline CachedCCWBase(Il2CppObject* obj) : ComObjectBase(obj), m_RefCount(0), // We do not hold any references upon its creation m_GCHandle(0) { Il2CppStaticAssert(utils::TemplateUtils::IsBaseOf, TDerived>::value); } virtual uint32_t STDCALL AddRef() IL2CPP_OVERRIDE { return AddRefImpl(); } virtual uint32_t STDCALL Release() IL2CPP_OVERRIDE { return ReleaseImpl(); } FORCE_INLINE uint32_t AddRefImpl() { const uint32_t refCount = Atomic::Increment(&m_RefCount); if (refCount == 1) { IL2CPP_ASSERT(m_GCHandle == 0); m_GCHandle = gc::GCHandle::New(GetManagedObjectInline(), false); } return refCount; } FORCE_INLINE uint32_t ReleaseImpl() { const uint32_t count = Atomic::Decrement(&m_RefCount); if (count == 0) { IL2CPP_ASSERT(m_GCHandle != 0); gc::GCHandle::Free(m_GCHandle); m_GCHandle = 0; } return count; } virtual void STDCALL Destroy() IL2CPP_FINAL IL2CPP_OVERRIDE { IL2CPP_ASSERT(m_RefCount == 0); TDerived* instance = static_cast(this); instance->~TDerived(); utils::Memory::Free(instance); } }; } } ================================================ FILE: unity_decoder/libil2cpp/vm/Class.cpp ================================================ #include "il2cpp-config.h" #include #include "metadata/ArrayMetadata.h" #include "metadata/GenericMetadata.h" #include "metadata/GenericMethod.h" #include "metadata/FieldLayout.h" #include "metadata/Il2CppTypeVector.h" #include "os/Atomic.h" #include "os/Mutex.h" #include "utils/Memory.h" #include "utils/StringUtils.h" #include "vm/Assembly.h" #include "vm/Class.h" #include "vm/Exception.h" #include "vm/Field.h" #include "vm/GenericClass.h" #include "vm/GenericContainer.h" #include "vm/Image.h" #include "vm/MetadataAlloc.h" #include "vm/MetadataCache.h" #include "vm/MetadataLock.h" #include "vm/Method.h" #include "vm/Property.h" #include "vm/Runtime.h" #include "vm/Reflection.h" #include "vm/Thread.h" #include "vm/Type.h" #include "vm/Object.h" #include "class-internals.h" #include "object-internals.h" #include "tabledefs.h" #include "gc/GarbageCollector.h" #include "utils/Il2CppHashMap.h" #include "utils/StringUtils.h" #include "utils/HashUtils.h" #include #include #include #include #if IL2CPP_DEBUGGER_ENABLED #include "il2cpp-debugger.h" #endif using il2cpp::metadata::ArrayMetadata; using il2cpp::metadata::FieldLayout; using il2cpp::metadata::GenericMetadata; using il2cpp::metadata::GenericMethod; using il2cpp::metadata::Il2CppTypeVector; using il2cpp::os::FastAutoLock; using il2cpp::utils::PointerHash; namespace il2cpp { namespace vm { static il2cpp::utils::dynamic_array s_staticFieldData; static int32_t s_FinalizerSlot = -1; static int32_t s_GetHashCodeSlot = -1; static void SetupGCDescriptor(Il2CppClass* klass); static void GetBitmapNoInit(Il2CppClass* klass, size_t* bitmap, size_t& maxSetBit, size_t parentOffset); static Il2CppClass* ResolveGenericInstanceType(Il2CppClass*, const il2cpp::vm::TypeNameParseInfo&, bool, bool); static bool InitLocked(Il2CppClass *klass, const FastAutoLock& lock); static void SetupVTable(Il2CppClass *klass, const FastAutoLock& lock); Il2CppClass* Class::FromIl2CppType(const Il2CppType* type) { #define RETURN_DEFAULT_TYPE(fieldName) do { IL2CPP_ASSERT(il2cpp_defaults.fieldName); return il2cpp_defaults.fieldName; } while (false) switch (type->type) { case IL2CPP_TYPE_OBJECT: RETURN_DEFAULT_TYPE(object_class); case IL2CPP_TYPE_VOID: RETURN_DEFAULT_TYPE(void_class); case IL2CPP_TYPE_BOOLEAN: RETURN_DEFAULT_TYPE(boolean_class); case IL2CPP_TYPE_CHAR: RETURN_DEFAULT_TYPE(char_class); case IL2CPP_TYPE_I1: RETURN_DEFAULT_TYPE(sbyte_class); case IL2CPP_TYPE_U1: RETURN_DEFAULT_TYPE(byte_class); case IL2CPP_TYPE_I2: RETURN_DEFAULT_TYPE(int16_class); case IL2CPP_TYPE_U2: RETURN_DEFAULT_TYPE(uint16_class); case IL2CPP_TYPE_I4: RETURN_DEFAULT_TYPE(int32_class); case IL2CPP_TYPE_U4: RETURN_DEFAULT_TYPE(uint32_class); case IL2CPP_TYPE_I: RETURN_DEFAULT_TYPE(int_class); case IL2CPP_TYPE_U: RETURN_DEFAULT_TYPE(uint_class); case IL2CPP_TYPE_I8: RETURN_DEFAULT_TYPE(int64_class); case IL2CPP_TYPE_U8: RETURN_DEFAULT_TYPE(uint64_class); case IL2CPP_TYPE_R4: RETURN_DEFAULT_TYPE(single_class); case IL2CPP_TYPE_R8: RETURN_DEFAULT_TYPE(double_class); case IL2CPP_TYPE_STRING: RETURN_DEFAULT_TYPE(string_class); case IL2CPP_TYPE_TYPEDBYREF: RETURN_DEFAULT_TYPE(typed_reference_class); case IL2CPP_TYPE_ARRAY: { Il2CppClass* elementClass = FromIl2CppType(type->data.array->etype); return Class::GetBoundedArrayClass(elementClass, type->data.array->rank, true); } case IL2CPP_TYPE_PTR: return Class::GetPtrClass(type->data.type); case IL2CPP_TYPE_FNPTR: NOT_IMPLEMENTED(Class::FromIl2CppType); return NULL; //mono_fnptr_class_get (type->data.method); case IL2CPP_TYPE_SZARRAY: { Il2CppClass* elementClass = FromIl2CppType(type->data.type); return Class::GetArrayClass(elementClass, 1); } case IL2CPP_TYPE_CLASS: case IL2CPP_TYPE_VALUETYPE: return Type::GetClass(type); case IL2CPP_TYPE_GENERICINST: return GenericClass::GetClass(type->data.generic_class); case IL2CPP_TYPE_VAR: return Class::FromGenericParameter(Type::GetGenericParameter(type)); case IL2CPP_TYPE_MVAR: return Class::FromGenericParameter(Type::GetGenericParameter(type)); default: NOT_IMPLEMENTED(Class::FromIl2CppType); } return NULL; #undef RETURN_DEFAULT_TYPE } /* From ECMA-335, I.8.7 Assignment compatibility: The reduced type of a type T is the following: 1. If the underlying type of T is: a. int8, or unsigned int8, then its reduced type is int8. b. int16, or unsigned int16, then its reduced type is int16. c. int32, or unsigned int32, then its reduced type is int32. d. int64, or unsigned int64, then its reduced type is int64. e. native int, or unsigned native int, then its reduced type is native int. 2. Otherwise, the reduced type is itself. */ static inline const Il2CppClass* GetReducedType(const Il2CppClass* type) { switch (type->byval_arg->type) { case IL2CPP_TYPE_I1: case IL2CPP_TYPE_U1: return il2cpp_defaults.sbyte_class; case IL2CPP_TYPE_I2: case IL2CPP_TYPE_U2: return il2cpp_defaults.int16_class; case IL2CPP_TYPE_I4: case IL2CPP_TYPE_U4: return il2cpp_defaults.int32_class; case IL2CPP_TYPE_I8: case IL2CPP_TYPE_U8: return il2cpp_defaults.int64_class; case IL2CPP_TYPE_I: case IL2CPP_TYPE_U: return il2cpp_defaults.int_class; default: return type; } } Il2CppClass* Class::FromSystemType(Il2CppReflectionType *type) { return Class::FromIl2CppType(type->type); } static void SetupInterfacesLocked(Il2CppClass* klass, const FastAutoLock& lock) { if (klass->generic_class) { Il2CppClass* genericTypeDefinition = GenericClass::GetTypeDefinition(klass->generic_class); Il2CppGenericContext* context = &klass->generic_class->context; if (genericTypeDefinition->interfaces_count > 0 && klass->implementedInterfaces == NULL) { IL2CPP_ASSERT(genericTypeDefinition->interfaces_count == klass->interfaces_count); klass->implementedInterfaces = (Il2CppClass**)MetadataCalloc(genericTypeDefinition->interfaces_count, sizeof(Il2CppClass*)); for (uint16_t i = 0; i < genericTypeDefinition->interfaces_count; i++) klass->implementedInterfaces[i] = Class::FromIl2CppType(GenericMetadata::InflateIfNeeded(MetadataCache::GetInterfaceFromIndex(genericTypeDefinition->typeDefinition->interfacesStart + i), context, false)); } } else if (klass->rank > 0) { ArrayMetadata::SetupArrayInterfaces(klass, lock); } else { if (klass->interfaces_count > 0 && klass->implementedInterfaces == NULL) { klass->implementedInterfaces = (Il2CppClass**)MetadataCalloc(klass->interfaces_count, sizeof(Il2CppClass*)); for (uint16_t i = 0; i < klass->interfaces_count; i++) klass->implementedInterfaces[i] = Class::FromIl2CppType(MetadataCache::GetInterfaceFromIndex(klass->typeDefinition->interfacesStart + i)); } } } typedef Il2CppHashMap > GenericParameterMap; static GenericParameterMap s_GenericParameterMap; Il2CppClass* Class::FromGenericParameter(const Il2CppGenericParameter *param) { IL2CPP_ASSERT(param->ownerIndex != kGenericContainerIndexInvalid); FastAutoLock lock(&g_MetadataLock); GenericParameterMap::const_iterator iter = s_GenericParameterMap.find(param); if (iter != s_GenericParameterMap.end()) return iter->second; Il2CppClass* klass = (Il2CppClass*)MetadataCalloc(1, sizeof(Il2CppClass)); klass->name = MetadataCache::GetStringFromIndex(param->nameIndex); klass->namespaze = ""; const Il2CppGenericContainer* container = MetadataCache::GetGenericContainerFromIndex(param->ownerIndex); klass->image = GenericContainer::GetDeclaringType(container)->image; klass->initialized = true; klass->parent = il2cpp_defaults.object_class; klass->castClass = klass->element_class = klass; klass->flags = TYPE_ATTRIBUTE_PUBLIC; Il2CppType* thisArg = (Il2CppType*)MetadataCalloc(1, sizeof(Il2CppType)); Il2CppType* byvalArg = (Il2CppType*)MetadataCalloc(1, sizeof(Il2CppType)); thisArg->type = byvalArg->type = container->is_method ? IL2CPP_TYPE_MVAR : IL2CPP_TYPE_VAR; thisArg->data.genericParameterIndex = byvalArg->data.genericParameterIndex = MetadataCache::GetIndexForGenericParameter(param); thisArg->byref = true; klass->this_arg = thisArg; klass->byval_arg = byvalArg; klass->instance_size = sizeof(void*); klass->thread_static_fields_size = -1; klass->native_size = -1; klass->size_inited = true; s_GenericParameterMap.insert(std::make_pair(param, klass)); return klass; } Il2CppClass* Class::GetElementClass(Il2CppClass *klass) { return klass->element_class; } const Il2CppType* Class::GetEnumBaseType(Il2CppClass *klass) { if (klass->element_class == klass) /* SRE or broken types */ return NULL; else return klass->element_class->byval_arg; } const EventInfo* Class::GetEvents(Il2CppClass *klass, void* *iter) { if (!iter) return NULL; if (!*iter) { Class::SetupEvents(klass); if (klass->event_count == 0) return NULL; *iter = const_cast(klass->events); return klass->events; } const EventInfo* eventInfo = (const EventInfo*)*iter; eventInfo++; if (eventInfo < klass->events + klass->event_count) { *iter = const_cast(eventInfo); return eventInfo; } return NULL; } FieldInfo* Class::GetFields(Il2CppClass *klass, void* *iter) { if (!iter) return NULL; if (!*iter) { Class::SetupFields(klass); if (klass->field_count == 0) return NULL; *iter = klass->fields; return klass->fields; } FieldInfo* fieldAddress = (FieldInfo*)*iter; fieldAddress++; if (fieldAddress < klass->fields + klass->field_count) { *iter = fieldAddress; return fieldAddress; } return NULL; } FieldInfo* Class::GetFieldFromName(Il2CppClass *klass, const char* name) { while (klass) { void* iter = NULL; FieldInfo* field; while ((field = GetFields(klass, &iter))) { if (strcmp(name, Field::GetName(field)) != 0) continue; return field; } klass = klass->parent; } return NULL; } const MethodInfo* Class::GetFinalizer(Il2CppClass *klass) { if (!klass->initialized) Class::Init(klass); if (!klass->has_finalize) return NULL; return klass->vtable[s_FinalizerSlot].method; } int32_t Class::GetInstanceSize(const Il2CppClass *klass) { IL2CPP_ASSERT(klass->size_inited); return klass->instance_size; } Il2CppClass* Class::GetInterfaces(Il2CppClass *klass, void* *iter) { if (!iter) return NULL; if (!*iter) { Class::SetupInterfaces(klass); if (klass->interfaces_count == 0) return NULL; *iter = &klass->implementedInterfaces[0]; return klass->implementedInterfaces[0]; } Il2CppClass** interfaceAddress = (Il2CppClass**)*iter; interfaceAddress++; if (interfaceAddress < &klass->implementedInterfaces[klass->interfaces_count]) { *iter = interfaceAddress; return *interfaceAddress; } return NULL; } const MethodInfo* Class::GetMethods(Il2CppClass *klass, void* *iter) { if (!iter) return NULL; if (!*iter) { Class::SetupMethods(klass); if (klass->method_count == 0) return NULL; *iter = &klass->methods[0]; return klass->methods[0]; } const MethodInfo** methodAddress = (const MethodInfo**)*iter; methodAddress++; if (methodAddress < &klass->methods[klass->method_count]) { *iter = methodAddress; return *methodAddress; } return NULL; } const MethodInfo* Class::GetMethodFromName(Il2CppClass *klass, const char* name, int argsCount) { return GetMethodFromNameFlags(klass, name, argsCount, 0); } const MethodInfo* Class::GetMethodFromNameFlags(Il2CppClass *klass, const char* name, int argsCount, int32_t flags) { Class::Init(klass); while (klass != NULL) { void* iter = NULL; while (const MethodInfo* method = Class::GetMethods(klass, &iter)) { if (method->name[0] == name[0] && !strcmp(name, method->name) && (argsCount == -1 || method->parameters_count == argsCount) && ((method->flags & flags) == flags)) { return method; } } klass = klass->parent; } return NULL; } const char* Class::GetName(Il2CppClass *klass) { return klass->name; } const char* Class::GetNamespace(Il2CppClass *klass) { return klass->namespaze; } Il2CppClass* Class::GetNestedTypes(Il2CppClass *klass, void* *iter) { if (!iter) return NULL; if (klass->generic_class) { IL2CPP_ASSERT(0 && "Class::GetNestedTypes should only be called on non-generic types and generic type definitions"); return NULL; } if (!*iter) { Class::SetupNestedTypes(klass); if (klass->nested_type_count == 0) return NULL; *iter = &klass->nestedTypes[0]; return klass->nestedTypes[0]; } Il2CppClass** nestedTypeAddress = (Il2CppClass**)*iter; nestedTypeAddress++; if (nestedTypeAddress < &klass->nestedTypes[klass->nested_type_count]) { *iter = nestedTypeAddress; return *nestedTypeAddress; } return NULL; } size_t Class::GetNumMethods(const Il2CppClass* klass) { return klass->method_count; } size_t Class::GetNumProperties(const Il2CppClass* klass) { return klass->property_count; } size_t Class::GetNumFields(const Il2CppClass* klass) { return klass->field_count; } Il2CppClass* Class::GetParent(Il2CppClass *klass) { return klass->parent; } const PropertyInfo* Class::GetProperties(Il2CppClass *klass, void* *iter) { if (!iter) return NULL; if (!*iter) { Class::SetupProperties(klass); if (klass->property_count == 0) return NULL; *iter = const_cast(klass->properties); return klass->properties; } const PropertyInfo* property = (const PropertyInfo*)*iter; property++; if (property < klass->properties + klass->property_count) { *iter = const_cast(property); return property; } return NULL; } const PropertyInfo* Class::GetPropertyFromName(Il2CppClass *klass, const char* name) { while (klass) { void* iter = NULL; while (const PropertyInfo* prop = GetProperties(klass, &iter)) { if (strcmp(name, Property::GetName(prop)) != 0) continue; return prop; } klass = klass->parent; } return NULL; } int32_t Class::GetValueSize(Il2CppClass *klass, uint32_t *align) { int32_t size; if (!klass->init_pending) Init(klass); IL2CPP_ASSERT(klass->valuetype); size = Class::GetInstanceSize(klass) - sizeof(Il2CppObject); if (align) *align = klass->minimumAlignment; return size; } bool Class::HasParent(Il2CppClass *klass, Il2CppClass *parent) { Class::SetupTypeHierarchy(klass); Class::SetupTypeHierarchy(parent); return HasParentUnsafe(klass, parent); } bool Class::IsAssignableFrom(Il2CppClass *klass, Il2CppClass *oklass) { // Cast to original class - fast path if (klass == oklass) return true; Class::Init(klass); Class::Init(oklass); // Following checks are always going to fail for interfaces if (!IsInterface(klass)) { // Array if (klass->rank) { if (oklass->rank != klass->rank) return false; if (oklass->castClass->valuetype) { // Full array covariance is defined only for reference types. // For value types, array element reduced types must match return GetReducedType(klass->castClass) == GetReducedType(oklass->castClass); } return Class::IsAssignableFrom(klass->castClass, oklass->castClass); } // System.Object else if (klass == il2cpp_defaults.object_class) { return true; } // Left is System.Nullable<> else if (Class::IsNullable(klass)) { if (Class::IsNullable(oklass)) NOT_IMPLEMENTED(Class::IsAssignableFrom); Il2CppClass* nullableArg = Class::GetNullableArgument(klass); return Class::IsAssignableFrom(nullableArg, oklass); } #if NET_4_0 if (klass->parent == il2cpp_defaults.multicastdelegate_class && klass->generic_class != NULL) { const Il2CppTypeDefinition* genericClass = MetadataCache::GetTypeDefinitionFromIndex(klass->generic_class->typeDefinitionIndex); const Il2CppGenericContainer* genericContainer = MetadataCache::GetGenericContainerFromIndex(genericClass->genericContainerIndex); if (IsGenericClassAssignableFrom(klass, oklass, genericContainer)) return true; } #endif return HasParentUnsafe(oklass, klass); } #if NET_4_0 if (klass->generic_class != NULL) { // checking for simple reference equality is not enough in this case because generic interface might have covariant and/or contravariant parameters const Il2CppTypeDefinition* genericInterface = MetadataCache::GetTypeDefinitionFromIndex(klass->generic_class->typeDefinitionIndex); const Il2CppGenericContainer* genericContainer = MetadataCache::GetGenericContainerFromIndex(genericInterface->genericContainerIndex); for (Il2CppClass* iter = oklass; iter != NULL; iter = iter->parent) { if (IsGenericClassAssignableFrom(klass, iter, genericContainer)) return true; for (uint16_t i = 0; i < iter->interfaces_count; ++i) { if (IsGenericClassAssignableFrom(klass, iter->implementedInterfaces[i], genericContainer)) return true; } for (uint16_t i = 0; i < iter->interface_offsets_count; ++i) { if (IsGenericClassAssignableFrom(klass, iter->interfaceOffsets[i].interfaceType, genericContainer)) return true; } } } else #endif { for (Il2CppClass* iter = oklass; iter != NULL; iter = iter->parent) { for (uint16_t i = 0; i < iter->interfaces_count; ++i) { if (iter->implementedInterfaces[i] == klass) return true; } // Check the interfaces we may have grafted on to the type (e.g IList, // ICollection, IEnumerable for array types). for (uint16_t i = 0; i < iter->interface_offsets_count; ++i) { if (iter->interfaceOffsets[i].interfaceType == klass) return true; } } } return false; } bool Class::IsGeneric(const Il2CppClass *klass) { return klass->is_generic; } bool Class::IsInflated(const Il2CppClass *klass) { return klass->generic_class != NULL; } bool Class::IsSubclassOf(Il2CppClass *klass, Il2CppClass *klassc, bool check_interfaces) { Class::SetupTypeHierarchy(klass); Class::SetupTypeHierarchy(klassc); Class::SetupInterfaces(klass); if (check_interfaces && IsInterface(klassc) && !IsInterface(klass)) { Il2CppClass *oklass = klass; while (oklass) { Class::SetupInterfaces(oklass); // TODO: we probably need to implement a faster check here for (uint16_t i = 0; i < oklass->interfaces_count; i++) { if (oklass->implementedInterfaces[i] == klassc) return true; } oklass = oklass->parent; } } else if (check_interfaces && IsInterface(klassc) && IsInterface(klass)) { // TODO: we probably need to implement a faster check here for (uint16_t i = 0; i < klass->interfaces_count; i++) { if (klass->implementedInterfaces[i] == klassc) return true; } } else { if (!IsInterface(klass) && HasParentUnsafe(klass, klassc)) return true; } /* * MS.NET thinks interfaces are a subclass of Object, so we think it as * well. */ if (klassc == il2cpp_defaults.object_class) return true; return false; } bool Class::IsValuetype(const Il2CppClass *klass) { return klass->valuetype; } bool Class::IsBlittable(const Il2CppClass *klass) { return klass->is_blittable; } enum FieldLayoutKind { FIELD_LAYOUT_INSTANCE, FIELD_LAYOUT_STATIC, FIELD_LAYOUT_THREADSTATIC, }; static void SetupFieldOffsets(FieldLayoutKind fieldLayoutKind, Il2CppClass* klass, size_t size, const std::vector& fieldOffsets) { IL2CPP_ASSERT(size < std::numeric_limits::max()); if (fieldLayoutKind == FIELD_LAYOUT_INSTANCE) klass->instance_size = static_cast(size); if (fieldLayoutKind == FIELD_LAYOUT_STATIC) klass->static_fields_size = static_cast(size); if (fieldLayoutKind == FIELD_LAYOUT_THREADSTATIC) klass->thread_static_fields_size = static_cast(size); if (!(klass->flags & TYPE_ATTRIBUTE_EXPLICIT_LAYOUT)) { size_t fieldIndex = 0; for (uint16_t i = 0; i < klass->field_count; i++) { FieldInfo* field = klass->fields + i; if (fieldLayoutKind == FIELD_LAYOUT_INSTANCE && field->type->attrs & FIELD_ATTRIBUTE_STATIC) continue; if (fieldLayoutKind == FIELD_LAYOUT_STATIC && !Field::IsNormalStatic(field)) continue; if (fieldLayoutKind == FIELD_LAYOUT_THREADSTATIC && !Field::IsThreadStatic(field)) continue; if (fieldLayoutKind == FIELD_LAYOUT_THREADSTATIC) { field->offset = THREAD_STATIC_FIELD_OFFSET; fieldIndex++; continue; } field->offset = static_cast(fieldOffsets[fieldIndex]); fieldIndex++; } } } static void ValidateFieldOffsets(FieldLayoutKind fieldLayoutKind, Il2CppClass* klass, size_t size, const std::vector& fieldOffsets) { if (fieldLayoutKind == FIELD_LAYOUT_INSTANCE && klass->parent && !(klass->flags & TYPE_ATTRIBUTE_EXPLICIT_LAYOUT)) IL2CPP_ASSERT(klass->instance_size == size); if (fieldLayoutKind == FIELD_LAYOUT_STATIC) IL2CPP_ASSERT(klass->static_fields_size == size); if (fieldLayoutKind == FIELD_LAYOUT_THREADSTATIC) IL2CPP_ASSERT(klass->thread_static_fields_size == size); if (!(klass->flags & TYPE_ATTRIBUTE_EXPLICIT_LAYOUT)) { size_t fieldIndex = 0; for (uint16_t i = 0; i < klass->field_count; i++) { FieldInfo* field = klass->fields + i; if (fieldLayoutKind == FIELD_LAYOUT_INSTANCE && field->type->attrs & FIELD_ATTRIBUTE_STATIC) continue; if (fieldLayoutKind == FIELD_LAYOUT_STATIC && !Field::IsNormalStatic(field)) continue; if (fieldLayoutKind == FIELD_LAYOUT_THREADSTATIC && !Field::IsThreadStatic(field)) continue; if (fieldLayoutKind == FIELD_LAYOUT_THREADSTATIC) { IL2CPP_ASSERT(fieldOffsets[fieldIndex] == -1); fieldIndex++; continue; } IL2CPP_ASSERT(field->offset == fieldOffsets[fieldIndex]); fieldIndex++; } } } static void LayoutFieldsLocked(Il2CppClass *klass, const FastAutoLock& lock) { if (Class::IsGeneric(klass)) return; size_t instanceSize = 0; size_t actualSize = 0; if (klass->parent) { IL2CPP_ASSERT(klass->parent->size_inited); klass->has_references |= klass->parent->has_references; instanceSize = klass->parent->instance_size; actualSize = klass->parent->actualSize; if (klass->valuetype) klass->minimumAlignment = 1; else klass->minimumAlignment = klass->parent->minimumAlignment; } else { actualSize = instanceSize = sizeof(Il2CppObject); klass->minimumAlignment = sizeof(Il2CppObject*); } if (klass->field_count) { for (uint16_t i = 0; i < klass->field_count; i++) { FieldInfo* field = klass->fields + i; if (!Field::IsInstance(field)) continue; const Il2CppType* ftype = Type::GetUnderlyingType(field->type); if (Type::IsEmptyType(ftype)) { std::string message; message += "The field '"; message += field->name; message += "' in type '"; message += klass->name; message += "' has a type which was not generated by il2cpp.exe. Consider using a generic type which is not nested so deeply."; il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetExecutionEngineException(message.c_str())); } if (Type::IsReference(ftype) || (Type::IsStruct(ftype) && Class::HasReferences(Class::FromIl2CppType(ftype)))) klass->has_references = true; } Il2CppTypeVector fieldTypes; Il2CppTypeVector staticFieldTypes; Il2CppTypeVector threadStaticFieldTypes; for (uint16_t i = 0; i < klass->field_count; i++) { FieldInfo* field = klass->fields + i; const Il2CppType* ftype = Type::GetUnderlyingType(field->type); if (Field::IsInstance(field)) fieldTypes.push_back(ftype); else if (Field::IsNormalStatic(field)) staticFieldTypes.push_back(ftype); else if (Field::IsThreadStatic(field)) threadStaticFieldTypes.push_back(ftype); } FieldLayout::FieldLayoutData layoutData; FieldLayout::FieldLayoutData staticLayoutData; FieldLayout::FieldLayoutData threadStaticLayoutData; FieldLayout::LayoutFields(instanceSize, actualSize, klass->minimumAlignment, fieldTypes, layoutData); instanceSize = layoutData.classSize; // This is a value type with no instance fields, but at least one static field. if (klass->valuetype && fieldTypes.size() == 0) { instanceSize = IL2CPP_SIZEOF_STRUCT_WITH_NO_INSTANCE_FIELDS + sizeof(Il2CppObject); klass->actualSize = IL2CPP_SIZEOF_STRUCT_WITH_NO_INSTANCE_FIELDS + sizeof(Il2CppObject); } // need to set this in case there are no fields in a generic instance type if (klass->generic_class) klass->instance_size = static_cast(instanceSize); klass->size_inited = true; FieldLayout::LayoutFields(0, 0, 1, staticFieldTypes, staticLayoutData); FieldLayout::LayoutFields(0, 0, 1, threadStaticFieldTypes, threadStaticLayoutData); klass->minimumAlignment = layoutData.minimumAlignment; klass->actualSize = static_cast(layoutData.actualClassSize); size_t staticSize = staticLayoutData.classSize; size_t threadStaticSize = threadStaticLayoutData.classSize; for (size_t i = 0; i < threadStaticLayoutData.FieldOffsets.size(); ++i) threadStaticLayoutData.FieldOffsets[i] = -1; if (klass->generic_class) { SetupFieldOffsets(FIELD_LAYOUT_INSTANCE, klass, instanceSize, layoutData.FieldOffsets); SetupFieldOffsets(FIELD_LAYOUT_STATIC, klass, staticSize, staticLayoutData.FieldOffsets); SetupFieldOffsets(FIELD_LAYOUT_THREADSTATIC, klass, threadStaticSize, threadStaticLayoutData.FieldOffsets); } else { #if IL2CPP_ENABLE_VALIDATE_FIELD_LAYOUT ValidateFieldOffsets(FIELD_LAYOUT_INSTANCE, klass, instanceSize, layoutData.FieldOffsets); ValidateFieldOffsets(FIELD_LAYOUT_STATIC, klass, staticSize, staticLayoutData.FieldOffsets); ValidateFieldOffsets(FIELD_LAYOUT_THREADSTATIC, klass, threadStaticSize, threadStaticLayoutData.FieldOffsets); #endif } } else { // need to set this in case there are no fields in a generic instance type if (klass->generic_class) klass->instance_size = static_cast(instanceSize); // Always set the actual size, as a derived class without fields could end up // with the wrong actual size (i.e. sizeof may be incorrect), if the last // field of the base class doesn't go to an alignment boundary and the compiler ABI // uses that extra space (as clang does). klass->actualSize = static_cast(actualSize); } if (klass->static_fields_size) { klass->static_fields = il2cpp::gc::GarbageCollector::AllocateFixed(klass->static_fields_size, NULL); s_staticFieldData.push_back(klass); il2cpp_runtime_stats.class_static_data_size += klass->static_fields_size; } if (klass->thread_static_fields_size) klass->thread_static_fields_offset = il2cpp::vm::Thread::AllocThreadStaticData(klass->thread_static_fields_size); } static void SetupFieldsFromDefinition(Il2CppClass* klass) { if (klass->field_count == 0) { klass->fields = NULL; return; } FieldInfo* fields = (FieldInfo*)MetadataCalloc(klass->field_count, sizeof(FieldInfo)); FieldInfo* newField = fields; FieldIndex start = klass->typeDefinition->fieldStart; IL2CPP_ASSERT(klass->typeDefinition->fieldStart != kFieldIndexInvalid); FieldIndex end = start + klass->field_count; for (FieldIndex fieldIndex = start; fieldIndex < end; ++fieldIndex) { const Il2CppFieldDefinition* fieldDefinition = MetadataCache::GetFieldDefinitionFromIndex(fieldIndex); newField->type = MetadataCache::GetIl2CppTypeFromIndex(fieldDefinition->typeIndex); newField->name = MetadataCache::GetStringFromIndex(fieldDefinition->nameIndex); newField->parent = klass; newField->offset = MetadataCache::GetFieldOffsetFromIndex(MetadataCache::GetIndexForTypeDefinition(klass), fieldIndex - start); newField->customAttributeIndex = fieldDefinition->customAttributeIndex; newField->token = fieldDefinition->token; newField++; } klass->fields = fields; } // passing lock to ensure we have acquired it. We can add asserts later void SetupFieldsLocked(Il2CppClass *klass, const FastAutoLock& lock) { if (klass->size_inited) return; if (klass->parent && !klass->parent->size_inited) SetupFieldsLocked(klass->parent, lock); if (klass->generic_class) { // for generic instance types, they just inflate the fields of their generic type definition // initialize the generic type definition and delegate to the generic logic InitLocked(GenericClass::GetTypeDefinition(klass->generic_class), lock); GenericClass::SetupFields(klass); } else { SetupFieldsFromDefinition(klass); } if (!Class::IsGeneric(klass)) LayoutFieldsLocked(klass, lock); klass->size_inited = true; } void Class::SetupFields(Il2CppClass *klass) { if (!klass->size_inited) { FastAutoLock lock(&g_MetadataLock); SetupFieldsLocked(klass, lock); } } // passing lock to ensure we have acquired it. We can add asserts later void SetupMethodsLocked(Il2CppClass *klass, const FastAutoLock& lock) { if ((!klass->method_count && !klass->rank) || klass->methods) return; if (klass->generic_class) { InitLocked(GenericClass::GetTypeDefinition(klass->generic_class), lock); GenericClass::SetupMethods(klass); } else if (klass->rank) { InitLocked(klass->element_class, lock); SetupVTable(klass, lock); } else { if (klass->method_count == 0) { klass->methods = NULL; return; } klass->methods = (const MethodInfo**)IL2CPP_CALLOC(klass->method_count, sizeof(MethodInfo*)); MethodInfo* methods = (MethodInfo*)IL2CPP_CALLOC(klass->method_count, sizeof(MethodInfo)); MethodInfo* newMethod = methods; MethodIndex start = klass->typeDefinition->methodStart; IL2CPP_ASSERT(start != kFieldIndexInvalid); MethodIndex end = start + klass->method_count; for (MethodIndex index = start; index < end; ++index) { const Il2CppMethodDefinition* methodDefinition = MetadataCache::GetMethodDefinitionFromIndex(index); newMethod->name = MetadataCache::GetStringFromIndex(methodDefinition->nameIndex); newMethod->methodPointer = MetadataCache::GetMethodPointerFromIndex(methodDefinition->methodIndex); newMethod->invoker_method = MetadataCache::GetMethodInvokerFromIndex(methodDefinition->invokerIndex); newMethod->declaring_type = klass; newMethod->return_type = MetadataCache::GetIl2CppTypeFromIndex(methodDefinition->returnType); ParameterInfo* parameters = (ParameterInfo*)IL2CPP_CALLOC(methodDefinition->parameterCount, sizeof(ParameterInfo)); ParameterInfo* newParameter = parameters; for (uint16_t paramIndex = 0; paramIndex < methodDefinition->parameterCount; ++paramIndex) { const Il2CppParameterDefinition* parameterDefinition = MetadataCache::GetParameterDefinitionFromIndex(methodDefinition->parameterStart + paramIndex); newParameter->name = MetadataCache::GetStringFromIndex(parameterDefinition->nameIndex); newParameter->position = paramIndex; newParameter->token = parameterDefinition->token; newParameter->customAttributeIndex = parameterDefinition->customAttributeIndex; newParameter->parameter_type = MetadataCache::GetIl2CppTypeFromIndex(parameterDefinition->typeIndex); newParameter++; } newMethod->parameters = parameters; newMethod->customAttributeIndex = methodDefinition->customAttributeIndex; newMethod->flags = methodDefinition->flags; newMethod->iflags = methodDefinition->iflags; newMethod->slot = methodDefinition->slot; newMethod->parameters_count = static_cast(methodDefinition->parameterCount); newMethod->is_inflated = false; newMethod->token = methodDefinition->token; newMethod->methodDefinition = methodDefinition; newMethod->genericContainer = MetadataCache::GetGenericContainerFromIndex(methodDefinition->genericContainerIndex); if (newMethod->genericContainer) newMethod->is_generic = true; klass->methods[index - start] = newMethod; newMethod++; } } } void Class::SetupMethods(Il2CppClass *klass) { if (klass->method_count || klass->rank) { FastAutoLock lock(&g_MetadataLock); SetupMethodsLocked(klass, lock); } } void SetupNestedTypesLocked(Il2CppClass *klass, const FastAutoLock& lock) { if (klass->generic_class) return; if (klass->nested_type_count > 0) { klass->nestedTypes = (Il2CppClass**)MetadataCalloc(klass->nested_type_count, sizeof(Il2CppClass*)); for (uint16_t i = 0; i < klass->nested_type_count; i++) klass->nestedTypes[i] = MetadataCache::GetNestedTypeFromIndex(klass->typeDefinition->nestedTypesStart + i); } } void Class::SetupNestedTypes(Il2CppClass *klass) { if (klass->generic_class) return; if (klass->nested_type_count) { FastAutoLock lock(&g_MetadataLock); SetupNestedTypesLocked(klass, lock); } } static void SetupVTable(Il2CppClass *klass, const FastAutoLock& lock) { if (klass->is_vtable_initialized) return; if (klass->generic_class) { Il2CppClass* genericTypeDefinition = GenericClass::GetTypeDefinition(klass->generic_class); Il2CppGenericContext* context = &klass->generic_class->context; if (genericTypeDefinition->interface_offsets_count > 0 && klass->interfaceOffsets == NULL) { klass->interface_offsets_count = genericTypeDefinition->interface_offsets_count; klass->interfaceOffsets = (Il2CppRuntimeInterfaceOffsetPair*)MetadataCalloc(genericTypeDefinition->interface_offsets_count, sizeof(Il2CppRuntimeInterfaceOffsetPair)); for (uint16_t i = 0; i < genericTypeDefinition->interface_offsets_count; i++) { Il2CppInterfaceOffsetPair interfaceOffset = MetadataCache::GetInterfaceOffsetIndex(genericTypeDefinition->typeDefinition->interfaceOffsetsStart + i); klass->interfaceOffsets[i].offset = interfaceOffset.offset; klass->interfaceOffsets[i].interfaceType = Class::FromIl2CppType(GenericMetadata::InflateIfNeeded(MetadataCache::GetIl2CppTypeFromIndex(interfaceOffset.interfaceTypeIndex), context, false)); } } if (genericTypeDefinition->vtable_count > 0) { klass->vtable_count = genericTypeDefinition->vtable_count; for (uint16_t i = 0; i < genericTypeDefinition->vtable_count; i++) { EncodedMethodIndex vtableMethodIndex = MetadataCache::GetVTableMethodFromIndex(genericTypeDefinition->typeDefinition->vtableStart + i); const MethodInfo* method = MetadataCache::GetMethodInfoFromIndex(vtableMethodIndex); if (GetEncodedIndexType(vtableMethodIndex) == kIl2CppMetadataUsageMethodRef) { const Il2CppGenericMethod* genericMethod = GenericMetadata::Inflate(method->genericMethod, context); method = GenericMethod::GetMethod(genericMethod); } else if (method && Class::IsGeneric(method->declaring_type)) { const Il2CppGenericMethod* gmethod = MetadataCache::GetGenericMethod(method, context->class_inst, NULL); method = GenericMethod::GetMethod(gmethod); } klass->vtable[i].method = method; if (method != NULL) { if (method->methodPointer) klass->vtable[i].methodPtr = method->methodPointer; else if (method->is_inflated && !method->is_generic && !method->genericMethod->context.method_inst) klass->vtable[i].methodPtr = MetadataCache::GetUnresolvedVirtualCallStub(method); } } } } else if (klass->rank) { InitLocked(klass->element_class, lock); ArrayMetadata::SetupArrayVTable(klass, lock); } else { if (klass->interface_offsets_count > 0 && klass->interfaceOffsets == NULL) { klass->interfaceOffsets = (Il2CppRuntimeInterfaceOffsetPair*)MetadataCalloc(klass->interface_offsets_count, sizeof(Il2CppRuntimeInterfaceOffsetPair)); for (uint16_t i = 0; i < klass->interface_offsets_count; i++) { Il2CppInterfaceOffsetPair interfaceOffset = MetadataCache::GetInterfaceOffsetIndex(klass->typeDefinition->interfaceOffsetsStart + i); klass->interfaceOffsets[i].offset = interfaceOffset.offset; klass->interfaceOffsets[i].interfaceType = Class::FromIl2CppType(MetadataCache::GetIl2CppTypeFromIndex(interfaceOffset.interfaceTypeIndex)); } } if (klass->vtable_count > 0) { for (uint16_t i = 0; i < klass->vtable_count; i++) { const MethodInfo* method = MetadataCache::GetMethodInfoFromIndex(MetadataCache::GetVTableMethodFromIndex(klass->typeDefinition->vtableStart + i)); klass->vtable[i].method = method; if (method != NULL) klass->vtable[i].methodPtr = method->methodPointer; } } } klass->is_vtable_initialized = 1; } static void SetupEventsLocked(Il2CppClass *klass, const FastAutoLock& lock) { if (klass->generic_class) { InitLocked(GenericClass::GetTypeDefinition(klass->generic_class), lock); GenericClass::SetupEvents(klass); } else if (klass->rank > 0) { // do nothing, arrays have no events IL2CPP_ASSERT(klass->event_count == 0); } else if (klass->event_count != 0) { // we need methods initialized since we reference them via index below SetupMethodsLocked(klass, lock); EventInfo* events = (EventInfo*)IL2CPP_CALLOC(klass->event_count, sizeof(EventInfo)); EventInfo* newEvent = events; EventIndex start = klass->typeDefinition->eventStart; IL2CPP_ASSERT(klass->typeDefinition->eventStart != kEventIndexInvalid); EventIndex end = start + klass->event_count; for (EventIndex eventIndex = start; eventIndex < end; ++eventIndex) { const Il2CppEventDefinition* eventDefinition = MetadataCache::GetEventDefinitionFromIndex(eventIndex); newEvent->eventType = MetadataCache::GetIl2CppTypeFromIndex(eventDefinition->typeIndex); newEvent->name = MetadataCache::GetStringFromIndex(eventDefinition->nameIndex); newEvent->parent = klass; if (eventDefinition->add != kMethodIndexInvalid) newEvent->add = klass->methods[eventDefinition->add]; if (eventDefinition->remove != kMethodIndexInvalid) newEvent->remove = klass->methods[eventDefinition->remove]; if (eventDefinition->raise != kMethodIndexInvalid) newEvent->raise = klass->methods[eventDefinition->raise]; newEvent->customAttributeIndex = eventDefinition->customAttributeIndex; newEvent->token = eventDefinition->token; newEvent++; } klass->events = events; } } void Class::SetupEvents(Il2CppClass *klass) { if (!klass->events && klass->event_count) { FastAutoLock lock(&g_MetadataLock); SetupEventsLocked(klass, lock); } } static void SetupPropertiesLocked(Il2CppClass *klass, const FastAutoLock& lock) { if (klass->generic_class) { InitLocked(GenericClass::GetTypeDefinition(klass->generic_class), lock); GenericClass::SetupProperties(klass); } else if (klass->property_count != 0) { // we need methods initialized since we reference them via index below SetupMethodsLocked(klass, lock); PropertyInfo* properties = (PropertyInfo*)IL2CPP_CALLOC(klass->property_count, sizeof(PropertyInfo)); PropertyInfo* newProperty = properties; PropertyIndex start = klass->typeDefinition->propertyStart; IL2CPP_ASSERT(klass->typeDefinition->propertyStart != kPropertyIndexInvalid); PropertyIndex end = start + klass->property_count; for (PropertyIndex propertyIndex = start; propertyIndex < end; ++propertyIndex) { const Il2CppPropertyDefinition* propertyDefinition = MetadataCache::GetPropertyDefinitionFromIndex(propertyIndex); newProperty->name = MetadataCache::GetStringFromIndex(propertyDefinition->nameIndex); newProperty->parent = klass; if (propertyDefinition->get != kMethodIndexInvalid) newProperty->get = klass->methods[propertyDefinition->get]; if (propertyDefinition->set != kMethodIndexInvalid) newProperty->set = klass->methods[propertyDefinition->set]; newProperty->attrs = propertyDefinition->attrs; newProperty->customAttributeIndex = propertyDefinition->customAttributeIndex; newProperty->token = propertyDefinition->token; newProperty++; } klass->properties = properties; } } void Class::SetupProperties(Il2CppClass *klass) { if (!klass->properties && klass->property_count) { FastAutoLock lock(&g_MetadataLock); SetupPropertiesLocked(klass, lock); } } static void SetupTypeHierarchyLocked(Il2CppClass *klass, const FastAutoLock& lock) { if (klass->typeHierarchy != NULL) return; if (klass->parent && !klass->parent->typeHierarchy) SetupTypeHierarchyLocked(klass->parent, lock); if (klass->parent) klass->typeHierarchyDepth = klass->parent->typeHierarchyDepth + 1; else klass->typeHierarchyDepth = 1; klass->typeHierarchy = (Il2CppClass**)MetadataCalloc(klass->typeHierarchyDepth, sizeof(Il2CppClass*)); if (klass->parent) { klass->typeHierarchy[klass->typeHierarchyDepth - 1] = klass; memcpy(klass->typeHierarchy, klass->parent->typeHierarchy, klass->parent->typeHierarchyDepth * sizeof(void*)); } else { klass->typeHierarchy[0] = klass; } } void Class::SetupTypeHierarchy(Il2CppClass *klass) { FastAutoLock lock(&g_MetadataLock); SetupTypeHierarchyLocked(klass, lock); } void Class::SetupInterfaces(Il2CppClass *klass) { FastAutoLock lock(&g_MetadataLock); SetupInterfacesLocked(klass, lock); } static bool InitLocked(Il2CppClass *klass, const FastAutoLock& lock) { if (klass->initialized) return true; NOT_IMPLEMENTED_NO_ASSERT(Class::Init, "Audit and compare to mono version"); klass->init_pending = true; klass->genericRecursionDepth++; if (klass->generic_class) InitLocked(GenericClass::GetTypeDefinition(klass->generic_class), lock); if (klass->byval_arg->type == IL2CPP_TYPE_ARRAY || klass->byval_arg->type == IL2CPP_TYPE_SZARRAY) { Il2CppClass *element_class = klass->element_class; if (!element_class->initialized) InitLocked(element_class, lock); } SetupInterfacesLocked(klass, lock); if (klass->parent && !klass->parent->initialized) InitLocked(klass->parent, lock); SetupMethodsLocked(klass, lock); SetupTypeHierarchyLocked(klass, lock); SetupVTable(klass, lock); if (!klass->size_inited) SetupFieldsLocked(klass, lock); SetupEventsLocked(klass, lock); SetupPropertiesLocked(klass, lock); SetupNestedTypesLocked(klass, lock); if (klass == il2cpp_defaults.object_class) { for (uint16_t slot = 0; slot < klass->vtable_count; slot++) { const MethodInfo* vmethod = klass->vtable[slot].method; if (!strcmp(vmethod->name, "GetHashCode")) s_GetHashCodeSlot = slot; else if (!strcmp(vmethod->name, "Finalize")) s_FinalizerSlot = slot; } IL2CPP_ASSERT(s_FinalizerSlot > 0); IL2CPP_ASSERT(s_GetHashCodeSlot > 0); } if (!Class::IsGeneric(klass)) SetupGCDescriptor(klass); #if IL2CPP_DEBUGGER_ENABLED // Gab: not sure this is the best place to put the typeload event notification, // we probably want to send a typeload event for all the know types at startup. il2cpp_debugger_notify_type_load(klass); #endif if (klass->generic_class) { const Il2CppTypeDefinition* typeDefinition = GenericClass::GetTypeDefinition(klass->generic_class)->typeDefinition; if (klass->genericRecursionDepth < GenericMetadata::MaximumRuntimeGenericDepth) klass->rgctx_data = GenericMetadata::InflateRGCTX(typeDefinition->rgctxStartIndex, typeDefinition->rgctxCount, &klass->generic_class->context); } klass->initialized = true; klass->init_pending = false; ++il2cpp_runtime_stats.initialized_class_count; return true; } bool Class::Init(Il2CppClass *klass) { IL2CPP_ASSERT(klass); if (!klass->initialized) { FastAutoLock lock(&g_MetadataLock); InitLocked(klass, lock); } return true; } Il2CppClass* Class::FromName(const Il2CppImage* image, const char* namespaze, const char *name) { return Image::ClassFromName(image, namespaze, name); } Il2CppClass* Class::GetArrayClass(Il2CppClass *element_class, uint32_t rank) { return GetBoundedArrayClass(element_class, rank, false); } Il2CppClass* Class::GetBoundedArrayClass(Il2CppClass *eclass, uint32_t rank, bool bounded) { return ArrayMetadata::GetBoundedArrayClass(eclass, rank, bounded); } Il2CppClass* Class::GetInflatedGenericInstanceClass(Il2CppClass* klass, const metadata::Il2CppTypeVector& types) { return GetInflatedGenericInstanceClass(klass, MetadataCache::GetGenericInst(types)); } Il2CppClass* Class::GetInflatedGenericInstanceClass(Il2CppClass* klass, const Il2CppGenericInst* genericInst) { IL2CPP_ASSERT(Class::IsGeneric(klass)); Il2CppGenericClass* gclass = GenericMetadata::GetGenericClass(klass, genericInst); return GenericClass::GetClass(gclass); } Il2CppClass* Class::InflateGenericClass(Il2CppClass* klass, Il2CppGenericContext *context) { const Il2CppType* inflated = InflateGenericType(klass->byval_arg, context); return FromIl2CppType(inflated); } const Il2CppType* Class::InflateGenericType(const Il2CppType* type, Il2CppGenericContext* context) { return GenericMetadata::InflateIfNeeded(type, context, true); } bool Class::HasDefaultConstructor(Il2CppClass* klass) { const char ctorName[] = ".ctor"; void* iter = NULL; while (const MethodInfo* method = Class::GetMethods(klass, &iter)) { if (strncmp(method->name, ctorName, utils::StringUtils::LiteralLength(ctorName)) == 0 && method->parameters_count == 0) return true; } return false; } int Class::GetFlags(const Il2CppClass *klass) { return klass->flags; } bool Class::IsAbstract(const Il2CppClass *klass) { return (klass->flags & TYPE_ATTRIBUTE_ABSTRACT) != 0; } bool Class::IsInterface(const Il2CppClass *klass) { return (klass->flags & TYPE_ATTRIBUTE_INTERFACE) || (klass->byval_arg->type == IL2CPP_TYPE_VAR) || (klass->byval_arg->type == IL2CPP_TYPE_MVAR); } bool Class::IsNullable(const Il2CppClass *klass) { return klass->generic_class != NULL && GenericClass::GetTypeDefinition(klass->generic_class) == il2cpp_defaults.generic_nullable_class; } Il2CppClass* Class::GetNullableArgument(const Il2CppClass* klass) { return Class::FromIl2CppType(klass->generic_class->context.class_inst->type_argv[0]); } int Class::GetArrayElementSize(const Il2CppClass *klass) { const Il2CppType *type = klass->byval_arg; handle_enum: switch (type->type) { case IL2CPP_TYPE_I1: case IL2CPP_TYPE_U1: case IL2CPP_TYPE_BOOLEAN: return 1; case IL2CPP_TYPE_I2: case IL2CPP_TYPE_U2: case IL2CPP_TYPE_CHAR: return 2; case IL2CPP_TYPE_I4: case IL2CPP_TYPE_U4: case IL2CPP_TYPE_R4: return 4; case IL2CPP_TYPE_I: case IL2CPP_TYPE_U: case IL2CPP_TYPE_PTR: case IL2CPP_TYPE_CLASS: case IL2CPP_TYPE_STRING: case IL2CPP_TYPE_OBJECT: case IL2CPP_TYPE_SZARRAY: case IL2CPP_TYPE_ARRAY: case IL2CPP_TYPE_VAR: case IL2CPP_TYPE_MVAR: return sizeof(Il2CppObject*); case IL2CPP_TYPE_I8: case IL2CPP_TYPE_U8: case IL2CPP_TYPE_R8: return 8; case IL2CPP_TYPE_VALUETYPE: if (Type::IsEnum(type)) { type = Class::GetEnumBaseType(Type::GetClass(type)); klass = klass->element_class; goto handle_enum; } return Class::GetInstanceSize(klass) - sizeof(Il2CppObject); case IL2CPP_TYPE_GENERICINST: type = GenericClass::GetTypeDefinition(type->data.generic_class)->byval_arg; goto handle_enum; case IL2CPP_TYPE_VOID: return 0; default: // g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type); NOT_IMPLEMENTED_NO_ASSERT(Class::GetArrayElementSize, "Should throw a nice error"); } return -1; } const Il2CppType* Class::GetType(Il2CppClass *klass) { return klass->byval_arg; } const Il2CppType* Class::GetType(Il2CppClass *klass, const TypeNameParseInfo &info) { // Attempt to resolve a generic type definition. if (Class::IsGeneric(klass)) klass = ResolveGenericInstanceType(klass, info, false, false); bool bounded = false; std::vector::const_iterator it = info.modifiers().begin(); if (info.is_bounded()) { bounded = false; } while (it != info.modifiers().end()) { if (*it == 0) { // byref is always the last modifier, so we can return here. return klass->this_arg; } if (*it == -1) { klass = Class::GetPtrClass(klass); } else if (*it == -2) { bounded = true; } else { klass = Class::GetBoundedArrayClass(klass, *it, bounded); } ++it; } if (klass == NULL) return NULL; return klass->byval_arg; } bool Class::HasAttribute(Il2CppClass *klass, Il2CppClass *attr_class) { return Reflection::HasAttribute(klass, attr_class); } bool Class::IsEnum(const Il2CppClass *klass) { return klass->enumtype; } const Il2CppImage* Class::GetImage(Il2CppClass *klass) { return klass->image; } const Il2CppGenericContainer* Class::GetGenericContainer(Il2CppClass *klass) { return MetadataCache::GetGenericContainerFromIndex(klass->genericContainerIndex); } const MethodInfo* Class::GetCCtor(Il2CppClass *klass) { if (!klass->has_cctor) return NULL; return GetMethodFromNameFlags(klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME); } const char* Class::GetFieldDefaultValue(const FieldInfo *field, const Il2CppType** type) { const Il2CppFieldDefaultValue *entry = MetadataCache::GetFieldDefaultValueForField(field); if (entry != NULL) { *type = MetadataCache::GetIl2CppTypeFromIndex(entry->typeIndex); if (entry->dataIndex == kDefaultValueIndexNull) return NULL; return (const char*)MetadataCache::GetFieldDefaultValueDataFromIndex(entry->dataIndex); } return NULL; } int Class::GetFieldMarshaledSize(const FieldInfo *field) { int marshaledFieldSize = MetadataCache::GetFieldMarshaledSizeForField(field); if (marshaledFieldSize != -1) return marshaledFieldSize; if (field->type->type == IL2CPP_TYPE_BOOLEAN) return 4; if (field->type->type == IL2CPP_TYPE_CHAR) return 1; size_t size = metadata::FieldLayout::GetTypeSizeAndAlignment(field->type).size; IL2CPP_ASSERT(size < static_cast(std::numeric_limits::max())); return static_cast(size); } Il2CppClass* Class::GetPtrClass(const Il2CppType* type) { return GetPtrClass(Class::FromIl2CppType(type)); } Il2CppClass* Class::GetPtrClass(Il2CppClass* elementClass) { FastAutoLock lock(&g_MetadataLock); Il2CppClass* pointerClass = MetadataCache::GetPointerType(elementClass); if (pointerClass) return pointerClass; pointerClass = (Il2CppClass*)MetadataCalloc(1, sizeof(Il2CppClass)); pointerClass->namespaze = elementClass->namespaze; pointerClass->name = il2cpp::utils::StringUtils::StringDuplicate(il2cpp::utils::StringUtils::Printf("%s*", elementClass->name).c_str()); pointerClass->image = elementClass->image; pointerClass->initialized = true; pointerClass->flags = TYPE_ATTRIBUTE_CLASS | (elementClass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); pointerClass->instance_size = sizeof(void*); Il2CppType* this_arg = (Il2CppType*)MetadataCalloc(1, sizeof(Il2CppType)); Il2CppType* byval_arg = (Il2CppType*)MetadataCalloc(1, sizeof(Il2CppType)); this_arg->type = byval_arg->type = IL2CPP_TYPE_PTR; this_arg->data.type = byval_arg->data.type = elementClass->byval_arg; this_arg->byref = true; pointerClass->this_arg = this_arg; pointerClass->byval_arg = byval_arg; pointerClass->parent = NULL; pointerClass->castClass = pointerClass->element_class = elementClass; MetadataCache::AddPointerType(elementClass, pointerClass); return pointerClass; } bool Class::HasReferences(Il2CppClass *klass) { if (klass->init_pending) { /* Be conservative */ return true; } else { Init(klass); return klass->has_references; } } const il2cpp::utils::dynamic_array& Class::GetStaticFieldData() { return s_staticFieldData; } const Il2CppDebugTypeInfo *Class::GetDebugInfo(const Il2CppClass *klass) { #if IL2CPP_DEBUGGER_ENABLED return klass->debug_info; #else return NULL; #endif } const size_t kWordSize = (8 * sizeof(size_t)); static inline void set_bit(size_t* bitmap, size_t index) { bitmap[index / kWordSize] |= (size_t)1 << (index % kWordSize); } size_t Class::GetBitmapSize(const Il2CppClass* klass) { size_t maxBits = klass->instance_size / sizeof(void*); size_t maxWords = 1 + (maxBits / sizeof(size_t)); return sizeof(size_t) * maxWords; } void Class::GetBitmap(Il2CppClass* klass, size_t* bitmap, size_t& maxSetBit) { Class::Init(klass); return il2cpp::vm::GetBitmapNoInit(klass, bitmap, maxSetBit, 0); } const char *Class::GetAssemblyName(const Il2CppClass *klass) { return klass->image->name; } void GetBitmapNoInit(Il2CppClass* klass, size_t* bitmap, size_t& maxSetBit, size_t parentOffset) { Il2CppClass* currentClass = klass; while (currentClass) { for (uint16_t index = 0; index < currentClass->field_count; index++) { FieldInfo* field = currentClass->fields + index; if (field->type->attrs & (FIELD_ATTRIBUTE_STATIC | FIELD_ATTRIBUTE_HAS_FIELD_RVA)) continue; IL2CPP_ASSERT(!field->type->byref); size_t offset = parentOffset + field->offset; const Il2CppType* type = Type::GetUnderlyingType(field->type); switch (type->type) { case IL2CPP_TYPE_I1: case IL2CPP_TYPE_U1: case IL2CPP_TYPE_BOOLEAN: case IL2CPP_TYPE_I2: case IL2CPP_TYPE_U2: case IL2CPP_TYPE_CHAR: case IL2CPP_TYPE_I4: case IL2CPP_TYPE_U4: case IL2CPP_TYPE_I8: case IL2CPP_TYPE_U8: case IL2CPP_TYPE_I: case IL2CPP_TYPE_U: case IL2CPP_TYPE_R4: case IL2CPP_TYPE_R8: case IL2CPP_TYPE_PTR: case IL2CPP_TYPE_FNPTR: break; case IL2CPP_TYPE_STRING: case IL2CPP_TYPE_SZARRAY: case IL2CPP_TYPE_CLASS: case IL2CPP_TYPE_OBJECT: case IL2CPP_TYPE_ARRAY: case IL2CPP_TYPE_VAR: case IL2CPP_TYPE_MVAR: IL2CPP_ASSERT(0 == (field->offset % sizeof(void*))); set_bit(bitmap, offset / sizeof(void*)); maxSetBit = std::max(maxSetBit, offset / sizeof(void*)); break; case IL2CPP_TYPE_GENERICINST: if (!Type::GenericInstIsValuetype(type)) { IL2CPP_ASSERT(0 == (field->offset % sizeof(void*))); set_bit(bitmap, offset / sizeof(void*)); maxSetBit = std::max(maxSetBit, offset / sizeof(void*)); break; } else { /* fall through */ } case IL2CPP_TYPE_VALUETYPE: { Il2CppClass* fieldClass = Class::FromIl2CppType(field->type); Class::Init(fieldClass); if (fieldClass->has_references) GetBitmapNoInit(fieldClass, bitmap, maxSetBit, offset - sizeof(Il2CppObject) /* nested field offset includes padding for boxed structure. Remove for struct fields */); break; } default: NOT_IMPLEMENTED(Class::GetClassBitmap); break; } } currentClass = currentClass->parent; } } void SetupGCDescriptor(Il2CppClass* klass) { const size_t kMaxAllocaSize = 1024; size_t bitmapSize = Class::GetBitmapSize(klass); size_t* bitmap = NULL; std::vector buffer(0); if (bitmapSize > kMaxAllocaSize) { buffer.resize(bitmapSize / sizeof(size_t)); bitmap = (size_t*)&buffer[0]; } else { bitmap = (size_t*)alloca(bitmapSize); } memset(bitmap, 0, bitmapSize); size_t maxSetBit = 0; GetBitmapNoInit(klass, bitmap, maxSetBit, 0); if (klass == il2cpp_defaults.string_class) klass->gc_desc = il2cpp::gc::GarbageCollector::MakeDescriptorForString(); else if (klass->rank) klass->gc_desc = il2cpp::gc::GarbageCollector::MakeDescriptorForArray(); else klass->gc_desc = il2cpp::gc::GarbageCollector::MakeDescriptorForObject(bitmap, (int)maxSetBit + 1); } #define CHECK_IF_NULL(v) \ if ( (v) == NULL && throwOnError ) \ Exception::Raise (Exception::GetTypeLoadException ()); \ if ( (v) == NULL ) \ return NULL; static Il2CppClass * resolve_generic_instance_internal(const il2cpp::vm::TypeNameParseInfo &info, Il2CppClass *generic_class, Il2CppTypeVector &generic_arguments, bool throwOnError) { Il2CppClass *klass = NULL; const Il2CppGenericContainer* container = Class::GetGenericContainer(generic_class); if (container->type_argc != generic_arguments.size()) il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetArgumentException("name", "The number of generic arguments provided doesn't equal the arity of the generic type definition.")); if (info.assembly_name().name.empty()) { const Il2CppImage* image = Image::GetExecutingImage(); klass = MetadataCache::GetGenericInstanceType(generic_class, generic_arguments); if (klass == NULL && image != Image::GetCorlib()) { // Try mscorlib image = (Il2CppImage*)Image::GetCorlib(); klass = MetadataCache::GetGenericInstanceType(generic_class, generic_arguments); } } else { const Il2CppAssembly *assembly = Assembly::Load(info.assembly_name().name.c_str()); CHECK_IF_NULL(assembly); Il2CppImage *image = (Il2CppImage*)Assembly::GetImage(assembly); CHECK_IF_NULL(image); klass = MetadataCache::GetGenericInstanceType(generic_class, generic_arguments); } return klass; } static Il2CppClass* ResolveGenericInstanceType(Il2CppClass* klass, const TypeNameParseInfo& info, bool throwOnError, bool ignoreCase) { if (info.has_generic_arguments()) { Il2CppTypeVector generic_arguments; generic_arguments.reserve(info.type_arguments().size()); std::vector::const_iterator it = info.type_arguments().begin(); while (it != info.type_arguments().end()) { const Il2CppType * generic_argument = Class::il2cpp_type_from_type_info(*it, throwOnError, ignoreCase); CHECK_IF_NULL(generic_argument); generic_arguments.push_back(generic_argument); ++it; } klass = resolve_generic_instance_internal(info, klass, generic_arguments, throwOnError); CHECK_IF_NULL(klass); } if (klass != NULL) Class::Init(klass); return klass; } static Il2CppClass* resolve_parse_info_internal(const TypeNameParseInfo& info, bool throwOnError, bool ignoreCase) { Il2CppClass *klass = NULL; if (info.assembly_name().name.empty()) { const Il2CppImage* image = Image::GetExecutingImage(); klass = Image::FromTypeNameParseInfo(image, info, ignoreCase); if (klass == NULL && image != Image::GetCorlib()) { // Try mscorlib image = (Il2CppImage*)Image::GetCorlib(); klass = Image::FromTypeNameParseInfo(image, info, ignoreCase); } } else { const Il2CppAssembly *assembly = Assembly::Load(info.assembly_name().name.c_str()); CHECK_IF_NULL(assembly); Il2CppImage *image = (Il2CppImage*)Assembly::GetImage(assembly); CHECK_IF_NULL(image); klass = Image::FromTypeNameParseInfo(image, info, ignoreCase); } return klass; } const Il2CppType* Class::il2cpp_type_from_type_info(const TypeNameParseInfo& info, bool throwOnError, bool ignoreCase) { Il2CppClass *klass = resolve_parse_info_internal(info, throwOnError, ignoreCase); CHECK_IF_NULL(klass); klass = ResolveGenericInstanceType(klass, info, throwOnError, ignoreCase); CHECK_IF_NULL(klass); const Il2CppType *type = Class::GetType(klass, info); CHECK_IF_NULL(type); return type; } Il2CppClass* Class::GetDeclaringType(Il2CppClass* klass) { return klass->declaringType; } NORETURN static void RaiseExceptionForNotFoundInterface(const Il2CppClass* klass, const Il2CppClass* itf, Il2CppMethodSlot slot) { std::string message; message = "Attempt to access method '" + Type::GetName(itf->byval_arg, IL2CPP_TYPE_NAME_FORMAT_IL) + "." + Method::GetName(itf->methods[slot]) + "' on type '" + Type::GetName(klass->byval_arg, IL2CPP_TYPE_NAME_FORMAT_IL) + "' failed."; Exception::Raise(il2cpp::vm::Exception::GetMethodAccessException(message.c_str())); } const VirtualInvokeData& Class::GetInterfaceInvokeDataFromVTableSlowPath(const Il2CppObject* obj, const Il2CppClass* itf, Il2CppMethodSlot slot) { const Il2CppClass* klass = obj->klass; #if NET_4_0 if (itf->generic_class != NULL) { const Il2CppTypeDefinition* genericInterface = MetadataCache::GetTypeDefinitionFromIndex(itf->generic_class->typeDefinitionIndex); const Il2CppGenericContainer* genericContainer = MetadataCache::GetGenericContainerFromIndex(genericInterface->genericContainerIndex); for (uint16_t i = 0; i < klass->interface_offsets_count; ++i) { const Il2CppRuntimeInterfaceOffsetPair* pair = klass->interfaceOffsets + i; if (IsGenericClassAssignableFrom(itf, pair->interfaceType, genericContainer)) { IL2CPP_ASSERT(pair->offset + slot < klass->vtable_count); return klass->vtable[pair->offset + slot]; } } } #endif if (klass->is_import_or_windows_runtime) { Il2CppIUnknown* iunknown = static_cast(obj)->identity; // It might be null if it's called on a dead (already released) or fake object if (iunknown != NULL) { if (itf->vtable_count > 0) { IL2CPP_ASSERT(slot < itf->vtable_count); // Nothing will be referencing these types directly, so we need to initialize them here const VirtualInvokeData& invokeData = itf->vtable[slot]; Init(invokeData.method->declaring_type); return invokeData; } // TO DO: add support for covariance/contravariance for projected interfaces like // System.Collections.Generic.IEnumerable`1 } } RaiseExceptionForNotFoundInterface(klass, itf, slot); IL2CPP_UNREACHABLE; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Class.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "blob.h" #include "class-internals.h" #include "metadata/Il2CppTypeVector.h" #include "utils/dynamic_array.h" #include "class-internals.h" #include "object-internals.h" #include "Exception.h" #include "Type.h" #if NET_4_0 #include "vm/MetadataCache.h" #include "tabledefs.h" #endif struct Il2CppClass; struct EventInfo; struct FieldInfo; struct PropertyInfo; struct MethodInfo; struct Il2CppImage; struct Il2CppReflectionType; struct Il2CppType; struct Il2CppDebugTypeInfo; struct Il2CppGenericContainer; struct Il2CppGenericContext; struct Il2CppGenericParameter; namespace il2cpp { namespace vm { class TypeNameParseInfo; class LIBIL2CPP_CODEGEN_API Class { public: static Il2CppClass* FromIl2CppType(const Il2CppType* type); static Il2CppClass* FromName(const Il2CppImage* image, const char* namespaze, const char *name); static Il2CppClass* FromSystemType(Il2CppReflectionType *type); static Il2CppClass* FromGenericParameter(const Il2CppGenericParameter *param); static Il2CppClass* GetElementClass(Il2CppClass *klass); static const Il2CppType* GetEnumBaseType(Il2CppClass *klass); static const EventInfo* GetEvents(Il2CppClass *klass, void* *iter); static FieldInfo* GetFields(Il2CppClass *klass, void* *iter); static FieldInfo* GetFieldFromName(Il2CppClass *klass, const char* name); static const MethodInfo* GetFinalizer(Il2CppClass *klass); static int32_t GetInstanceSize(const Il2CppClass *klass); static Il2CppClass* GetInterfaces(Il2CppClass *klass, void* *iter); static const MethodInfo* GetMethods(Il2CppClass *klass, void* *iter); static const MethodInfo* GetMethodFromName(Il2CppClass *klass, const char* name, int argsCount); static const MethodInfo* GetMethodFromNameFlags(Il2CppClass *klass, const char* name, int argsCount, int32_t flags); static const char* GetName(Il2CppClass *klass); static const char* GetNamespace(Il2CppClass *klass); static Il2CppClass* GetNestedTypes(Il2CppClass *klass, void* *iter); static size_t GetNumMethods(const Il2CppClass* klass); static size_t GetNumProperties(const Il2CppClass* klass); static size_t GetNumFields(const Il2CppClass* klass); static Il2CppClass* GetParent(Il2CppClass *klass); static const PropertyInfo* GetProperties(Il2CppClass *klass, void* *iter); static const PropertyInfo* GetPropertyFromName(Il2CppClass *klass, const char* name); static int32_t GetValueSize(Il2CppClass *klass, uint32_t *align); static bool HasParent(Il2CppClass *klass, Il2CppClass *parent); // we assume that the Il2CppClass's have already been initialized in this case, like in code generation static bool HasParentUnsafe(const Il2CppClass* klass, const Il2CppClass* parent) { return klass->typeHierarchyDepth >= parent->typeHierarchyDepth && klass->typeHierarchy[parent->typeHierarchyDepth - 1] == parent; } static bool IsAssignableFrom(Il2CppClass *klass, Il2CppClass *oklass); static bool IsGeneric(const Il2CppClass *klass); static bool IsInflated(const Il2CppClass *klass); static bool IsSubclassOf(Il2CppClass *klass, Il2CppClass *klassc, bool check_interfaces); static bool IsValuetype(const Il2CppClass *klass); static bool IsBlittable(const Il2CppClass *klass); static bool HasDefaultConstructor(Il2CppClass* klass); static int GetFlags(const Il2CppClass *klass); static bool IsAbstract(const Il2CppClass *klass); static bool IsInterface(const Il2CppClass *klass); static bool IsNullable(const Il2CppClass *klass); static Il2CppClass* GetNullableArgument(const Il2CppClass* klass); static int GetArrayElementSize(const Il2CppClass *klass); static const Il2CppType* GetType(Il2CppClass *klass); static const Il2CppType* GetType(Il2CppClass *klass, const TypeNameParseInfo &info); static bool HasAttribute(Il2CppClass *klass, Il2CppClass *attr_class); static bool IsEnum(const Il2CppClass *klass); static const Il2CppImage* GetImage(Il2CppClass* klass); static const Il2CppDebugTypeInfo *GetDebugInfo(const Il2CppClass *klass); static const char *GetAssemblyName(const Il2CppClass *klass); public: //internal static FORCE_INLINE const VirtualInvokeData& GetInterfaceInvokeDataFromVTable(const Il2CppObject* obj, const Il2CppClass* itf, Il2CppMethodSlot slot) { const Il2CppClass* klass = obj->klass; IL2CPP_ASSERT(klass->initialized); IL2CPP_ASSERT(slot < itf->method_count); for (uint16_t i = 0; i < klass->interface_offsets_count; i++) { if (klass->interfaceOffsets[i].interfaceType == itf) { int32_t offset = klass->interfaceOffsets[i].offset; IL2CPP_ASSERT(offset != -1); IL2CPP_ASSERT(offset + slot < klass->vtable_count); return klass->vtable[offset + slot]; } } return GetInterfaceInvokeDataFromVTableSlowPath(obj, itf, slot); } static bool Init(Il2CppClass *klass); static Il2CppClass* GetArrayClass(Il2CppClass *element_class, uint32_t rank); static Il2CppClass* GetBoundedArrayClass(Il2CppClass *element_class, uint32_t rank, bool bounded); static Il2CppClass* GetInflatedGenericInstanceClass(Il2CppClass* klass, const metadata::Il2CppTypeVector& types); static Il2CppClass* GetInflatedGenericInstanceClass(Il2CppClass* klass, const Il2CppGenericInst* genericInst); static Il2CppClass* InflateGenericClass(Il2CppClass* klass, Il2CppGenericContext *context); static const Il2CppType* InflateGenericType(const Il2CppType* type, Il2CppGenericContext *context); static Il2CppClass* GetArrayClassCached(Il2CppClass *element_class, uint32_t rank) { return GetArrayClass(element_class, rank); } static const Il2CppGenericContainer* GetGenericContainer(Il2CppClass *klass); static const MethodInfo* GetCCtor(Il2CppClass *klass); static const char* GetFieldDefaultValue(const FieldInfo *field, const Il2CppType** type); static int GetFieldMarshaledSize(const FieldInfo *field); static Il2CppClass* GetPtrClass(const Il2CppType* type); static Il2CppClass* GetPtrClass(Il2CppClass* elementClass); static bool HasReferences(Il2CppClass *klass); static void SetupEvents(Il2CppClass *klass); static void SetupFields(Il2CppClass *klass); static void SetupMethods(Il2CppClass *klass); static void SetupNestedTypes(Il2CppClass *klass); static void SetupProperties(Il2CppClass *klass); static void SetupTypeHierarchy(Il2CppClass *klass); static void SetupInterfaces(Il2CppClass *klass); static const il2cpp::utils::dynamic_array& GetStaticFieldData(); static size_t GetBitmapSize(const Il2CppClass* klass); static void GetBitmap(Il2CppClass* klass, size_t* bitmap, size_t& maxSetBit); static const Il2CppType* il2cpp_type_from_type_info(const TypeNameParseInfo& info, bool throwOnError, bool ignoreCase); static Il2CppClass* GetDeclaringType(Il2CppClass* klass); private: #if NET_4_0 static FORCE_INLINE bool IsGenericClassAssignableFrom(const Il2CppClass* klass, const Il2CppClass* oklass, const Il2CppGenericContainer* genericContainer) { const Il2CppGenericClass* genericClass = klass->generic_class; const Il2CppGenericClass* oGenericClass = oklass->generic_class; if (oGenericClass == NULL || oGenericClass->typeDefinitionIndex != genericClass->typeDefinitionIndex) return false; const int32_t genericParameterCount = genericContainer->type_argc; const Il2CppGenericInst* genericInst = genericClass->context.class_inst; IL2CPP_ASSERT(genericInst->type_argc == genericParameterCount); const Il2CppGenericInst* oGenericInst = oGenericClass->context.class_inst; IL2CPP_ASSERT(oGenericInst->type_argc == genericParameterCount); for (int32_t i = 0; i < genericParameterCount; ++i) { const Il2CppGenericParameter* genericParameter = MetadataCache::GetGenericParameterFromIndex(genericContainer->genericParameterStart + i); const int32_t parameterVariance = genericParameter->flags & GENERIC_PARAMETER_ATTRIBUTE_VARIANCE_MASK; Il2CppClass* genericParameterType = Class::FromIl2CppType(genericInst->type_argv[i]); Il2CppClass* oGenericParameterType = Class::FromIl2CppType(oGenericInst->type_argv[i]); if (parameterVariance == GENERIC_PARAMETER_ATTRIBUTE_NON_VARIANT || Class::IsValuetype(genericParameterType) || Class::IsValuetype(oGenericParameterType)) { if (genericParameterType != oGenericParameterType) return false; } else if (parameterVariance == GENERIC_PARAMETER_ATTRIBUTE_COVARIANT) { if (!Class::IsAssignableFrom(genericParameterType, oGenericParameterType)) return false; } else { IL2CPP_ASSERT(parameterVariance == GENERIC_PARAMETER_ATTRIBUTE_CONTRAVARIANT); if (!Class::IsAssignableFrom(oGenericParameterType, genericParameterType)) return false; } } return true; } #endif // we don't want this method to get inlined because that makes GetInterfaceInvokeDataFromVTable method itself very large and performance suffers static IL2CPP_NO_INLINE const VirtualInvokeData& GetInterfaceInvokeDataFromVTableSlowPath(const Il2CppObject* obj, const Il2CppClass* itf, Il2CppMethodSlot slot); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/ComObjectBase.cpp ================================================ #include "il2cpp-config.h" #include "metadata/GenericMetadata.h" #include "vm/Class.h" #include "vm/ComObjectBase.h" #include "vm/GenericClass.h" #include "vm/MetadataCache.h" using namespace il2cpp::vm; il2cpp_hresult_t STDCALL ComObjectBase::GetRuntimeClassName(Il2CppHString* className) { Il2CppClass* objectClass = GetManagedObjectInline()->klass; if (il2cpp_defaults.ireference_class != NULL && !Class::IsInflated(objectClass) && (Class::IsValuetype(objectClass) || objectClass == il2cpp_defaults.string_class)) { // For value types/strings we're supposed to return the name of its boxed representation, i.e. Windows.Foundation.IReference`1 const Il2CppGenericInst* inst = MetadataCache::GetGenericInst(&objectClass->byval_arg, 1); Il2CppGenericClass* genericClass = metadata::GenericMetadata::GetGenericClass(il2cpp_defaults.ireference_class, inst); objectClass = GenericClass::GetClass(genericClass); } const char* name = MetadataCache::GetWindowsRuntimeClassName(objectClass); if (name == NULL) { *className = NULL; return IL2CPP_S_OK; } UTF16String nameUtf16 = utils::StringUtils::Utf8ToUtf16(name); return os::WindowsRuntime::CreateHString(utils::StringView(nameUtf16.c_str(), nameUtf16.length()), className); } il2cpp_hresult_t STDCALL ComObjectBase::GetTrustLevel(int32_t* trustLevel) { *trustLevel = 0; return IL2CPP_S_OK; } Il2CppObject* STDCALL ComObjectBase::GetManagedObject() { return GetManagedObjectInline(); } il2cpp_hresult_t STDCALL ComObjectBase::GetUnmarshalClass(const Il2CppGuid& iid, void* object, uint32_t context, void* reserved, uint32_t flags, Il2CppGuid* clsid) { Il2CppIMarshal* freeThreadedMarshaler; il2cpp_hresult_t hr = GetFreeThreadedMarshalerNoAddRef(&freeThreadedMarshaler); if (IL2CPP_HR_FAILED(hr)) return hr; return freeThreadedMarshaler->GetUnmarshalClass(iid, object, context, reserved, flags, clsid); } il2cpp_hresult_t STDCALL ComObjectBase::GetMarshalSizeMax(const Il2CppGuid& iid, void* object, uint32_t context, void* reserved, uint32_t flags, uint32_t* size) { Il2CppIMarshal* freeThreadedMarshaler; il2cpp_hresult_t hr = GetFreeThreadedMarshalerNoAddRef(&freeThreadedMarshaler); if (IL2CPP_HR_FAILED(hr)) return hr; return freeThreadedMarshaler->GetMarshalSizeMax(iid, object, context, reserved, flags, size); } il2cpp_hresult_t STDCALL ComObjectBase::MarshalInterface(Il2CppIStream* stream, const Il2CppGuid& iid, void* object, uint32_t context, void* reserved, uint32_t flags) { Il2CppIMarshal* freeThreadedMarshaler; il2cpp_hresult_t hr = GetFreeThreadedMarshalerNoAddRef(&freeThreadedMarshaler); if (IL2CPP_HR_FAILED(hr)) return hr; return freeThreadedMarshaler->MarshalInterface(stream, iid, object, context, reserved, flags); } il2cpp_hresult_t STDCALL ComObjectBase::UnmarshalInterface(Il2CppIStream* stream, const Il2CppGuid& iid, void** object) { Il2CppIMarshal* freeThreadedMarshaler; il2cpp_hresult_t hr = GetFreeThreadedMarshalerNoAddRef(&freeThreadedMarshaler); if (IL2CPP_HR_FAILED(hr)) return hr; return freeThreadedMarshaler->UnmarshalInterface(stream, iid, object); } il2cpp_hresult_t STDCALL ComObjectBase::ReleaseMarshalData(Il2CppIStream* stream) { Il2CppIMarshal* freeThreadedMarshaler; il2cpp_hresult_t hr = GetFreeThreadedMarshalerNoAddRef(&freeThreadedMarshaler); if (IL2CPP_HR_FAILED(hr)) return hr; return freeThreadedMarshaler->ReleaseMarshalData(stream); } il2cpp_hresult_t STDCALL ComObjectBase::DisconnectObject(uint32_t reserved) { Il2CppIMarshal* freeThreadedMarshaler; il2cpp_hresult_t hr = GetFreeThreadedMarshalerNoAddRef(&freeThreadedMarshaler); if (IL2CPP_HR_FAILED(hr)) return hr; return freeThreadedMarshaler->DisconnectObject(reserved); } il2cpp_hresult_t ComObjectBase::GetFreeThreadedMarshalerNoAddRef(Il2CppIMarshal** destination) { Il2CppIMarshal* freeThreadedMarshaler = m_FreeThreadedMarshaler; if (freeThreadedMarshaler == NULL) { // We don't really want to aggregate FTM, as then we'd have to store its IUnknown too // So we pass NULL as the first parameter Il2CppIUnknown* freeThreadedMarshalerUnknown; il2cpp_hresult_t hr = COM::CreateFreeThreadedMarshaler(NULL, &freeThreadedMarshalerUnknown); if (IL2CPP_HR_FAILED(hr)) return hr; hr = freeThreadedMarshalerUnknown->QueryInterface(Il2CppIMarshal::IID, reinterpret_cast(&freeThreadedMarshaler)); freeThreadedMarshalerUnknown->Release(); if (IL2CPP_HR_FAILED(hr)) return hr; if (Atomic::CompareExchangePointer(&m_FreeThreadedMarshaler, freeThreadedMarshaler, NULL) != NULL) { freeThreadedMarshaler->Release(); freeThreadedMarshaler = m_FreeThreadedMarshaler; } } *destination = freeThreadedMarshaler; return IL2CPP_S_OK; } ================================================ FILE: unity_decoder/libil2cpp/vm/ComObjectBase.h ================================================ #pragma once #include "gc/GCHandle.h" #include "il2cpp-string-types.h" #include "os/WindowsRuntime.h" #include "vm/Atomic.h" #include "vm/COM.h" #include "vm/Exception.h" #include "vm/MarshalAlloc.h" #include "vm/WindowsRuntime.h" #include "utils/Memory.h" #include "utils/StringUtils.h" struct Il2CppObject; struct Il2CppIUnknown; namespace il2cpp { namespace vm { struct LIBIL2CPP_CODEGEN_API NOVTABLE ComObjectBase : Il2CppIInspectable, Il2CppIMarshal, Il2CppIManagedObjectHolder { private: Il2CppIMarshal* m_FreeThreadedMarshaler; Il2CppObject* m_ManagedObject; public: inline ComObjectBase(Il2CppObject* obj) : m_ManagedObject(obj), m_FreeThreadedMarshaler(NULL) { IL2CPP_ASSERT(obj != NULL); } inline ~ComObjectBase() { if (m_FreeThreadedMarshaler) m_FreeThreadedMarshaler->Release(); } virtual il2cpp_hresult_t STDCALL GetRuntimeClassName(Il2CppHString* className) IL2CPP_OVERRIDE; virtual il2cpp_hresult_t STDCALL GetTrustLevel(int32_t* trustLevel) IL2CPP_OVERRIDE; virtual Il2CppObject* STDCALL GetManagedObject() IL2CPP_OVERRIDE; virtual il2cpp_hresult_t STDCALL GetUnmarshalClass(const Il2CppGuid& iid, void* object, uint32_t context, void* reserved, uint32_t flags, Il2CppGuid* clsid) IL2CPP_OVERRIDE; virtual il2cpp_hresult_t STDCALL GetMarshalSizeMax(const Il2CppGuid& iid, void* object, uint32_t context, void* reserved, uint32_t flags, uint32_t* size) IL2CPP_OVERRIDE; virtual il2cpp_hresult_t STDCALL MarshalInterface(Il2CppIStream* stream, const Il2CppGuid& iid, void* object, uint32_t context, void* reserved, uint32_t flags) IL2CPP_OVERRIDE; virtual il2cpp_hresult_t STDCALL UnmarshalInterface(Il2CppIStream* stream, const Il2CppGuid& iid, void** object) IL2CPP_OVERRIDE; virtual il2cpp_hresult_t STDCALL ReleaseMarshalData(Il2CppIStream* stream) IL2CPP_OVERRIDE; virtual il2cpp_hresult_t STDCALL DisconnectObject(uint32_t reserved) IL2CPP_OVERRIDE; FORCE_INLINE Il2CppObject* GetManagedObjectInline() const { return m_ManagedObject; } protected: FORCE_INLINE Il2CppIInspectable* GetIdentity() { return this; } private: ComObjectBase(const ComObjectBase&); ComObjectBase& operator=(const ComObjectBase&); il2cpp_hresult_t GetFreeThreadedMarshalerNoAddRef(Il2CppIMarshal** destination); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Debug.cpp ================================================ #include "il2cpp-config.h" #if IL2CPP_DEBUGGER_ENABLED #include #include "../class-internals.h" #include "vm/Object.h" #include "vm/Debug.h" #include "vm/StackTrace.h" #include "vm/Type.h" namespace il2cpp { namespace vm { const Il2CppDebugDocument *Debug::GetDocument(const Il2CppDebugTypeInfo *info) { return info->document; } const char *Debug::DocumentGetFilename(const Il2CppDebugDocument *document) { return document->filename; } const char *Debug::DocumentGetDirectory(const Il2CppDebugDocument *document) { return document->directory; } const Il2CppDebugDocument* Debug::GetDocument(const Il2CppDebugMethodInfo* info) { return info->document; } const int32_t* Debug::GetOffsetTable(const Il2CppDebugMethodInfo* info) { return info->offsets_table; } size_t Debug::GetCodeSize(const Il2CppDebugMethodInfo* info) { return info->code_size; } void Debug::UpdateFrameIlOffset(int32_t il_offset) { IL2CPP_ASSERT(0 && "Not implemented"); } const Il2CppDebugLocalsInfo **Debug::GetLocalsInfo(const Il2CppDebugMethodInfo* info) { return info->locals; } const Il2CppClass *Debug::GetType(const Il2CppDebugLocalsInfo *info) { return info->type; } const char *Debug::GetName(const Il2CppDebugLocalsInfo *info) { return info->name; } uint32_t Debug::GetStartOffset(const Il2CppDebugLocalsInfo *info) { return info->start_offset; } uint32_t Debug::GetEndOffset(const Il2CppDebugLocalsInfo *info) { return info->end_offset; } Il2CppObject *Debug::GetParamValue(const Il2CppStackFrameInfo *info, uint32_t position) { IL2CPP_ASSERT(info != 0 && "Debug::GetParamValue cannot be invoked on a null Il2CppDebugMethodInfo."); IL2CPP_ASSERT(position < info->method->parameters_count && "Debug::GetParamValue was invoked with an outside of range position"); Il2CppClass *param_type = Type::GetClass(info->method->parameters[position].parameter_type); void *param_addr = info->params[position]; if (param_type->valuetype) return Object::Box(param_type, param_addr); return static_cast(param_addr); } Il2CppObject *Debug::GetLocalValue(const Il2CppStackFrameInfo *info, uint32_t position) { IL2CPP_ASSERT(info != 0 && "Debug::GetLocalValue cannot be invoked on a null Il2CppDebugMethodInfo."); IL2CPP_ASSERT(position < info->locals_count && "Debug::GetLocalValue was invoked with an outside of range position"); Il2CppClass *local_type = info->method->debug_info->locals[position]->type; void *local_addr = info->locals[position]; if (local_type->valuetype) return Object::Box(local_type, local_addr); return static_cast(local_addr); } void *Debug::GetBreakpointDataAt(const Il2CppDebugMethodInfo* info, int64_t uid, int32_t offset) { IL2CPP_ASSERT(info != 0 && "Debug::GetBreakpointDataAt cannot be invoked on a null Il2CppDebugMethodInfo."); IL2CPP_ASSERT(offset < info->code_size && "Debug::GetBreakpointDataAt invoked with an invalid offset."); if (uid < 0) return NULL; SequencePointRecord *record = &info->sequence_points[uid]; IL2CPP_ASSERT(record->start_offset <= offset && record->end_offset >= offset && "Debug::GetBreakpointDataAt invoked with an invalid offset (or sequnce point not matching)."); return record->user_data; } void Debug::SetBreakpointDataAt(const Il2CppDebugMethodInfo* info, uint64_t location, void *data) { IL2CPP_ASSERT(info != 0 && "Debug::SetBreakpointDataAt be invoked on a null Il2CppDebugMethodInfo."); IL2CPP_ASSERT(location < info->code_size && "Debug::SetBreakpointDataAt invoked with an invalid location."); SequencePointRecord *found = NULL; for (int32_t i = 0; i < info->sequence_points_count; ++i) { SequencePointRecord *record = &info->sequence_points[i]; if (location < record->start_offset) continue; if (record->end_offset < location) continue; found = record; break; } IL2CPP_ASSERT(found && "Debug::SetBreakpointDataAt invoked with an invalid location."); found->user_data = data; } void Debug::ClearBreakpointData(const Il2CppDebugMethodInfo* info) { IL2CPP_ASSERT(info != 0 && "Debug::ClearBreakpointData be invoked on a null Il2CppDebugMethodInfo."); for (int32_t i = 0; i < info->sequence_points_count; ++i) { SequencePointRecord *record = &info->sequence_points[i]; record->user_data = NULL; } } void Debug::ClearBreakpointDataAt(const Il2CppDebugMethodInfo* info, uint64_t location) { IL2CPP_ASSERT(info != 0 && "Debug::ClearBreakpointDataAt be invoked on a null Il2CppDebugMethodInfo."); SequencePointRecord *found = NULL; for (int32_t i = 0; i < info->sequence_points_count; ++i) { SequencePointRecord *record = &info->sequence_points[i]; if (location < record->start_offset) continue; if (record->end_offset < location) continue; found = record; break; } IL2CPP_ASSERT(found && "Debug::ClearBreakpointDataAt invoked with an invalid location."); found->user_data = NULL; } } /* namespace vm */ } /* namespace il2cpp */ #endif ================================================ FILE: unity_decoder/libil2cpp/vm/Debug.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppThread; struct Il2CppDebugDocument; struct Il2CppDebugTypeInfo; struct Il2CppDebugMethodInfo; struct Il2CppDebugLocalsInfo; struct Il2CppStackFrameInfo; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API Debug { public: static const Il2CppDebugDocument* GetDocument(const Il2CppDebugTypeInfo* type); static const char *DocumentGetFilename(const Il2CppDebugDocument *document); static const char *DocumentGetDirectory(const Il2CppDebugDocument *document); static const Il2CppDebugDocument* GetDocument(const Il2CppDebugMethodInfo* info); static const int32_t* GetOffsetTable(const Il2CppDebugMethodInfo* info); static size_t GetCodeSize(const Il2CppDebugMethodInfo* info); static void UpdateFrameIlOffset(int32_t il_offset); static const Il2CppDebugLocalsInfo **GetLocalsInfo(const Il2CppDebugMethodInfo* info); static const Il2CppClass *GetType(const Il2CppDebugLocalsInfo *info); static const char *GetName(const Il2CppDebugLocalsInfo *info); static uint32_t GetStartOffset(const Il2CppDebugLocalsInfo *info); static uint32_t GetEndOffset(const Il2CppDebugLocalsInfo *info); static Il2CppObject *GetParamValue(const Il2CppStackFrameInfo *info, uint32_t position); static Il2CppObject *GetLocalValue(const Il2CppStackFrameInfo *info, uint32_t position); static void *GetBreakpointDataAt(const Il2CppDebugMethodInfo* info, int64_t uid, int32_t offset); static void SetBreakpointDataAt(const Il2CppDebugMethodInfo* info, uint64_t location, void *data); static void ClearBreakpointData(const Il2CppDebugMethodInfo* info); static void ClearBreakpointDataAt(const Il2CppDebugMethodInfo* info, uint64_t location); public: //internal private: }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Domain.cpp ================================================ #include "il2cpp-config.h" #include "vm/Class.h" #include "vm/Domain.h" #include "vm/Object.h" #include "vm/Runtime.h" #include "vm/Thread.h" #include "gc/GarbageCollector.h" #include "class-internals.h" #include "object-internals.h" namespace il2cpp { namespace vm { Il2CppDomain* Domain::S_domain = NULL; Il2CppDomain* Domain::GetCurrent() { if (S_domain) return S_domain; // allocate using gc memory since we hold onto object references S_domain = (Il2CppDomain*)il2cpp::gc::GarbageCollector::AllocateFixed(sizeof(Il2CppDomain), NULL); return S_domain; } Il2CppDomain* Domain::GetRoot() { // just one domain for now return GetCurrent(); } void Domain::ContextInit(Il2CppDomain *domain) { Il2CppClass* klass = Class::FromName(il2cpp_defaults.corlib, "System.Runtime.Remoting.Contexts", "Context"); Il2CppAppContext* context = (Il2CppAppContext*)Object::New(klass); // To match Mono's implementation we do not call the constructor here. If we do, context_id will be 1, which // is not correct. context->domain_id = domain->domain_id; context->context_id = 0; domain->default_context = context; } void Domain::ContextSet(Il2CppAppContext* context) { IL2CPP_OBJECT_SETREF(il2cpp::vm::Thread::Current()->GetInternalThread(), current_appcontext, (Il2CppObject*)context); } Il2CppAppContext* Domain::ContextGet() { return (Il2CppAppContext*)il2cpp::vm::Thread::Current()->GetInternalThread()->current_appcontext; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Domain.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppDomain; struct Il2CppAppContext; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API Domain { public: static Il2CppDomain* GetCurrent(); static Il2CppDomain* GetRoot(); static void ContextInit(Il2CppDomain *domain); static void ContextSet(Il2CppAppContext* context); static Il2CppAppContext* ContextGet(); private: static Il2CppDomain* S_domain; }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Enum.cpp ================================================ #include "vm/Enum.h" #include "object-internals.h" #include "class-internals.h" #include "vm/Array.h" #include "vm/Class.h" #include "vm/Reflection.h" #include "vm/GenericClass.h" #include "vm/Field.h" #include "vm/String.h" #include "vm/Type.h" #include "utils/MemoryRead.h" namespace il2cpp { namespace vm { #if NET_4_0 static uint64_t GetEnumFieldValue(Il2CppClass* enumType, FieldInfo* field) { const Il2CppType* type = NULL; const char* ptr = Class::GetFieldDefaultValue(field, &type); switch (Class::GetEnumBaseType(enumType)->type) { case IL2CPP_TYPE_I1: // Sign extend return static_cast(static_cast(*ptr)); case IL2CPP_TYPE_U1: return (uint8_t)*ptr; case IL2CPP_TYPE_CHAR: return utils::ReadChar(ptr); case IL2CPP_TYPE_I2: // Sign extend return static_cast(static_cast(utils::Read16(ptr))); case IL2CPP_TYPE_U2: return utils::Read16(ptr); case IL2CPP_TYPE_I4: // Sign extend return static_cast(static_cast(utils::Read32(ptr))); case IL2CPP_TYPE_U4: return utils::Read32(ptr); case IL2CPP_TYPE_U8: case IL2CPP_TYPE_I8: return utils::Read64(ptr); default: IL2CPP_ASSERT(0); return 0; } } #endif bool Enum::GetEnumValuesAndNames(Il2CppClass* enumType, Il2CppArray** values, Il2CppArray** names) { size_t nvalues = Class::GetNumFields(enumType) ? Class::GetNumFields(enumType) - 1 : 0; bool sorted = true; #if !NET_4_0 *values = vm::Array::New(enumType, (il2cpp_array_size_t)nvalues); #else *values = vm::Array::New(il2cpp_defaults.uint64_class, (il2cpp_array_size_t)nvalues); uint64_t field_value, previous_value = 0; #endif *names = vm::Array::New(il2cpp_defaults.string_class, (il2cpp_array_size_t)nvalues); // TODO: write barriers! if (enumType->generic_class) enumType = GenericClass::GetTypeDefinition(enumType->generic_class); FieldInfo* field; void* iter = NULL; int j = 0; while ((field = Class::GetFields(enumType, &iter))) { if (strcmp("value__", field->name) == 0) continue; if (Field::IsDeleted(field)) continue; il2cpp_array_setref(*names, j, il2cpp::vm::String::New(Field::GetName(field))); #if !NET_4_0 const Il2CppType* type = NULL; const char *p = Class::GetFieldDefaultValue(field, &type); switch (Class::GetEnumBaseType(enumType)->type) { case IL2CPP_TYPE_U1: case IL2CPP_TYPE_I1: il2cpp_array_set(*values, uint8_t, j, *p); break; case IL2CPP_TYPE_CHAR: il2cpp_array_set(*values, Il2CppChar, j, utils::ReadChar(p)); break; case IL2CPP_TYPE_U2: case IL2CPP_TYPE_I2: il2cpp_array_set(*values, uint16_t, j, utils::Read16(p)); break; case IL2CPP_TYPE_U4: case IL2CPP_TYPE_I4: il2cpp_array_set(*values, uint32_t, j, utils::Read32(p)); break; case IL2CPP_TYPE_U8: case IL2CPP_TYPE_I8: il2cpp_array_set(*values, uint64_t, j, utils::Read64(p)); break; default: IL2CPP_ASSERT(0); } #else field_value = GetEnumFieldValue(enumType, field); il2cpp_array_set(*values, uint64_t, j, field_value); if (previous_value > field_value) sorted = false; previous_value = field_value; #endif j++; } return sorted; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Enum.h ================================================ #pragma once #include #include "il2cpp-config.h" namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API Enum { public: // exported static bool GetEnumValuesAndNames(Il2CppClass* enumType, Il2CppArray** values, Il2CppArray** names); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Event.cpp ================================================ #include "vm/Event.h" #include "class-internals.h" namespace il2cpp { namespace vm { uint32_t Event::GetToken(const EventInfo *eventInfo) { return eventInfo->token; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Event.h ================================================ #pragma once #include #include "il2cpp-config.h" struct EventInfo; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API Event { public: // exported static uint32_t GetToken(const EventInfo *eventInfo); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Exception.cpp ================================================ #include "il2cpp-config.h" #include "os/MarshalStringAlloc.h" #include "os/WindowsRuntime.h" #include "vm/Array.h" #include "vm/Class.h" #include "vm/Exception.h" #include "vm/Object.h" #include "vm/Runtime.h" #include "vm/StackTrace.h" #include "vm/String.h" #include "Image.h" #include "../utils/StringUtils.h" #include "tabledefs.h" #include "class-internals.h" #include "object-internals.h" namespace il2cpp { namespace vm { NORETURN void Exception::Raise(Il2CppException* ex) { if (ex->trace_ips == NULL) { // Only write the stack trace if there is not one already in the exception. // When we exit managed try/finally and try/catch blocks with an exception, this method is // called with the original exception which already has the proper stack trace. // Getting the stack trace again here will lose the frames between the original throw // and the finally or catch block. const StackFrames& frames = *StackTrace::GetStackFrames(); size_t i = frames.size() - 1; Il2CppArray* ips = Array::New(il2cpp_defaults.int_class, (il2cpp_array_size_t)frames.size()); for (StackFrames::const_iterator iter = frames.begin(); iter != frames.end(); ++iter, --i) { il2cpp_array_set(ips, const MethodInfo*, i, (*iter).method); } IL2CPP_OBJECT_SETREF(ex, trace_ips, ips); } throw Il2CppExceptionWrapper(ex); } NORETURN void Exception::RaiseOutOfMemoryException() { RaiseOutOfMemoryException(utils::StringView::Empty()); } NORETURN void Exception::RaiseOutOfMemoryException(const utils::StringView& msg) { Raise(GetOutOfMemoryException(msg)); } NORETURN void Exception::RaiseNullReferenceException() { RaiseNullReferenceException(utils::StringView::Empty()); } NORETURN void Exception::RaiseNullReferenceException(const utils::StringView& msg) { Raise(GetNullReferenceException(msg)); } NORETURN void Exception::RaiseDivideByZeroException() { Raise(GetDivideByZeroException()); } NORETURN void Exception::RaiseOverflowException() { Raise(GetOverflowException()); } NORETURN void Exception::RaiseArgumentOutOfRangeException(const char* msg) { Raise(GetArgumentOutOfRangeException(msg)); } inline static Il2CppException* TryGetExceptionFromRestrictedErrorInfo(Il2CppIRestrictedErrorInfo* errorInfo) { Il2CppILanguageExceptionErrorInfo* languageExceptionInfo; il2cpp_hresult_t hr = errorInfo->QueryInterface(Il2CppILanguageExceptionErrorInfo::IID, reinterpret_cast(&languageExceptionInfo)); if (IL2CPP_HR_SUCCEEDED(hr)) { Il2CppIUnknown* languageException; hr = languageExceptionInfo->GetLanguageException(&languageException); languageExceptionInfo->Release(); if (IL2CPP_HR_SUCCEEDED(hr) && languageException != NULL) // It can succeed and return null exception if there's no exception info { Il2CppIManagedObjectHolder* managedObjectHolder; hr = languageException->QueryInterface(Il2CppIManagedObjectHolder::IID, reinterpret_cast(&managedObjectHolder)); languageException->Release(); if (IL2CPP_HR_SUCCEEDED(hr)) { Il2CppException* exception = reinterpret_cast(managedObjectHolder->GetManagedObject()); managedObjectHolder->Release(); // TODO: set restricted error info instead of releaseing it here errorInfo->Release(); return exception; } } } return NULL; } inline static UTF16String GetMessageFromRestrictedErrorInfo(Il2CppIRestrictedErrorInfo* errorInfo) { UTF16String result; il2cpp_hresult_t error; Il2CppChar* bstrDescription; Il2CppChar* bstrRestrictedDescription; Il2CppChar* bstrCapabilitySid; il2cpp_hresult_t hr = errorInfo->GetErrorDetails(&bstrDescription, &error, &bstrRestrictedDescription, &bstrCapabilitySid); if (IL2CPP_HR_SUCCEEDED(hr)) { int descriptionLength = 0; int restrictedDescriptionLength = 0; if (bstrDescription != NULL) os::MarshalStringAlloc::GetBStringLength(bstrDescription, &descriptionLength); if (bstrRestrictedDescription != NULL) os::MarshalStringAlloc::GetBStringLength(bstrRestrictedDescription, &restrictedDescriptionLength); result.append(bstrDescription, descriptionLength); if (restrictedDescriptionLength > 0) { result.append(kIl2CppNewLine); result.append(bstrRestrictedDescription, restrictedDescriptionLength); } if (bstrDescription != NULL) os::MarshalStringAlloc::FreeBString(bstrDescription); if (bstrRestrictedDescription != NULL) os::MarshalStringAlloc::FreeBString(bstrRestrictedDescription); if (bstrCapabilitySid != NULL) os::MarshalStringAlloc::FreeBString(bstrCapabilitySid); } return result; } // When doing COM interop, any unrecognized hresult gets turned into a COMException // When doing Windows Runtime interop, any unrecognized hresult gets turned into a System.Exception // Go figure. Il2CppException* Exception::Get(il2cpp_hresult_t hresult, bool defaultToCOMException) { UTF16String message; Il2CppIRestrictedErrorInfo* errorInfo = os::WindowsRuntime::GetRestrictedErrorInfo(); if (errorInfo != NULL) { // First, try retrieving the original exception from restricted error info Il2CppException* exception = TryGetExceptionFromRestrictedErrorInfo(errorInfo); if (exception != NULL) return exception; // If we got here, restricted error info contained no existing managed exception message = GetMessageFromRestrictedErrorInfo(errorInfo); // To do: instead of releasing it here, store it on the exception that we're about to return errorInfo->Release(); } switch (hresult) { case IL2CPP_E_NOTIMPL: return FromNameMsg(Image::GetCorlib(), "System", "NotImplementedException", message); case IL2CPP_E_NOINTERFACE: return GetInvalidCastException(message); case IL2CPP_E_POINTER: return GetNullReferenceException(message); case IL2CPP_COR_E_OPERATIONCANCELED: return FromNameMsg(Image::GetCorlib(), "System", "OperationCanceledException", message); case IL2CPP_E_ACCESS_DENIED: return GetUnauthorizedAccessException(message); case IL2CPP_E_OUTOFMEMORY: return GetOutOfMemoryException(message); case IL2CPP_E_INVALIDARG: return GetArgumentException(utils::StringView::Empty(), message); case IL2CPP_COR_E_OBJECTDISPOSED: case IL2CPP_RO_E_CLOSED: return FromNameMsg(Image::GetCorlib(), "System", "ObjectDisposedException", message, hresult); case IL2CPP_E_FAIL: { if (message.empty()) message = utils::StringUtils::Utf8ToUtf16("Unspecified error"); return FromNameMsg(Image::GetCorlib(), "System.Runtime.InteropServices", "COMException", message, hresult); } case IL2CPP_COR_E_PLATFORMNOTSUPPORTED: { if (message.empty()) message = utils::StringUtils::Utf8ToUtf16("Operation is not supported on this platform."); return GetPlatformNotSupportedException(message); } default: return defaultToCOMException ? Exception::FromNameMsg(vm::Image::GetCorlib(), "System.Runtime.InteropServices", "COMException", message, hresult) : Exception::FromNameMsg(vm::Image::GetCorlib(), "System", "Exception", message, hresult); } } NORETURN void Exception::Raise(il2cpp_hresult_t hresult, bool defaultToCOMException) { Raise(Get(hresult, defaultToCOMException)); } Il2CppException* Exception::FromNameMsg(const Il2CppImage* image, const char *name_space, const char *name, const char *msg) { UTF16String utf16Msg; if (msg != NULL) utf16Msg = utils::StringUtils::Utf8ToUtf16(msg); return FromNameMsg(image, name_space, name, utf16Msg); } Il2CppException* Exception::FromNameMsg(const Il2CppImage* image, const char* name_space, const char* name, const utils::StringView& msg) { Il2CppClass* exceptionClass = Class::FromName(image, name_space, name); Il2CppException* ex = (Il2CppException*)Object::New(exceptionClass); Runtime::ObjectInit((Il2CppObject*)ex); if (msg.Length() > 0) IL2CPP_OBJECT_SETREF(ex, message, String::NewUtf16(msg)); return ex; } Il2CppException* Exception::FromNameMsg(const Il2CppImage* image, const char *name_space, const char* name, const utils::StringView& msg, il2cpp_hresult_t hresult) { Il2CppException* ex = FromNameMsg(image, name_space, name, msg); ex->hresult = hresult; return ex; } Il2CppException * Exception::GetArgumentException(const char *arg, const char *msg) { Il2CppException* ex = FromNameMsg(Image::GetCorlib(), "System", "ArgumentException", msg); if (arg) { Il2CppArgumentException *argex = (Il2CppArgumentException*)ex; IL2CPP_OBJECT_SETREF(argex, argName, String::New(arg)); } return ex; } Il2CppException* Exception::GetArgumentException(const utils::StringView& arg, const utils::StringView& msg) { Il2CppException* ex = FromNameMsg(Image::GetCorlib(), "System", "ArgumentException", msg); if (arg.Length() > 0) { Il2CppArgumentException *argex = (Il2CppArgumentException*)ex; IL2CPP_OBJECT_SETREF(argex, argName, String::NewUtf16(arg)); } return ex; } Il2CppException * Exception::GetArgumentNullException(const char *arg) { Il2CppException* ex = FromNameMsg(Image::GetCorlib(), "System", "ArgumentNullException", NULL); if (arg) { Il2CppArgumentException *argex = (Il2CppArgumentException*)ex; IL2CPP_OBJECT_SETREF(argex, argName, String::New(arg)); } return ex; } Il2CppException * Exception::GetArgumentOutOfRangeException(const char *arg) { Il2CppException* ex = FromNameMsg(Image::GetCorlib(), "System", "ArgumentOutOfRangeException", NULL); if (arg) { Il2CppArgumentException *argex = (Il2CppArgumentException*)ex; IL2CPP_OBJECT_SETREF(argex, argName, String::New(arg)); } return ex; } Il2CppException * Exception::GetTypeInitializationException(const char *msg, Il2CppException* innerException) { Il2CppException* ex = FromNameMsg(Image::GetCorlib(), "System", "TypeInitializationException", msg); if (innerException != NULL) IL2CPP_OBJECT_SETREF(ex, inner_ex, innerException); return ex; } Il2CppException* Exception::GetInvalidCastException(const char* msg) { return FromNameMsg(Image::GetCorlib(), "System", "InvalidCastException", msg); } Il2CppException* Exception::GetInvalidCastException(const utils::StringView& msg) { return FromNameMsg(Image::GetCorlib(), "System", "InvalidCastException", msg); } Il2CppException* Exception::GetIndexOutOfRangeException() { return GetIndexOutOfRangeException(utils::StringView::Empty()); } Il2CppException* Exception::GetIndexOutOfRangeException(const utils::StringView& msg) { return FromNameMsg(Image::GetCorlib(), "System", "IndexOutOfRangeException", msg); } Il2CppException* Exception::GetNullReferenceException(const utils::StringView& msg) { return FromNameMsg(vm::Image::GetCorlib(), "System", "NullReferenceException", msg); } Il2CppException* Exception::GetTypeLoadException() { return FromNameMsg(vm::Image::GetCorlib(), "System", "TypeLoadException", NULL); } Il2CppException* Exception::GetOutOfMemoryException(const utils::StringView& msg) { return FromNameMsg(vm::Image::GetCorlib(), "System", "OutOfMemoryException", msg); } Il2CppException* Exception::GetOverflowException() { return FromNameMsg(vm::Image::GetCorlib(), "System", "OverflowException", NULL); } Il2CppException* Exception::GetOverflowException(const char* msg) { return FromNameMsg(vm::Image::GetCorlib(), "System", "OverflowException", msg); } Il2CppException* Exception::GetFormatException(const char* msg) { return FromNameMsg(vm::Image::GetCorlib(), "System", "FormatException", msg); } Il2CppException* Exception::GetSystemException() { return FromNameMsg(vm::Image::GetCorlib(), "System", "SystemException", NULL); } Il2CppException* Exception::GetNotSupportedException(const char* msg) { return FromNameMsg(vm::Image::GetCorlib(), "System", "NotSupportedException", msg); } Il2CppException* Exception::GetArrayTypeMismatchException() { return FromNameMsg(vm::Image::GetCorlib(), "System", "ArrayTypeMismatchException", NULL); } Il2CppException* Exception::GetTypeLoadException(const char* msg) { return FromNameMsg(vm::Image::GetCorlib(), "System", "TypeLoadException", msg); } Il2CppException* Exception::GetEntryPointNotFoundException(const char* msg) { return FromNameMsg(vm::Image::GetCorlib(), "System", "EntryPointNotFoundException", msg); } Il2CppException* Exception::GetDllNotFoundException(const char* msg) { return FromNameMsg(vm::Image::GetCorlib(), "System", "DllNotFoundException", msg); } Il2CppException * Exception::GetInvalidOperationException(const char* msg) { return FromNameMsg(Image::GetCorlib(), "System", "InvalidOperationException", msg); } Il2CppException* Exception::GetThreadInterruptedException() { return FromNameMsg(vm::Image::GetCorlib(), "System.Threading", "ThreadInterruptedException", NULL); } Il2CppException* Exception::GetThreadAbortException() { return FromNameMsg(vm::Image::GetCorlib(), "System.Threading", "ThreadAbortException", NULL); } Il2CppException* Exception::GetThreadStateException(const char* msg) { return FromNameMsg(vm::Image::GetCorlib(), "System.Threading", "ThreadStateException", msg); } Il2CppException* Exception::GetSynchronizationLockException(const char* msg) { return FromNameMsg(vm::Image::GetCorlib(), "System.Threading", "SynchronizationLockException", msg); } Il2CppException * Exception::GetMissingMethodException(const char* msg) { return FromNameMsg(Image::GetCorlib(), "System", "MissingMethodException", msg); } Il2CppException * Exception::GetMarshalDirectiveException(const char* msg) { return FromNameMsg(Image::GetCorlib(), "System.Runtime.InteropServices", "MarshalDirectiveException", msg); } Il2CppException * Exception::GetTargetException(const char* msg) { return FromNameMsg(Image::GetCorlib(), "System.Reflection", "TargetException", msg); } Il2CppException * Exception::GetExecutionEngineException(const char* msg) { return FromNameMsg(Image::GetCorlib(), "System", "ExecutionEngineException", msg); } Il2CppException* Exception::GetMethodAccessException(const char* msg) { return FromNameMsg(Image::GetCorlib(), "System", "MethodAccessException", msg); } Il2CppException* Exception::GetUnauthorizedAccessException(const utils::StringView& msg) { return FromNameMsg(Image::GetCorlib(), "System", "UnauthorizedAccessException", msg); } Il2CppException * Exception::GetMaxmimumNestedGenericsException() { return GetNotSupportedException(MAXIMUM_NESTED_GENERICS_EXCEPTION_MESSAGE); } Il2CppException* Exception::GetDivideByZeroException() { return FromNameMsg(vm::Image::GetCorlib(), "System", "DivideByZeroException", NULL); } Il2CppException* Exception::GetPlatformNotSupportedException(const utils::StringView& msg) { return FromNameMsg(Image::GetCorlib(), "System", "PlatformNotSupportedException", msg); } Il2CppException* Exception::GetFileLoadException(const char* msg) { return FromNameMsg(Image::GetCorlib(), "System.IO", "FileLoadException", msg); } void Exception::StoreExceptionInfo(Il2CppException* ex, Il2CppString* exceptionString) { // To do: try retrieving IRestrictedErrorInfo here os::WindowsRuntime::OriginateLanguageException(ex, exceptionString); } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Exception.h ================================================ #pragma once #include #include #include "il2cpp-config.h" #include "utils/StringView.h" struct Il2CppException; struct Il2CppImage; struct Il2CppClass; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API Exception { // exported public: static Il2CppException* Get(il2cpp_hresult_t hresult, bool defaultToCOMException); static NORETURN void Raise(Il2CppException* ex); static NORETURN void RaiseOutOfMemoryException(); static NORETURN void RaiseOutOfMemoryException(const utils::StringView& msg); static NORETURN void RaiseNullReferenceException(); static NORETURN void RaiseNullReferenceException(const utils::StringView& msg); static NORETURN void RaiseDivideByZeroException(); static NORETURN void RaiseOverflowException(); static NORETURN void RaiseArgumentOutOfRangeException(const char* msg); static NORETURN void Raise(il2cpp_hresult_t hresult, bool defaultToCOMException); inline static void RaiseIfFailed(il2cpp_hresult_t hresult, bool defaultToCOMException) { if (IL2CPP_HR_FAILED(hresult)) Raise(hresult, defaultToCOMException); } ////TODO: rename to NewFromClassNameAndMessage static Il2CppException* FromNameMsg(const Il2CppImage* image, const char* name_space, const char* name, const char* msg); static Il2CppException* FromNameMsg(const Il2CppImage* image, const char* name_space, const char* name, const utils::StringView& msg); static Il2CppException* FromNameMsg(const Il2CppImage* image, const char* name_space, const char* name, const utils::StringView& msg, il2cpp_hresult_t hresult); public: ////TODO: rename all of these to NewXXX static Il2CppException* GetArgumentException(const char *arg, const char *msg); static Il2CppException* GetArgumentException(const utils::StringView& arg, const utils::StringView& msg); static Il2CppException* GetArgumentNullException(const char *arg); static Il2CppException* GetArgumentOutOfRangeException(const char *arg); static Il2CppException* GetTypeInitializationException(const char *msg, Il2CppException* innerException); static Il2CppException* GetIndexOutOfRangeException(); static Il2CppException* GetIndexOutOfRangeException(const utils::StringView& msg); static Il2CppException* GetNullReferenceException(const utils::StringView& msg); static Il2CppException* GetInvalidCastException(const char* msg); static Il2CppException* GetInvalidCastException(const utils::StringView& msg); static Il2CppException* GetTypeLoadException(); static Il2CppException* GetOutOfMemoryException(const utils::StringView& msg); static Il2CppException* GetOverflowException(); static Il2CppException* GetOverflowException(const char* msg); static Il2CppException* GetFormatException(const char* msg); static Il2CppException* GetSystemException(); static Il2CppException* GetNotSupportedException(const char* msg); static Il2CppException* GetArrayTypeMismatchException(); static Il2CppException* GetTypeLoadException(const char* msg); static Il2CppException* GetEntryPointNotFoundException(const char* msg); static Il2CppException* GetDllNotFoundException(const char* msg); static Il2CppException* GetInvalidOperationException(const char* msg); static Il2CppException* GetThreadInterruptedException(); static Il2CppException* GetThreadAbortException(); static Il2CppException* GetThreadStateException(const char* msg); static Il2CppException* GetSynchronizationLockException(const char* msg); static Il2CppException* GetMissingMethodException(const char* msg); static Il2CppException* GetMarshalDirectiveException(const char* msg); static Il2CppException* GetTargetException(const char* msg); static Il2CppException* GetExecutionEngineException(const char* msg); static Il2CppException* GetMethodAccessException(const char* msg); static Il2CppException* GetUnauthorizedAccessException(const utils::StringView& msg); static Il2CppException* GetDivideByZeroException(); static Il2CppException* GetPlatformNotSupportedException(const utils::StringView& msg); static Il2CppException* GetFileLoadException(const char* msg); static Il2CppException* GetMaxmimumNestedGenericsException(); static void StoreExceptionInfo(Il2CppException* ex, Il2CppString* exceptionString); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Field.cpp ================================================ #include "il2cpp-config.h" #include "utils/StringUtils.h" #include "vm/Class.h" #include "vm/GenericClass.h" #include "vm/Field.h" #include "vm/Object.h" #include "vm/Reflection.h" #include "vm/Runtime.h" #include "vm/String.h" #include "vm/Type.h" #include #include "class-internals.h" #include "object-internals.h" #include "tabledefs.h" #include "utils/MemoryRead.h" #include "vm-utils/BlobReader.h" using namespace il2cpp::utils; namespace il2cpp { namespace vm { static void set_value(const Il2CppType *type, void *dest, void *value, bool deref_pointer); const char* Field::GetName(FieldInfo *field) { return field->name; } Il2CppClass* Field::GetParent(FieldInfo *field) { return field->parent; } int Field::GetFlags(FieldInfo *field) { return field->type->attrs; } size_t Field::GetOffset(FieldInfo *field) { return field->offset; } void Field::GetValue(Il2CppObject *obj, FieldInfo *field, void *value) { void *src; IL2CPP_ASSERT(obj); IL2CPP_ASSERT(!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)); src = (char*)obj + field->offset; set_value(field->type, value, src, true); } uint32_t Field::GetToken(const FieldInfo *field) { return field->token; } Il2CppObject* Field::GetValueObject(FieldInfo *field, Il2CppObject *obj) { Il2CppClass* fieldType = Class::FromIl2CppType(field->type); if (field->type->attrs & FIELD_ATTRIBUTE_LITERAL) { if (fieldType->valuetype) { void* value = alloca(fieldType->instance_size - sizeof(Il2CppObject)); Field::GetDefaultFieldValue(field, value); return Object::Box(fieldType, value); } else { Il2CppObject* value; Field::GetDefaultFieldValue(field, &value); return value; } } void* fieldAddress; if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) { if (field->offset == THREAD_STATIC_FIELD_OFFSET) { NOT_IMPLEMENTED_NO_ASSERT(Field::GetValueObject, "Field::GetValueObject is not implemented for thread-static fields"); return NULL; } Runtime::ClassInit(field->parent); fieldAddress = static_cast(field->parent->static_fields) + field->offset; } else { IL2CPP_ASSERT(obj); fieldAddress = reinterpret_cast(obj) + field->offset; } return Object::Box(fieldType, fieldAddress); } const Il2CppType* Field::GetType(FieldInfo *field) { return field->type; } bool Field::HasAttribute(FieldInfo *field, Il2CppClass *attr_class) { return Reflection::HasAttribute(field, attr_class); } bool Field::IsDeleted(FieldInfo *field) { return false; } void Field::SetValue(Il2CppObject *obj, const FieldInfo *field, void *value) { void *dest; IL2CPP_ASSERT(!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)); dest = (char*)obj + field->offset; set_value(field->type, dest, value, false); } void Field::GetDefaultFieldValue(FieldInfo *field, void *value) { const Il2CppType* type = NULL; const char* data; data = Class::GetFieldDefaultValue(field, &type); BlobReader::GetConstantValueFromBlob(type->type, data, value); } void Field::StaticGetValue(FieldInfo *field, void *value) { void *src = NULL; IL2CPP_ASSERT(field->type->attrs & FIELD_ATTRIBUTE_STATIC); if (field->type->attrs & FIELD_ATTRIBUTE_LITERAL) { GetDefaultFieldValue(field, value); return; } // ensure parent is initialized so that static fields memory has been allocated Class::SetupFields(field->parent); if (field->offset == THREAD_STATIC_FIELD_OFFSET) { // Thread static NOT_IMPLEMENTED_NO_ASSERT(Field::StaticGetValue, "Field::StaticGetValue is not implemented for thread-static fields"); } else { src = ((char*)field->parent->static_fields) + field->offset; } set_value(field->type, value, src, true); } void Field::StaticSetValue(FieldInfo *field, void *value) { void *dest = NULL; IL2CPP_ASSERT(field->type->attrs & FIELD_ATTRIBUTE_STATIC); IL2CPP_ASSERT(!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)); // ensure parent is initialized so that static fields memory has been allocated Class::Init(field->parent); if (field->offset == THREAD_STATIC_FIELD_OFFSET) { NOT_IMPLEMENTED_NO_ASSERT(Field::StaticSetValue, "Field::SetValueObject is not implemented for thread-static fields"); return; } else { dest = ((char*)field->parent->static_fields) + field->offset; } set_value(field->type, dest, value, false); } void Field::SetInstanceFieldValueObject(Il2CppObject* objectInstance, FieldInfo* field, Il2CppObject* value) { assert(!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL)); assert(!Class::FromIl2CppType(field->type)->valuetype); *reinterpret_cast(reinterpret_cast(objectInstance) + field->offset) = value; // Object write barrier needed here } static void set_value(const Il2CppType *type, void *dest, void *value, bool deref_pointer) { int t; if (type->byref) { /* object fields cannot be byref, so we don't need a wbarrier here */ void* *p = (void**)dest; *p = value; return; } t = type->type; handle_enum: switch (t) { case IL2CPP_TYPE_BOOLEAN: case IL2CPP_TYPE_I1: case IL2CPP_TYPE_U1: { uint8_t *p = (uint8_t*)dest; *p = value ? *(uint8_t*)value : 0; return; } case IL2CPP_TYPE_I2: case IL2CPP_TYPE_U2: { uint16_t *p = (uint16_t*)dest; *p = value ? *(uint16_t*)value : 0; return; } case IL2CPP_TYPE_CHAR: { Il2CppChar* p = (Il2CppChar*)dest; *p = value ? *(Il2CppChar*)value : 0; return; } #if SIZEOF_VOID_P == 4 case IL2CPP_TYPE_I: case IL2CPP_TYPE_U: #endif case IL2CPP_TYPE_I4: case IL2CPP_TYPE_U4: { int32_t *p = (int32_t*)dest; *p = value ? *(int32_t*)value : 0; return; } #if SIZEOF_VOID_P == 8 case IL2CPP_TYPE_I: case IL2CPP_TYPE_U: #endif case IL2CPP_TYPE_I8: case IL2CPP_TYPE_U8: { int64_t *p = (int64_t*)dest; *p = value ? *(int64_t*)value : 0; return; } case IL2CPP_TYPE_R4: { float *p = (float*)dest; *p = value ? *(float*)value : 0; return; } case IL2CPP_TYPE_R8: { double *p = (double*)dest; *p = value ? *(double*)value : 0; return; } case IL2CPP_TYPE_STRING: case IL2CPP_TYPE_SZARRAY: case IL2CPP_TYPE_CLASS: case IL2CPP_TYPE_OBJECT: case IL2CPP_TYPE_ARRAY: *(void**)dest = (deref_pointer ? *(void**)value : value); //mono_gc_wbarrier_generic_store (dest, deref_pointer? *(void**)value: value); return; case IL2CPP_TYPE_FNPTR: case IL2CPP_TYPE_PTR: { void* *p = (void**)dest; *p = deref_pointer ? *(void**)value : value; return; } case IL2CPP_TYPE_VALUETYPE: /* note that 't' and 'type->type' can be different */ if (type->type == IL2CPP_TYPE_VALUETYPE && Type::IsEnum(type)) { t = Class::GetEnumBaseType(Type::GetClass(type))->type; goto handle_enum; } else { Il2CppClass *klass = Class::FromIl2CppType(type); int size = Class::GetValueSize(klass, NULL); if (value == NULL) { memset(dest, 0, size); } else { memcpy(dest, value, size); //mono_gc_wbarrier_value_copy (dest, value, size, klass); } } return; case IL2CPP_TYPE_GENERICINST: t = GenericClass::GetTypeDefinition(type->data.generic_class)->byval_arg->type; goto handle_enum; default: IL2CPP_ASSERT(0); } } const char* Field::GetData(FieldInfo *field) { if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) { const Il2CppType* type = NULL; return Class::GetFieldDefaultValue(field, &type); } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) { NOT_IMPLEMENTED_NO_ASSERT(Field::GetData, "This works for array initialization data. Revisit any other RVA use case."); const Il2CppType* type = NULL; return Class::GetFieldDefaultValue(field, &type); } else { return NULL; } } bool Field::IsInstance(FieldInfo* field) { return (field->type->attrs & FIELD_ATTRIBUTE_STATIC) == 0; } bool Field::IsNormalStatic(FieldInfo* field) { if ((field->type->attrs & FIELD_ATTRIBUTE_STATIC) == 0) return false; if (field->offset == THREAD_STATIC_FIELD_OFFSET) return false; if ((field->type->attrs & FIELD_ATTRIBUTE_LITERAL) != 0) return false; return true; } bool Field::IsThreadStatic(FieldInfo* field) { if ((field->type->attrs & FIELD_ATTRIBUTE_STATIC) == 0) return false; if (field->offset != -1) return false; if ((field->type->attrs & FIELD_ATTRIBUTE_LITERAL) != 0) return false; return true; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Field.h ================================================ #pragma once #include #include "il2cpp-config.h" struct FieldInfo; struct Il2CppType; struct Il2CppClass; struct Il2CppObject; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API Field { public: // exported static const Il2CppType* GetType(FieldInfo *field); static Il2CppClass* GetParent(FieldInfo *field); static int GetFlags(FieldInfo *field); static const char* GetName(FieldInfo *field); static size_t GetOffset(FieldInfo *field); static void GetValue(Il2CppObject *obj, FieldInfo *field, void *value); static uint32_t GetToken(const FieldInfo *field); static Il2CppObject* GetValueObject(FieldInfo *field, Il2CppObject *obj); static bool HasAttribute(FieldInfo *field, Il2CppClass *attr_class); static bool IsDeleted(FieldInfo *field); static void SetValue(Il2CppObject *obj, const FieldInfo *field, void *value); static void StaticGetValue(FieldInfo *field, void *value); static void StaticSetValue(FieldInfo *field, void *value); static void SetInstanceFieldValueObject(Il2CppObject* objectInstance, FieldInfo* field, Il2CppObject* value); public: // internal static const char* GetData(FieldInfo *field); static void GetDefaultFieldValue(FieldInfo *field, void *value); static bool IsInstance(FieldInfo* field); static bool IsNormalStatic(FieldInfo* field); static bool IsThreadStatic(FieldInfo* field); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/GenericClass.cpp ================================================ #include "il2cpp-config.h" #include "metadata/GenericMetadata.h" #include "os/Mutex.h" #include "utils/Memory.h" #include "vm/Class.h" #include "vm/GenericClass.h" #include "vm/Exception.h" #include "vm/MetadataAlloc.h" #include "vm/MetadataCache.h" #include "vm/MetadataLock.h" #include "class-internals.h" #include "metadata.h" using il2cpp::metadata::GenericMetadata; using il2cpp::os::FastAutoLock; namespace il2cpp { namespace vm { void GenericClass::SetupMethods(Il2CppClass* genericInstanceType) { Il2CppClass* genericTypeDefinition = GenericClass::GetTypeDefinition(genericInstanceType->generic_class); uint16_t methodCount = genericTypeDefinition->method_count; IL2CPP_ASSERT(genericTypeDefinition->method_count == genericInstanceType->method_count); if (methodCount == 0) { genericInstanceType->methods = NULL; return; } const MethodInfo** methods = (const MethodInfo**)MetadataCalloc(methodCount, sizeof(MethodInfo*)); for (uint16_t methodIndex = 0; methodIndex < methodCount; ++methodIndex) { const MethodInfo* methodDefinition = genericTypeDefinition->methods[methodIndex]; methods[methodIndex] = GenericMetadata::Inflate(methodDefinition, genericInstanceType, GenericClass::GetContext(genericInstanceType->generic_class)); } genericInstanceType->methods = methods; il2cpp_runtime_stats.method_count += methodCount; } static void InflatePropertyDefinition(const PropertyInfo* propertyDefinition, PropertyInfo* newProperty, Il2CppClass* declaringClass, Il2CppGenericContext* context) { newProperty->attrs = propertyDefinition->attrs; newProperty->parent = declaringClass; newProperty->name = propertyDefinition->name; newProperty->customAttributeIndex = propertyDefinition->customAttributeIndex; newProperty->token = propertyDefinition->token; if (propertyDefinition->get) newProperty->get = GenericMetadata::Inflate(propertyDefinition->get, declaringClass, context); if (propertyDefinition->set) newProperty->set = GenericMetadata::Inflate(propertyDefinition->set, declaringClass, context); } void GenericClass::SetupProperties(Il2CppClass* genericInstanceType) { Il2CppClass* genericTypeDefinition = GenericClass::GetTypeDefinition(genericInstanceType->generic_class); uint16_t propertyCount = genericTypeDefinition->property_count; IL2CPP_ASSERT(genericTypeDefinition->property_count == genericInstanceType->property_count); if (propertyCount == 0) { genericInstanceType->properties = NULL; return; } PropertyInfo* properties = (PropertyInfo*)MetadataCalloc(propertyCount, sizeof(PropertyInfo)); PropertyInfo* property = properties; for (uint16_t propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex) { InflatePropertyDefinition(genericTypeDefinition->properties + propertyIndex, property, genericInstanceType, GenericClass::GetContext(genericInstanceType->generic_class)); property++; } genericInstanceType->properties = properties; } static void InflateEventDefinition(const EventInfo* eventDefinition, EventInfo* newEvent, Il2CppClass* declaringClass, Il2CppGenericContext* context) { newEvent->eventType = GenericMetadata::InflateIfNeeded(eventDefinition->eventType, context, false); newEvent->name = eventDefinition->name; newEvent->parent = declaringClass; newEvent->customAttributeIndex = eventDefinition->customAttributeIndex; newEvent->token = eventDefinition->token; if (eventDefinition->add) newEvent->add = GenericMetadata::Inflate(eventDefinition->add, declaringClass, context); if (eventDefinition->raise) newEvent->raise = GenericMetadata::Inflate(eventDefinition->raise, declaringClass, context); if (eventDefinition->remove) newEvent->remove = GenericMetadata::Inflate(eventDefinition->remove, declaringClass, context); } void GenericClass::SetupEvents(Il2CppClass* genericInstanceType) { Il2CppClass* genericTypeDefinition = GenericClass::GetTypeDefinition(genericInstanceType->generic_class); uint16_t eventCount = genericTypeDefinition->event_count; IL2CPP_ASSERT(genericTypeDefinition->event_count == genericInstanceType->event_count); if (eventCount == 0) { genericInstanceType->events = NULL; return; } EventInfo* events = (EventInfo*)MetadataCalloc(eventCount, sizeof(EventInfo)); EventInfo* event = events; for (uint16_t eventIndex = 0; eventIndex < eventCount; ++eventIndex) { InflateEventDefinition(genericTypeDefinition->events + eventIndex, event, genericInstanceType, GenericClass::GetContext(genericInstanceType->generic_class)); event++; } genericInstanceType->events = events; } static FieldInfo* InflateFieldDefinition(const FieldInfo* fieldDefinition, FieldInfo* newField, Il2CppClass* declaringClass, Il2CppGenericContext* context) { newField->type = GenericMetadata::InflateIfNeeded(fieldDefinition->type, context, false); newField->name = fieldDefinition->name; newField->parent = declaringClass; newField->offset = fieldDefinition->offset; newField->customAttributeIndex = fieldDefinition->customAttributeIndex; newField->token = fieldDefinition->token; return newField; } void GenericClass::SetupFields(Il2CppClass* genericInstanceType) { Il2CppClass* genericTypeDefinition = GenericClass::GetTypeDefinition(genericInstanceType->generic_class); uint16_t fieldCount = genericTypeDefinition->field_count; IL2CPP_ASSERT(genericTypeDefinition->field_count == genericInstanceType->field_count); if (fieldCount == 0) { genericInstanceType->fields = NULL; return; } FieldInfo* fields = (FieldInfo*)MetadataCalloc(fieldCount, sizeof(FieldInfo)); FieldInfo* field = fields; for (uint16_t fieldIndex = 0; fieldIndex < fieldCount; ++fieldIndex) { InflateFieldDefinition(genericTypeDefinition->fields + fieldIndex, field, genericInstanceType, GenericClass::GetContext(genericInstanceType->generic_class)); field++; } genericInstanceType->fields = fields; } Il2CppClass* GenericClass::GetClass(Il2CppGenericClass *gclass) { FastAutoLock lock(&g_MetadataLock); Il2CppClass* definition = GetTypeDefinition(gclass); if (definition == NULL) vm::Exception::Raise(vm::Exception::GetMaxmimumNestedGenericsException()); if (!gclass->cached_class) { Il2CppClass* klass = gclass->cached_class = (Il2CppClass*)MetadataCalloc(1, sizeof(Il2CppClass) + (sizeof(VirtualInvokeData) * definition->vtable_count)); klass->name = definition->name; klass->namespaze = definition->namespaze; klass->image = definition->image; klass->flags = definition->flags; //klass->type_token = definition->type_token; klass->generic_class = gclass; Il2CppClass* genericTypeDefinition = GenericClass::GetTypeDefinition(klass->generic_class); Il2CppGenericContext* context = &klass->generic_class->context; if (genericTypeDefinition->parent) klass->parent = Class::FromIl2CppType(GenericMetadata::InflateIfNeeded(genericTypeDefinition->parent->byval_arg, context, false)); if (genericTypeDefinition->declaringType) klass->declaringType = Class::FromIl2CppType(GenericMetadata::InflateIfNeeded(genericTypeDefinition->declaringType->byval_arg, context, false)); Il2CppType* thisArg = (Il2CppType*)MetadataCalloc(1, sizeof(Il2CppType)); Il2CppType* byValArg = (Il2CppType*)MetadataCalloc(1, sizeof(Il2CppType)); thisArg->type = byValArg->type = IL2CPP_TYPE_GENERICINST; thisArg->data.generic_class = byValArg->data.generic_class = gclass; thisArg->byref = true; klass->this_arg = thisArg; klass->byval_arg = byValArg; klass->event_count = definition->event_count; klass->field_count = definition->field_count; klass->interfaces_count = definition->interfaces_count; klass->method_count = definition->method_count; klass->property_count = definition->property_count; klass->enumtype = definition->enumtype; klass->valuetype = definition->valuetype; klass->element_class = klass->castClass = klass; klass->has_cctor = definition->has_cctor; klass->has_finalize = definition->has_finalize; klass->native_size = klass->thread_static_fields_offset = -1; klass->customAttributeIndex = definition->customAttributeIndex; klass->token = definition->token; klass->interopData = MetadataCache::GetInteropDataForType(klass->byval_arg); if (Class::IsNullable(klass)) klass->element_class = klass->castClass = Class::GetNullableArgument(klass); if (klass->enumtype) klass->element_class = klass->castClass = definition->element_class; klass->is_import_or_windows_runtime = definition->is_import_or_windows_runtime; } return gclass->cached_class; } Il2CppGenericContext* GenericClass::GetContext(Il2CppGenericClass *gclass) { return &gclass->context; } Il2CppClass* GenericClass::GetTypeDefinition(Il2CppGenericClass *gclass) { return MetadataCache::GetTypeInfoFromTypeDefinitionIndex(gclass->typeDefinitionIndex); } bool GenericClass::IsEnum(Il2CppGenericClass *gclass) { return IsValueType(gclass) && GetTypeDefinition(gclass)->enumtype; } bool GenericClass::IsValueType(Il2CppGenericClass *gclass) { return GetTypeDefinition(gclass)->valuetype; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/GenericClass.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppClass; struct Il2CppGenericClass; struct Il2CppGenericContext; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API GenericClass { public: // exported public: //internal static Il2CppClass* GetClass(Il2CppGenericClass *gclass); static Il2CppGenericContext* GetContext(Il2CppGenericClass *gclass); static Il2CppClass* GetTypeDefinition(Il2CppGenericClass *gclass); static bool IsEnum(Il2CppGenericClass *gclass); static bool IsValueType(Il2CppGenericClass *gclass); static void SetupEvents(Il2CppClass* genericInstanceType); static void SetupFields(Il2CppClass* genericInstanceType); static void SetupMethods(Il2CppClass* genericInstanceType); static void SetupProperties(Il2CppClass* genericInstanceType); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/GenericContainer.cpp ================================================ #include "il2cpp-config.h" #include "GenericContainer.h" #include "MetadataCache.h" namespace il2cpp { namespace vm { Il2CppClass* GenericContainer::GetDeclaringType(const Il2CppGenericContainer* genericContainer) { if (genericContainer->is_method) return MetadataCache::GetMethodInfoFromMethodDefinitionIndex(genericContainer->ownerIndex)->declaring_type; return MetadataCache::GetTypeInfoFromTypeDefinitionIndex(genericContainer->ownerIndex); } const Il2CppGenericParameter* GenericContainer::GetGenericParameter(const Il2CppGenericContainer* genericContainer, uint16_t index) { IL2CPP_ASSERT(index < genericContainer->type_argc); return MetadataCache::GetGenericParameterFromIndex(genericContainer->genericParameterStart + index); } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/GenericContainer.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "il2cpp-metadata.h" struct Il2CppClass; struct Il2CppGenericContainer; struct Il2CppGenericParameter; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API GenericContainer { public: // exported public: //internal static Il2CppClass* GetDeclaringType(const Il2CppGenericContainer* genericContainer); static const Il2CppGenericParameter* GetGenericParameter(const Il2CppGenericContainer* genericContainer, uint16_t index); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Image.cpp ================================================ #include "il2cpp-config.h" #include #include #include #include "os/MemoryMappedFile.h" #include "os/Mutex.h" #include "utils/StringUtils.h" #include "vm/Class.h" #include "vm/Image.h" #include "vm/MetadataCache.h" #include "vm/StackTrace.h" #include "vm/Type.h" #include "utils/HashUtils.h" #include "utils/Il2CppHashMap.h" #include "utils/StringUtils.h" #include "vm-utils/VmStringUtils.h" using il2cpp::utils::HashUtils; using il2cpp::utils::StringUtils; struct NamespaceAndNamePairHash { size_t operator()(const std::pair& pair) const { return HashUtils::Combine(StringUtils::Hash(pair.first), StringUtils::Hash(pair.second)); } }; struct NamespaceAndNamePairEquals { bool operator()(const std::pair& p1, const std::pair& p2) const { return !strcmp(p1.first, p2.first) && !strcmp(p1.second, p2.second); } }; struct NamespaceAndNamePairLess { bool operator()(const std::pair& p1, const std::pair& p2) const { int namespaceCompare = strcmp(p1.first, p2.first); if (namespaceCompare < 0) return true; if (namespaceCompare > 0) return false; return strcmp(p1.second, p2.second) < 0; } }; struct Il2CppNameToTypeDefinitionIndexHashTable : public Il2CppHashMap, TypeDefinitionIndex, NamespaceAndNamePairHash, NamespaceAndNamePairEquals> { typedef Il2CppHashMap, TypeDefinitionIndex, NamespaceAndNamePairHash, NamespaceAndNamePairEquals> Base; Il2CppNameToTypeDefinitionIndexHashTable() : Base() { } }; namespace il2cpp { namespace vm { const Il2CppAssembly* Image::GetAssembly(const Il2CppImage* image) { return MetadataCache::GetAssemblyFromIndex(image->assemblyIndex); } typedef il2cpp::vm::StackFrames::const_reverse_iterator StackReverseIterator; static bool IsSystemType(Il2CppClass* klass) { return strcmp(klass->namespaze, "System") == 0 && strcmp(klass->name, "Type") == 0; } static bool IsSystemReflectionAssembly(Il2CppClass* klass) { return strcmp(klass->namespaze, "System.Reflection") == 0 && strcmp(klass->name, "Assembly") == 0; } static StackReverseIterator GetNextImageFromStack(StackReverseIterator first, StackReverseIterator last) { for (StackReverseIterator it = first; it != last; it++) { Il2CppClass* klass = it->method->declaring_type; if (klass->image != NULL && !IsSystemType(klass) && !IsSystemReflectionAssembly(klass)) { return it; } } return last; } const Il2CppImage* Image::GetExecutingImage() { const il2cpp::vm::StackFrames& stack = *StackTrace::GetStackFrames(); StackReverseIterator imageIt = GetNextImageFromStack(stack.rbegin(), stack.rend()); if (imageIt != stack.rend()) { return imageIt->method->declaring_type->image; } // Fallback to corlib if no image is found return const_cast(Image::GetCorlib()); } const Il2CppImage* Image::GetCallingImage() { const il2cpp::vm::StackFrames& stack = *StackTrace::GetStackFrames(); StackReverseIterator imageIt = GetNextImageFromStack(stack.rbegin(), stack.rend()); if (imageIt != stack.rend()) { imageIt = GetNextImageFromStack(++imageIt, stack.rend()); if (imageIt != stack.rend()) { return imageIt->method->declaring_type->image; } } // Fallback to corlib if no image is found return const_cast(Image::GetCorlib()); } const char * Image::GetName(const Il2CppImage* image) { return image->name; } const char * Image::GetFileName(const Il2CppImage* image) { return image->name; } const MethodInfo* Image::GetEntryPoint(const Il2CppImage* image) { if (image->entryPointIndex == -1) return NULL; return MetadataCache::GetMethodInfoFromMethodDefinitionIndex(image->entryPointIndex); } Il2CppImage* Image::GetCorlib() { return il2cpp_defaults.corlib; } static os::FastMutex s_ClassFromNameMutex; // This must be called when the s_ClassFromNameMutex is held. static void AddTypeToNametoClassHashTable(Il2CppNameToTypeDefinitionIndexHashTable* hashTable, TypeDefinitionIndex typeIndex) { const Il2CppTypeDefinition* typeDefinition = MetadataCache::GetTypeDefinitionFromIndex(typeIndex); // don't add nested types if (typeDefinition->declaringTypeIndex != kTypeIndexInvalid) return; hashTable->insert(std::make_pair(std::make_pair(MetadataCache::GetStringFromIndex(typeDefinition->namespaceIndex), MetadataCache::GetStringFromIndex(typeDefinition->nameIndex)), typeIndex)); } Il2CppClass* Image::ClassFromName(const Il2CppImage* image, const char* namespaze, const char *name) { if (!image->nameToClassHashTable) { os::FastAutoLock lock(&s_ClassFromNameMutex); if (!image->nameToClassHashTable) { image->nameToClassHashTable = new Il2CppNameToTypeDefinitionIndexHashTable(); for (uint32_t index = 0; index < image->typeCount; index++) { TypeDefinitionIndex typeIndex = image->typeStart + index; AddTypeToNametoClassHashTable(image->nameToClassHashTable, typeIndex); } for (uint32_t index = 0; index < image->exportedTypeCount; index++) { TypeDefinitionIndex typeIndex = MetadataCache::GetExportedTypeFromIndex(image->exportedTypeStart + index); if (typeIndex != kTypeIndexInvalid) AddTypeToNametoClassHashTable(image->nameToClassHashTable, typeIndex); } } } Il2CppNameToTypeDefinitionIndexHashTable::const_iterator iter = image->nameToClassHashTable->find(std::make_pair(namespaze, name)); if (iter != image->nameToClassHashTable->end()) return MetadataCache::GetTypeInfoFromTypeDefinitionIndex(iter->second); return NULL; } void Image::GetTypes(const Il2CppImage* image, bool exportedOnly, TypeVector* target) { size_t typeCount = Image::GetNumTypes(image); for (size_t sourceIndex = 0; sourceIndex < typeCount; sourceIndex++) { const Il2CppClass* type = Image::GetType(image, sourceIndex); if (strcmp(type->name, "") == 0) { continue; } target->push_back(type); } } size_t Image::GetNumTypes(const Il2CppImage* image) { return image->typeCount; } const Il2CppClass* Image::GetType(const Il2CppImage* image, size_t index) { size_t typeDefinitionIndex = image->typeStart + index; IL2CPP_ASSERT(typeDefinitionIndex <= static_cast(std::numeric_limits::max())); return MetadataCache::GetTypeInfoFromTypeDefinitionIndex(static_cast(typeDefinitionIndex)); } static bool StringsMatch(const char* left, const char* right, bool ignoreCase) { if (!ignoreCase) { return strcmp(left, right) == 0; } else { utils::VmStringUtils::CaseInsensitiveComparer comparer; return comparer(left, right); } } static Il2CppClass* FindClassMatching(const Il2CppImage* image, const char* namespaze, const char *name, Il2CppClass* declaringType, bool ignoreCase) { for (uint32_t i = 0; i < image->typeCount; i++) { Il2CppClass* type = MetadataCache::GetTypeInfoFromTypeDefinitionIndex(image->typeStart + i); if (type->declaringType == declaringType && StringsMatch(namespaze, type->namespaze, ignoreCase) && StringsMatch(name, type->name, ignoreCase)) { return type; } } return NULL; } static Il2CppClass* FindExportedClassMatching(const Il2CppImage* image, const char* namespaze, const char *name, Il2CppClass* declaringType, bool ignoreCase) { for (uint32_t i = 0; i < image->exportedTypeCount; i++) { TypeDefinitionIndex typeIndex = MetadataCache::GetExportedTypeFromIndex(image->exportedTypeStart + i); if (typeIndex != kTypeIndexInvalid) { Il2CppClass* type = MetadataCache::GetTypeInfoFromTypeDefinitionIndex(typeIndex); if (type->declaringType == declaringType && StringsMatch(namespaze, type->namespaze, ignoreCase) && StringsMatch(name, type->name, ignoreCase)) { return type; } } } return NULL; } static Il2CppClass* FindNestedType(Il2CppClass* klass, const char* name) { void* iter = NULL; while (Il2CppClass* nestedType = Class::GetNestedTypes(klass, &iter)) { if (!strcmp(name, nestedType->name)) return nestedType; } return NULL; } Il2CppClass* Image::FromTypeNameParseInfo(const Il2CppImage* image, const TypeNameParseInfo &info, bool ignoreCase) { const char* ns = info.ns().c_str(); const char* name = info.name().c_str(); Il2CppClass *parent_class = FindClassMatching(image, ns, name, NULL, ignoreCase); if (parent_class == NULL) { parent_class = FindExportedClassMatching(image, ns, name, NULL, ignoreCase); if (parent_class == NULL) return NULL; } std::vector::const_iterator it = info.nested().begin(); while (it != info.nested().end()) { parent_class = FindNestedType(parent_class, (*it).c_str()); if (parent_class == NULL) return NULL; ++it; } return parent_class; } static os::FastMutex s_Mutex; static std::vector s_CachedResourceData; static std::map s_CachedMemoryMappedResourceFiles; void Image::CacheMemoryMappedResourceFile(Il2CppReflectionAssembly* assembly, void* memoryMappedFile) { os::FastAutoLock lock(&s_Mutex); s_CachedMemoryMappedResourceFiles[assembly] = memoryMappedFile; } void* Image::GetCachedMemoryMappedResourceFile(Il2CppReflectionAssembly* assembly) { os::FastAutoLock lock(&s_Mutex); std::map::iterator entry = s_CachedMemoryMappedResourceFiles.find(assembly); if (entry != s_CachedMemoryMappedResourceFiles.end()) return entry->second; return NULL; } void Image::CacheResourceData(EmbeddedResourceRecord record, void* data) { os::FastAutoLock lock(&s_Mutex); s_CachedResourceData.push_back(EmbeddedResourceData(record, data)); } void* Image::GetCachedResourceData(const Il2CppImage* image, const std::string& name) { os::FastAutoLock lock(&s_Mutex); for (std::vector::iterator it = s_CachedResourceData.begin(); it != s_CachedResourceData.end(); ++it) { if (it->record.image == image && it->record.name == name) return it->data; } return NULL; } void Image::ClearCachedResourceData() { os::FastAutoLock lock(&s_Mutex); for (std::map::iterator i = s_CachedMemoryMappedResourceFiles.begin(); i != s_CachedMemoryMappedResourceFiles.end(); ++i) os::MemoryMappedFile::Unmap(i->second); s_CachedMemoryMappedResourceFiles.clear(); s_CachedResourceData.clear(); } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Image.h ================================================ #pragma once #include #include #include #include "il2cpp-config.h" struct Il2CppClass; struct MethodInfo; struct Il2CppAssembly; struct Il2CppDelegate; struct Il2CppImage; struct Il2CppType; struct Il2CppGenericContext; struct Il2CppGenericContainer; struct Il2CppReflectionAssembly; struct Il2CppArray; class AssemblyVector; namespace il2cpp { namespace vm { typedef std::vector TypeVector; class TypeNameParseInfo; struct EmbeddedResourceRecord { EmbeddedResourceRecord(const Il2CppImage* image, const std::string& name, uint32_t offset, uint32_t size) : image(image), name(name), offset(offset), size(size) {} const Il2CppImage* image; std::string name; uint32_t offset; uint32_t size; }; class LIBIL2CPP_CODEGEN_API Image { // exported public: static Il2CppImage* GetCorlib(); public: static const char * GetName(const Il2CppImage* image); static const char * GetFileName(const Il2CppImage* image); static const Il2CppAssembly* GetAssembly(const Il2CppImage* image); static const MethodInfo* GetEntryPoint(const Il2CppImage* image); static const Il2CppImage* GetExecutingImage(); static const Il2CppImage* GetCallingImage(); static size_t GetNumTypes(const Il2CppImage* image); static const Il2CppClass* GetType(const Il2CppImage* image, size_t index); static Il2CppClass* FromTypeNameParseInfo(const Il2CppImage* image, const TypeNameParseInfo &info, bool ignoreCase); static Il2CppClass* ClassFromName(const Il2CppImage* image, const char* namespaze, const char *name); static void GetTypes(const Il2CppImage* image, bool exportedOnly, TypeVector* target); struct EmbeddedResourceData { EmbeddedResourceData(EmbeddedResourceRecord record, void* data) : record(record), data(data) {} EmbeddedResourceRecord record; void* data; }; static void CacheMemoryMappedResourceFile(Il2CppReflectionAssembly* assembly, void* memoryMappedFile); static void* GetCachedMemoryMappedResourceFile(Il2CppReflectionAssembly* assembly); static void CacheResourceData(EmbeddedResourceRecord record, void* data); static void* GetCachedResourceData(const Il2CppImage* image, const std::string& name); static void ClearCachedResourceData(); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/InternalCalls.cpp ================================================ #include "il2cpp-config.h" #include "vm/InternalCalls.h" #include "vm/Runtime.h" #include #include typedef std::map ICallMap; static ICallMap s_InternalCalls; namespace il2cpp { namespace vm { void InternalCalls::Add(const char* name, Il2CppMethodPointer method) { //ICallMap::iterator res = s_InternalCalls.find(name); // TODO: Don't assert right now because Unity adds some icalls multiple times. //if (res != icalls.end()) // IL2CPP_ASSERT(0 && "Adding internal call twice!"); IL2CPP_ASSERT(method); s_InternalCalls[name] = method; } Il2CppMethodPointer InternalCalls::Resolve(const char* name) { // Try to find the whole name first, then search using just type::method // if parameters were passed // ex: First, System.Foo::Bar(System.Int32) // Then, System.Foo::Bar ICallMap::iterator res = s_InternalCalls.find(name); if (res != s_InternalCalls.end()) return res->second; std::string shortName(name); size_t index = shortName.find('('); if (index != std::string::npos) { shortName = shortName.substr(0, index); res = s_InternalCalls.find(shortName); if (res != s_InternalCalls.end()) return res->second; } return NULL; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/InternalCalls.h ================================================ #pragma once #include "il2cpp-config.h" namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API InternalCalls { public: static void Init(); static void Add(const char* name, Il2CppMethodPointer method); static Il2CppMethodPointer Resolve(const char* name); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/LastError.cpp ================================================ #include "LastError.h" #include "Thread.h" #include "os/LastError.h" namespace il2cpp { namespace vm { int32_t LastError::s_LastErrorThreadLocalStorageOffset = -1; uint32_t LastError::GetLastError() { if (s_LastErrorThreadLocalStorageOffset == -1) return 0; return *(uint32_t*)Thread::GetThreadStaticData(s_LastErrorThreadLocalStorageOffset); } void LastError::StoreLastError() { // Get the last error first, before any other calls (so that we don't stomp on it). uint32_t lastError = os::LastError::GetLastError(); uint32_t* lastErrorTls = (uint32_t*)Thread::GetThreadStaticData(s_LastErrorThreadLocalStorageOffset); *lastErrorTls = lastError; } void LastError::InitializeLastErrorThreadStatic() { if (s_LastErrorThreadLocalStorageOffset == -1) s_LastErrorThreadLocalStorageOffset = Thread::AllocThreadStaticData(sizeof(uint32_t)); } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/LastError.h ================================================ #pragma once #include #include "il2cpp-config.h" namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API LastError { public: static uint32_t GetLastError(); static void StoreLastError(); static void InitializeLastErrorThreadStatic(); private: static int32_t s_LastErrorThreadLocalStorageOffset; }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/LibraryLoader.cpp ================================================ #include "LibraryLoader.h" #include "os/LibraryLoader.h" #include "utils/StringUtils.h" namespace il2cpp { namespace vm { static Il2CppSetFindPlugInCallback s_FindPluginCallback = NULL; void* LibraryLoader::LoadLibrary(il2cpp::utils::StringView nativeDynamicLibrary) { if (s_FindPluginCallback) { StringViewAsNullTerminatedStringOf(Il2CppNativeChar, nativeDynamicLibrary, libraryName); const Il2CppNativeChar* modifiedLibraryName = s_FindPluginCallback(libraryName); if (modifiedLibraryName != libraryName) { utils::StringView modifiedDynamicLibrary(modifiedLibraryName, utils::StringUtils::StrLen(modifiedLibraryName)); return os::LibraryLoader::LoadDynamicLibrary(modifiedDynamicLibrary); } } return os::LibraryLoader::LoadDynamicLibrary(nativeDynamicLibrary); } void LibraryLoader::SetFindPluginCallback(Il2CppSetFindPlugInCallback method) { IL2CPP_ASSERT(method == NULL || s_FindPluginCallback == NULL); s_FindPluginCallback = method; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/LibraryLoader.h ================================================ #pragma once #include "il2cpp-config.h" #include "utils/StringView.h" struct PInvokeArguments; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API LibraryLoader { public: static void* LoadLibrary(il2cpp::utils::StringView nativeDynamicLibrary); static void SetFindPluginCallback(Il2CppSetFindPlugInCallback method); }; } /* namespace vm */ } /* namespace il2cpp*/ ================================================ FILE: unity_decoder/libil2cpp/vm/Liveness.cpp ================================================ #include "il2cpp-config.h" #include "gc/GarbageCollector.h" #include #include "vm/Array.h" #include "vm/Class.h" #include "vm/Field.h" #include "vm/Liveness.h" #include "vm/Type.h" #include "tabledefs.h" #include "class-internals.h" #include "object-internals.h" typedef il2cpp::utils::dynamic_array custom_growable_array; #define MARK_OBJ(obj) \ do { \ (obj)->klass = (Il2CppClass*)(((size_t)(obj)->klass) | (size_t)1); \ } while (0) #define CLEAR_OBJ(obj) \ do { \ (obj)->klass = (Il2CppClass*)(((size_t)(obj)->klass) & ~(size_t)1); \ } while (0) #define IS_MARKED(obj) \ (((size_t)(obj)->klass) & (size_t)1) #define GET_CLASS(obj) \ ((Il2CppClass*)(((size_t)(obj)->klass) & ~(size_t)1)) namespace il2cpp { namespace vm { /* number of sub elements of an array to process before recursing * we take a depth first approach to use stack space rather than re-allocating * processing array which requires restarting world to ensure allocator lock is not held */ const int kArrayElementsPerChunk = 256; /* how far we recurse processing array elements before we stop. Prevents stack overflow */ const int kMaxTraverseRecursionDepth = 128; struct LivenessState { LivenessState(Il2CppClass* filter, uint32_t maxCount, Liveness::register_object_callback callback, void*callback_userdata, Liveness::WorldChangedCallback onWorldStarted, Liveness::WorldChangedCallback onWorldStopped); ~LivenessState(); void Finalize(); void Reset(); void TraverseObjects(); void FilterObjects(); static void TraverseGenericObject(Il2CppObject* object, LivenessState* state); static void TraverseObject(Il2CppObject* object, LivenessState* state); static void TraverseGCDescriptor(Il2CppObject* object, LivenessState* state); static bool TraverseObjectInternal(Il2CppObject* object, bool isStruct, Il2CppClass* klass, LivenessState* state); static void TraverseArray(Il2CppArray* array, LivenessState* state); static bool AddProcessObject(Il2CppObject* object, LivenessState* state); static bool ShouldProcessValue(Il2CppObject* val, Il2CppClass* filter); static bool FieldCanContainReferences(FieldInfo* field); void SafeGrowArray(custom_growable_array* array); static bool ShouldTraverseObjects(size_t index, int32_t recursion_depth) { // Add kArrayElementsPerChunk objects at a time and then traverse return ((index + 1) & (kArrayElementsPerChunk - 1)) == 0 && recursion_depth < kMaxTraverseRecursionDepth; } int32_t first_index_in_all_objects; custom_growable_array* all_objects; Il2CppClass* filter; custom_growable_array* process_array; uint32_t initial_alloc_count; void* callback_userdata; Liveness::register_object_callback filter_callback; Liveness::WorldChangedCallback onWorldStarted; Liveness::WorldChangedCallback onWorldStopped; int32_t traverse_depth; // track recursion. Prevent stack overflow by limiting recurion }; LivenessState::LivenessState(Il2CppClass* filter, uint32_t maxCount, Liveness::register_object_callback callback, void*callback_userdata, Liveness::WorldChangedCallback onWorldStarted, Liveness::WorldChangedCallback onWorldStopped) : first_index_in_all_objects(0), all_objects(NULL), filter(NULL), process_array(NULL), initial_alloc_count(0), callback_userdata(NULL), filter_callback(NULL), onWorldStarted(onWorldStarted), onWorldStopped(onWorldStopped) { // construct liveness_state; // allocate memory for the following structs // all_objects: contains a list of all referenced objects to be able to clean the vtable bits after the traversal // process_array. array that contains the objcets that should be processed. this should run depth first to reduce memory usage // if all_objects run out of space, run through list, add objects that match the filter, clear bit in vtable and then clear the array. maxCount = maxCount < 1000 ? 1000 : maxCount; all_objects = new custom_growable_array(); all_objects->reserve(maxCount * 4); process_array = new custom_growable_array(); process_array->reserve(maxCount); first_index_in_all_objects = 0; this->filter = filter; this->callback_userdata = callback_userdata; this->filter_callback = callback; } LivenessState::~LivenessState() { delete all_objects; delete process_array; } void LivenessState::Finalize() { for (size_t i = 0; i < all_objects->size(); i++) { Il2CppObject* object = (*all_objects)[i]; CLEAR_OBJ(object); } } void LivenessState::Reset() { first_index_in_all_objects = (int32_t)all_objects->size(); process_array->resize_uninitialized(0); } void LivenessState::TraverseObjects() { Il2CppObject* object = NULL; traverse_depth++; while (process_array->size() > 0) { object = process_array->back(); process_array->pop_back(); TraverseGenericObject(object, this); } traverse_depth--; } void LivenessState::FilterObjects() { Il2CppObject* filtered_objects[64]; int32_t num_objects = 0; size_t i = (size_t)first_index_in_all_objects; for (; i < all_objects->size(); i++) { Il2CppObject* object = (*all_objects)[i]; if (ShouldProcessValue(object, filter)) filtered_objects[num_objects++] = object; if (num_objects == 64) { filter_callback(filtered_objects, 64, callback_userdata); num_objects = 0; } } if (num_objects != 0) filter_callback(filtered_objects, num_objects, callback_userdata); } void LivenessState::TraverseGenericObject(Il2CppObject* object, LivenessState* state) { NOT_IMPLEMENTED_NO_ASSERT(LivenessState::TraverseGenericObject, "Use GC bitmap when we have one"); #if IL2CPP_HAS_GC_DESCRIPTORS size_t gc_desc = (size_t)(GET_CLASS(object)->gc_desc); if (gc_desc & (size_t)1) TraverseGCDescriptor(object, state); else #endif if (GET_CLASS(object)->rank) TraverseArray((Il2CppArray*)object, state); else TraverseObject(object, state); } void LivenessState::TraverseObject(Il2CppObject* object, LivenessState* state) { TraverseObjectInternal(object, false, GET_CLASS(object), state); } void LivenessState::TraverseGCDescriptor(Il2CppObject* object, LivenessState* state) { #define WORDSIZE ((int)sizeof(size_t)*8) int i = 0; size_t mask = (size_t)(GET_CLASS(object)->gc_desc); IL2CPP_ASSERT(mask & (size_t)1); for (i = 0; i < WORDSIZE - 2; i++) { size_t offset = ((size_t)1 << (WORDSIZE - 1 - i)); if (mask & offset) { Il2CppObject* val = *(Il2CppObject**)(((char*)object) + i * sizeof(void*)); AddProcessObject(val, state); } } } bool LivenessState::TraverseObjectInternal(Il2CppObject* object, bool isStruct, Il2CppClass* klass, LivenessState* state) { FieldInfo *field; Il2CppClass *p; bool added_objects = false; IL2CPP_ASSERT(object); if (!klass->initialized) { IL2CPP_ASSERT(isStruct); return false; } // subtract the added offset for the vtable. This is added to the offset even though it is a struct if (isStruct) object--; for (p = klass; p != NULL; p = p->parent) { void* iter = NULL; while ((field = Class::GetFields(p, &iter))) { if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) continue; if (!FieldCanContainReferences(field)) continue; if (Type::IsStruct(field->type)) { char* offseted = (char*)object; offseted += field->offset; if (Type::IsGenericInstance(field->type)) { IL2CPP_ASSERT(field->type->data.generic_class->cached_class); added_objects |= TraverseObjectInternal((Il2CppObject*)offseted, true, field->type->data.generic_class->cached_class, state); } else added_objects |= TraverseObjectInternal((Il2CppObject*)offseted, true, Type::GetClass(field->type), state); continue; } if (field->offset == THREAD_STATIC_FIELD_OFFSET) { IL2CPP_ASSERT(0); } else { Il2CppObject* val = NULL; Field::GetValue(object, field, &val); added_objects |= AddProcessObject(val, state); } } } return added_objects; } void LivenessState::TraverseArray(Il2CppArray* array, LivenessState* state) { size_t i = 0; bool has_references; Il2CppObject* object = (Il2CppObject*)array; Il2CppClass* element_class; size_t elementClassSize; size_t array_length; IL2CPP_ASSERT(object); element_class = GET_CLASS(object)->element_class; has_references = !Class::IsValuetype(element_class); IL2CPP_ASSERT(element_class->size_inited != 0); FieldInfo* field; void* iter = NULL; while ((field = Class::GetFields(element_class, &iter))) { has_references |= FieldCanContainReferences(field); if (has_references) break; } if (!has_references) return; array_length = Array::GetLength(array); if (element_class->valuetype) { size_t items_processed = 0; elementClassSize = Class::GetArrayElementSize(element_class); for (i = 0; i < array_length; i++) { Il2CppObject* object = (Il2CppObject*)il2cpp_array_addr_with_size(array, (int32_t)elementClassSize, i); if (TraverseObjectInternal(object, 1, element_class, state)) items_processed++; // Add 64 objects at a time and then traverse if (ShouldTraverseObjects(items_processed, state->traverse_depth)) state->TraverseObjects(); } } else { size_t items_processed = 0; for (i = 0; i < array_length; i++) { Il2CppObject* val = il2cpp_array_get(array, Il2CppObject*, i); if (AddProcessObject(val, state)) items_processed++; // Add 64 objects at a time and then traverse if (ShouldTraverseObjects(items_processed, state->traverse_depth)) state->TraverseObjects(); } } } bool LivenessState::AddProcessObject(Il2CppObject* object, LivenessState* state) { if (!object || IS_MARKED(object)) return false; bool has_references = GET_CLASS(object)->has_references; if (has_references || ShouldProcessValue(object, state->filter)) { // TODO if (state->all_objects->size() == state->all_objects->capacity()) state->SafeGrowArray(state->all_objects); state->all_objects->push_back(object); MARK_OBJ(object); } // Check if klass has further references - if not skip adding if (has_references) { if (state->process_array->size() == state->process_array->capacity()) state->SafeGrowArray(state->process_array); state->process_array->push_back(object); return true; } return false; } bool LivenessState::ShouldProcessValue(Il2CppObject* val, Il2CppClass* filter) { Il2CppClass* val_class = GET_CLASS(val); if (filter && !Class::HasParentUnsafe(val_class, filter)) return false; return true; } bool LivenessState::FieldCanContainReferences(FieldInfo* field) { if (Type::IsStruct(field->type)) return true; if (field->type->attrs & FIELD_ATTRIBUTE_LITERAL) return false; if (field->type->type == IL2CPP_TYPE_STRING) return false; return Type::IsReference(field->type); } void LivenessState::SafeGrowArray(custom_growable_array* array) { // if all_objects run out of space, run through list // clear bit in vtable, start the world, reallocate, stop the world and continue for (size_t i = 0; i < all_objects->size(); i++) { Il2CppObject* object = (*all_objects)[i]; CLEAR_OBJ(object); } Liveness::StartWorld(onWorldStarted); array->reserve(array->capacity() * 2); Liveness::StopWorld(onWorldStopped); for (size_t i = 0; i < all_objects->size(); i++) { Il2CppObject* object = (*all_objects)[i]; MARK_OBJ(object); } } void* Liveness::Begin(Il2CppClass* filter, int max_object_count, register_object_callback callback, void* userdata, WorldChangedCallback onWorldStarted, WorldChangedCallback onWorldStopped) { // ensure filter is initialized so we can do fast (and lock free) check HasParentUnsafe Class::SetupTypeHierarchy(filter); LivenessState* state = new LivenessState(filter, max_object_count, callback, userdata, onWorldStarted, onWorldStopped); StopWorld(onWorldStopped); // no allocations can happen beyond this point return state; } void Liveness::End(void* state) { LivenessState* lstate = (LivenessState*)state; lstate->Finalize(); WorldChangedCallback onWorldStarted = lstate->onWorldStarted; StartWorld(onWorldStarted); delete lstate; } void Liveness::FromRoot(Il2CppObject* root, void* state) { LivenessState* liveness_state = (LivenessState*)state; liveness_state->Reset(); liveness_state->process_array->push_back(root); liveness_state->TraverseObjects(); //Filter objects and call callback to register found objects liveness_state->FilterObjects(); } void Liveness::FromStatics(void* state) { LivenessState* liveness_state = (LivenessState*)state; const il2cpp::utils::dynamic_array& classesWithStatics = Class::GetStaticFieldData(); liveness_state->Reset(); for (il2cpp::utils::dynamic_array::const_iterator iter = classesWithStatics.begin(); iter != classesWithStatics.end(); iter++) { Il2CppClass* klass = *iter; FieldInfo *field; if (!klass) continue; if (klass->image == il2cpp_defaults.corlib) continue; if (klass->size_inited == 0) continue; void* fieldIter = NULL; while ((field = Class::GetFields(klass, &fieldIter))) { if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) continue; if (!LivenessState::FieldCanContainReferences(field)) continue; // shortcut check for thread-static field if (field->offset == THREAD_STATIC_FIELD_OFFSET) continue; if (Type::IsStruct(field->type)) { char* offseted = (char*)klass->static_fields; offseted += field->offset; if (Type::IsGenericInstance(field->type)) { IL2CPP_ASSERT(field->type->data.generic_class->cached_class); LivenessState::TraverseObjectInternal((Il2CppObject*)offseted, true, field->type->data.generic_class->cached_class, liveness_state); } else { LivenessState::TraverseObjectInternal((Il2CppObject*)offseted, true, Type::GetClass(field->type), liveness_state); } } else { Il2CppObject* val = NULL; Field::StaticGetValue(field, &val); if (val) { LivenessState::AddProcessObject(val, liveness_state); } } } } liveness_state->TraverseObjects(); //Filter objects and call callback to register found objects liveness_state->FilterObjects(); } void Liveness::StopWorld(WorldChangedCallback onWorldStopped) { onWorldStopped(); il2cpp::gc::GarbageCollector::StopWorld(); } void Liveness::StartWorld(WorldChangedCallback onWorldStarted) { il2cpp::gc::GarbageCollector::StartWorld(); onWorldStarted(); } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Liveness.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppClass; struct Il2CppObject; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API Liveness { public: typedef void (*register_object_callback)(Il2CppObject** arr, int size, void* userdata); typedef void (*WorldChangedCallback)(); static void* Begin(Il2CppClass* filter, int max_object_count, register_object_callback callback, void* userdata, WorldChangedCallback onWorldStarted, WorldChangedCallback onWorldStopped); static void End(void* state); static void FromRoot(Il2CppObject* root, void* state); static void FromStatics(void* state); static void StopWorld(WorldChangedCallback onWorldStopped); static void StartWorld(WorldChangedCallback onWorldStarted); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/MarshalAlloc.cpp ================================================ #include "il2cpp-config.h" #include "MarshalAlloc.h" #include "os/MarshalAlloc.h" #include "os/ThreadLocalValue.h" #include "vm/Exception.h" #include #include namespace il2cpp { namespace vm { #if _DEBUG static os::ThreadLocalValue s_Allocations; static os::FastMutex s_AllocationStorageMutex; static std::deque > > s_AllocationStorage; static std::vector >& GetAllocationsForCurrentThread() { std::vector >* ptr = NULL; s_Allocations.GetValue(reinterpret_cast(&ptr)); if (ptr == NULL) { os::FastAutoLock lock(&s_AllocationStorageMutex); s_AllocationStorage.push_back(std::vector >()); ptr = &s_AllocationStorage.back(); s_Allocations.SetValue(ptr); } return *ptr; } static std::map* GetAllocationsForCurrentFrame() { std::vector >& currentThreadAllocations = GetAllocationsForCurrentThread(); if (currentThreadAllocations.size() > 0) return ¤tThreadAllocations.back(); return NULL; } #endif void* MarshalAlloc::Allocate(size_t size) { void* ptr = os::MarshalAlloc::Allocate(size); #if _DEBUG std::map* allocations = GetAllocationsForCurrentFrame(); if (allocations != NULL) (*allocations)[ptr] = size; #endif return ptr; } void* MarshalAlloc::ReAlloc(void* ptr, size_t size) { void* realloced = os::MarshalAlloc::ReAlloc(ptr, size); #if _DEBUG std::map* allocations = GetAllocationsForCurrentFrame(); if (allocations != NULL) { if (ptr != NULL && ptr != realloced) { std::map::iterator found = allocations->find(ptr); IL2CPP_ASSERT(found != allocations->end() && "Invalid call to MarshalAlloc::ReAlloc. The pointer is not in the allocation list."); allocations->erase(found); } (*allocations)[realloced] = size; } #endif return realloced; } void MarshalAlloc::Free(void* ptr) { #if _DEBUG std::map* allocations = GetAllocationsForCurrentFrame(); if (allocations != NULL) { std::map::iterator found = allocations->find(ptr); if (found != allocations->end()) // It might not be necessarily allocated by us, e.g. we might be freeing memory that's returned from native P/Invoke call allocations->erase(found); } #endif os::MarshalAlloc::Free(ptr); } void* MarshalAlloc::AllocateHGlobal(size_t size) { // should use Unity's memory management here! return malloc(size); } void* MarshalAlloc::ReAllocHGlobal(void* ptr, size_t size) { // should use Unity's memory management here! return realloc(ptr, size); } void MarshalAlloc::FreeHGlobal(void* ptr) { // should use Unity's memory management here! free(ptr); } #if _DEBUG void MarshalAlloc::PushAllocationFrame() { GetAllocationsForCurrentThread().push_back(std::map()); } void MarshalAlloc::PopAllocationFrame() { GetAllocationsForCurrentThread().pop_back(); } bool MarshalAlloc::HasUnfreedAllocations() { std::map* allocations = GetAllocationsForCurrentFrame(); return allocations != NULL && allocations->size() > 0; } void MarshalAlloc::ClearAllTrackedAllocations() { std::map* allocations = GetAllocationsForCurrentFrame(); if (allocations != NULL) allocations->clear(); } #endif } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/MarshalAlloc.h ================================================ #pragma once #include "il2cpp-config.h" #if _DEBUG #include #include "os/Mutex.h" #endif namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API MarshalAlloc { public: static void* Allocate(size_t size); static void* ReAlloc(void* ptr, size_t size); static void Free(void* ptr); static void* AllocateHGlobal(size_t size); static void* ReAllocHGlobal(void* ptr, size_t size); static void FreeHGlobal(void* ptr); #if _DEBUG static void PushAllocationFrame(); static void PopAllocationFrame(); static bool HasUnfreedAllocations(); static void ClearAllTrackedAllocations(); #endif }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/MemoryInformation.cpp ================================================ #include "il2cpp-config.h" #include "MemoryInformation.h" #include "gc/GarbageCollector.h" #include "gc/GCHandle.h" #include "metadata/ArrayMetadata.h" #include "metadata/GenericMetadata.h" #include "vm/Assembly.h" #include "vm/Class.h" #include "vm/MetadataCache.h" #include "vm/Type.h" #include "utils/Memory.h" #include "class-internals.h" #include "object-internals.h" #include "tabledefs.h" #include #include namespace il2cpp { namespace vm { namespace MemoryInformation { using namespace il2cpp::metadata; struct GatherMetadataContext { uint32_t currentIndex; std::map allTypes; }; static void GatherMetadataCallback(Il2CppClass* type, void* context) { if (type->initialized) { GatherMetadataContext* ctx = static_cast(context); ctx->allTypes.insert(std::make_pair(type, ctx->currentIndex++)); } } static inline int FindTypeInfoIndexInMap(const std::map& allTypes, Il2CppClass* typeInfo) { std::map::const_iterator it = allTypes.find(typeInfo); if (it == allTypes.end()) return -1; return it->second; } static inline void GatherMetadata(Il2CppMetadataSnapshot& metadata) { GatherMetadataContext gatherMetadataContext = { 0 }; const AssemblyVector* allAssemblies = Assembly::GetAllAssemblies(); for (AssemblyVector::const_iterator it = allAssemblies->begin(); it != allAssemblies->end(); it++) { const Il2CppImage& image = *MetadataCache::GetImageFromIndex((*it)->imageIndex); for (uint32_t i = 0; i < image.typeCount; i++) { Il2CppClass* type = MetadataCache::GetTypeInfoFromTypeDefinitionIndex(image.typeStart + i); if (type->initialized) gatherMetadataContext.allTypes.insert(std::make_pair(type, gatherMetadataContext.currentIndex++)); } } ArrayMetadata::WalkArrays(GatherMetadataCallback, &gatherMetadataContext); ArrayMetadata::WalkSZArrays(GatherMetadataCallback, &gatherMetadataContext); GenericMetadata::WalkAllGenericClasses(GatherMetadataCallback, &gatherMetadataContext); MetadataCache::WalkPointerTypes(GatherMetadataCallback, &gatherMetadataContext); const std::map& allTypes = gatherMetadataContext.allTypes; metadata.typeCount = static_cast(allTypes.size()); metadata.types = static_cast(IL2CPP_CALLOC(metadata.typeCount, sizeof(Il2CppMetadataType))); for (std::map::const_iterator it = allTypes.begin(); it != allTypes.end(); it++) { Il2CppClass* typeInfo = it->first; uint32_t index = it->second; Il2CppMetadataType& type = metadata.types[index]; if (typeInfo->rank > 0) { type.flags = static_cast(kArray | (kArrayRankMask & (typeInfo->rank << 16))); type.baseOrElementTypeIndex = FindTypeInfoIndexInMap(allTypes, typeInfo->element_class); } else { type.flags = (typeInfo->valuetype || typeInfo->byval_arg->type == IL2CPP_TYPE_PTR) ? kValueType : kNone; type.fieldCount = 0; if (typeInfo->field_count > 0) { type.fields = static_cast(IL2CPP_CALLOC(typeInfo->field_count, sizeof(Il2CppMetadataField))); for (int i = 0; i < typeInfo->field_count; i++) { Il2CppMetadataField& field = metadata.types[index].fields[type.fieldCount]; FieldInfo* fieldInfo = typeInfo->fields + i; field.typeIndex = FindTypeInfoIndexInMap(allTypes, Class::FromIl2CppType(fieldInfo->type)); // This will happen if fields type is not initialized // It's OK to skip it, because it means the field is guaranteed to be null on any object if (field.typeIndex == -1) continue; //literals have no actual storage, and are not relevant in this context. if ((fieldInfo->type->attrs & FIELD_ATTRIBUTE_LITERAL) != 0) continue; field.isStatic = (fieldInfo->type->attrs & FIELD_ATTRIBUTE_STATIC) != 0; field.offset = fieldInfo->offset; field.name = fieldInfo->name; type.fieldCount++; } } type.staticsSize = typeInfo->static_fields_size; if (type.staticsSize > 0 && typeInfo->static_fields != NULL) { type.statics = static_cast(IL2CPP_MALLOC(type.staticsSize)); memcpy(type.statics, typeInfo->static_fields, type.staticsSize); } Il2CppClass* baseType = Class::GetParent(typeInfo); type.baseOrElementTypeIndex = baseType != NULL ? FindTypeInfoIndexInMap(allTypes, baseType) : -1; } type.assemblyName = MetadataCache::GetStringFromIndex(MetadataCache::GetAssemblyFromIndex(typeInfo->image->assemblyIndex)->aname.nameIndex); std::string typeName = Type::GetName(typeInfo->byval_arg, IL2CPP_TYPE_NAME_FORMAT_IL); type.name = static_cast(IL2CPP_CALLOC(typeName.length() + 1, sizeof(char))); memcpy(type.name, typeName.c_str(), typeName.length() + 1); type.typeInfoAddress = reinterpret_cast(typeInfo); type.size = (typeInfo->valuetype) != 0 ? (typeInfo->instance_size - sizeof(Il2CppObject)) : typeInfo->instance_size; } } struct SectionIterationContext { Il2CppManagedMemorySection* currentSection; }; static void AllocateMemoryForSection(void* context, void* sectionStart, void* sectionEnd) { SectionIterationContext* ctx = static_cast(context); Il2CppManagedMemorySection& section = *ctx->currentSection; section.sectionStartAddress = reinterpret_cast(sectionStart); ptrdiff_t sectionSize = static_cast(sectionEnd) - static_cast(sectionStart); if (sizeof(void*) > 4) // This assert is only valid on 64-bit IL2CPP_ASSERT(sectionSize <= static_cast(std::numeric_limits::max())); section.sectionSize = static_cast(sectionSize); section.sectionBytes = static_cast(IL2CPP_MALLOC(section.sectionSize)); ctx->currentSection++; } static void CopyHeapSection(void* context, void* sectionStart, void* sectionEnd) { SectionIterationContext* ctx = static_cast(context); Il2CppManagedMemorySection& section = *ctx->currentSection; IL2CPP_ASSERT(section.sectionStartAddress == reinterpret_cast(sectionStart)); IL2CPP_ASSERT(section.sectionSize == static_cast(sectionEnd) - static_cast(sectionStart)); memcpy(section.sectionBytes, sectionStart, section.sectionSize); ctx->currentSection++; } static void* CaptureHeapInfo(void* voidManagedHeap) { Il2CppManagedHeap& heap = *(Il2CppManagedHeap*)voidManagedHeap; heap.sectionCount = static_cast(il2cpp::gc::GarbageCollector::GetSectionCount()); heap.sections = static_cast(IL2CPP_CALLOC(heap.sectionCount, sizeof(Il2CppManagedMemorySection))); SectionIterationContext iterationContext = { heap.sections }; il2cpp::gc::GarbageCollector::ForEachHeapSection(&iterationContext, AllocateMemoryForSection); return NULL; } static void FreeIL2CppManagedHeap(Il2CppManagedHeap& heap) { for (uint32_t i = 0; i < heap.sectionCount; i++) { IL2CPP_FREE(heap.sections[i].sectionBytes); } IL2CPP_FREE(heap.sections); } struct VerifyHeapSectionStillValidIterationContext { Il2CppManagedMemorySection* currentSection; bool wasValid; }; static void VerifyHeapSectionIsStillValid(void* context, void* sectionStart, void* sectionEnd) { VerifyHeapSectionStillValidIterationContext* iterationContext = (VerifyHeapSectionStillValidIterationContext*)context; if (iterationContext->currentSection->sectionSize != static_cast(sectionEnd) - static_cast(sectionStart)) iterationContext->wasValid = false; else if (iterationContext->currentSection->sectionStartAddress != reinterpret_cast(sectionStart)) iterationContext->wasValid = false; iterationContext->currentSection++; } static bool IsIL2CppManagedHeapStillValid(Il2CppManagedHeap& heap) { if (heap.sectionCount != static_cast(il2cpp::gc::GarbageCollector::GetSectionCount())) return false; VerifyHeapSectionStillValidIterationContext iterationContext = { heap.sections, true }; il2cpp::gc::GarbageCollector::ForEachHeapSection(&iterationContext, VerifyHeapSectionIsStillValid); return iterationContext.wasValid; } // The difficulty in capturing the managed snapshot is that we need to do quite some work with the world stopped, // to make sure that our snapshot is "valid", and didn't change as we were copying it. However, stopping the world, // makes it so you cannot take any lock or allocations. We deal with it like this: // // 1) We take note of the amount of heap sections and their sizes, and we allocate memory to copy them into. // 2) We stop the world. // 3) We check if the amount of heapsections and their sizes didn't change in the mean time. If they did, try again. // 4) Now, with the world still stopped, we memcpy() the memory from the real heapsections, into the memory that we // allocated for their copies. // 5) Start the world again. static inline void CaptureManagedHeap(Il2CppManagedHeap& heap) { for (;;) { il2cpp::gc::GarbageCollector::CallWithAllocLockHeld(CaptureHeapInfo, &heap); il2cpp::gc::GarbageCollector::StopWorld(); if (IsIL2CppManagedHeapStillValid(heap)) break; il2cpp::gc::GarbageCollector::StartWorld(); FreeIL2CppManagedHeap(heap); } SectionIterationContext iterationContext = { heap.sections }; il2cpp::gc::GarbageCollector::ForEachHeapSection(&iterationContext, CopyHeapSection); il2cpp::gc::GarbageCollector::StartWorld(); } struct GCHandleTargetIterationContext { std::vector managedObjects; }; static void GCHandleIterationCallback(Il2CppObject* managedObject, void* context) { GCHandleTargetIterationContext* ctx = static_cast(context); ctx->managedObjects.push_back(managedObject); } static inline void CaptureGCHandleTargets(Il2CppGCHandles& gcHandles) { GCHandleTargetIterationContext gcHandleTargetIterationContext; il2cpp::gc::GCHandle::WalkStrongGCHandleTargets(GCHandleIterationCallback, &gcHandleTargetIterationContext); const std::vector& trackedObjects = gcHandleTargetIterationContext.managedObjects; gcHandles.trackedObjectCount = static_cast(trackedObjects.size()); gcHandles.pointersToObjects = static_cast(IL2CPP_CALLOC(gcHandles.trackedObjectCount, sizeof(uint64_t))); for (uint32_t i = 0; i < gcHandles.trackedObjectCount; i++) gcHandles.pointersToObjects[i] = reinterpret_cast(trackedObjects[i]); } void FillRuntimeInformation(Il2CppRuntimeInformation& runtimeInfo) { runtimeInfo.pointerSize = static_cast(sizeof(void*)); runtimeInfo.objectHeaderSize = static_cast(sizeof(Il2CppObject)); runtimeInfo.arrayHeaderSize = static_cast(kIl2CppSizeOfArray); runtimeInfo.arraySizeOffsetInHeader = kIl2CppOffsetOfArrayLength; runtimeInfo.arrayBoundsOffsetInHeader = kIl2CppOffsetOfArrayBounds; runtimeInfo.allocationGranularity = static_cast(2 * sizeof(void*)); } Il2CppManagedMemorySnapshot* CaptureManagedMemorySnapshot() { Il2CppManagedMemorySnapshot* snapshot = static_cast(IL2CPP_MALLOC_ZERO(sizeof(Il2CppManagedMemorySnapshot))); GatherMetadata(snapshot->metadata); CaptureManagedHeap(snapshot->heap); CaptureGCHandleTargets(snapshot->gcHandles); FillRuntimeInformation(snapshot->runtimeInformation); return snapshot; } void FreeCapturedManagedMemorySnapshot(Il2CppManagedMemorySnapshot* snapshot) { FreeIL2CppManagedHeap(snapshot->heap); IL2CPP_FREE(snapshot->gcHandles.pointersToObjects); Il2CppMetadataSnapshot& metadata = snapshot->metadata; for (uint32_t i = 0; i < metadata.typeCount; i++) { if ((metadata.types[i].flags & kArray) == 0) { IL2CPP_FREE(metadata.types[i].fields); IL2CPP_FREE(metadata.types[i].statics); } IL2CPP_FREE(metadata.types[i].name); } IL2CPP_FREE(metadata.types); IL2CPP_FREE(snapshot); } } // namespace MemoryInformation } // namespace vm } // namespace il2cpp ================================================ FILE: unity_decoder/libil2cpp/vm/MemoryInformation.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppMetadataField { uint32_t offset; uint32_t typeIndex; const char* name; bool isStatic; }; enum Il2CppMetadataTypeFlags { kNone = 0, kValueType = 1 << 0, kArray = 1 << 1, kArrayRankMask = 0xFFFF0000 }; struct Il2CppMetadataType { Il2CppMetadataTypeFlags flags; // If it's an array, rank is encoded in the upper 2 bytes Il2CppMetadataField* fields; uint32_t fieldCount; uint32_t staticsSize; uint8_t* statics; uint32_t baseOrElementTypeIndex; char* name; const char* assemblyName; uint64_t typeInfoAddress; uint32_t size; }; struct Il2CppMetadataSnapshot { uint32_t typeCount; Il2CppMetadataType* types; }; struct Il2CppManagedMemorySection { uint64_t sectionStartAddress; uint32_t sectionSize; uint8_t* sectionBytes; }; struct Il2CppManagedHeap { uint32_t sectionCount; Il2CppManagedMemorySection* sections; }; struct Il2CppStacks { uint32_t stackCount; Il2CppManagedMemorySection* stacks; }; struct NativeObject { uint32_t gcHandleIndex; uint32_t size; uint32_t instanceId; uint32_t classId; uint32_t referencedNativeObjectIndicesCount; uint32_t* referencedNativeObjectIndices; }; struct Il2CppGCHandles { uint32_t trackedObjectCount; uint64_t* pointersToObjects; }; struct Il2CppRuntimeInformation { uint32_t pointerSize; uint32_t objectHeaderSize; uint32_t arrayHeaderSize; uint32_t arrayBoundsOffsetInHeader; uint32_t arraySizeOffsetInHeader; uint32_t allocationGranularity; }; struct Il2CppManagedMemorySnapshot { Il2CppManagedHeap heap; Il2CppStacks stacks; Il2CppMetadataSnapshot metadata; Il2CppGCHandles gcHandles; Il2CppRuntimeInformation runtimeInformation; void* additionalUserInformation; }; namespace il2cpp { namespace vm { namespace MemoryInformation { Il2CppManagedMemorySnapshot* CaptureManagedMemorySnapshot(); void FreeCapturedManagedMemorySnapshot(Il2CppManagedMemorySnapshot* snapshot); } } } ================================================ FILE: unity_decoder/libil2cpp/vm/MetadataAlloc.cpp ================================================ #include "il2cpp-config.h" #include "MetadataAlloc.h" #include "class-internals.h" #include "utils/MemoryPool.h" using il2cpp::utils::MemoryPool; namespace il2cpp { namespace vm { // we allocate these dynamically on runtime initialization // because the pool uses standard allocators, and we want to give embedding // client the chance to install their own allocator callbacks static MemoryPool* s_MetadataMemoryPool; static MemoryPool* s_GenericClassMemoryPool; static MemoryPool* s_GenericMethodMemoryPool; // This initial size (256k/512k) allows us enough room to initialize metadata // an empty Unity project and have a bit of room leftover. const size_t kInitialRegionSize = IL2CPP_SIZEOF_VOID_P * 64 * 1024; void MetadataAllocInitialize() { s_MetadataMemoryPool = new MemoryPool(kInitialRegionSize); // these can use the default smaller initial pool size s_GenericClassMemoryPool = new MemoryPool(); s_GenericMethodMemoryPool = new MemoryPool(); } void MetadataAllocCleanup() { delete s_MetadataMemoryPool; s_MetadataMemoryPool = NULL; delete s_GenericClassMemoryPool; s_GenericClassMemoryPool = NULL; delete s_GenericMethodMemoryPool; s_GenericMethodMemoryPool = NULL; } void* MetadataMalloc(size_t size) { return s_MetadataMemoryPool->Malloc(size); } void* MetadataCalloc(size_t count, size_t size) { return s_MetadataMemoryPool->Calloc(count, size); } Il2CppGenericClass* MetadataAllocGenericClass() { return (Il2CppGenericClass*)s_GenericClassMemoryPool->Calloc(1, sizeof(Il2CppGenericClass)); } Il2CppGenericMethod* MetadataAllocGenericMethod() { return (Il2CppGenericMethod*)s_GenericMethodMemoryPool->Calloc(1, sizeof(Il2CppGenericMethod)); } } } ================================================ FILE: unity_decoder/libil2cpp/vm/MetadataAlloc.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppGenericClass; struct Il2CppGenericMethod; namespace il2cpp { namespace vm { void MetadataAllocInitialize(); void MetadataAllocCleanup(); // These allocators assume the g_MetadataLock lock is held void* MetadataMalloc(size_t size); void* MetadataCalloc(size_t count, size_t size); // These metadata structures have their own locks, since they do lightweight initialization Il2CppGenericClass* MetadataAllocGenericClass(); Il2CppGenericMethod* MetadataAllocGenericMethod(); } // namespace vm } // namespace il2cpp ================================================ FILE: unity_decoder/libil2cpp/vm/MetadataCache.cpp ================================================ #include "il2cpp-config.h" #include "MetadataCache.h" #include #include #include "class-internals.h" #include "tabledefs.h" #include "gc/GarbageCollector.h" #include "metadata/ArrayMetadata.h" #include "metadata/GenericMetadata.h" #include "metadata/GenericMethod.h" #include "metadata/Il2CppTypeCompare.h" #include "metadata/Il2CppTypeHash.h" #include "metadata/Il2CppTypeVector.h" #include "metadata/Il2CppGenericContextCompare.h" #include "metadata/Il2CppGenericContextHash.h" #include "metadata/Il2CppGenericInstCompare.h" #include "metadata/Il2CppGenericInstHash.h" #include "metadata/Il2CppGenericMethodCompare.h" #include "metadata/Il2CppGenericMethodHash.h" #include "metadata/Il2CppSignatureCompare.h" #include "metadata/Il2CppSignatureHash.h" #include "os/Atomic.h" #include "os/Mutex.h" #include "utils/CallOnce.h" #include "utils/Collections.h" #include "utils/HashUtils.h" #include "utils/Il2CppHashMap.h" #include "utils/Il2CppHashSet.h" #include "utils/Memory.h" #include "utils/StringUtils.h" #include "utils/PathUtils.h" #include "vm/Assembly.h" #include "vm/Class.h" #include "vm/GenericClass.h" #include "vm/MetadataAlloc.h" #include "vm/MetadataLoader.h" #include "vm/MetadataLock.h" #include "vm/Method.h" #include "vm/Object.h" #include "vm/String.h" #include "vm/Type.h" #include "mono-runtime/il2cpp-mapping.h" #include "vm-utils/NativeSymbol.h" #include "vm-utils/VmStringUtils.h" using namespace il2cpp; using namespace il2cpp::utils::collections; using namespace il2cpp::vm; using il2cpp::gc::GarbageCollector; using il2cpp::metadata::ArrayMetadata; using il2cpp::metadata::GenericMetadata; using il2cpp::metadata::GenericMethod; using il2cpp::metadata::Il2CppGenericContextCompare; using il2cpp::metadata::Il2CppGenericContextHash; using il2cpp::metadata::Il2CppGenericInstCompare; using il2cpp::metadata::Il2CppGenericInstHash; using il2cpp::metadata::Il2CppGenericMethodCompare; using il2cpp::metadata::Il2CppGenericMethodHash; using il2cpp::metadata::Il2CppTypeLess; using il2cpp::metadata::Il2CppTypeEqualityComparer; using il2cpp::metadata::Il2CppTypeHash; using il2cpp::metadata::Il2CppTypeVector; using il2cpp::metadata::Il2CppSignatureCompare; using il2cpp::metadata::Il2CppSignatureHash; using il2cpp::os::Atomic; using il2cpp::os::FastAutoLock; using il2cpp::os::FastMutex; using il2cpp::utils::CallOnce; using il2cpp::utils::HashUtils; using il2cpp::utils::OnceFlag; using il2cpp::utils::PointerHash; using il2cpp::utils::StringUtils; using il2cpp::utils::VmStringUtils; typedef std::map PointerTypeMap; typedef Il2CppHashMap, VmStringUtils::CaseSensitiveComparer> WindowsRuntimeTypeNameToClassMap; typedef Il2CppHashMap > ClassToWindowsRuntimeTypeNameMap; typedef Il2CppHashSet Il2CppGenericMethodSet; typedef Il2CppGenericMethodSet::const_iterator Il2CppGenericMethodSetIter; static Il2CppGenericMethodSet s_GenericMethodSet; struct Il2CppMetadataCache { FastMutex m_CacheMutex; PointerTypeMap m_PointerTypes; }; static Il2CppMetadataCache s_MetadataCache; static Il2CppClass** s_TypeInfoTable = NULL; static Il2CppClass** s_TypeInfoDefinitionTable = NULL; static const MethodInfo** s_MethodInfoDefinitionTable = NULL; static Il2CppString** s_StringLiteralTable = NULL; static const Il2CppGenericMethod** s_GenericMethodTable = NULL; static int32_t s_ImagesCount = 0; static Il2CppImage* s_ImagesTable = NULL; typedef Il2CppHashSet Il2CppGenericInstSet; static Il2CppGenericInstSet s_GenericInstSet; typedef Il2CppHashMap Il2CppMethodTableMap; typedef Il2CppMethodTableMap::const_iterator Il2CppMethodTableMapIter; static Il2CppMethodTableMap s_MethodTableMap; typedef Il2CppHashMap, Il2CppMethodPointer, Il2CppSignatureHash, Il2CppSignatureCompare> Il2CppUnresolvedSignatureMap; typedef Il2CppUnresolvedSignatureMap::const_iterator Il2CppUnresolvedSignatureMapIter; static Il2CppUnresolvedSignatureMap *s_pUnresolvedSignatureMap; static const Il2CppCodeRegistration * s_Il2CppCodeRegistration; static const Il2CppMetadataRegistration * s_Il2CppMetadataRegistration; static const Il2CppCodeGenOptions* s_Il2CppCodeGenOptions; static CustomAttributesCache** s_CustomAttributesCaches; static CustomAttributeTypeCache** s_CustomAttributeTypeCaches; static WindowsRuntimeTypeNameToClassMap s_WindowsRuntimeTypeNameToClassMap; static ClassToWindowsRuntimeTypeNameMap s_ClassToWindowsRuntimeTypeNameMap; struct InteropDataToTypeConverter { inline const Il2CppType* operator()(const Il2CppInteropData& interopData) const { return interopData.type; } }; typedef il2cpp::utils::collections::ArrayValueMap InteropDataMap; static InteropDataMap s_InteropData; template static T MetadataOffset(void* metadata, size_t sectionOffset, size_t itemIndex) { return reinterpret_cast(reinterpret_cast(metadata) + sectionOffset) + itemIndex; } void MetadataCache::Register(const Il2CppCodeRegistration* const codeRegistration, const Il2CppMetadataRegistration* const metadataRegistration, const Il2CppCodeGenOptions* const codeGenOptions) { s_Il2CppCodeRegistration = codeRegistration; s_Il2CppMetadataRegistration = metadataRegistration; s_Il2CppCodeGenOptions = codeGenOptions; for (int32_t j = 0; j < metadataRegistration->genericClassesCount; j++) if (metadataRegistration->genericClasses[j]->typeDefinitionIndex != kTypeIndexInvalid) metadata::GenericMetadata::RegisterGenericClass(metadataRegistration->genericClasses[j]); for (int32_t i = 0; i < metadataRegistration->genericInstsCount; i++) s_GenericInstSet.insert(metadataRegistration->genericInsts[i]); s_InteropData.assign_external(codeRegistration->interopData, codeRegistration->interopDataCount); } static void* s_GlobalMetadata; static const Il2CppGlobalMetadataHeader* s_GlobalMetadataHeader; void MetadataCache::Initialize() { s_GlobalMetadata = vm::MetadataLoader::LoadMetadataFile("global-metadata.dat"); s_GlobalMetadataHeader = (const Il2CppGlobalMetadataHeader*)s_GlobalMetadata; IL2CPP_ASSERT(s_GlobalMetadataHeader->sanity == 0xFAB11BAF); IL2CPP_ASSERT(s_GlobalMetadataHeader->version == 24); const Il2CppAssembly* assemblies = (const Il2CppAssembly*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->assembliesOffset); for (uint32_t i = 0; i < s_GlobalMetadataHeader->assembliesCount / sizeof(Il2CppAssembly); i++) il2cpp::vm::Assembly::Register(assemblies + i); // Pre-allocate these arrays so we don't need to lock when reading later. // These arrays hold the runtime metadata representation for metadata explicitly // referenced during conversion. There is a corresponding table of same size // in the converted metadata, giving a description of runtime metadata to construct. s_TypeInfoTable = (Il2CppClass**)IL2CPP_CALLOC(s_Il2CppMetadataRegistration->typesCount, sizeof(Il2CppClass*)); s_TypeInfoDefinitionTable = (Il2CppClass**)IL2CPP_CALLOC(s_GlobalMetadataHeader->typeDefinitionsCount / sizeof(Il2CppTypeDefinition), sizeof(Il2CppClass*)); s_MethodInfoDefinitionTable = (const MethodInfo**)IL2CPP_CALLOC(s_GlobalMetadataHeader->methodsCount / sizeof(Il2CppMethodDefinition), sizeof(MethodInfo*)); s_GenericMethodTable = (const Il2CppGenericMethod**)IL2CPP_CALLOC(s_Il2CppMetadataRegistration->methodSpecsCount, sizeof(Il2CppGenericMethod*)); s_ImagesCount = s_GlobalMetadataHeader->imagesCount / sizeof(Il2CppImageDefinition); s_ImagesTable = (Il2CppImage*)IL2CPP_CALLOC(s_ImagesCount, sizeof(Il2CppImage)); // setup all the Il2CppImages. There are not many and it avoid locks later on const Il2CppImageDefinition* imagesDefinitions = (const Il2CppImageDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->imagesOffset); for (int32_t imageIndex = 0; imageIndex < s_ImagesCount; imageIndex++) { const Il2CppImageDefinition* imageDefinition = imagesDefinitions + imageIndex; Il2CppImage* image = s_ImagesTable + imageIndex; image->name = GetStringFromIndex(imageDefinition->nameIndex); std::string nameNoExt = utils::PathUtils::PathNoExtension(image->name); image->nameNoExt = (char*)IL2CPP_CALLOC(nameNoExt.size() + 1, sizeof(char)); strcpy(const_cast(image->nameNoExt), nameNoExt.c_str()); image->assemblyIndex = imageDefinition->assemblyIndex; image->typeStart = imageDefinition->typeStart; image->typeCount = imageDefinition->typeCount; image->exportedTypeStart = imageDefinition->exportedTypeStart; image->exportedTypeCount = imageDefinition->exportedTypeCount; image->entryPointIndex = imageDefinition->entryPointIndex; image->token = imageDefinition->token; } InitializeUnresolvedSignatureTable(); #if IL2CPP_ENABLE_NATIVE_STACKTRACES std::vector managedMethods; const Il2CppTypeDefinition* typeDefinitions = (const Il2CppTypeDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->typeDefinitionsOffset); for (size_t i = 0; i < s_GlobalMetadataHeader->assembliesCount / sizeof(Il2CppAssembly); i++) { const Il2CppImage* image = MetadataCache::GetImageFromIndex(assemblies[i].imageIndex); for (size_t j = 0; j < image->typeCount; j++) { const Il2CppTypeDefinition* type = typeDefinitions + image->typeStart + j; for (uint16_t u = 0; u < type->method_count; u++) { const Il2CppMethodDefinition* methodDefinition = GetMethodDefinitionFromIndex(type->methodStart + u); MethodDefinitionKey currentMethodList; currentMethodList.methodIndex = type->methodStart + u; currentMethodList.method = GetMethodPointerFromIndex(methodDefinition->methodIndex); if (currentMethodList.method) managedMethods.push_back(currentMethodList); } } } for (int32_t i = 0; i < s_Il2CppMetadataRegistration->genericMethodTableCount; i++) { const Il2CppGenericMethodFunctionsDefinitions* genericMethodIndices = s_Il2CppMetadataRegistration->genericMethodTable + i; MethodDefinitionKey currentMethodList; GenericMethodIndex genericMethodIndex = genericMethodIndices->genericMethodIndex; IL2CPP_ASSERT(genericMethodIndex < s_Il2CppMetadataRegistration->methodSpecsCount); const Il2CppMethodSpec* methodSpec = s_Il2CppMetadataRegistration->methodSpecs + genericMethodIndex; currentMethodList.methodIndex = methodSpec->methodDefinitionIndex; IL2CPP_ASSERT(genericMethodIndices->indices.methodIndex < static_cast(s_Il2CppCodeRegistration->genericMethodPointersCount)); currentMethodList.method = s_Il2CppCodeRegistration->genericMethodPointers[genericMethodIndices->indices.methodIndex]; managedMethods.push_back(currentMethodList); } il2cpp::utils::NativeSymbol::RegisterMethods(managedMethods); #endif } void MetadataCache::InitializeStringLiteralTable() { s_StringLiteralTable = (Il2CppString**)GarbageCollector::AllocateFixed(s_GlobalMetadataHeader->stringLiteralCount / sizeof(Il2CppStringLiteral) * sizeof(Il2CppString*), NULL); } void MetadataCache::InitializeGenericMethodTable() { for (int32_t i = 0; i < s_Il2CppMetadataRegistration->genericMethodTableCount; i++) { const Il2CppGenericMethodFunctionsDefinitions* genericMethodIndices = s_Il2CppMetadataRegistration->genericMethodTable + i; const Il2CppGenericMethod* genericMethod = GetGenericMethodFromIndex(genericMethodIndices->genericMethodIndex); s_MethodTableMap.insert(std::make_pair(genericMethod, &genericMethodIndices->indices)); } } void MetadataCache::InitializeWindowsRuntimeTypeNamesTables() { int32_t typeCount = s_GlobalMetadataHeader->windowsRuntimeTypeNamesSize / sizeof(Il2CppWindowsRuntimeTypeNamePair); const Il2CppWindowsRuntimeTypeNamePair* windowsRuntimeTypeNames = MetadataOffset(s_GlobalMetadata, s_GlobalMetadataHeader->windowsRuntimeTypeNamesOffset, 0); for (int32_t i = 0; i < typeCount; i++) { Il2CppWindowsRuntimeTypeNamePair typeNamePair = windowsRuntimeTypeNames[i]; const char* name = GetStringFromIndex(typeNamePair.nameIndex); const Il2CppType* type = GetIl2CppTypeFromIndex(typeNamePair.typeIndex); s_WindowsRuntimeTypeNameToClassMap.insert(std::make_pair(name, Class::FromIl2CppType(type))); s_ClassToWindowsRuntimeTypeNameMap.insert(std::make_pair(Class::FromIl2CppType(type), name)); } } // this is called later in the intialization cycle with more systems setup like GC void MetadataCache::InitializeGCSafe() { InitializeStringLiteralTable(); InitializeGenericMethodTable(); InitializeWindowsRuntimeTypeNamesTables(); } void MetadataCache::InitializeUnresolvedSignatureTable() { s_pUnresolvedSignatureMap = new Il2CppUnresolvedSignatureMap(); for (uint32_t i = 0; i < s_Il2CppCodeRegistration->unresolvedVirtualCallCount; ++i) { const Il2CppRange* range = MetadataOffset(s_GlobalMetadata, s_GlobalMetadataHeader->unresolvedVirtualCallParameterRangesOffset, i); il2cpp::utils::dynamic_array signature; for (int j = 0; j < range->length; ++j) { TypeIndex typeIndex = *MetadataOffset(s_GlobalMetadata, s_GlobalMetadataHeader->unresolvedVirtualCallParameterTypesOffset, range->start + j); const Il2CppType* type = MetadataCache::GetIl2CppTypeFromIndex(typeIndex); signature.push_back(type); } (*s_pUnresolvedSignatureMap)[signature] = s_Il2CppCodeRegistration->unresolvedVirtualCallPointers[i]; } } Il2CppClass* MetadataCache::GetGenericInstanceType(Il2CppClass* genericTypeDefinition, const Il2CppTypeVector& genericArgumentTypes) { const Il2CppGenericInst* inst = MetadataCache::GetGenericInst(genericArgumentTypes); Il2CppGenericClass* genericClass = GenericMetadata::GetGenericClass(genericTypeDefinition, inst); return GenericClass::GetClass(genericClass); } const MethodInfo* MetadataCache::GetGenericInstanceMethod(const MethodInfo* genericMethodDefinition, const Il2CppGenericContext* context) { const MethodInfo* method = genericMethodDefinition; const Il2CppGenericInst* classInst = context->class_inst; const Il2CppGenericInst* methodInst = context->method_inst; if (genericMethodDefinition->is_inflated) { IL2CPP_ASSERT(genericMethodDefinition->declaring_type->generic_class); classInst = genericMethodDefinition->declaring_type->generic_class->context.class_inst; method = genericMethodDefinition->genericMethod->methodDefinition; } const Il2CppGenericMethod* gmethod = GetGenericMethod(method, classInst, methodInst); return GenericMethod::GetMethod(gmethod); } const MethodInfo* MetadataCache::GetGenericInstanceMethod(const MethodInfo* genericMethodDefinition, const Il2CppTypeVector& genericArgumentTypes) { Il2CppGenericContext context = { NULL, GetGenericInst(genericArgumentTypes) }; return GetGenericInstanceMethod(genericMethodDefinition, &context); } const Il2CppGenericContext* MetadataCache::GetMethodGenericContext(const MethodInfo* method) { if (!method->is_inflated) { NOT_IMPLEMENTED(Image::GetMethodGenericContext); return NULL; } return &method->genericMethod->context; } const MethodInfo* MetadataCache::GetGenericMethodDefinition(const MethodInfo* method) { if (!method->is_inflated) { NOT_IMPLEMENTED(Image::GetGenericMethodDefinition); return NULL; } return method->genericMethod->methodDefinition; } const Il2CppGenericContainer* MetadataCache::GetMethodGenericContainer(const MethodInfo* method) { return method->genericContainer; } Il2CppClass* MetadataCache::GetPointerType(Il2CppClass* type) { os::FastAutoLock lock(&s_MetadataCache.m_CacheMutex); PointerTypeMap::const_iterator i = s_MetadataCache.m_PointerTypes.find(type); if (i == s_MetadataCache.m_PointerTypes.end()) return NULL; return i->second; } Il2CppClass* MetadataCache::GetWindowsRuntimeClass(const std::string& fullName) { WindowsRuntimeTypeNameToClassMap::iterator it = s_WindowsRuntimeTypeNameToClassMap.find(fullName.c_str()); if (it != s_WindowsRuntimeTypeNameToClassMap.end()) return it->second; return NULL; } const char* MetadataCache::GetWindowsRuntimeClassName(const Il2CppClass* klass) { ClassToWindowsRuntimeTypeNameMap::iterator it = s_ClassToWindowsRuntimeTypeNameMap.find(klass); if (it != s_ClassToWindowsRuntimeTypeNameMap.end()) return it->second; return NULL; } void MetadataCache::AddPointerType(Il2CppClass* type, Il2CppClass* pointerType) { os::FastAutoLock lock(&s_MetadataCache.m_CacheMutex); s_MetadataCache.m_PointerTypes.insert(std::make_pair(type, pointerType)); } const Il2CppGenericInst* MetadataCache::GetGenericInst(const Il2CppType* const* types, uint32_t typeCount) { // temporary inst to lookup a permanent one that may already exist Il2CppGenericInst inst; inst.type_argc = typeCount; inst.type_argv = (const Il2CppType**)alloca(inst.type_argc * sizeof(Il2CppType*)); size_t index = 0; const Il2CppType* const* typesEnd = types + typeCount; for (const Il2CppType* const* iter = types; iter != typesEnd; ++iter, ++index) inst.type_argv[index] = *iter; os::FastAutoLock lock(&s_MetadataCache.m_CacheMutex); Il2CppGenericInstSet::const_iterator iter = s_GenericInstSet.find(&inst); if (iter != s_GenericInstSet.end()) return *iter; Il2CppGenericInst* newInst = (Il2CppGenericInst*)IL2CPP_MALLOC(sizeof(Il2CppGenericInst)); newInst->type_argc = typeCount; newInst->type_argv = (const Il2CppType**)IL2CPP_MALLOC(newInst->type_argc * sizeof(Il2CppType*)); index = 0; for (const Il2CppType* const* iter = types; iter != typesEnd; ++iter, ++index) newInst->type_argv[index] = *iter; s_GenericInstSet.insert(newInst); ++il2cpp_runtime_stats.generic_instance_count; return newInst; } const Il2CppGenericInst* MetadataCache::GetGenericInst(const Il2CppTypeVector& types) { return GetGenericInst(&types[0], static_cast(types.size())); } static FastMutex s_GenericMethodMutex; const Il2CppGenericMethod* MetadataCache::GetGenericMethod(const MethodInfo* methodDefinition, const Il2CppGenericInst* classInst, const Il2CppGenericInst* methodInst) { Il2CppGenericMethod method = { 0 }; method.methodDefinition = methodDefinition; method.context.class_inst = classInst; method.context.method_inst = methodInst; FastAutoLock lock(&s_GenericMethodMutex); Il2CppGenericMethodSet::const_iterator iter = s_GenericMethodSet.find(&method); if (iter != s_GenericMethodSet.end()) return *iter; Il2CppGenericMethod* newMethod = MetadataAllocGenericMethod(); newMethod->methodDefinition = methodDefinition; newMethod->context.class_inst = classInst; newMethod->context.method_inst = methodInst; s_GenericMethodSet.insert(newMethod); return newMethod; } // this logic must match the C# logic in GenericSharingAnalysis.GetSharedTypeForGenericParameter static const Il2CppGenericInst* GetSharedInst(const Il2CppGenericInst* inst) { if (inst == NULL) return NULL; Il2CppTypeVector types; for (uint32_t i = 0; i < inst->type_argc; ++i) { if (Type::IsReference(inst->type_argv[i])) types.push_back(il2cpp_defaults.object_class->byval_arg); else { const Il2CppType* type = inst->type_argv[i]; if (s_Il2CppCodeGenOptions->enablePrimitiveValueTypeGenericSharing) { type = Type::GetUnderlyingType(type); if (type->type == IL2CPP_TYPE_BOOLEAN) type = il2cpp_defaults.byte_class->byval_arg; else if (type->type == IL2CPP_TYPE_CHAR) type = il2cpp_defaults.uint16_class->byval_arg; } if (Type::IsGenericInstance(type)) { const Il2CppGenericInst* sharedInst = GetSharedInst(type->data.generic_class->context.class_inst); Il2CppGenericClass* gklass = GenericMetadata::GetGenericClass(type->data.generic_class->typeDefinitionIndex, sharedInst); Il2CppClass* klass = GenericClass::GetClass(gklass); type = klass->byval_arg; } types.push_back(type); } } const Il2CppGenericInst* sharedInst = MetadataCache::GetGenericInst(types); return sharedInst; } InvokerMethod MetadataCache::GetInvokerMethodPointer(const MethodInfo* methodDefinition, const Il2CppGenericContext* context) { Il2CppGenericMethod method = { 0 }; method.methodDefinition = const_cast(methodDefinition); method.context.class_inst = context->class_inst; method.context.method_inst = context->method_inst; Il2CppMethodTableMapIter iter = s_MethodTableMap.find(&method); if (iter != s_MethodTableMap.end()) { IL2CPP_ASSERT(iter->second->invokerIndex >= 0); if (static_cast(iter->second->invokerIndex) < s_Il2CppCodeRegistration->invokerPointersCount) return s_Il2CppCodeRegistration->invokerPointers[iter->second->invokerIndex]; return NULL; } // get the shared version if it exists method.context.class_inst = GetSharedInst(context->class_inst); method.context.method_inst = GetSharedInst(context->method_inst); iter = s_MethodTableMap.find(&method); if (iter != s_MethodTableMap.end()) { IL2CPP_ASSERT(iter->second->invokerIndex >= 0); if (static_cast(iter->second->invokerIndex) < s_Il2CppCodeRegistration->invokerPointersCount) return s_Il2CppCodeRegistration->invokerPointers[iter->second->invokerIndex]; return NULL; } return NULL; } Il2CppMethodPointer MetadataCache::GetMethodPointer(const MethodInfo* methodDefinition, const Il2CppGenericContext* context) { Il2CppGenericMethod method = { 0 }; method.methodDefinition = const_cast(methodDefinition); method.context.class_inst = context->class_inst; method.context.method_inst = context->method_inst; Il2CppMethodTableMapIter iter = s_MethodTableMap.find(&method); if (iter != s_MethodTableMap.end()) { IL2CPP_ASSERT(iter->second->invokerIndex >= 0); if (static_cast(iter->second->methodIndex) < s_Il2CppCodeRegistration->genericMethodPointersCount) return s_Il2CppCodeRegistration->genericMethodPointers[iter->second->methodIndex]; return NULL; } method.context.class_inst = GetSharedInst(context->class_inst); method.context.method_inst = GetSharedInst(context->method_inst); iter = s_MethodTableMap.find(&method); if (iter != s_MethodTableMap.end()) { IL2CPP_ASSERT(iter->second->invokerIndex >= 0); if (static_cast(iter->second->methodIndex) < s_Il2CppCodeRegistration->genericMethodPointersCount) return s_Il2CppCodeRegistration->genericMethodPointers[iter->second->methodIndex]; return NULL; } return NULL; } Il2CppClass* MetadataCache::GetTypeInfoFromTypeIndex(TypeIndex index) { if (index == kTypeIndexInvalid) return NULL; IL2CPP_ASSERT(index < s_Il2CppMetadataRegistration->typesCount && "Invalid type index "); if (s_TypeInfoTable[index]) return s_TypeInfoTable[index]; const Il2CppType* type = s_Il2CppMetadataRegistration->types[index]; Il2CppClass *klass = il2cpp::vm::Class::FromIl2CppType(type); Class::Init(klass); s_TypeInfoTable[index] = klass; return s_TypeInfoTable[index]; } const Il2CppType* MetadataCache::GetIl2CppTypeFromIndex(TypeIndex index) { if (index == kTypeIndexInvalid) return NULL; IL2CPP_ASSERT(index < s_Il2CppMetadataRegistration->typesCount && "Invalid type index "); return s_Il2CppMetadataRegistration->types[index]; } const MethodInfo* MetadataCache::GetMethodInfoFromIndex(EncodedMethodIndex methodIndex) { uint32_t index = GetDecodedMethodIndex(methodIndex); if (index == 0) return NULL; if (GetEncodedIndexType(methodIndex) == kIl2CppMetadataUsageMethodRef) return GenericMethod::GetMethod(GetGenericMethodFromIndex(index)); else return MetadataCache::GetMethodInfoFromMethodDefinitionIndex(index); } const Il2CppGenericMethod* MetadataCache::GetGenericMethodFromIndex(GenericMethodIndex index) { IL2CPP_ASSERT(index < s_Il2CppMetadataRegistration->methodSpecsCount); if (s_GenericMethodTable[index]) return s_GenericMethodTable[index]; const Il2CppMethodSpec* methodSpec = s_Il2CppMetadataRegistration->methodSpecs + index; const MethodInfo* methodDefinition = GetMethodInfoFromMethodDefinitionIndex(methodSpec->methodDefinitionIndex); const Il2CppGenericInst* classInst = NULL; const Il2CppGenericInst* methodInst = NULL; if (methodSpec->classIndexIndex != -1) { IL2CPP_ASSERT(methodSpec->classIndexIndex < s_Il2CppMetadataRegistration->genericInstsCount); classInst = s_Il2CppMetadataRegistration->genericInsts[methodSpec->classIndexIndex]; } if (methodSpec->methodIndexIndex != -1) { IL2CPP_ASSERT(methodSpec->methodIndexIndex < s_Il2CppMetadataRegistration->genericInstsCount); methodInst = s_Il2CppMetadataRegistration->genericInsts[methodSpec->methodIndexIndex]; } s_GenericMethodTable[index] = GetGenericMethod(methodDefinition, classInst, methodInst); return s_GenericMethodTable[index]; } Il2CppMethodPointer MetadataCache::GetMethodPointerFromIndex(MethodIndex index) { if (index == kMethodIndexInvalid) return NULL; IL2CPP_ASSERT(index >= 0 && static_cast(index) < s_Il2CppCodeRegistration->methodPointersCount); return s_Il2CppCodeRegistration->methodPointers[index]; } InvokerMethod MetadataCache::GetMethodInvokerFromIndex(MethodIndex index) { if (index == kMethodIndexInvalid) return NULL; IL2CPP_ASSERT(index >= 0 && static_cast(index) < s_Il2CppCodeRegistration->invokerPointersCount); return s_Il2CppCodeRegistration->invokerPointers[index]; } const Il2CppInteropData* MetadataCache::GetInteropDataForType(const Il2CppType* type) { IL2CPP_ASSERT(type != NULL); InteropDataMap::iterator interopData = s_InteropData.find_first(type); if (interopData == s_InteropData.end()) return NULL; return interopData; } Il2CppMethodPointer MetadataCache::GetReversePInvokeWrapperFromIndex(MethodIndex index) { if (index == kMethodIndexInvalid) return NULL; IL2CPP_ASSERT(index >= 0 && static_cast(index) < s_Il2CppCodeRegistration->reversePInvokeWrapperCount); return s_Il2CppCodeRegistration->reversePInvokeWrappers[index]; } static const Il2CppType* GetReducedType(const Il2CppType* type) { if (type->byref) return il2cpp_defaults.object_class->byval_arg; if (Type::IsEnum(type)) type = Type::GetUnderlyingType(type); switch (type->type) { case IL2CPP_TYPE_BOOLEAN: return il2cpp_defaults.sbyte_class->byval_arg; case IL2CPP_TYPE_CHAR: return il2cpp_defaults.int16_class->byval_arg; case IL2CPP_TYPE_BYREF: case IL2CPP_TYPE_CLASS: case IL2CPP_TYPE_OBJECT: case IL2CPP_TYPE_STRING: case IL2CPP_TYPE_ARRAY: case IL2CPP_TYPE_SZARRAY: return il2cpp_defaults.object_class->byval_arg; case IL2CPP_TYPE_GENERICINST: if (Type::GenericInstIsValuetype(type)) return type; else return il2cpp_defaults.object_class->byval_arg; default: return type; } } Il2CppMethodPointer MetadataCache::GetUnresolvedVirtualCallStub(const MethodInfo* method) { il2cpp::utils::dynamic_array signature; signature.push_back(GetReducedType(method->return_type)); for (int i = 0; i < method->parameters_count; ++i) signature.push_back(GetReducedType(method->parameters[i].parameter_type)); Il2CppUnresolvedSignatureMapIter it = s_pUnresolvedSignatureMap->find(signature); if (it != s_pUnresolvedSignatureMap->end()) return it->second; return NULL; } static const Il2CppImage* GetImageForTypeDefinitionIndex(TypeDefinitionIndex index) { for (int32_t imageIndex = 0; imageIndex < s_ImagesCount; imageIndex++) { const Il2CppImage* image = s_ImagesTable + imageIndex; IL2CPP_ASSERT(index >= 0); if (index >= image->typeStart && static_cast(index) < (image->typeStart + image->typeCount)) return image; } IL2CPP_ASSERT(0 && "Failed to find owning image for type"); return NULL; } enum PackingSize { Zero, One, Two, Four, Eight, Sixteen, ThirtyTwo, SixtyFour, OneHundredTwentyEight }; static uint8_t ConvertPackingSizeEnumToValue(PackingSize packingSize) { switch (packingSize) { case Zero: return 0; case One: return 1; case Two: return 2; case Four: return 4; case Eight: return 8; case Sixteen: return 16; case ThirtyTwo: return 32; case SixtyFour: return 64; case OneHundredTwentyEight: return 128; default: Assert(0 && "Invalid packing size!"); return 0; } } static const int kBitIsValueType = 1; static const int kBitIsEnum = 2; static const int kBitHasFinalizer = 3; static const int kBitHasStaticConstructor = 4; static const int kBitIsBlittable = 5; static const int kBitIsImportOrWindowsRuntime = 6; static const int kPackingSize = 7; // This uses 4 bits from bit 7 to bit 10 static Il2CppClass* FromTypeDefinition(TypeDefinitionIndex index) { IL2CPP_ASSERT(index >= 0 && static_cast(index) < s_GlobalMetadataHeader->typeDefinitionsCount / sizeof(Il2CppTypeDefinition)); const Il2CppTypeDefinition* typeDefinitions = (const Il2CppTypeDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->typeDefinitionsOffset); const Il2CppTypeDefinition* typeDefinition = typeDefinitions + index; const Il2CppTypeDefinitionSizes* typeDefinitionSizes = s_Il2CppMetadataRegistration->typeDefinitionsSizes[index]; Il2CppClass* typeInfo = (Il2CppClass*)IL2CPP_CALLOC(1, sizeof(Il2CppClass) + (sizeof(VirtualInvokeData) * typeDefinition->vtable_count)); typeInfo->image = GetImageForTypeDefinitionIndex(index); typeInfo->name = MetadataCache::GetStringFromIndex(typeDefinition->nameIndex); typeInfo->namespaze = MetadataCache::GetStringFromIndex(typeDefinition->namespaceIndex); typeInfo->customAttributeIndex = typeDefinition->customAttributeIndex; typeInfo->byval_arg = MetadataCache::GetIl2CppTypeFromIndex(typeDefinition->byvalTypeIndex); typeInfo->this_arg = MetadataCache::GetIl2CppTypeFromIndex(typeDefinition->byrefTypeIndex); typeInfo->typeDefinition = typeDefinition; typeInfo->genericContainerIndex = typeDefinition->genericContainerIndex; typeInfo->instance_size = typeDefinitionSizes->instance_size; typeInfo->actualSize = typeDefinitionSizes->instance_size; // actualySize is instance_size for compiler generated values typeInfo->native_size = typeDefinitionSizes->native_size; typeInfo->static_fields_size = typeDefinitionSizes->static_fields_size; typeInfo->thread_static_fields_size = typeDefinitionSizes->thread_static_fields_size; typeInfo->thread_static_fields_offset = -1; typeInfo->flags = typeDefinition->flags; typeInfo->valuetype = (typeDefinition->bitfield >> (kBitIsValueType - 1)) & 0x1; typeInfo->enumtype = (typeDefinition->bitfield >> (kBitIsEnum - 1)) & 0x1; typeInfo->is_generic = typeDefinition->genericContainerIndex != kGenericContainerIndexInvalid; // generic if we have a generic container typeInfo->has_finalize = (typeDefinition->bitfield >> (kBitHasFinalizer - 1)) & 0x1; typeInfo->has_cctor = (typeDefinition->bitfield >> (kBitHasStaticConstructor - 1)) & 0x1; typeInfo->is_blittable = (typeDefinition->bitfield >> (kBitIsBlittable - 1)) & 0x1; typeInfo->is_import_or_windows_runtime = (typeDefinition->bitfield >> (kBitIsImportOrWindowsRuntime - 1)) & 0x1; typeInfo->packingSize = ConvertPackingSizeEnumToValue(static_cast((typeDefinition->bitfield >> (kPackingSize - 1)) & 0xF)); typeInfo->method_count = typeDefinition->method_count; typeInfo->property_count = typeDefinition->property_count; typeInfo->field_count = typeDefinition->field_count; typeInfo->event_count = typeDefinition->event_count; typeInfo->nested_type_count = typeDefinition->nested_type_count; typeInfo->vtable_count = typeDefinition->vtable_count; typeInfo->interfaces_count = typeDefinition->interfaces_count; typeInfo->interface_offsets_count = typeDefinition->interface_offsets_count; typeInfo->token = typeDefinition->token; typeInfo->interopData = MetadataCache::GetInteropDataForType(typeInfo->byval_arg); if (typeDefinition->parentIndex != kTypeIndexInvalid) typeInfo->parent = Class::FromIl2CppType(MetadataCache::GetIl2CppTypeFromIndex(typeDefinition->parentIndex)); if (typeDefinition->declaringTypeIndex != kTypeIndexInvalid) typeInfo->declaringType = Class::FromIl2CppType(MetadataCache::GetIl2CppTypeFromIndex(typeDefinition->declaringTypeIndex)); typeInfo->castClass = typeInfo->element_class = typeInfo; if (typeInfo->enumtype) typeInfo->castClass = typeInfo->element_class = Class::FromIl2CppType(MetadataCache::GetIl2CppTypeFromIndex(typeDefinition->elementTypeIndex)); return typeInfo; } const Il2CppAssembly* MetadataCache::GetAssemblyFromIndex(AssemblyIndex index) { if (index == kGenericContainerIndexInvalid) return NULL; IL2CPP_ASSERT(index >= 0 && static_cast(index) <= s_GlobalMetadataHeader->assembliesCount / sizeof(Il2CppAssembly)); const Il2CppAssembly* assemblies = (const Il2CppAssembly*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->assembliesOffset); return assemblies + index; } const Il2CppAssembly* MetadataCache::GetAssemblyByName(const std::string& name) { const Il2CppAssembly* assemblies = (const Il2CppAssembly*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->assembliesOffset); const char* nameToFind = name.c_str(); for (int i = 0; i < (int)(s_GlobalMetadataHeader->assembliesCount / sizeof(Il2CppAssembly)); i++) { const Il2CppAssembly* assembly = assemblies + i; const char* assemblyName = GetStringFromIndex(assembly->aname.nameIndex); if (strcmp(assemblyName, nameToFind) == 0) return assembly; } return NULL; } Il2CppImage* MetadataCache::GetImageFromIndex(ImageIndex index) { if (index == kGenericContainerIndexInvalid) return NULL; IL2CPP_ASSERT(index <= s_ImagesCount); return s_ImagesTable + index; } Il2CppClass* MetadataCache::GetTypeInfoFromTypeDefinitionIndex(TypeDefinitionIndex index) { if (index == kTypeIndexInvalid) return NULL; IL2CPP_ASSERT(index >= 0 && static_cast(index) < s_GlobalMetadataHeader->typeDefinitionsCount / sizeof(Il2CppTypeDefinition)); if (!s_TypeInfoDefinitionTable[index]) { // we need to use the metadata lock, since we may need to retrieve other Il2CppClass's when setting. Our parent may be a generic instance for example FastAutoLock lock(&g_MetadataLock); // double checked locking if (!s_TypeInfoDefinitionTable[index]) s_TypeInfoDefinitionTable[index] = FromTypeDefinition(index); } return s_TypeInfoDefinitionTable[index]; } const Il2CppTypeDefinition* MetadataCache::GetTypeDefinitionFromIndex(TypeDefinitionIndex index) { if (index == kTypeDefinitionIndexInvalid) return NULL; IL2CPP_ASSERT(index >= 0 && static_cast(index) < s_GlobalMetadataHeader->typeDefinitionsCount / sizeof(Il2CppTypeDefinition)); const Il2CppTypeDefinition* typeDefinitions = (const Il2CppTypeDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->typeDefinitionsOffset); return typeDefinitions + index; } TypeDefinitionIndex MetadataCache::GetExportedTypeFromIndex(TypeDefinitionIndex index) { if (index == kTypeDefinitionIndexInvalid) return kTypeDefinitionIndexInvalid; IL2CPP_ASSERT(index >= 0 && static_cast(index) < s_GlobalMetadataHeader->exportedTypeDefinitionsCount / sizeof(TypeDefinitionIndex)); TypeDefinitionIndex* exportedTypes = (TypeDefinitionIndex*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->exportedTypeDefinitionsOffset); return *(exportedTypes + index); } const Il2CppGenericContainer* MetadataCache::GetGenericContainerFromIndex(GenericContainerIndex index) { if (index == kGenericContainerIndexInvalid) return NULL; IL2CPP_ASSERT(index >= 0 && static_cast(index) <= s_GlobalMetadataHeader->genericContainersCount / sizeof(Il2CppGenericContainer)); const Il2CppGenericContainer* genericContainers = (const Il2CppGenericContainer*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->genericContainersOffset); return genericContainers + index; } const Il2CppGenericParameter* MetadataCache::GetGenericParameterFromIndex(GenericParameterIndex index) { if (index == kGenericParameterIndexInvalid) return NULL; IL2CPP_ASSERT(index >= 0 && static_cast(index) <= s_GlobalMetadataHeader->genericParametersCount / sizeof(Il2CppGenericParameter)); const Il2CppGenericParameter* genericParameters = (const Il2CppGenericParameter*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->genericParametersOffset); return genericParameters + index; } const Il2CppType* MetadataCache::GetGenericParameterConstraintFromIndex(GenericParameterConstraintIndex index) { IL2CPP_ASSERT(index >= 0 && static_cast(index) <= s_GlobalMetadataHeader->genericParameterConstraintsCount / sizeof(TypeIndex)); const TypeIndex* constraintIndices = (const TypeIndex*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->genericParameterConstraintsOffset); return GetIl2CppTypeFromIndex(constraintIndices[index]); } Il2CppClass* MetadataCache::GetNestedTypeFromIndex(NestedTypeIndex index) { IL2CPP_ASSERT(index >= 0 && static_cast(index) <= s_GlobalMetadataHeader->nestedTypesCount / sizeof(TypeDefinitionIndex)); const TypeDefinitionIndex* nestedTypeIndices = (const TypeDefinitionIndex*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->nestedTypesOffset); return GetTypeInfoFromTypeDefinitionIndex(nestedTypeIndices[index]); } const Il2CppType* MetadataCache::GetInterfaceFromIndex(InterfacesIndex index) { IL2CPP_ASSERT(index >= 0 && static_cast(index) <= s_GlobalMetadataHeader->interfacesCount / sizeof(TypeIndex)); const TypeIndex* interfaceIndices = (const TypeIndex*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->interfacesOffset); return GetIl2CppTypeFromIndex(interfaceIndices[index]); } EncodedMethodIndex MetadataCache::GetVTableMethodFromIndex(VTableIndex index) { IL2CPP_ASSERT(index >= 0 && static_cast(index) <= s_GlobalMetadataHeader->vtableMethodsCount / sizeof(EncodedMethodIndex)); const EncodedMethodIndex* methodReferences = (const EncodedMethodIndex*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->vtableMethodsOffset); return methodReferences[index]; } Il2CppInterfaceOffsetPair MetadataCache::GetInterfaceOffsetIndex(InterfaceOffsetIndex index) { IL2CPP_ASSERT(index >= 0 && static_cast(index) <= s_GlobalMetadataHeader->interfaceOffsetsCount / sizeof(Il2CppInterfaceOffsetPair)); const Il2CppInterfaceOffsetPair* interfaceOffsets = (const Il2CppInterfaceOffsetPair*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->interfaceOffsetsOffset); return interfaceOffsets[index]; } const Il2CppRGCTXDefinition* MetadataCache::GetRGCTXDefinitionFromIndex(RGCTXIndex index) { IL2CPP_ASSERT(index >= 0 && static_cast(index) <= s_GlobalMetadataHeader->rgctxEntriesCount / sizeof(Il2CppRGCTXDefinition)); const Il2CppRGCTXDefinition* rgctxEntries = (const Il2CppRGCTXDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->rgctxEntriesOffset); return rgctxEntries + index; } const Il2CppEventDefinition* MetadataCache::GetEventDefinitionFromIndex(EventIndex index) { IL2CPP_ASSERT(index >= 0 && static_cast(index) <= s_GlobalMetadataHeader->eventsCount / sizeof(Il2CppEventDefinition)); const Il2CppEventDefinition* events = (const Il2CppEventDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->eventsOffset); return events + index; } const Il2CppFieldDefinition* MetadataCache::GetFieldDefinitionFromIndex(FieldIndex index) { IL2CPP_ASSERT(index >= 0 && static_cast(index) <= s_GlobalMetadataHeader->fieldsCount / sizeof(Il2CppFieldDefinition)); const Il2CppFieldDefinition* fields = (const Il2CppFieldDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->fieldsOffset); return fields + index; } const Il2CppFieldDefaultValue* MetadataCache::GetFieldDefaultValueFromIndex(FieldIndex index) { IL2CPP_ASSERT(index >= 0 && static_cast(index) <= s_GlobalMetadataHeader->fieldDefaultValuesCount / sizeof(Il2CppFieldDefaultValue)); const Il2CppFieldDefaultValue* defaultValues = (const Il2CppFieldDefaultValue*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->fieldDefaultValuesOffset); return defaultValues + index; } const uint8_t* MetadataCache::GetFieldDefaultValueDataFromIndex(FieldIndex index) { IL2CPP_ASSERT(index >= 0 && static_cast(index) <= s_GlobalMetadataHeader->fieldAndParameterDefaultValueDataCount / sizeof(uint8_t)); const uint8_t* defaultValuesData = (const uint8_t*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->fieldAndParameterDefaultValueDataOffset); return defaultValuesData + index; } const Il2CppFieldDefaultValue* MetadataCache::GetFieldDefaultValueForField(const FieldInfo* field) { Il2CppClass* parent = field->parent; size_t fieldIndex = (field - parent->fields); if (Type::IsGenericInstance(parent->byval_arg)) fieldIndex += GenericClass::GetTypeDefinition(parent->generic_class)->typeDefinition->fieldStart; else fieldIndex += parent->typeDefinition->fieldStart; const Il2CppFieldDefaultValue *start = (const Il2CppFieldDefaultValue*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->fieldDefaultValuesOffset); const Il2CppFieldDefaultValue *entry = start; while (entry < start + s_GlobalMetadataHeader->fieldDefaultValuesCount) { if (fieldIndex == entry->fieldIndex) { return entry; } entry++; } IL2CPP_ASSERT(0); return NULL; } const Il2CppParameterDefaultValue * il2cpp::vm::MetadataCache::GetParameterDefaultValueForParameter(const MethodInfo* method, const ParameterInfo* parameter) { if (Method::IsGenericInstance(method)) method = GetGenericMethodDefinition(method); IL2CPP_ASSERT(!Method::IsGenericInstance(method)); if (method->methodDefinition == NULL) return NULL; size_t parameterIndex = method->methodDefinition->parameterStart + parameter->position; const Il2CppParameterDefaultValue *start = (const Il2CppParameterDefaultValue*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->parameterDefaultValuesOffset); const Il2CppParameterDefaultValue *entry = start; while (entry < start + s_GlobalMetadataHeader->parameterDefaultValuesCount) { if (parameterIndex == entry->parameterIndex) return entry; entry++; } return NULL; } const uint8_t* MetadataCache::GetParameterDefaultValueDataFromIndex(ParameterIndex index) { IL2CPP_ASSERT(index >= 0 && static_cast(index) <= s_GlobalMetadataHeader->fieldAndParameterDefaultValueDataCount / sizeof(uint8_t)); const uint8_t* defaultValuesData = (const uint8_t*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->fieldAndParameterDefaultValueDataOffset); return defaultValuesData + index; } int MetadataCache::GetFieldMarshaledSizeForField(const FieldInfo* field) { Il2CppClass* parent = field->parent; size_t fieldIndex = (field - parent->fields); fieldIndex += parent->typeDefinition->fieldStart; const Il2CppFieldMarshaledSize *start = (const Il2CppFieldMarshaledSize*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->fieldMarshaledSizesOffset); const Il2CppFieldMarshaledSize *entry = start; while ((intptr_t)entry < (intptr_t)start + s_GlobalMetadataHeader->fieldMarshaledSizesCount) { if (fieldIndex == entry->fieldIndex) return entry->size; entry++; } return -1; } const Il2CppMethodDefinition* MetadataCache::GetMethodDefinitionFromIndex(MethodIndex index) { IL2CPP_ASSERT(index >= 0 && static_cast(index) <= s_GlobalMetadataHeader->methodsCount / sizeof(Il2CppMethodDefinition)); const Il2CppMethodDefinition* methods = (const Il2CppMethodDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->methodsOffset); return methods + index; } const MethodInfo* MetadataCache::GetMethodInfoFromMethodDefinitionIndex(MethodIndex index) { IL2CPP_ASSERT(index >= 0 && static_cast(index) <= s_GlobalMetadataHeader->methodsCount / sizeof(Il2CppMethodDefinition)); if (!s_MethodInfoDefinitionTable[index]) { const Il2CppMethodDefinition* methodDefinition = GetMethodDefinitionFromIndex(index); Il2CppClass* typeInfo = GetTypeInfoFromTypeDefinitionIndex(methodDefinition->declaringType); Class::SetupMethods(typeInfo); s_MethodInfoDefinitionTable[index] = typeInfo->methods[index - typeInfo->typeDefinition->methodStart]; } return s_MethodInfoDefinitionTable[index]; } const Il2CppPropertyDefinition* MetadataCache::GetPropertyDefinitionFromIndex(PropertyIndex index) { IL2CPP_ASSERT(index >= 0 && static_cast(index) <= s_GlobalMetadataHeader->propertiesCount / sizeof(Il2CppPropertyDefinition)); const Il2CppPropertyDefinition* properties = (const Il2CppPropertyDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->propertiesOffset); return properties + index; } const Il2CppParameterDefinition* MetadataCache::GetParameterDefinitionFromIndex(ParameterIndex index) { IL2CPP_ASSERT(index >= 0 && static_cast(index) <= s_GlobalMetadataHeader->parametersCount / sizeof(Il2CppParameterDefinition)); const Il2CppParameterDefinition* parameters = (const Il2CppParameterDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->parametersOffset); return parameters + index; } int32_t MetadataCache::GetFieldOffsetFromIndex(TypeIndex typeIndex, int32_t fieldIndexInType) { IL2CPP_ASSERT(typeIndex <= s_Il2CppMetadataRegistration->typeDefinitionsSizesCount); return s_Il2CppMetadataRegistration->fieldOffsets[typeIndex][fieldIndexInType]; } int32_t MetadataCache::GetReferenceAssemblyIndexIntoAssemblyTable(int32_t referencedAssemblyTableIndex) { IL2CPP_ASSERT(referencedAssemblyTableIndex >= 0 && static_cast(referencedAssemblyTableIndex) <= s_GlobalMetadataHeader->referencedAssembliesCount / sizeof(int32_t)); const int32_t* referenceAssemblyIndicies = (const int32_t*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->referencedAssembliesOffset); return referenceAssemblyIndicies[referencedAssemblyTableIndex]; } const TypeDefinitionIndex MetadataCache::GetIndexForTypeDefinition(const Il2CppClass* typeDefinition) { IL2CPP_ASSERT(typeDefinition->typeDefinition); const Il2CppTypeDefinition* typeDefinitions = (const Il2CppTypeDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->typeDefinitionsOffset); IL2CPP_ASSERT(typeDefinition->typeDefinition >= typeDefinitions && typeDefinition->typeDefinition < typeDefinitions + s_GlobalMetadataHeader->typeDefinitionsCount); ptrdiff_t index = typeDefinition->typeDefinition - typeDefinitions; IL2CPP_ASSERT(index <= std::numeric_limits::max()); return static_cast(index); } const GenericParameterIndex MetadataCache::GetIndexForGenericParameter(const Il2CppGenericParameter* genericParameter) { const Il2CppGenericParameter* genericParameters = (const Il2CppGenericParameter*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->genericParametersOffset); IL2CPP_ASSERT(genericParameter >= genericParameters && genericParameter < genericParameters + s_GlobalMetadataHeader->genericParametersCount); ptrdiff_t index = genericParameter - genericParameters; IL2CPP_ASSERT(index <= std::numeric_limits::max()); return static_cast(index); } static OnceFlag s_CustomAttributesOnceFlag; static void InitializeCustomAttributesCaches(void* arg) { s_CustomAttributesCaches = (CustomAttributesCache**)IL2CPP_CALLOC(s_Il2CppCodeRegistration->customAttributeCount, sizeof(CustomAttributesCache*)); s_CustomAttributeTypeCaches = (CustomAttributeTypeCache**)IL2CPP_CALLOC(s_Il2CppCodeRegistration->customAttributeCount, sizeof(CustomAttributeTypeCache*)); } CustomAttributesCache* MetadataCache::GenerateCustomAttributesCache(CustomAttributeIndex index) { if (index == 0) return NULL; IL2CPP_ASSERT(index > 0 && index <= s_Il2CppCodeRegistration->customAttributeCount); IL2CPP_ASSERT(index > 0 && index <= static_cast(s_GlobalMetadataHeader->attributesInfoCount / sizeof(Il2CppCustomAttributeTypeRange))); CallOnce(s_CustomAttributesOnceFlag, &InitializeCustomAttributesCaches, NULL); // use atomics rather than a Mutex here to avoid deadlock. The attribute generators call arbitrary managed code CustomAttributesCache* cache = Atomic::ReadPointer(&s_CustomAttributesCaches[index]); if (cache == NULL) { const Il2CppCustomAttributeTypeRange* attributeTypeRange = MetadataOffset(s_GlobalMetadata, s_GlobalMetadataHeader->attributesInfoOffset, index); cache = (CustomAttributesCache*)IL2CPP_CALLOC(1, sizeof(CustomAttributesCache)); cache->count = attributeTypeRange->count; cache->attributes = (Il2CppObject**)GarbageCollector::AllocateFixed(sizeof(Il2CppObject *) * cache->count, 0); for (int32_t i = 0; i < attributeTypeRange->count; i++) { IL2CPP_ASSERT(attributeTypeRange->start + i < s_GlobalMetadataHeader->attributeTypesCount); TypeIndex typeIndex = *MetadataOffset(s_GlobalMetadata, s_GlobalMetadataHeader->attributeTypesOffset, attributeTypeRange->start + i); cache->attributes[i] = il2cpp::vm::Object::New(GetTypeInfoFromTypeIndex(typeIndex)); } // generated code calls the attribute constructor and sets any fields/properties s_Il2CppCodeRegistration->customAttributeGenerators[index](cache); CustomAttributesCache* original = Atomic::CompareExchangePointer(&s_CustomAttributesCaches[index], cache, (CustomAttributesCache*)NULL); if (original) { // A non-NULL return value indicates some other thread already generated this cache. // We need to cleanup the resources we allocated GarbageCollector::FreeFixed(cache->attributes); IL2CPP_FREE(cache); cache = original; } } return cache; } CustomAttributeTypeCache* MetadataCache::GenerateCustomAttributeTypeCache(CustomAttributeIndex index) { if (index == 0) return NULL; IL2CPP_ASSERT(index > 0 && index <= s_Il2CppCodeRegistration->customAttributeCount); IL2CPP_ASSERT(index > 0 && index <= static_cast(s_GlobalMetadataHeader->attributesInfoCount / sizeof(Il2CppCustomAttributeTypeRange))); CallOnce(s_CustomAttributesOnceFlag, &InitializeCustomAttributesCaches, NULL); // use atomics rather than a Mutex here to avoid deadlock. The attribute generators call arbitrary managed code CustomAttributeTypeCache* cache = Atomic::ReadPointer(&s_CustomAttributeTypeCaches[index]); if (cache == NULL) { const Il2CppCustomAttributeTypeRange* attributeTypeRange = MetadataOffset(s_GlobalMetadata, s_GlobalMetadataHeader->attributesInfoOffset, index); cache = (CustomAttributeTypeCache*)IL2CPP_CALLOC(1, sizeof(CustomAttributeTypeCache)); cache->count = attributeTypeRange->count; cache->attributeTypes = (Il2CppClass**)IL2CPP_CALLOC(cache->count, sizeof(Il2CppClass*)); for (int32_t i = 0; i < attributeTypeRange->count; i++) { IL2CPP_ASSERT(attributeTypeRange->start + i < s_GlobalMetadataHeader->attributeTypesCount); TypeIndex typeIndex = *MetadataOffset(s_GlobalMetadata, s_GlobalMetadataHeader->attributeTypesOffset, attributeTypeRange->start + i); cache->attributeTypes[i] = GetTypeInfoFromTypeIndex(typeIndex); } CustomAttributeTypeCache* original = Atomic::CompareExchangePointer(&s_CustomAttributeTypeCaches[index], cache, (CustomAttributeTypeCache*)NULL); if (original) { // A non-NULL return value indicates some other thread already generated this cache. // We need to cleanup the resources we allocated IL2CPP_FREE(cache->attributeTypes); IL2CPP_FREE(cache); cache = original; } } return cache; } Il2CppString* MetadataCache::GetStringLiteralFromIndex(StringLiteralIndex index) { if (index == kStringLiteralIndexInvalid) return NULL; IL2CPP_ASSERT(index >= 0 && static_cast(index) < s_GlobalMetadataHeader->stringLiteralCount / sizeof(Il2CppStringLiteral) && "Invalid string literal index "); if (s_StringLiteralTable[index]) return s_StringLiteralTable[index]; const Il2CppStringLiteral* stringLiteral = (const Il2CppStringLiteral*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->stringLiteralOffset) + index; s_StringLiteralTable[index] = String::NewLen((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->stringLiteralDataOffset + stringLiteral->dataIndex, stringLiteral->length); return s_StringLiteralTable[index]; } const char* MetadataCache::GetStringFromIndex(StringIndex index) { IL2CPP_ASSERT(index <= s_GlobalMetadataHeader->stringCount); const char* strings = ((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->stringOffset) + index; return strings; } FieldInfo* MetadataCache::GetFieldInfoFromIndex(EncodedMethodIndex index) { IL2CPP_ASSERT(s_GlobalMetadataHeader->fieldRefsCount >= 0 && index <= static_cast(s_GlobalMetadataHeader->fieldRefsCount)); const Il2CppFieldRef* fieldRef = MetadataOffset(s_GlobalMetadata, s_GlobalMetadataHeader->fieldRefsOffset, index); Il2CppClass* typeInfo = GetTypeInfoFromTypeIndex(fieldRef->typeIndex); return typeInfo->fields + fieldRef->fieldIndex; } void MetadataCache::InitializeMethodMetadata(uint32_t index) { IL2CPP_ASSERT(s_GlobalMetadataHeader->metadataUsageListsCount >= 0 && index <= static_cast(s_GlobalMetadataHeader->metadataUsageListsCount)); const Il2CppMetadataUsageList* metadataUsageLists = MetadataOffset(s_GlobalMetadata, s_GlobalMetadataHeader->metadataUsageListsOffset, index); uint32_t start = metadataUsageLists->start; uint32_t count = metadataUsageLists->count; for (uint32_t i = 0; i < count; i++) { uint32_t offset = start + i; IL2CPP_ASSERT(s_GlobalMetadataHeader->metadataUsagePairsCount >= 0 && offset <= static_cast(s_GlobalMetadataHeader->metadataUsagePairsCount)); const Il2CppMetadataUsagePair* metadataUsagePairs = MetadataOffset(s_GlobalMetadata, s_GlobalMetadataHeader->metadataUsagePairsOffset, offset); uint32_t destinationIndex = metadataUsagePairs->destinationIndex; uint32_t encodedSourceIndex = metadataUsagePairs->encodedSourceIndex; Il2CppMetadataUsage usage = GetEncodedIndexType(encodedSourceIndex); uint32_t decodedIndex = GetDecodedMethodIndex(encodedSourceIndex); switch (usage) { case kIl2CppMetadataUsageTypeInfo: *s_Il2CppMetadataRegistration->metadataUsages[destinationIndex] = GetTypeInfoFromTypeIndex(decodedIndex); break; case kIl2CppMetadataUsageIl2CppType: *s_Il2CppMetadataRegistration->metadataUsages[destinationIndex] = const_cast(GetIl2CppTypeFromIndex(decodedIndex)); break; case kIl2CppMetadataUsageMethodDef: case kIl2CppMetadataUsageMethodRef: *s_Il2CppMetadataRegistration->metadataUsages[destinationIndex] = const_cast(GetMethodInfoFromIndex(encodedSourceIndex)); break; case kIl2CppMetadataUsageFieldInfo: *s_Il2CppMetadataRegistration->metadataUsages[destinationIndex] = GetFieldInfoFromIndex(decodedIndex); break; case kIl2CppMetadataUsageStringLiteral: *s_Il2CppMetadataRegistration->metadataUsages[destinationIndex] = GetStringLiteralFromIndex(decodedIndex); break; default: NOT_IMPLEMENTED(MetadataCache::InitializeMethodMetadata); break; } } } void MetadataCache::WalkPointerTypes(WalkTypesCallback callback, void* context) { os::FastAutoLock lock(&s_MetadataCache.m_CacheMutex); for (PointerTypeMap::iterator it = s_MetadataCache.m_PointerTypes.begin(); it != s_MetadataCache.m_PointerTypes.end(); it++) { callback(it->second, context); } } ================================================ FILE: unity_decoder/libil2cpp/vm/MetadataCache.h ================================================ #pragma once #include #include #include "il2cpp-config.h" #include "Assembly.h" #include "metadata/Il2CppTypeVector.h" #include "class-internals.h" struct MethodInfo; struct Il2CppClass; struct Il2CppGenericContainer; struct Il2CppGenericContext; struct Il2CppGenericInst; struct Il2CppGenericMethod; struct Il2CppType; struct Il2CppString; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API MetadataCache { public: static void Register(const Il2CppCodeRegistration * const codeRegistration, const Il2CppMetadataRegistration * const metadataRegistration, const Il2CppCodeGenOptions* const codeGenOptions); static void Initialize(); static void InitializeGCSafe(); static Il2CppClass* GetGenericInstanceType(Il2CppClass* genericTypeDefinition, const il2cpp::metadata::Il2CppTypeVector& genericArgumentTypes); static const MethodInfo* GetGenericInstanceMethod(const MethodInfo* genericMethodDefinition, const Il2CppGenericContext* context); static const MethodInfo* GetGenericInstanceMethod(const MethodInfo* genericMethodDefinition, const il2cpp::metadata::Il2CppTypeVector& genericArgumentTypes); static const Il2CppGenericContext* GetMethodGenericContext(const MethodInfo* method); static const Il2CppGenericContainer* GetMethodGenericContainer(const MethodInfo* method); static const MethodInfo* GetGenericMethodDefinition(const MethodInfo* method); static Il2CppClass* GetPointerType(Il2CppClass* type); static Il2CppClass* GetWindowsRuntimeClass(const std::string& fullName); static const char* GetWindowsRuntimeClassName(const Il2CppClass* klass); static void AddPointerType(Il2CppClass* type, Il2CppClass* pointerType); static const Il2CppGenericInst* GetGenericInst(const Il2CppType* const* types, uint32_t typeCount); static const Il2CppGenericInst* GetGenericInst(const il2cpp::metadata::Il2CppTypeVector& types); static const Il2CppGenericMethod* GetGenericMethod(const MethodInfo* methodDefinition, const Il2CppGenericInst* classInst, const Il2CppGenericInst* methodInst); static InvokerMethod GetInvokerMethodPointer(const MethodInfo* methodDefinition, const Il2CppGenericContext* context); static Il2CppMethodPointer GetMethodPointer(const MethodInfo* methodDefinition, const Il2CppGenericContext* context); static Il2CppClass* GetTypeInfoFromTypeIndex(TypeIndex index); static const Il2CppType* GetIl2CppTypeFromIndex(TypeIndex index); static const MethodInfo* GetMethodInfoFromIndex(EncodedMethodIndex index); static const Il2CppGenericMethod* GetGenericMethodFromIndex(GenericMethodIndex index); static Il2CppString* GetStringLiteralFromIndex(StringLiteralIndex index); static const char* GetStringFromIndex(StringIndex index); static FieldInfo* GetFieldInfoFromIndex(EncodedMethodIndex index); static void InitializeMethodMetadata(uint32_t index); static Il2CppMethodPointer GetMethodPointerFromIndex(MethodIndex index); static InvokerMethod GetMethodInvokerFromIndex(MethodIndex index); static const Il2CppInteropData* GetInteropDataForType(const Il2CppType* type); static Il2CppMethodPointer GetReversePInvokeWrapperFromIndex(MethodIndex index); static Il2CppMethodPointer GetUnresolvedVirtualCallStub(const MethodInfo* method); static const Il2CppAssembly* GetAssemblyFromIndex(AssemblyIndex index); static const Il2CppAssembly* GetAssemblyByName(const std::string& name); static Il2CppImage* GetImageFromIndex(ImageIndex index); static Il2CppClass* GetTypeInfoFromTypeDefinitionIndex(TypeDefinitionIndex index); static const Il2CppTypeDefinition* GetTypeDefinitionFromIndex(TypeDefinitionIndex index); static TypeDefinitionIndex GetExportedTypeFromIndex(TypeDefinitionIndex index); static const Il2CppGenericContainer* GetGenericContainerFromIndex(GenericContainerIndex index); static const Il2CppGenericParameter* GetGenericParameterFromIndex(GenericParameterIndex index); static const Il2CppType* GetGenericParameterConstraintFromIndex(GenericParameterConstraintIndex index); static Il2CppClass* GetNestedTypeFromIndex(NestedTypeIndex index); static const Il2CppType* GetInterfaceFromIndex(InterfacesIndex index); static EncodedMethodIndex GetVTableMethodFromIndex(VTableIndex index); static Il2CppInterfaceOffsetPair GetInterfaceOffsetIndex(InterfaceOffsetIndex index); static const Il2CppRGCTXDefinition* GetRGCTXDefinitionFromIndex(RGCTXIndex index); static const Il2CppEventDefinition* GetEventDefinitionFromIndex(EventIndex index); static const Il2CppFieldDefinition* GetFieldDefinitionFromIndex(FieldIndex index); static const Il2CppFieldDefaultValue* GetFieldDefaultValueFromIndex(FieldIndex index); static const uint8_t* GetFieldDefaultValueDataFromIndex(FieldIndex index); static const Il2CppFieldDefaultValue* GetFieldDefaultValueForField(const FieldInfo* field); static const uint8_t* GetParameterDefaultValueDataFromIndex(ParameterIndex index); static const Il2CppParameterDefaultValue* GetParameterDefaultValueForParameter(const MethodInfo* method, const ParameterInfo* parameter); static int GetFieldMarshaledSizeForField(const FieldInfo* field); static const Il2CppMethodDefinition* GetMethodDefinitionFromIndex(MethodIndex index); static const MethodInfo* GetMethodInfoFromMethodDefinitionIndex(MethodIndex index); static const Il2CppPropertyDefinition* GetPropertyDefinitionFromIndex(PropertyIndex index); static const Il2CppParameterDefinition* GetParameterDefinitionFromIndex(ParameterIndex index); // returns the compiler computer field offset for type definition fields static int32_t GetFieldOffsetFromIndex(TypeIndex typeIndex, int32_t fieldIndexInType); static int32_t GetReferenceAssemblyIndexIntoAssemblyTable(int32_t referencedAssemblyTableIndex); static const TypeDefinitionIndex GetIndexForTypeDefinition(const Il2CppClass* typeDefinition); static const GenericParameterIndex GetIndexForGenericParameter(const Il2CppGenericParameter* genericParameter); static CustomAttributesCache* GenerateCustomAttributesCache(CustomAttributeIndex index); static CustomAttributeTypeCache* GenerateCustomAttributeTypeCache(CustomAttributeIndex index); typedef void(*WalkTypesCallback)(Il2CppClass* type, void* context); static void WalkPointerTypes(WalkTypesCallback callback, void* context); private: static void InitializeUnresolvedSignatureTable(); static void InitializeStringLiteralTable(); static void InitializeGenericMethodTable(); static void InitializeWindowsRuntimeTypeNamesTables(); }; } // namespace vm } // namespace il2cpp ================================================ FILE: unity_decoder/libil2cpp/vm/MetadataLoader.cpp ================================================ #include "il2cpp-config.h" #include "MetadataLoader.h" #include "os/File.h" #include "os/MemoryMappedFile.h" #include "os/Mutex.h" #include "utils/PathUtils.h" #include "utils/Runtime.h" using namespace il2cpp::os; using namespace il2cpp::vm; void* MetadataLoader::LoadMetadataFile(const char* fileName) { std::string resourcesDirectory = utils::PathUtils::Combine(utils::Runtime::GetDataDir(), utils::StringView("Metadata")); std::string resourceFilePath = utils::PathUtils::Combine(resourcesDirectory, utils::StringView(fileName, strlen(fileName))); int error = 0; FileHandle* handle = File::Open(resourceFilePath, kFileModeOpen, kFileAccessRead, kFileShareRead, kFileOptionsNone, &error); if (error != 0) return NULL; void* fileBuffer = MemoryMappedFile::Map(handle); File::Close(handle, &error); if (error != 0) { MemoryMappedFile::Unmap(fileBuffer); fileBuffer = NULL; return NULL; } return fileBuffer; } ================================================ FILE: unity_decoder/libil2cpp/vm/MetadataLoader.h ================================================ #pragma once #include "il2cpp-config.h" namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API MetadataLoader { public: static void* LoadMetadataFile(const char* fileName); }; } // namespace vm } // namespace il2cpp ================================================ FILE: unity_decoder/libil2cpp/vm/MetadataLock.h ================================================ #pragma once #include "il2cpp-config.h" #include "os/Mutex.h" namespace il2cpp { namespace vm { extern il2cpp::os::FastMutex g_MetadataLock; } // namespace vm } // namespace il2cpp ================================================ FILE: unity_decoder/libil2cpp/vm/Method.cpp ================================================ #include "il2cpp-config.h" #include "vm/Method.h" #include "tabledefs.h" #include "class-internals.h" #include "vm/Class.h" #include "vm/MetadataCache.h" #include "vm/Object.h" #include "vm/Reflection.h" #include "vm/Type.h" namespace il2cpp { namespace vm { const Il2CppType* Method::GetReturnType(const MethodInfo* method) { return method->return_type; } Il2CppClass *Method::GetDeclaringType(const MethodInfo* method) { return method->declaring_type; } const char* Method::GetName(const MethodInfo *method) { return method->name; } bool Method::IsGeneric(const MethodInfo *method) { return method->is_generic; } bool Method::IsInflated(const MethodInfo *method) { return method->is_inflated; } bool Method::IsGenericInstance(const MethodInfo *method) { return method->is_inflated && !method->is_generic; } bool Method::IsInstance(const MethodInfo *method) { return !(method->flags & METHOD_ATTRIBUTE_STATIC); } uint32_t Method::GetParamCount(const MethodInfo *method) { return method->parameters_count; } const Il2CppType* Method::GetParam(const MethodInfo *method, uint32_t index) { if (index < method->parameters_count) return method->parameters[index].parameter_type; else return NULL; } const char* Method::GetParamName(const MethodInfo *method, uint32_t index) { IL2CPP_ASSERT(method != NULL && "Method::GetParamName cannot be invoked with a NULL MethodInfo."); if (index >= method->parameters_count) return NULL; return method->parameters[index].name; } Il2CppClass* Method::GetClass(const MethodInfo *method) { return method->declaring_type; } bool Method::HasAttribute(const MethodInfo *method, Il2CppClass *attr_class) { return Reflection::HasAttribute(method, attr_class); } const Il2CppDebugMethodInfo *Method::GetDebugInfo(const MethodInfo *method) { #if IL2CPP_DEBUGGER_ENABLED return method->debug_info; #else return NULL; #endif } uint32_t Method::GetImplementationFlags(const MethodInfo *method) { return method->iflags; } uint32_t Method::GetFlags(const MethodInfo *method) { return method->flags; } uint32_t Method::GetToken(const MethodInfo *method) { return method->token; } // From ECMA-335, I.10.2 Overloading // Methods and properties can be overloaded by: // * Number of parameters // * Type of any parameter // * Calling convention <------ not stored in our metadata yet // * Custom modifiers <------ not supported by il2cpp // * Whether a parameter is passed by value or by reference static bool AreParametersSame(const ParameterInfo* params1, const ParameterInfo* params2, int count) { for (int i = 0; i < count; i++) { const Il2CppType* param1 = params1[i].parameter_type; const Il2CppType* param2 = params2[i].parameter_type; if (param1->byref != param2->byref) { return false; } if (Class::FromIl2CppType(param1) != Class::FromIl2CppType(param2)) { return false; } } return true; } static int CompareParameters(const ParameterInfo* params1, const ParameterInfo* params2, int count) { for (int i = 0; i < count; i++) { const Il2CppType* param1 = params1[i].parameter_type; const Il2CppType* param2 = params2[i].parameter_type; if (param1->byref == param2->byref) { return Class::FromIl2CppType(param1) < Class::FromIl2CppType(param2); } return param1->byref < param2->byref; } return true; } bool Method::IsSameOverloadSignature(const MethodInfo* method1, const MethodInfo* method2) { if (method1->parameters_count != method2->parameters_count) { return false; } return AreParametersSame(method1->parameters, method2->parameters, method1->parameters_count); } bool Method::IsSameOverloadSignature(const PropertyInfo* property1, const PropertyInfo* property2) { uint8_t parameterCount1, parameterCount2; const ParameterInfo* parameters1; const ParameterInfo* parameters2; if (property1->get != NULL) { parameterCount1 = property1->get->parameters_count; parameters1 = property1->get->parameters; } else { // In set method, value is the last parameter, so we just don't care about it parameterCount1 = property1->set->parameters_count - 1; parameters1 = property1->set->parameters; } if (property2->get != NULL) { parameterCount2 = property2->get->parameters_count; parameters2 = property2->get->parameters; } else { parameterCount2 = property2->set->parameters_count - 1; parameters2 = property2->set->parameters; } if (parameterCount1 != parameterCount2) { return false; } return AreParametersSame(parameters1, parameters2, parameterCount1); } int Method::CompareOverloadSignature(const PropertyInfo* property1, const PropertyInfo* property2) { uint8_t parameterCount1, parameterCount2; const ParameterInfo* parameters1; const ParameterInfo* parameters2; if (property1->get != NULL) { parameterCount1 = property1->get->parameters_count; parameters1 = property1->get->parameters; } else { // In set method, value is the last parameter, so we just don't care about it parameterCount1 = property1->set->parameters_count - 1; parameters1 = property1->set->parameters; } if (property2->get != NULL) { parameterCount2 = property2->get->parameters_count; parameters2 = property2->get->parameters; } else { parameterCount2 = property2->set->parameters_count - 1; parameters2 = property2->set->parameters; } if (parameterCount1 == parameterCount2) { return CompareParameters(parameters1, parameters2, parameterCount1); } return parameterCount1 < parameterCount2; } const char* Method::GetParameterDefaultValue(const MethodInfo* method, const ParameterInfo *parameter, const Il2CppType** type, bool* isExplicitySetNullDefaultValue) { *isExplicitySetNullDefaultValue = false; const Il2CppParameterDefaultValue *entry = MetadataCache::GetParameterDefaultValueForParameter(method, parameter); if (entry == NULL) return NULL; *type = MetadataCache::GetIl2CppTypeFromIndex(entry->typeIndex); if (entry->dataIndex == kDefaultValueIndexNull) { *isExplicitySetNullDefaultValue = true; return NULL; } return (const char*)MetadataCache::GetParameterDefaultValueDataFromIndex(entry->dataIndex); } std::string Method::GetFullName(const MethodInfo* method) { std::string str; str += Type::GetName(method->declaring_type->byval_arg, IL2CPP_TYPE_NAME_FORMAT_FULL_NAME); str += "::"; str += Method::GetName(method); return str; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Method.h ================================================ #pragma once #include #include #include "il2cpp-config.h" struct MethodInfo; struct PropertyInfo; struct ParameterInfo; struct Il2CppString; struct Il2CppType; struct Il2CppClass; struct Il2CppDebugMethodInfo; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API Method { public: static const Il2CppType* GetReturnType(const MethodInfo* method); static const char* GetName(const MethodInfo *method); static std::string GetFullName(const MethodInfo* method); static bool IsGeneric(const MethodInfo *method); static bool IsInflated(const MethodInfo *method); static bool IsInstance(const MethodInfo *method); static bool IsGenericInstance(const MethodInfo *method); static uint32_t GetParamCount(const MethodInfo *method); static const Il2CppType* GetParam(const MethodInfo *method, uint32_t index); static Il2CppClass* GetClass(const MethodInfo *method); static bool HasAttribute(const MethodInfo *method, Il2CppClass *attr_class); static Il2CppClass *GetDeclaringType(const MethodInfo* method); static const Il2CppDebugMethodInfo *GetDebugInfo(const MethodInfo *method); static uint32_t GetImplementationFlags(const MethodInfo *method); static uint32_t GetFlags(const MethodInfo *method); static uint32_t GetToken(const MethodInfo *method); static const char* GetParamName(const MethodInfo *method, uint32_t index); static bool IsSameOverloadSignature(const MethodInfo* method1, const MethodInfo* method2); static bool IsSameOverloadSignature(const PropertyInfo* property1, const PropertyInfo* property2); static int CompareOverloadSignature(const PropertyInfo* property1, const PropertyInfo* property2); static const char* GetParameterDefaultValue(const MethodInfo *method, const ParameterInfo* parameter, const Il2CppType** type, bool* isExplicitySetNullDefaultValue); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Module.cpp ================================================ #include "vm/Module.h" #include "class-internals.h" namespace il2cpp { namespace vm { uint32_t Module::GetToken(const Il2CppImage *image) { return image->token; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Module.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppImage; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API Module { public: // exported static uint32_t GetToken(const Il2CppImage *image); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Monitor.cpp ================================================ #include "il2cpp-config.h" #include "object-internals.h" #include "vm/Monitor.h" #if IL2CPP_SUPPORT_THREADS #include "os/Atomic.h" #include "os/Event.h" #include "os/Semaphore.h" #include "os/Thread.h" #include "vm/Exception.h" #include "vm/Thread.h" #include "utils/ThreadSafeFreeList.h" #include using namespace il2cpp; // Mostly follows the algorithm outlined in "Implementing Fast Java Monitors with Relaxed-Locks". /// State of a lock associated with an object. /// /// Allocated from the normal non-GC heap and kept on a free list. This means that an object that is /// not unlocked before it is reclaimed will leak its monitor. However, it allows us to not have to /// synchronize with the GC and to efficiently reuse a small number of monitor instances between an /// arbitrary number of managed objects. /// // NOTE: We do *NOT* allow deletion of monitors as threads may be hanging on to monitors even as they // are already back on the free list (and maybe even in use somewhere else already). struct MonitorData : public utils::ThreadSafeFreeListNode { static const os::Thread::ThreadId kCanBeAcquiredByOtherThread = os::Thread::kInvalidThreadId; static const os::Thread::ThreadId kHasBeenReturnedToFreeList = (os::Thread::ThreadId)-1; /// ID of thread that currently has the object locked or one of the two values above. /// /// This signals three possible states: /// /// 1) Contains a valid thread ID. Means the monitor is owned by that thread and only that thread can /// change the value of this field. /// 2) Contains kCanBeAcquiredByOtherThread. Means monitor is still live and attached to an object /// but is up for grabs by whichever thread manages to swap the value of this field for its own /// thread ID first. /// 3) Contains kHasBeenReturnedToFreeList. Means monitor is not attached to any object and can be /// acquired by any thread *but* only through the free list. ALIGN_TYPE(8) volatile uint64_t owningThreadId; /// Number of times the object has been locked on the owning thread. Everything above 1 indicates /// a recursive lock. /// NOTE: This field is never reset to zero. uint32_t recursiveLockingCount; /// Semaphore used to signal other blocked threads that the monitor has become available. /// The "ready queue" is implicit in the list of threads waiting on this semaphore. os::Semaphore semaphore; /// Number of threads that are already waiting or are about to wait for a lock on the monitor. volatile uint32_t numThreadsWaitingForSemaphore; /// Event that a waiting thread fires to acknowledge that it has been kicked off a monitor by the thread /// already holding a lock on the object being waited for. This happens when the locking thread decides /// to deflate the locked object and thus kill the monitor but then some other thread comes along and /// decides to wait on the monitor-to-be-killed. os::Event flushAcknowledged; /// Node in list of waiting threads. /// /// Memory management is done the same way as for MonitorData itself. The same constraints apply. /// Wait nodes are returned to the free list by the threads that have created them except for abandoned /// nodes which may be returned by the pulsing thread. /// /// NOTE: Every wait node must be cleaned up by the wait thread that allocated it. struct PulseWaitingListNode : public utils::ThreadSafeFreeListNode { enum State { /// Node is waiting to be reused. kUnused, /// Node is waiting to be signaled. kWaiting }; /// Next node in "threadsWaitingForPulse" list. /// NOTE: Once on the list, this field may only be modified by the thread holding a lock /// on the respective monitor. PulseWaitingListNode* nextNode; /// Event to notify waiting thread of pulse. il2cpp::os::Event signalWaitingThread; /// Current usage state. This is not set atomically. Change this state only if you /// are at a known sequence point. int32_t state; static il2cpp::utils::ThreadSafeFreeList s_FreeList; PulseWaitingListNode() : nextNode(NULL) , state(kUnused) {} void Release() { state = kUnused; signalWaitingThread.Reset(); s_FreeList.Release(this); } static PulseWaitingListNode* Allocate() { PulseWaitingListNode* node = s_FreeList.Allocate(); IL2CPP_ASSERT(node->state == kUnused); return node; } }; /// List of threads waiting for a pulse on the monitor. /// NOTE: This field may be modified concurrently by several threads (no lock). PulseWaitingListNode* threadsWaitingForPulse; static il2cpp::utils::ThreadSafeFreeList s_FreeList; MonitorData() : owningThreadId(kHasBeenReturnedToFreeList) , recursiveLockingCount(1) , numThreadsWaitingForSemaphore(0) , threadsWaitingForPulse(NULL) , semaphore(0, std::numeric_limits::max()) { } bool IsAcquired() const { return (owningThreadId != kCanBeAcquiredByOtherThread && owningThreadId != kHasBeenReturnedToFreeList); } bool TryAcquire(uint64_t threadId) { return (os::Atomic::CompareExchange64(&owningThreadId, threadId, kCanBeAcquiredByOtherThread) == kCanBeAcquiredByOtherThread); } void Unacquire() { IL2CPP_ASSERT(owningThreadId == os::Thread::CurrentThreadId()); os::Atomic::Exchange64(&owningThreadId, kCanBeAcquiredByOtherThread); } /// Mark current thread as being blocked in Monitor.Enter(), i.e. as "ready to acquire monitor /// whenever it becomes available." void AddCurrentThreadToReadyList() { os::Atomic::Increment(&numThreadsWaitingForSemaphore); vm::Thread::SetState(vm::Thread::Current(), vm::kThreadStateWaitSleepJoin); } /// Mark current thread is no longer being blocked on the monitor. int RemoveCurrentThreadFromReadyList() { int numRemainingWaitingThreads = os::Atomic::Decrement(&numThreadsWaitingForSemaphore); vm::Thread::ClrState(vm::Thread::Current(), vm::kThreadStateWaitSleepJoin); return numRemainingWaitingThreads; } /// Acknowledge that the owning thread has decided to kill the monitor (a.k.a. deflate the corresponding /// object) while we were waiting on it. void VacateDyingMonitor() { RemoveCurrentThreadFromReadyList(); flushAcknowledged.Set(); } void PushOntoPulseWaitingList(PulseWaitingListNode* node) { // Change state to waiting. Safe to not do this atomically as at this point, // the waiting thread is the only one with access to the node. node->state = PulseWaitingListNode::kWaiting; // Race other wait threads until we've successfully linked the // node into the list. while (true) { PulseWaitingListNode* nextNode = threadsWaitingForPulse; node->nextNode = nextNode; if (os::Atomic::CompareExchangePointer(&threadsWaitingForPulse, node, nextNode) == nextNode) break; } } /// Get the next wait node and remove it from the list. /// NOTE: Calling thread *must* have the monitor locked. PulseWaitingListNode* PopNextFromPulseWaitingList() { IL2CPP_ASSERT(owningThreadId == os::Thread::CurrentThreadId()); PulseWaitingListNode* head = threadsWaitingForPulse; if (!head) return NULL; // Grab the node for ourselves. We take the node even if some other thread // changes "threadsWaitingForPulse" in the meantime. If that happens, we don't // unlink the node and the node will stay on the list until the waiting thread // cleans up the list. PulseWaitingListNode* next = head->nextNode; if (os::Atomic::CompareExchangePointer(&threadsWaitingForPulse, next, head) == head) head->nextNode = NULL; return head; } /// Remove the given waiting node from "threadsWaitingForPulse". /// NOTE: Calling thread *must* have the monitor locked. bool RemoveFromPulseWaitingList(PulseWaitingListNode* node) { IL2CPP_ASSERT(owningThreadId == os::Thread::CurrentThreadId()); // This function works only because threads calling Wait() on the monitor will only // ever *prepend* nodes to the list. This means that only the "threadsWaitingForPulse" // variable is actually shared between threads whereas the list contents are owned // by the thread that has the monitor locked. tryAgain: PulseWaitingListNode * previous = NULL; for (PulseWaitingListNode* current = threadsWaitingForPulse; current != NULL;) { // Go through list looking for node. if (current != node) { previous = current; current = current->nextNode; continue; } // Node found. Remove. if (previous) previous->nextNode = node->nextNode; else { // We may have to change "threadsWaitingForPulse" and thus have to synchronize // with other threads. if (os::Atomic::CompareExchangePointer(&threadsWaitingForPulse, node->nextNode, node) != node) { // One or more other threads have changed the list. goto tryAgain; } } node->nextNode = NULL; return true; } // Not found in list. return false; } }; utils::ThreadSafeFreeList MonitorData::s_FreeList; utils::ThreadSafeFreeList MonitorData::PulseWaitingListNode::s_FreeList; static MonitorData* GetMonitorAndThrowIfNotLockedByCurrentThread(Il2CppObject* obj) { // Fetch monitor data. MonitorData* monitor = os::Atomic::ReadPointer(&obj->monitor); if (!monitor) { // No one locked this object. vm::Exception::Raise(vm::Exception::GetSynchronizationLockException("Object is not locked.")); } // Throw SynchronizationLockException if we're not holding a lock. // NOTE: Unlike .NET, Mono simply ignores this and does not throw. uint64_t currentThreadId = os::Thread::CurrentThreadId(); if (monitor->owningThreadId != currentThreadId) { vm::Exception::Raise(vm::Exception::GetSynchronizationLockException ("Object has not been locked by this thread.")); } return monitor; } namespace il2cpp { namespace vm { void Monitor::Enter(Il2CppObject* object) { TryEnter(object, std::numeric_limits::max()); } bool Monitor::TryEnter(Il2CppObject* obj, uint32_t timeOutMilliseconds) { uint64_t currentThreadId = os::Thread::CurrentThreadId(); while (true) { MonitorData* installedMonitor = os::Atomic::ReadPointer(&obj->monitor); if (!installedMonitor) { // Set up a new monitor. MonitorData* newlyAllocatedMonitorForThisThread = MonitorData::s_FreeList.Allocate(); IL2CPP_ASSERT(os::Atomic::Read64((int64_t*)&newlyAllocatedMonitorForThisThread->owningThreadId) == MonitorData::kHasBeenReturnedToFreeList && "Monitor on freelist cannot be owned by thread!"); os::Atomic::Exchange64(&newlyAllocatedMonitorForThisThread->owningThreadId, currentThreadId); // Try to install the monitor on the object (aka "inflate" the object). if (os::Atomic::CompareExchangePointer(&obj->monitor, newlyAllocatedMonitorForThisThread, (MonitorData*)NULL) == NULL) { // Done. There was no contention on this object. This is // the fast path. IL2CPP_ASSERT(obj->monitor); IL2CPP_ASSERT(obj->monitor->recursiveLockingCount == 1); IL2CPP_ASSERT(obj->monitor->owningThreadId == currentThreadId); return true; } else { // Some other thread raced us and won. Retry. os::Atomic::Exchange64(&newlyAllocatedMonitorForThisThread->owningThreadId, MonitorData::kHasBeenReturnedToFreeList); MonitorData::s_FreeList.Release(newlyAllocatedMonitorForThisThread); continue; } } // Object was locked previously. See if we already have the lock. if (os::Atomic::Read64(&installedMonitor->owningThreadId) == currentThreadId) { // Yes, recursive lock. Just increase count. ++installedMonitor->recursiveLockingCount; return true; } // Attempt to acquire lock if it's free if (installedMonitor->TryAcquire(currentThreadId)) { // There is no locking around the sections of this logic to speed // things up, there is potential for race condition to reset the objects // monitor. If it has been reset prior to successfully coming out of // TryAquire, dont return, unaquire the installedMonitor, go back through the logic again to grab a // a valid monitor. if (!obj->monitor) { installedMonitor->Unacquire(); continue; } // Ownership of monitor passed from previously locking thread to us. IL2CPP_ASSERT(installedMonitor->recursiveLockingCount == 1); IL2CPP_ASSERT(obj->monitor == installedMonitor); return true; } // Getting an immediate lock failed, so if we have a zero timeout now, // entering the monitor failed. if (timeOutMilliseconds == 0) return false; // Object was locked by other thread. Let the monitor know we are waiting for a lock. installedMonitor->AddCurrentThreadToReadyList(); if (os::Atomic::ReadPointer(&obj->monitor) != installedMonitor) { // Another thread deflated the object while we tried to lock it. Get off // the monitor. // NOTE: By now we may already be dealing with a monitor that is back on the free list // or even installed on an object again. installedMonitor->VacateDyingMonitor(); // NOTE: The "Implementing Fast Java Monitors with Relaxed-Locks" paper describes a path // that may lead to monitors being leaked if the thread currently holding a lock sees our // temporary increment of numWaitingThreads and ends up not deflating the object. However, // we can only ever end up inside this branch here if the locking thread has already decided to // deflate, so I don't see how we can leak here. // Retry. continue; } // NOTE: At this point, we are in the waiting line for the monitor. However, the thread currently // locking the monitor may still have already made the decision to deflate the object so we may // still get kicked off the monitor. // Wait for the locking thread to signal us. while (os::Atomic::ReadPointer(&obj->monitor) == installedMonitor) { // Try to grab the object for ourselves. if (installedMonitor->TryAcquire(currentThreadId)) { // Ownership of monitor passed from previously locking thread to us. IL2CPP_ASSERT(installedMonitor->recursiveLockingCount == 1); IL2CPP_ASSERT(obj->monitor == installedMonitor); installedMonitor->RemoveCurrentThreadFromReadyList(); return true; } // Wait for owner to signal us. os::WaitStatus waitStatus; try { if (timeOutMilliseconds != std::numeric_limits::max()) { // Perform a timed wait. waitStatus = installedMonitor->semaphore.Wait(timeOutMilliseconds, true); } else { // Perform an infinite wait. We may still be interrupted, however. waitStatus = installedMonitor->semaphore.Wait(true); } } catch (...) { // This is paranoid but in theory a user APC could throw an exception from within Wait(). // Just make sure we clean up properly. installedMonitor->RemoveCurrentThreadFromReadyList(); throw; } ////TODO: adjust wait time if we have a Wait() failure and before going another round if (waitStatus == os::kWaitStatusTimeout) { // Wait failed. Get us off the list. int newNumWaitingThreads = installedMonitor->RemoveCurrentThreadFromReadyList(); // If there are no more waiting threads on this monitor, we need to check for leaking. // This may happen if the locking thread has just been executing a Monitor.Exit(), seen // the positive numWaitingThread count, and decided that it thus cannot deflate the object // and will trigger the semaphore. However, we've just decided to give up waiting, so if // we were the only thread waiting and no one ever attempts to lock the object again, the // monitor will stick around with no one ever deflating the object. // // We solve this by simply trying to acquire ownership of the monitor if we were the last // waiting thread and if that succeeds, we simply change from returning with a time out // failure to returning with a successful lock. if (!newNumWaitingThreads && os::Atomic::ReadPointer(&obj->monitor) == installedMonitor) { if (installedMonitor->TryAcquire(currentThreadId)) { // We've successfully acquired a lock on the object. IL2CPP_ASSERT(installedMonitor->recursiveLockingCount == 1); IL2CPP_ASSERT(obj->monitor == installedMonitor); return true; } } // Catch the case where a timeout expired the very moment the owning thread decided to // get us to vacate the monitor by sending an acknowledgement just to make sure. if (os::Atomic::ReadPointer(&obj->monitor) != installedMonitor) installedMonitor->flushAcknowledged.Set(); return false; } } // Owner has deflated the object and the monitor is no longer associated with the // object we're trying to lock. Signal to the owner that we acknowledge this and // move off the monitor. installedMonitor->VacateDyingMonitor(); } return false; } void Monitor::Exit(Il2CppObject* obj) { // Fetch monitor data. MonitorData* monitor = GetMonitorAndThrowIfNotLockedByCurrentThread(obj); // We have the object lock. Undo one single invocation of Enter(). int newLockingCount = monitor->recursiveLockingCount - 1; if (newLockingCount > 0) { // Was recursively locked. Lock still held by us. monitor->recursiveLockingCount = newLockingCount; return; } // See if there are already threads ready to take over the lock. if (os::Atomic::Add(&monitor->numThreadsWaitingForSemaphore, 0) != 0) { // Yes, so relinquish ownership of the object and signal the next thread. monitor->Unacquire(); monitor->semaphore.Post(); } else if (monitor->threadsWaitingForPulse) { // No, but there's threads waiting for a pulse so we can't deflate the object. // The wait nodes may already have been abandoned but that is for the pulsing // and waiting threads to sort out. Either way, if there ever is going to be a // pulse, *some* thread will get around to looking at this monitor again so all // we do here is relinquish ownership. monitor->Unacquire(); // there is a race as follows: T1 is our thread and we own monitor lock // T1 - checks numThreadsWaitingForSemaphore and sees 0 // T2 - sees T1 has lock. Increments numThreadsWaitingForSemaphore // T2 - tries to acquire monitor, but we hold it // T2 - waits on semaphore // T1 - we unacquire and wait to be pulsed (if Exit is called from Wait) // Result: deadlock as semaphore is never posted // Fix: double check 'numThreadsWaitingForSemaphore' after we've unacquired // Worst case might be an extra post, which will just incur an additional // pass through the loop with an extra attempt to acquire the monitor with a CAS if (os::Atomic::Add(&monitor->numThreadsWaitingForSemaphore, 0) != 0) monitor->semaphore.Post(); } else { // Seems like no other thread is interested in the monitor. Deflate the object. os::Atomic::ExchangePointer(&obj->monitor, (MonitorData*)NULL); // At this point the monitor is no longer associated with the object and we cannot safely // "re-attach" it. We need to make sure that all threads still having a reference to the // monitor let go of it before we put the monitor back on the free list. // // IMPORTANT: We still *own* the monitor at this point. No other thread can acquire it and // we must not let go of the monitor until we have kicked all other threads off of it. monitor->flushAcknowledged.Reset(); while (os::Atomic::Add(&monitor->numThreadsWaitingForSemaphore, 0) != 0) { monitor->semaphore.Post(monitor->numThreadsWaitingForSemaphore); // If a thread starts waiting right after we have read numThreadsWaitingForSemaphore, // we won't release the semaphore enough times. So don't wait spend a long time waiting // for acknowledgement here. monitor->flushAcknowledged.Wait(1, false); } // IMPORTANT: At this point, all other threads must have either already vacated the monitor or // be on a path that makes them vacate the monitor next. The latter may happen if a thread // is stopped right before adding itself to the ready list of our monitor in which case we // will not see the thread on numThreadsWaitingForSemaphore. If we then put the monitor back // on the freelist and then afterwards the other thread is resumed, it will still put itself // on the ready list only to then realize it got the wrong monitor. // So, even for monitors on the free list, we accept that a thread may temporarily add itself // to the wrong monitor's ready list as long as all it does it simply remove itself right after // realizing the mistake. // Release monitor back to free list. IL2CPP_ASSERT(monitor->owningThreadId == os::Thread::CurrentThreadId()); os::Atomic::Exchange64(&monitor->owningThreadId, MonitorData::kHasBeenReturnedToFreeList); MonitorData::s_FreeList.Release(monitor); } } static void PulseMonitor(Il2CppObject* obj, bool all = false) { // Grab monitor. MonitorData* monitor = GetMonitorAndThrowIfNotLockedByCurrentThread(obj); bool isFirst = true; while (true) { // Grab next waiting thread, if any. MonitorData::PulseWaitingListNode* waitNode = monitor->PopNextFromPulseWaitingList(); if (!waitNode) break; // Pulse thread. waitNode->signalWaitingThread.Set(); // Stop if we're only supposed to pulse the one thread. if (isFirst && !all) break; isFirst = false; } } void Monitor::Pulse(Il2CppObject* object) { PulseMonitor(object, false); } void Monitor::PulseAll(Il2CppObject* object) { PulseMonitor(object, true); } void Monitor::Wait(Il2CppObject* object) { TryWait(object, std::numeric_limits::max()); } bool Monitor::TryWait(Il2CppObject* object, uint32_t timeoutMilliseconds) { MonitorData* monitor = GetMonitorAndThrowIfNotLockedByCurrentThread(object); // Undo any recursive locking but remember the count so we can restore it // after we have re-acquired the lock. uint32_t oldLockingCount = monitor->recursiveLockingCount; monitor->recursiveLockingCount = 1; // Add us to the pulse waiting list for the monitor (except if we won't be // waiting for a pulse at all). MonitorData::PulseWaitingListNode* waitNode = NULL; if (timeoutMilliseconds != 0) { waitNode = MonitorData::PulseWaitingListNode::Allocate(); monitor->PushOntoPulseWaitingList(waitNode); } // Release the monitor. Exit(object); monitor = NULL; // Wait for pulse (if we either have a timeout or are supposed to // wait infinitely). os::WaitStatus pulseWaitStatus = os::kWaitStatusSuccess; Il2CppException* exceptionThrownDuringWait = NULL; if (timeoutMilliseconds != 0) { pulseWaitStatus = os::kWaitStatusFailure; try { vm::ThreadStateSetter state(vm::kThreadStateWaitSleepJoin); pulseWaitStatus = waitNode->signalWaitingThread.Wait(timeoutMilliseconds, true); } catch (Il2CppExceptionWrapper& exception) { // Exception occurred during wait. Remember exception but continue with reacquisition // and cleanup. We re-throw later. exceptionThrownDuringWait = exception.ex; pulseWaitStatus = os::kWaitStatusFailure; } } ////TODO: deal with exception here // Reacquire the monitor. Enter(object); // Monitor *may* have changed. monitor = object->monitor; // Restore recursion count. monitor->recursiveLockingCount = oldLockingCount; // Get rid of wait list node. if (waitNode) { // Make sure the node is gone from the wait list. If the pulsing thread already did // that, this won't do anything. monitor->RemoveFromPulseWaitingList(waitNode); // And hand it back for reuse. waitNode->Release(); waitNode = NULL; } // If the wait was interrupted by an exception (most likely a ThreadInterruptedException), // then re-throw now. // // NOTE: We delay this to until after we've gone through the reacquisition sequence as we // have to guarantee that when Monitor.Wait() exits -- whether successfully or not --, it // still holds a lock. Otherwise a lock() statement around the Wait() will throw an exception, // for example. if (exceptionThrownDuringWait) vm::Exception::Raise(exceptionThrownDuringWait); ////TODO: According to MSDN, the timeout indicates whether we reacquired the lock in time //// and not just whether the pulse came in time. Thus the current code is imprecise. return (pulseWaitStatus != os::kWaitStatusTimeout); } bool Monitor::IsAcquired(Il2CppObject* object) { MonitorData* monitor = object->monitor; if (!monitor) return false; return monitor->IsAcquired(); } } /* namespace vm */ } /* namespace il2cpp */ #endif // IL2CPP_SUPPORT_THREADS ================================================ FILE: unity_decoder/libil2cpp/vm/Monitor.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppObject; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API Monitor { public: static void Enter(Il2CppObject* object); static bool TryEnter(Il2CppObject* object, uint32_t timeout); static void Exit(Il2CppObject* object); static void Pulse(Il2CppObject* object); static void PulseAll(Il2CppObject* object); static void Wait(Il2CppObject* object); static bool TryWait(Il2CppObject* object, uint32_t timeout); static bool IsAcquired(Il2CppObject* object); }; #if !IL2CPP_SUPPORT_THREADS inline void Monitor::Enter(Il2CppObject* object) { } inline bool Monitor::TryEnter(Il2CppObject* object, uint32_t timeout) { return true; } inline void Monitor::Exit(Il2CppObject* object) { } inline void Monitor::Pulse(Il2CppObject* object) { } inline void Monitor::PulseAll(Il2CppObject* object) { } inline void Monitor::Wait(Il2CppObject* object) { } inline bool Monitor::TryWait(Il2CppObject* object, uint32_t timeout) { return true; } inline bool Monitor::IsAcquired(Il2CppObject* object) { return true; } #endif } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/NonCachedCCWBase.h ================================================ #pragma once #include "gc/GCHandle.h" #include "vm/ComObjectBase.h" #include "utils/TemplateUtils.h" namespace il2cpp { namespace vm { template struct NOVTABLE NonCachedCCWBase : ComObjectBase { private: volatile uint32_t m_RefCount; uint32_t m_GCHandle; public: inline NonCachedCCWBase(Il2CppObject* obj) : ComObjectBase(obj), m_RefCount(1) // We start with a ref count of 1 { m_GCHandle = gc::GCHandle::New(GetManagedObjectInline(), false); IL2CPP_ASSERT(m_GCHandle != 0); Il2CppStaticAssert(utils::TemplateUtils::IsBaseOf, TDerived>::value); } inline ~NonCachedCCWBase() { IL2CPP_ASSERT(m_GCHandle != 0); gc::GCHandle::Free(m_GCHandle); m_GCHandle = 0; } FORCE_INLINE uint32_t AddRefImpl() { return Atomic::Increment(&m_RefCount); } FORCE_INLINE uint32_t ReleaseImpl() { const uint32_t count = Atomic::Decrement(&m_RefCount); if (count == 0) Destroy(); return count; } FORCE_INLINE static TDerived* __CreateInstance(Il2CppObject* obj) { void* memory = utils::Memory::Malloc(sizeof(TDerived)); if (memory == NULL) Exception::RaiseOutOfMemoryException(); return new(memory)TDerived(obj); } virtual void STDCALL Destroy() IL2CPP_FINAL IL2CPP_OVERRIDE { IL2CPP_ASSERT(m_RefCount == 0); TDerived* instance = static_cast(this); instance->~TDerived(); utils::Memory::Free(instance); } }; } } ================================================ FILE: unity_decoder/libil2cpp/vm/Object.cpp ================================================ #include "il2cpp-config.h" #include #include "utils/StringUtils.h" #include "vm/Array.h" #include "vm/Class.h" #include "vm/Exception.h" #include "vm/MetadataCache.h" #include "vm/Object.h" #include "vm/Profiler.h" #include "vm/RCW.h" #include "vm/Runtime.h" #include "vm/Reflection.h" #include "vm/String.h" #include "vm/Thread.h" #include "vm/Type.h" #include "class-internals.h" #include "object-internals.h" #include "gc/gc_wrapper.h" #include "gc/GarbageCollector.h" #include "tabledefs.h" #if IL2CPP_GC_BOEHM #define ALLOC_PTRFREE(obj, vt, size) do { (obj) = (Il2CppObject*)GC_MALLOC_ATOMIC ((size)); (obj)->klass = (vt); (obj)->monitor = NULL;} while (0) #define ALLOC_OBJECT(obj, vt, size) do { (obj) = (Il2CppObject*)GC_MALLOC ((size)); (obj)->klass = (vt);} while (0) #ifdef GC_GCJ_SUPPORT #define ALLOC_TYPED(dest, size, type) do { (dest) = (Il2CppObject*)GC_gcj_malloc ((size),(type)); } while (0) #else #define GC_NO_DESCRIPTOR (NULL) #define ALLOC_TYPED(dest, size, type) do { (dest) = GC_MALLOC ((size)); *(void**)dest = (type);} while (0) #endif #else #ifdef HAVE_SGEN_GC #define GC_NO_DESCRIPTOR (NULL) #define ALLOC_PTRFREE(obj, vt, size) do { (obj) = mono_gc_alloc_obj (vt, size);} while (0) #define ALLOC_OBJECT(obj, vt, size) do { (obj) = mono_gc_alloc_obj (vt, size);} while (0) #define ALLOC_TYPED(dest, size, type) do { (dest) = mono_gc_alloc_obj (type, size);} while (0) #else #define ALLOC_PTRFREE(obj, vt, size) do { (obj) = (Il2CppObject*)malloc ((size)); (obj)->klass = (vt); (obj)->monitor = NULL;} while (0) #define ALLOC_OBJECT(obj, vt, size) do { (obj) = (Il2CppObject*)calloc (1, (size)); (obj)->klass = (vt);} while (0) #define ALLOC_TYPED(dest, size, type) do { (dest) = (Il2CppObject*)(calloc (1, (size))); *(void**)dest = (type);} while (0) #endif #endif namespace il2cpp { namespace vm { Il2CppObject * Object::Allocate(size_t size, Il2CppClass *typeInfo) { IL2CPP_ASSERT(typeInfo->initialized); Il2CppObject *o; ALLOC_OBJECT(o, typeInfo, size); ++il2cpp_runtime_stats.new_object_count; return o; } Il2CppObject * Object::AllocatePtrFree(size_t size, Il2CppClass *typeInfo) { IL2CPP_ASSERT(typeInfo->initialized); Il2CppObject *o; ALLOC_PTRFREE(o, typeInfo, size); ++il2cpp_runtime_stats.new_object_count; return o; } Il2CppObject * Object::AllocateSpec(size_t size, Il2CppClass *typeInfo) { IL2CPP_ASSERT(typeInfo->initialized); Il2CppObject *o; ALLOC_TYPED(o, size, typeInfo); ++il2cpp_runtime_stats.new_object_count; return o; } Il2CppObject* Object::Box(Il2CppClass *typeInfo, void* val) { Class::Init(typeInfo); if (!typeInfo->valuetype) return *(Il2CppObject**)val; if (Class::IsNullable(typeInfo)) { /* From ECMA-335, I.8.2.4 Boxing and unboxing of values: All value types have an operation called box. Boxing a value of any value type produces its boxed value; i.e., a value of the corresponding boxed type containing a bitwise copy of the original value. If the value type is a nullable typedefined as an instantiation of the value type System.Nullable the result is a null reference or bitwise copy of its Value property of type T, depending on its HasValue property (false and true, respectively). */ typeInfo = Class::GetNullableArgument(typeInfo); Class::Init(typeInfo); bool hasValue = *reinterpret_cast(static_cast(val) + typeInfo->instance_size - sizeof(Il2CppObject)); if (!hasValue) return NULL; } size_t size = Class::GetInstanceSize(typeInfo); Il2CppObject* obj = Object::New(typeInfo); size = size - sizeof(Il2CppObject); memcpy(((char*)obj) + sizeof(Il2CppObject), val, size); return obj; } Il2CppObject* Object::Clone(Il2CppObject *obj) { Il2CppObject *o; int size; NOT_IMPLEMENTED_NO_ASSERT(Object::Clone, "Finish implementation"); size = obj->klass->instance_size; o = Allocate(size, obj->klass); /* do not copy the sync state */ memcpy((char*)o + sizeof(Il2CppObject), (char*)obj + sizeof(Il2CppObject), size - sizeof(Il2CppObject)); //#ifdef HAVE_SGEN_GC // if (obj->vtable->klass->has_references) // mono_gc_wbarrier_object (o); //#endif if (obj->klass->has_finalize) il2cpp::gc::GarbageCollector::RegisterFinalizerForNewObject(o); #if IL2CPP_ENABLE_PROFILER if (Profiler::ProfileAllocations()) Profiler::Allocation(o, obj->klass); #endif return o; } Il2CppClass* Object::GetClass(Il2CppObject* obj) { return obj->klass; } #if IL2CPP_SIZEOF_VOID_P == 8 const int kObjectAlignmentShift = 3; #elif IL2CPP_SIZEOF_VOID_P == 4 const int kObjectAlignmentShift = 2; #else #error Invalid architecture size #endif int32_t Object::GetHash(Il2CppObject* obj) { // shift away unused bits due to alignment, then use Knuth's multiplicative hash return (((uint32_t)(intptr_t)(obj)) >> kObjectAlignmentShift) * 2654435761u; } uint32_t Object::GetSize(Il2CppObject* obj) { Il2CppClass* klass = GetClass(obj); if (klass == il2cpp_defaults.string_class) { return sizeof(Il2CppString) + 2 * utils::StringUtils::GetLength((Il2CppString*)obj) + 2; } else if (obj->klass->rank) { Il2CppArray *array = (Il2CppArray*)obj; size_t size = kIl2CppSizeOfArray + Array::GetElementSize(klass) * Array::GetLength(array); if (array->bounds) { size += 3; size &= ~3; size += sizeof(Il2CppArrayBounds) * obj->klass->rank; } return (uint32_t)size; } else { return Class::GetInstanceSize(klass); } } const MethodInfo* Object::GetVirtualMethod(Il2CppObject *obj, const MethodInfo *method) { if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) return method; Il2CppClass* methodDeclaringType = method->declaring_type; if (!Class::IsInterface(methodDeclaringType)) return obj->klass->vtable[method->slot].method; return Class::GetInterfaceInvokeDataFromVTable(obj, methodDeclaringType, method->slot).method; } Il2CppObject* Object::IsInst(Il2CppObject *obj, Il2CppClass *klass) { if (!obj) return NULL; Il2CppClass* objClass = Object::GetClass(obj); if (!objClass->is_import_or_windows_runtime) return Class::IsAssignableFrom(klass, objClass) ? obj : NULL; // check if klass has an interface id if (Class::IsInterface(klass) && klass->interopData != NULL) { const Il2CppGuid* iid = klass->interopData->guid; if (iid != NULL) { Il2CppIUnknown* unknown = RCW::QueryInterface(static_cast(obj), *iid); if (unknown) { unknown->Release(); return static_cast(obj); } } } return (klass == il2cpp_defaults.object_class) ? obj : NULL; } Il2CppObject* Object::New(Il2CppClass *klass) { // same as NewAllocSpecific as we only support a single domain return NewAllocSpecific(klass); } Il2CppObject* Object::NewPinned(Il2CppClass *klass) { #if (IL2CPP_GC_BOEHM || IL2CPP_GC_NULL) return New(klass); #else NOT_IMPLEMENTED(Object::NewPinned); #endif } Il2CppObject * Object::NewAllocSpecific(Il2CppClass *klass) { Il2CppObject *o = NULL; NOT_IMPLEMENTED_NO_ASSERT(Object::NewAllocSpecific, "We really shouldn't need this initialization"); Class::Init(klass); if (Class::IsNullable(klass)) klass = il2cpp::vm::Class::GetNullableArgument(klass); if (!klass->has_references) { o = NewPtrFree(klass); } #if IL2CPP_HAS_GC_DESCRIPTORS else if (klass->gc_desc != GC_NO_DESCRIPTOR) { o = AllocateSpec(klass->instance_size, klass); } #endif else { o = Allocate(klass->instance_size, klass); } if (klass->has_finalize) il2cpp::gc::GarbageCollector::RegisterFinalizerForNewObject(o); #if IL2CPP_ENABLE_PROFILER if (Profiler::ProfileAllocations()) Profiler::Allocation(o, klass); #endif Runtime::ClassInit(klass); return o; } Il2CppObject* Object::NewPtrFree(Il2CppClass *klass) { Il2CppObject *obj = {0}; IL2CPP_ASSERT(klass->initialized); IL2CPP_ASSERT(!klass->has_references); ALLOC_PTRFREE(obj, klass, klass->instance_size); #if NEED_TO_ZERO_PTRFREE /* an inline memset is much faster for the common vcase of small objects * note we assume the allocated size is a multiple of sizeof (void*). */ if (klass->instance_size < 128) { void* *p, *end; end = (void**)((char*)obj + klass->instance_size); p = (void**)((char*)obj + sizeof(Il2CppObject)); while (p < end) { *p = NULL; ++p; } } else { memset((char*)obj + sizeof(Il2CppObject), 0, klass->instance_size - sizeof(Il2CppObject)); } #endif ++il2cpp_runtime_stats.new_object_count; return obj; } void* Object::Unbox(Il2CppObject* obj) { void* val = (void*)(((char*)obj) + sizeof(Il2CppObject)); return val; } void Object::UnboxNullable(Il2CppObject* obj, Il2CppClass* nullableArgumentClass, void* storage) { uint32_t valueSize = nullableArgumentClass->instance_size - sizeof(Il2CppObject); if (obj == NULL) { *(static_cast(storage) + valueSize) = false; } else { memcpy(storage, Unbox(obj), valueSize); *(static_cast(storage) + valueSize) = true; } } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Object.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppString; struct Il2CppObject; struct Il2CppClass; struct MethodInfo; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API Object { public: static Il2CppObject* Box(Il2CppClass *klass, void* data); static Il2CppClass* GetClass(Il2CppObject* obj); static int32_t GetHash(Il2CppObject* obj); static uint32_t GetSize(Il2CppObject* obj); static const MethodInfo* GetVirtualMethod(Il2CppObject *obj, const MethodInfo *method); static Il2CppObject * IsInst(Il2CppObject *obj, Il2CppClass *klass); static Il2CppObject* New(Il2CppClass *klass); static void* Unbox(Il2CppObject* obj); static void UnboxNullable(Il2CppObject* obj, Il2CppClass* nullableArgumentClass, void* storage); static Il2CppObject * Clone(Il2CppObject *obj); static Il2CppObject* NewPinned(Il2CppClass *klass); private: static Il2CppObject * NewAllocSpecific(Il2CppClass *klass); static Il2CppObject* NewPtrFree(Il2CppClass *klass); static Il2CppObject* Allocate(size_t size, Il2CppClass *typeInfo); static Il2CppObject* AllocatePtrFree(size_t size, Il2CppClass *typeInfo); static Il2CppObject* AllocateSpec(size_t size, Il2CppClass *typeInfo); friend class Array; friend class RCW; friend class String; }; } /* namespace vm */ } /* namespace il2cpp */ #define IL2CPP_OBJECT_SETREF(obj, fieldname, value) do {\ /*mono_gc_wbarrier_set_field ((Il2CppObject*)(obj), &((obj)->fieldname), (Il2CppObject*)value); */\ (obj)->fieldname = (value); \ } while (0) ================================================ FILE: unity_decoder/libil2cpp/vm/Parameter.cpp ================================================ #include "il2cpp-config.h" #include "metadata.h" #include "class-internals.h" #include "object-internals.h" #include "Parameter.h" #include "vm-utils/BlobReader.h" #include "vm/Class.h" #include "vm/Object.h" #include "vm/Method.h" #include namespace il2cpp { namespace vm { Il2CppObject* Parameter::GetDefaultParameterValueObject(const MethodInfo* method, const ParameterInfo* parameter, bool* isExplicitySetNullDefaultValue) { const Il2CppType* typeOfDefaultValue; const char* data = Method::GetParameterDefaultValue(method, parameter, &typeOfDefaultValue, isExplicitySetNullDefaultValue); if (data == NULL) return NULL; Il2CppClass* parameterType = Class::FromIl2CppType(parameter->parameter_type); if (parameterType->valuetype) { Class::SetupFields(parameterType); IL2CPP_ASSERT(parameterType->size_inited); void* value = alloca(parameterType->instance_size - sizeof(Il2CppObject)); utils::BlobReader::GetConstantValueFromBlob(typeOfDefaultValue->type, data, value); return Object::Box(parameterType, value); } Il2CppObject* value = NULL; utils::BlobReader::GetConstantValueFromBlob(typeOfDefaultValue->type, data, &value); return value; } } } ================================================ FILE: unity_decoder/libil2cpp/vm/Parameter.h ================================================ #pragma once #include "il2cpp-config.h" struct ParameterInfo; struct Il2CppObject; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API Parameter { public: // internal static Il2CppObject* GetDefaultParameterValueObject(const MethodInfo* method, const ParameterInfo* parameter, bool* isExplicitySetNullDefaultValue); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Path.cpp ================================================ #include "il2cpp-config.h" #include "vm/Path.h" #include "os/Path.h" namespace il2cpp { namespace vm { static std::string s_TempPath; void Path::SetTempPath(const char* path) { s_TempPath = path; } std::string Path::GetTempPath() { if (!s_TempPath.empty()) return s_TempPath; return os::Path::GetTempPath(); } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Path.h ================================================ #pragma once #include "il2cpp-config.h" #include namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API Path { public: static void SetTempPath(const char* path); static std::string GetTempPath(); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/PlatformInvoke.cpp ================================================ #include "il2cpp-config.h" #include "object-internals.h" #include "class-internals.h" #include "il2cpp-vm-support.h" #include "PlatformInvoke.h" #include "Exception.h" #include "LibraryLoader.h" #include "MetadataCache.h" #include "Object.h" #include "Method.h" #include "Type.h" #include "os/LibraryLoader.h" #include "os/MarshalStringAlloc.h" #include "utils/Memory.h" #include "utils/StringViewStream.h" #include "utils/StringUtils.h" #include "vm-utils/NativeDelegateMethodCache.h" #include "vm-utils/VmStringUtils.h" #include #include namespace il2cpp { namespace vm { void PlatformInvoke::SetFindPluginCallback(Il2CppSetFindPlugInCallback method) { LibraryLoader::SetFindPluginCallback(method); } Il2CppMethodPointer PlatformInvoke::Resolve(const PInvokeArguments& pinvokeArgs) { // Before resolving a P/Invoke, check against a hardcoded list of "known P/Invokes" that is different for every platform. // This bit solves several different problems we have when P/Invoking into native system libraries from mscorlib.dll. // Some platforms, like UWP, just don't allow you to load to load system libraries at runtime dynamically. // On other platforms (THEY SHALL NOT BE NAMED :O), while the functions that mscorlib.dll wants to P/Invoke into exist, // They exist in different system libraries than it is said in the DllImport attribute. Il2CppMethodPointer function = os::LibraryLoader::GetHardcodedPInvokeDependencyFunctionPointer(pinvokeArgs.moduleName, pinvokeArgs.entryPoint); if (function != NULL) return function; void* dynamicLibrary = NULL; if (utils::VmStringUtils::CaseSensitiveEquals(il2cpp::utils::StringUtils::NativeStringToUtf8(pinvokeArgs.moduleName.Str()).c_str(), "__InternalDynamic")) dynamicLibrary = LibraryLoader::LoadLibrary(il2cpp::utils::StringView::Empty()); else dynamicLibrary = LibraryLoader::LoadLibrary(pinvokeArgs.moduleName); if (dynamicLibrary == NULL) { std::basic_string message; message += IL2CPP_NATIVE_STRING("Unable to load DLL '"); message += pinvokeArgs.moduleName.Str(); message += IL2CPP_NATIVE_STRING("': The specified module could not be found."); Exception::Raise(Exception::GetDllNotFoundException(il2cpp::utils::StringUtils::NativeStringToUtf8(message).c_str())); } function = os::LibraryLoader::GetFunctionPointer(dynamicLibrary, pinvokeArgs); if (function == NULL) { std::basic_string message; message += IL2CPP_NATIVE_STRING("Unable to find an entry point named '"); message += il2cpp::utils::StringUtils::Utf8ToNativeString(pinvokeArgs.entryPoint.Str()); message += IL2CPP_NATIVE_STRING("' in '"); message += pinvokeArgs.moduleName.Str(); message += IL2CPP_NATIVE_STRING("'."); Exception::Raise(Exception::GetEntryPointNotFoundException(il2cpp::utils::StringUtils::NativeStringToUtf8(message).c_str())); } return function; } void PlatformInvoke::MarshalFree(void* ptr) { if (ptr != NULL) MarshalAlloc::Free(ptr); } char* PlatformInvoke::MarshalCSharpStringToCppString(Il2CppString* managedString) { if (managedString == NULL) return NULL; std::string utf8String = utils::StringUtils::Utf16ToUtf8(managedString->chars); char* nativeString = MarshalAllocateStringBuffer(utf8String.size() + 1); strcpy(nativeString, utf8String.c_str()); return nativeString; } void PlatformInvoke::MarshalCSharpStringToCppStringFixed(Il2CppString* managedString, char* buffer, int numberOfCharacters) { if (managedString == NULL) { *buffer = '\0'; } else { std::string utf8String = utils::StringUtils::Utf16ToUtf8(managedString->chars, numberOfCharacters - 1); strcpy(buffer, utf8String.c_str()); } } Il2CppChar* PlatformInvoke::MarshalCSharpStringToCppWString(Il2CppString* managedString) { if (managedString == NULL) return NULL; int32_t stringLength = utils::StringUtils::GetLength(managedString); Il2CppChar* nativeString = MarshalAllocateStringBuffer(stringLength + 1); for (int32_t i = 0; i < managedString->length; ++i) nativeString[i] = managedString->chars[i]; nativeString[managedString->length] = '\0'; return nativeString; } void PlatformInvoke::MarshalCSharpStringToCppWStringFixed(Il2CppString* managedString, Il2CppChar* buffer, int numberOfCharacters) { if (managedString == NULL) { *buffer = '\0'; } else { int32_t stringLength = std::min(utils::StringUtils::GetLength(managedString), numberOfCharacters - 1); for (int32_t i = 0; i < stringLength; ++i) buffer[i] = managedString->chars[i]; buffer[stringLength] = '\0'; } } il2cpp_hresult_t PlatformInvoke::MarshalCSharpStringToCppBStringNoThrow(Il2CppString* managedString, Il2CppChar** bstr) { IL2CPP_ASSERT(bstr); if (managedString == NULL) { *bstr = NULL; return IL2CPP_S_OK; } int32_t stringLength = utils::StringUtils::GetLength(managedString); Il2CppChar* stringChars = utils::StringUtils::GetChars(managedString); return os::MarshalStringAlloc::AllocateBStringLength(stringChars, stringLength, bstr); } Il2CppChar* PlatformInvoke::MarshalCSharpStringToCppBString(Il2CppString* managedString) { Il2CppChar* bstr; const il2cpp_hresult_t hr = MarshalCSharpStringToCppBStringNoThrow(managedString, &bstr); IL2CPP_VM_RAISE_IF_FAILED(hr, true); return bstr; } Il2CppString* PlatformInvoke::MarshalCppStringToCSharpStringResult(const char* value) { if (value == NULL) return NULL; return String::New(value); } Il2CppString* PlatformInvoke::MarshalCppWStringToCSharpStringResult(const Il2CppChar* value) { if (value == NULL) return NULL; return String::NewUtf16(value, (int32_t)utils::StringUtils::StrLen(value)); } Il2CppString* PlatformInvoke::MarshalCppBStringToCSharpStringResult(const Il2CppChar* value) { if (value == NULL) return NULL; int32_t length; const il2cpp_hresult_t hr = os::MarshalStringAlloc::GetBStringLength(value, &length); IL2CPP_VM_RAISE_IF_FAILED(hr, true); return String::NewUtf16(value, length); } void PlatformInvoke::MarshalFreeBString(Il2CppChar* value) { const il2cpp_hresult_t hr = os::MarshalStringAlloc::FreeBString(value); IL2CPP_VM_RAISE_IF_FAILED(hr, true); } char* PlatformInvoke::MarshalStringBuilder(Il2CppStringBuilder* stringBuilder) { if (stringBuilder == NULL) return NULL; #if !NET_4_0 size_t stringLength = utils::StringUtils::GetLength(stringBuilder->str); // not sure if this is necessary but it's better to be safe than sorry IL2CPP_ASSERT(static_cast(stringLength) >= stringBuilder->length); if (static_cast(stringLength) < stringBuilder->length) stringLength = stringBuilder->length; std::string utf8String = utils::StringUtils::Utf16ToUtf8(stringBuilder->str->chars, stringBuilder->length); if (stringLength < utf8String.length()) stringLength = utf8String.length(); char* nativeString = MarshalAllocateStringBuffer(stringLength + 1); strcpy(nativeString, utf8String.c_str()); return nativeString; #else size_t stringLength = 0; Il2CppStringBuilder* currentBuilder = stringBuilder; std::vector utf8Chunks; std::vector builders; while (true) { if (currentBuilder == NULL) break; const Il2CppChar *str = (Il2CppChar*)il2cpp::vm::Array::GetFirstElementAddress(currentBuilder->chunkChars); std::string utf8String = utils::StringUtils::Utf16ToUtf8(str, (int)currentBuilder->chunkChars->max_length); utf8Chunks.push_back(utf8String); builders.push_back(currentBuilder); size_t lenToCount = std::max((size_t)currentBuilder->chunkChars->max_length, utf8String.size()); stringLength += lenToCount; currentBuilder = currentBuilder->chunkPrevious; } char* nativeString = MarshalAllocateStringBuffer(stringLength + 1); // We need to zero out the memory because the chunkChar array lengh may have been larger than the chunkLength // and when this happens we'll have a utf8String that is smaller than the the nativeString we allocated. When we go to copy the // chunk utf8String into the nativeString it won't fill everything and we can end up with w/e junk value was in that memory before memset(nativeString, 0, sizeof(char) * (stringLength + 1)); if (stringLength > 0) { int offsetAdjustment = 0; for (int i = (int)utf8Chunks.size() - 1; i >= 0; i--) { std::string utf8String = utf8Chunks[i]; const char* utf8CString = utf8String.c_str(); memcpy(nativeString + builders[i]->chunkOffset + offsetAdjustment, utf8CString, (int)utf8String.size()); offsetAdjustment += (int)utf8String.size() - builders[i]->chunkLength; } } return nativeString; #endif } Il2CppChar* PlatformInvoke::MarshalWStringBuilder(Il2CppStringBuilder* stringBuilder) { if (stringBuilder == NULL) return NULL; #if !NET_4_0 int32_t stringLength = utils::StringUtils::GetLength(stringBuilder->str); // not sure if this is necessary but it's better to be safe than sorry IL2CPP_ASSERT(stringLength >= stringBuilder->length); if (stringLength < stringBuilder->length) stringLength = stringBuilder->length; Il2CppChar* nativeString = MarshalAllocateStringBuffer(stringLength + 1); for (int32_t i = 0; i < stringBuilder->length; ++i) nativeString[i] = stringBuilder->str->chars[i]; nativeString[stringBuilder->length] = '\0'; return nativeString; #else size_t stringLength = 0; Il2CppStringBuilder* currentBuilder = stringBuilder; while (true) { if (currentBuilder == NULL) break; stringLength += (size_t)currentBuilder->chunkChars->max_length; currentBuilder = currentBuilder->chunkPrevious; } Il2CppChar* nativeString = MarshalAllocateStringBuffer(stringLength + 1); if (stringLength > 0) { currentBuilder = stringBuilder; while (true) { if (currentBuilder == NULL) break; const Il2CppChar *str = (Il2CppChar*)il2cpp::vm::Array::GetFirstElementAddress(currentBuilder->chunkChars); memcpy(nativeString + currentBuilder->chunkOffset, str, (int)currentBuilder->chunkChars->max_length * sizeof(Il2CppChar)); currentBuilder = currentBuilder->chunkPrevious; } } nativeString[stringLength] = '\0'; return nativeString; #endif } void PlatformInvoke::MarshalStringBuilderResult(Il2CppStringBuilder* stringBuilder, char* buffer) { if (stringBuilder == NULL || buffer == NULL) return; #if !NET_4_0 Il2CppString* managedString = MarshalCppStringToCSharpStringResult(buffer); stringBuilder->str = managedString; stringBuilder->length = utils::StringUtils::GetLength(managedString); #else UTF16String utf16String = utils::StringUtils::Utf8ToUtf16(buffer); IL2CPP_OBJECT_SETREF(stringBuilder, chunkChars, il2cpp::vm::Array::New(il2cpp_defaults.char_class, (int)utf16String.size() + 1)); for (int i = 0; i < (int)utf16String.size(); i++) il2cpp_array_set(stringBuilder->chunkChars, Il2CppChar, i, utf16String[i]); il2cpp_array_set(stringBuilder->chunkChars, Il2CppChar, (int)utf16String.size(), '\0'); stringBuilder->chunkLength = (int)utf16String.size(); stringBuilder->chunkOffset = 0; IL2CPP_OBJECT_SETREF(stringBuilder, chunkPrevious, NULL); #endif } void PlatformInvoke::MarshalWStringBuilderResult(Il2CppStringBuilder* stringBuilder, Il2CppChar* buffer) { if (stringBuilder == NULL || buffer == NULL) return; #if !NET_4_0 Il2CppString* managedString = MarshalCppWStringToCSharpStringResult(buffer); stringBuilder->str = managedString; stringBuilder->length = utils::StringUtils::GetLength(managedString); #else int len = (int)utils::StringUtils::StrLen(buffer); IL2CPP_OBJECT_SETREF(stringBuilder, chunkChars, il2cpp::vm::Array::New(il2cpp_defaults.char_class, len + 1)); for (int i = 0; i < len; i++) il2cpp_array_set(stringBuilder->chunkChars, Il2CppChar, i, buffer[i]); il2cpp_array_set(stringBuilder->chunkChars, Il2CppChar, len, '\0'); stringBuilder->chunkLength = len; stringBuilder->chunkOffset = 0; IL2CPP_OBJECT_SETREF(stringBuilder, chunkPrevious, NULL); #endif } Il2CppIntPtr PlatformInvoke::MarshalDelegate(Il2CppDelegate* d) { if (d == NULL) return Il2CppIntPtr::Zero; if (d->method->is_inflated) vm::Exception::Raise(vm::Exception::GetNotSupportedException("IL2CPP does not support marshaling delegates that point to generic methods.")); IL2CPP_ASSERT(d->method->methodDefinition); Il2CppMethodPointer reversePInvokeWrapper = MetadataCache::GetReversePInvokeWrapperFromIndex(d->method->methodDefinition->reversePInvokeWrapperIndex); if (reversePInvokeWrapper == NULL) { // Okay, we cannot marshal it for some reason. Figure out why. if (Method::IsInstance(d->method)) vm::Exception::Raise(vm::Exception::GetNotSupportedException("IL2CPP does not support marshaling delegates that point to instance methods to native code.")); vm::Exception::Raise(vm::Exception::GetNotSupportedException("To marshal a managed method, please add an attribute named 'MonoPInvokeCallback' to the method definition.")); } Il2CppIntPtr functionPointer; functionPointer.m_value = (void*)reversePInvokeWrapper; return functionPointer; } Il2CppDelegate* PlatformInvoke::MarshalFunctionPointerToDelegate(void* functionPtr, Il2CppClass* delegateType) { if (!Class::HasParent(delegateType, il2cpp_defaults.delegate_class)) Exception::Raise(Exception::GetArgumentException("t", "Type must derive from Delegate.")); if (Class::IsGeneric(delegateType) || Class::IsInflated(delegateType)) Exception::Raise(Exception::GetArgumentException("t", "The specified Type must not be a generic type definition.")); const Il2CppInteropData* interopData = delegateType->interopData; Il2CppMethodPointer managedToNativeWrapperMethodPointer = interopData != NULL ? interopData->delegatePInvokeWrapperFunction : NULL; if (managedToNativeWrapperMethodPointer == NULL) Exception::Raise(Exception::GetMarshalDirectiveException(utils::StringUtils::Printf("Cannot marshal P/Invoke call through delegate of type '%s.%s'", Class::GetNamespace(delegateType), Class::GetName(delegateType)).c_str())); Il2CppObject* delegate = il2cpp::vm::Object::New(delegateType); Il2CppMethodPointer nativeFunctionPointer = (Il2CppMethodPointer)functionPtr; const MethodInfo* method = utils::NativeDelegateMethodCache::GetNativeDelegate(nativeFunctionPointer); if (method == NULL) { MethodInfo* newMethod = (MethodInfo*)IL2CPP_CALLOC(1, sizeof(MethodInfo)); newMethod->methodPointer = nativeFunctionPointer; newMethod->invoker_method = NULL; utils::NativeDelegateMethodCache::AddNativeDelegate(nativeFunctionPointer, newMethod); method = newMethod; } Type::ConstructDelegate((Il2CppDelegate*)delegate, delegate, managedToNativeWrapperMethodPointer, method); return (Il2CppDelegate*)delegate; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/PlatformInvoke.h ================================================ #pragma once #include "il2cpp-config.h" #include "blob.h" #include "metadata.h" #include "object-internals.h" #include "vm/Array.h" #include "vm/Class.h" #include "vm/MarshalAlloc.h" #include "vm/Object.h" #include "vm/String.h" #include "utils/StringView.h" struct Il2CppString; struct Il2CppStringBuilder; struct PInvokeArguments { const il2cpp::utils::StringView moduleName; const il2cpp::utils::StringView entryPoint; Il2CppCallConvention callingConvention; Il2CppCharSet charSet; int parameterSize; bool isNoMangle; // Says whether P/Invoke should append to function name 'A'/'W' according to charSet. }; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API PlatformInvoke { public: static void SetFindPluginCallback(Il2CppSetFindPlugInCallback method); static Il2CppMethodPointer Resolve(const PInvokeArguments& pinvokeArgs); static void MarshalFree(void* ptr); static char* MarshalCSharpStringToCppString(Il2CppString* managedString); static void MarshalCSharpStringToCppStringFixed(Il2CppString* managedString, char* buffer, int numberOfCharacters); static Il2CppChar* MarshalCSharpStringToCppWString(Il2CppString* managedString); static void MarshalCSharpStringToCppWStringFixed(Il2CppString* managedString, Il2CppChar* buffer, int numberOfCharacters); static il2cpp_hresult_t MarshalCSharpStringToCppBStringNoThrow(Il2CppString* managedString, Il2CppChar** bstr); static Il2CppChar* MarshalCSharpStringToCppBString(Il2CppString* managedString); static Il2CppString* MarshalCppStringToCSharpStringResult(const char* value); static Il2CppString* MarshalCppWStringToCSharpStringResult(const Il2CppChar* value); static Il2CppString* MarshalCppBStringToCSharpStringResult(const Il2CppChar* value); static void MarshalFreeBString(Il2CppChar* value); static char* MarshalStringBuilder(Il2CppStringBuilder* stringBuilder); static Il2CppChar* MarshalWStringBuilder(Il2CppStringBuilder* stringBuilder); static void MarshalStringBuilderResult(Il2CppStringBuilder* stringBuilder, char* buffer); static void MarshalWStringBuilderResult(Il2CppStringBuilder* stringBuilder, Il2CppChar* buffer); static Il2CppIntPtr MarshalDelegate(Il2CppDelegate* d); static Il2CppDelegate* MarshalFunctionPointerToDelegate(void* functionPtr, Il2CppClass* delegateType); template static T* MarshalAllocateStringBuffer(size_t numberOfCharacters) { return (T*)MarshalAlloc::Allocate(numberOfCharacters * sizeof(T)); } }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Profiler.cpp ================================================ #include "il2cpp-config.h" #include "utils/dynamic_array.h" #include "vm/Profiler.h" #if IL2CPP_ENABLE_PROFILER namespace il2cpp { namespace vm { struct ProfilerDesc { Il2CppProfiler* profiler; Il2CppProfileFlags events; Il2CppProfileFunc shutdownCallback; Il2CppProfileMethodFunc methodEnterCallback; Il2CppProfileMethodFunc methodLeaveCallback; Il2CppProfileAllocFunc allocationCallback; Il2CppProfileGCFunc gcEventCallback; Il2CppProfileGCResizeFunc gcHeapResizeCallback; }; typedef il2cpp::utils::dynamic_array ProfilersVec; static ProfilersVec s_profilers; Il2CppProfileFlags Profiler::s_profilerEvents; void Profiler::Install(Il2CppProfiler *prof, Il2CppProfileFunc shutdownCallback) { ProfilerDesc* desc = (ProfilerDesc*)calloc(1, sizeof(ProfilerDesc)); desc->profiler = prof; desc->shutdownCallback = shutdownCallback; s_profilers.push_back(desc); } void Profiler::SetEvents(Il2CppProfileFlags events) { Il2CppProfileFlags value = IL2CPP_PROFILE_NONE; if (s_profilers.size()) s_profilers.back()->events = events; for (ProfilersVec::iterator iter = s_profilers.begin(); iter != s_profilers.end(); iter++) value = (Il2CppProfileFlags)(value | (*iter)->events); s_profilerEvents = value; } void Profiler::InstallEnterLeave(Il2CppProfileMethodFunc enter, Il2CppProfileMethodFunc fleave) { if (!s_profilers.size()) return; s_profilers.back()->methodEnterCallback = enter; s_profilers.back()->methodLeaveCallback = fleave; } void Profiler::InstallAllocation(Il2CppProfileAllocFunc callback) { if (!s_profilers.size()) return; s_profilers.back()->allocationCallback = callback; } void Profiler::InstallGC(Il2CppProfileGCFunc callback, Il2CppProfileGCResizeFunc heap_resize_callback) { if (!s_profilers.size()) return; s_profilers.back()->gcEventCallback = callback; s_profilers.back()->gcHeapResizeCallback = heap_resize_callback; } #if IL2CPP_ENABLE_PROFILER void Profiler::Allocation(Il2CppObject *obj, Il2CppClass *klass) { for (ProfilersVec::const_iterator iter = s_profilers.begin(); iter != s_profilers.end(); iter++) { if (((*iter)->events & IL2CPP_PROFILE_ALLOCATIONS) && (*iter)->allocationCallback) (*iter)->allocationCallback((*iter)->profiler, obj, klass); } } void Profiler::MethodEnter(const MethodInfo *method) { for (ProfilersVec::const_iterator iter = s_profilers.begin(); iter != s_profilers.end(); iter++) { if (((*iter)->events & IL2CPP_PROFILE_ENTER_LEAVE) && (*iter)->methodEnterCallback) (*iter)->methodEnterCallback((*iter)->profiler, method); } } void Profiler::MethodExit(const MethodInfo *method) { for (ProfilersVec::const_iterator iter = s_profilers.begin(); iter != s_profilers.end(); iter++) { if (((*iter)->events & IL2CPP_PROFILE_ENTER_LEAVE) && (*iter)->methodLeaveCallback) (*iter)->methodLeaveCallback((*iter)->profiler, method); } } void Profiler::GCEvent(Il2CppGCEvent eventType) { for (ProfilersVec::const_iterator iter = s_profilers.begin(); iter != s_profilers.end(); iter++) { if (((*iter)->events & IL2CPP_PROFILE_GC) && (*iter)->gcEventCallback) (*iter)->gcEventCallback((*iter)->profiler, eventType, 0); } } void Profiler::GCHeapResize(int64_t newSize) { for (ProfilersVec::const_iterator iter = s_profilers.begin(); iter != s_profilers.end(); iter++) { if (((*iter)->events & IL2CPP_PROFILE_GC) && (*iter)->gcEventCallback) (*iter)->gcHeapResizeCallback((*iter)->profiler, newSize); } } #endif } /* namespace vm */ } /* namespace il2cpp */ #endif // IL2CPP_ENABLE_PROFILER ================================================ FILE: unity_decoder/libil2cpp/vm/Profiler.h ================================================ #pragma once #include #include "il2cpp-config.h" namespace il2cpp { namespace vm { #if IL2CPP_ENABLE_PROFILER class LIBIL2CPP_CODEGEN_API Profiler { // exported public: static void Install(Il2CppProfiler *prof, Il2CppProfileFunc shutdownCallback); static void SetEvents(Il2CppProfileFlags events); static void InstallEnterLeave(Il2CppProfileMethodFunc enter, Il2CppProfileMethodFunc fleave); static void InstallAllocation(Il2CppProfileAllocFunc callback); static void InstallGC(Il2CppProfileGCFunc callback, Il2CppProfileGCResizeFunc heap_resize_callback); // internal public: static void Allocation(Il2CppObject *obj, Il2CppClass *klass); static void MethodEnter(const MethodInfo *method); static void MethodExit(const MethodInfo *method); static void GCEvent(Il2CppGCEvent eventType); static void GCHeapResize(int64_t newSize); static Il2CppProfileFlags s_profilerEvents; static inline bool ProfileAllocations() { return (s_profilerEvents & IL2CPP_PROFILE_ALLOCATIONS) != 0; } private: }; #endif } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Property.cpp ================================================ #include "il2cpp-config.h" #include "vm/Property.h" #include "class-internals.h" namespace il2cpp { namespace vm { uint32_t Property::GetFlags(const PropertyInfo* prop) { return prop->attrs; } const MethodInfo* Property::GetGetMethod(const PropertyInfo* prop) { return prop->get; } const MethodInfo* Property::GetSetMethod(const PropertyInfo* prop) { return prop->set; } const char* Property::GetName(const PropertyInfo* prop) { return prop->name; } Il2CppClass* Property::GetParent(const PropertyInfo* prop) { return prop->parent; } uint32_t Property::GetToken(const PropertyInfo* prop) { return prop->token; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Property.h ================================================ #pragma once #include #include "il2cpp-config.h" struct MethodInfo; struct PropertyInfo; struct Il2CppClass; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API Property { public: // exported static uint32_t GetFlags(const PropertyInfo* prop); static const MethodInfo* GetGetMethod(const PropertyInfo* prop); static const MethodInfo* GetSetMethod(const PropertyInfo* prop); static const char* GetName(const PropertyInfo* prop); static Il2CppClass* GetParent(const PropertyInfo* prop); static uint32_t GetToken(const PropertyInfo* prop); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/RCW.cpp ================================================ #include "il2cpp-config.h" #include "object-internals.h" #include "class-internals.h" #include "il2cpp-vm-support.h" #include "gc/GCHandle.h" #include "metadata/GenericMetadata.h" #include "vm/Exception.h" #include "vm/Field.h" #include "vm/GenericClass.h" #include "vm/MetadataCache.h" #include "vm/Object.h" #include "vm/PlatformInvoke.h" #include "vm/RCW.h" #include "vm/Runtime.h" #include "os/COM.h" #include "os/Mutex.h" #include "os/WindowsRuntime.h" #include "utils/Il2CppHashMap.h" #include "utils/HashUtils.h" #include "utils/StringUtils.h" const Il2CppGuid Il2CppIUnknown::IID = { 0x00000000, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 }; const Il2CppGuid Il2CppISequentialStream::IID = { 0x0c733a30, 0x2a1c, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d }; const Il2CppGuid Il2CppIStream::IID = { 0x0000000c, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 }; const Il2CppGuid Il2CppIMarshal::IID = { 0x00000003, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 }; const Il2CppGuid Il2CppIManagedObject::IID = { 0xc3fcc19e, 0xa970, 0x11d2, 0x8b, 0x5a, 0x00, 0xa0, 0xc9, 0xb7, 0xc9, 0xc4 }; const Il2CppGuid Il2CppIManagedObjectHolder::IID = { 0xd4bbc1c8, 0xf5bf, 0x4647, 0x94, 0x95, 0x2e, 0x5c, 0xf, 0x20, 0xf7, 0x5d }; const Il2CppGuid Il2CppIInspectable::IID = { 0xaf86e2e0, 0xb12d, 0x4c6a, 0x9c, 0x5a, 0xd7, 0xaa, 0x65, 0x10, 0x1E, 0x90 }; const Il2CppGuid Il2CppIActivationFactory::IID = { 0x00000035, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 }; const Il2CppGuid Il2CppIRestrictedErrorInfo::IID = { 0x82ba7092, 0x4c88, 0x427d, 0xa7, 0xbc, 0x16, 0xdd, 0x93, 0xfe, 0xb6, 0x7e }; const Il2CppGuid Il2CppILanguageExceptionErrorInfo::IID = { 0x04a2dbf3, 0xdf83, 0x116c, 0x09, 0x46, 0x08, 0x12, 0xab, 0xf6, 0xe0, 0x7d }; const Il2CppGuid Il2CppIAgileObject::IID = { 0x94ea2b94, 0xe9cc, 0x49e0, 0xc0, 0xff, 0xee, 0x64, 0xca, 0x8f, 0x5b, 0x90 }; using il2cpp::utils::PointerHash; namespace il2cpp { using namespace os; namespace vm { typedef Il2CppHashMap > RCWCache; static FastMutex s_RCWCacheMutex; static RCWCache s_RCWCache; void RCW::Register(Il2CppComObject* rcw) { FastAutoLock lock(&s_RCWCacheMutex); const bool inserted = s_RCWCache.insert(std::make_pair(rcw->identity, gc::GCHandle::NewWeakref(rcw, false))).second; Assert(inserted); } static inline Il2CppIUnknown* GetIdentity(Il2CppIUnknown* unknown) { Il2CppIUnknown* identity; il2cpp_hresult_t hr = unknown->QueryInterface(Il2CppIUnknown::IID, reinterpret_cast(&identity)); IL2CPP_VM_RAISE_IF_FAILED(hr, true); IL2CPP_ASSERT(identity); return identity; } // Shameless comment copycat from .NET Native (https://github.com/dotnet/corert/blob/374c3d47992a7c444ec7d1dfe94b1780de942a55/src/System.Private.Interop/src/Shared/McgComHelpers.cs#L557): // 1. Prefer using the class returned from GetRuntimeClassName // 2. Otherwise use the class (if there) in the signature // 3. Out of options - create Il2CppComObject static inline Il2CppClass* GetClassForRCW(Il2CppIInspectable* inspectable, Il2CppClass* fallbackClass) { Il2CppHString className; il2cpp_hresult_t hr = inspectable->GetRuntimeClassName(&className); if (IL2CPP_HR_FAILED(hr) || className == NULL) return fallbackClass; uint32_t classNameLength; const Il2CppChar* classNamePtr = os::WindowsRuntime::GetHStringBuffer(className, &classNameLength); std::string classNameUtf8 = utils::StringUtils::Utf16ToUtf8(classNamePtr, classNameLength); os::WindowsRuntime::DeleteHString(className); Il2CppClass* rcwClass = MetadataCache::GetWindowsRuntimeClass(classNameUtf8); return rcwClass != NULL ? rcwClass : fallbackClass; } static inline Il2CppClass* GetClassForRCW(Il2CppIUnknown* unknown, Il2CppClass* fallbackClass) { Il2CppIInspectable* inspectable; il2cpp_hresult_t hr = unknown->QueryInterface(Il2CppIInspectable::IID, reinterpret_cast(&inspectable)); if (IL2CPP_HR_FAILED(hr)) return fallbackClass; Il2CppClass* result = GetClassForRCW(inspectable, fallbackClass); inspectable->Release(); return result; } Il2CppObject* ReboxIReference(Il2CppIUnknown* comObject, Il2CppClass* objectClass); Il2CppObject* ReboxKeyValuePair(Il2CppIUnknown* comObject, Il2CppClass* keyValuePairGenericInstance); Il2CppObject* ReboxUri(Il2CppIUnknown* comObject); Il2CppObject* ReboxIfBoxed(Il2CppIUnknown* comObject, Il2CppClass* objectClass) { if (strcmp(objectClass->namespaze, "Windows.Foundation") == 0 && strcmp(objectClass->name, "IReference`1") == 0) return ReboxIReference(comObject, objectClass); if (strcmp(objectClass->namespaze, "System.Collections.Generic") == 0 && strcmp(objectClass->name, "KeyValuePair`2") == 0) return ReboxKeyValuePair(comObject, objectClass); if (objectClass == il2cpp_defaults.system_uri_class) return ReboxUri(comObject); return NULL; } Il2CppObject* ReboxIReference(Il2CppIUnknown* comObject, Il2CppClass* objectClass) { Class::Init(objectClass); // Sanity checks IL2CPP_ASSERT(Class::IsInflated(objectClass)); IL2CPP_ASSERT(objectClass->vtable_count == 1); // IReference`1 only has get_Value method const MethodInfo* getValueMethod = objectClass->vtable[0].method; IL2CPP_ASSERT(strcmp(getValueMethod->name, "get_Value") == 0); // We don't really want to allocate it on the GC heap for this little invocation Il2CppComObject fakeRcw; fakeRcw.klass = objectClass; fakeRcw.monitor = NULL; fakeRcw.identity = comObject; Il2CppException* exception = NULL; Il2CppObject* reboxed = Runtime::Invoke(getValueMethod, &fakeRcw, NULL, &exception); if (exception != NULL) Exception::Raise(exception); return reboxed; } Il2CppObject* ReboxKeyValuePair(Il2CppIUnknown* comObject, Il2CppClass* keyValuePairGenericInstance) { Class::Init(keyValuePairGenericInstance); // Sanity checks IL2CPP_ASSERT(Class::IsInflated(keyValuePairGenericInstance)); IL2CPP_ASSERT(il2cpp_defaults.ikey_value_pair_class != NULL); // Retrieve Windows.Foundation.Collections.IKeyValuePair`1 generic instance Il2CppGenericClass* iKeyValuePairGenericClass = metadata::GenericMetadata::GetGenericClass(il2cpp_defaults.ikey_value_pair_class, keyValuePairGenericInstance->generic_class->context.class_inst); Il2CppClass* iKeyValuePairGenericInstance = GenericClass::GetClass(iKeyValuePairGenericClass); Class::Init(iKeyValuePairGenericInstance); IL2CPP_ASSERT(iKeyValuePairGenericInstance->vtable_count == 2); const MethodInfo* getKeyMethod = iKeyValuePairGenericInstance->vtable[0].method; IL2CPP_ASSERT(strcmp(getKeyMethod->name, "get_Key") == 0); const MethodInfo* getValueMethod = iKeyValuePairGenericInstance->vtable[1].method; IL2CPP_ASSERT(strcmp(getValueMethod->name, "get_Value") == 0); Il2CppComObject fakeRcw; fakeRcw.klass = il2cpp_defaults.il2cpp_com_object_class; fakeRcw.monitor = NULL; fakeRcw.identity = comObject; // Create new boxed key value pair Il2CppObject* reboxed = Object::New(keyValuePairGenericInstance); for (uint16_t i = 0; i < 2; i++) { const MethodInfo* methodToInvoke; const FieldInfo& field = keyValuePairGenericInstance->fields[i]; // Figure out which getter to call if (strcmp(field.name, "key") == 0) { methodToInvoke = getKeyMethod; } else if (strcmp(field.name, "value") == 0) { methodToInvoke = getValueMethod; } // Call the getter Il2CppException* exception = NULL; Il2CppObject* fieldValue = Runtime::Invoke(methodToInvoke, &fakeRcw, NULL, &exception); if (exception != NULL) Exception::Raise(exception); // Set the field in our reboxed key value pair instance if (Class::FromIl2CppType(field.type)->valuetype) { Field::SetValue(reboxed, &field, Object::Unbox(fieldValue)); } else { Field::SetValue(reboxed, &field, fieldValue); } } return reboxed; } Il2CppObject* ReboxUri(Il2CppIUnknown* comObject) { Il2CppClass* systemUriClass = il2cpp_defaults.system_uri_class; Il2CppClass* iUriRuntimeClassClass = il2cpp_defaults.windows_foundation_iuri_runtime_class_class; Class::Init(systemUriClass); Class::Init(iUriRuntimeClassClass); const int kGetRawUriMethodIndex = 10; // IUriRuntimeClass::get_RawUri IL2CPP_ASSERT(iUriRuntimeClassClass->vtable_count > kGetRawUriMethodIndex); VirtualInvokeData getRawUriInvokeData = iUriRuntimeClassClass->vtable[kGetRawUriMethodIndex]; IL2CPP_ASSERT(strcmp(getRawUriInvokeData.method->name, "get_RawUri") == 0); Il2CppComObject fakeRcw; fakeRcw.klass = il2cpp_defaults.il2cpp_com_object_class; fakeRcw.monitor = NULL; fakeRcw.identity = comObject; Il2CppObject* rawUri = Runtime::InvokeWithThrow(getRawUriInvokeData.method, &fakeRcw, NULL); const MethodInfo* uriConstructor = NULL; uint16_t uriMethodCount = systemUriClass->method_count; for (uint16_t i = 0; i < uriMethodCount; i++) { const MethodInfo* method = systemUriClass->methods[i]; if (strcmp(method->name, ".ctor") == 0 && method->parameters_count == 1 && method->parameters[0].parameter_type->type == IL2CPP_TYPE_STRING) { uriConstructor = method; break; } } IL2CPP_ASSERT(uriConstructor); Il2CppObject* reboxedUri = Object::New(systemUriClass); void* constructorArgs[1] = { rawUri }; Runtime::InvokeWithThrow(uriConstructor, reboxedUri, constructorArgs); return reboxedUri; } template static inline Il2CppObject* GetOrCreateRCW(T* comObject, Il2CppClass* objectClass) { IL2CPP_ASSERT(comObject != NULL); if (!isSealedClassInstance) { // 1. Check if comObject is actually our COM Callable Wrapper Il2CppIManagedObjectHolder* managedHolder; il2cpp_hresult_t hr = comObject->QueryInterface(Il2CppIManagedObjectHolder::IID, reinterpret_cast(&managedHolder)); if (IL2CPP_HR_SUCCEEDED(hr)) { Il2CppObject* instance = managedHolder->GetManagedObject(); managedHolder->Release(); IL2CPP_ASSERT(instance); return instance; } } Il2CppIUnknown* identity = GetIdentity(comObject); // 2. Try to find it in RCW cache FastAutoLock lock(&s_RCWCacheMutex); RCWCache::iterator iter = s_RCWCache.find(identity); if (iter != s_RCWCache.end()) { Il2CppObject* obj = gc::GCHandle::GetTarget(iter->second); if (obj != NULL) { identity->Release(); identity = NULL; return obj; } else { // The RCW was already queued for finalization. // Erase it from the cache and let us create a new one. s_RCWCache.erase(iter); } } // 3. Figure out the concrete RCW class if (!isSealedClassInstance) { objectClass = GetClassForRCW(comObject, objectClass); // If object class is one of the blessed unboxable classes, // unbox the object from its windows runtime representation, // unmarshal it, box it to Il2CppObject and return it // // Current list of unboxable classes: // Windows.Foundation.IReference`1 // System.Collections.Generic.KeyValuePair`2 // System.Uri Il2CppObject* reboxed = ReboxIfBoxed(comObject, objectClass); if (reboxed != NULL) return reboxed; } IL2CPP_ASSERT(Class::HasParent(objectClass, il2cpp_defaults.il2cpp_com_object_class)); // 4. Create RCW object Il2CppComObject* rcw = static_cast(Object::New(objectClass)); rcw->identity = identity; // 5. Insert it into the cache const bool inserted = s_RCWCache.insert(std::make_pair(identity, gc::GCHandle::NewWeakref(rcw, false))).second; Assert(inserted); return rcw; } Il2CppObject* RCW::GetOrCreateFromIUnknown(Il2CppIUnknown* unknown, Il2CppClass* fallbackClass) { return GetOrCreateRCW(unknown, fallbackClass); } Il2CppObject* RCW::GetOrCreateFromIInspectable(Il2CppIInspectable* inspectable, Il2CppClass* fallbackClass) { return GetOrCreateRCW(inspectable, fallbackClass); } Il2CppObject* RCW::GetOrCreateForSealedClass(Il2CppIUnknown* unknown, Il2CppClass* objectClass) { return GetOrCreateRCW(unknown, objectClass); } void RCW::Cleanup(Il2CppComObject* rcw) { FastAutoLock lock(&s_RCWCacheMutex); RCWCache::iterator iter = s_RCWCache.find(rcw->identity); // It is possible for us to not find object in the cache if two RCWs for the same IUnknown get // finalized in a row: then, the first finalizer will remove the NULL object, and the second one // will not find it. if (iter != s_RCWCache.end()) { Il2CppObject* obj = gc::GCHandle::GetTarget(iter->second); // If it's null, it means that the cache contains our object // but the weak GC handle has been invalidated by the GC already // If it's equal to our object, it means that RCW::Cleanup was // called manually, and we should also delete it from the cache // Otherwise, it's a different object. It means that we have already // created a new RCW in place of this one during the time // it had been queued for finalization if (obj == NULL || obj == rcw) s_RCWCache.erase(iter); } } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/RCW.h ================================================ #pragma once #include "il2cpp-config.h" #include "object-internals.h" struct Il2CppComObject; struct Il2CppGuid; struct Il2CppIUnknown; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API RCW { public: static void Register(Il2CppComObject* rcw); static Il2CppObject* GetOrCreateFromIUnknown(Il2CppIUnknown* unknown, Il2CppClass* fallbackClass); static Il2CppObject* GetOrCreateFromIInspectable(Il2CppIInspectable* inspectable, Il2CppClass* fallbackClass); static Il2CppObject* GetOrCreateForSealedClass(Il2CppIUnknown* unknown, Il2CppClass* objectClass); static void Cleanup(Il2CppComObject* rcw); template inline static Il2CppIUnknown* QueryInterface(Il2CppComObject* rcw, const Il2CppGuid& iid) { IL2CPP_ASSERT(rcw); IL2CPP_ASSERT(rcw->identity); Il2CppIUnknown* result; const il2cpp_hresult_t hr = rcw->identity->QueryInterface(iid, reinterpret_cast(&result)); if (IL2CPP_HR_FAILED(hr)) { if (throwOnError) Exception::Raise(hr, true); return NULL; } IL2CPP_ASSERT(result); return result; } }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Random.cpp ================================================ #include "il2cpp-config.h" #include "vm/Random.h" #include "os/Cryptography.h" namespace il2cpp { namespace vm { bool Random::Open() { return il2cpp::os::Cryptography::OpenCryptographyProvider(); } void* Random::Create() { il2cpp::os::Cryptography::OpenCryptographyProvider(); return il2cpp::os::Cryptography::GetCryptographyProvider(); } void Random::Free(void* handle) { il2cpp::os::Cryptography::ReleaseCryptographyProvider(handle); } /** * mono_rand_try_get_bytes: * @handle: A pointer to an RNG handle. Handle is set to NULL on failure. * @buffer: A buffer into which to write random data. * @buffer_size: Number of bytes to write into buffer. * @error: Set on error. * * Returns: FALSE on failure and sets @error, TRUE on success. * * Extracts bytes from an RNG handle. */ bool Random::TryGetBytes(void* *handle, unsigned char *buffer, int buffer_size) { IL2CPP_ASSERT(handle); void* provider = *handle; if (!il2cpp::os::Cryptography::FillBufferWithRandomBytes(provider, buffer_size, buffer)) { il2cpp::os::Cryptography::ReleaseCryptographyProvider(provider); /* we may have lost our context with CryptoAPI, but all hope isn't lost yet! */ provider = il2cpp::os::Cryptography::GetCryptographyProvider(); if (!il2cpp::os::Cryptography::FillBufferWithRandomBytes(provider, buffer_size, buffer)) { il2cpp::os::Cryptography::ReleaseCryptographyProvider(provider); *handle = 0; //mono_error_set_execution_engine(error, "Failed to gen random bytes (%d)", GetLastError()); return false; } } return true; } /** * mono_rand_try_get_uint32: * @handle: A pointer to an RNG handle. Handle is set to NULL on failure. * @val: A pointer to a 32-bit unsigned int, to which the result will be written. * @min: Result will be greater than or equal to this value. * @max: Result will be less than or equal to this value. * * Returns: FALSE on failure, TRUE on success. * * Extracts one 32-bit unsigned int from an RNG handle. */ bool Random::TryGetUnsignedInt32(void* *handle, uint32_t *val, uint32_t min, uint32_t max) { IL2CPP_ASSERT(val); if (!TryGetBytes(handle, (unsigned char*)val, sizeof(uint32_t))) return false; double randomDouble = ((double)*val) / (((double)UINT32_MAX) + 1); // Range is [0,1) *val = (uint32_t)(randomDouble * (max - min + 1) + min); IL2CPP_ASSERT(*val >= min); IL2CPP_ASSERT(*val <= max); return true; } uint32_t Random::Next(void** handle, uint32_t min, uint32_t max) { uint32_t val; bool ok = TryGetUnsignedInt32(handle, &val, min, max); IL2CPP_ASSERT(ok); return val; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Random.h ================================================ #pragma once namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API Random { public: static bool Open(); static void* Create(); static void Free(void* handle); static bool TryGetBytes(void** handle, unsigned char *buffer, int buffer_size); static bool TryGetUnsignedInt32(void** handle, uint32_t *val, uint32_t min, uint32_t max); static uint32_t Next(void** handle, uint32_t min, uint32_t max); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Reflection.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "object-internals.h" #include "tabledefs.h" #include "mono-structs.h" #include "gc/GCHandle.h" #include "metadata/Il2CppTypeCompare.h" #include "metadata/Il2CppTypeHash.h" #include "os/Mutex.h" #include "vm/Array.h" #include "vm/Class.h" #include "vm/Field.h" #include "vm/Image.h" #include "vm/MetadataCache.h" #include "vm/Object.h" #include "vm/Parameter.h" #include "vm/Reflection.h" #include "vm/String.h" #include "vm/AssemblyName.h" #include "utils/Il2CppHashMap.h" #include "utils/StringUtils.h" #include "utils/HashUtils.h" #include "gc/AppendOnlyGCHashMap.h" #include "gc/Allocator.h" using il2cpp::metadata::Il2CppTypeEqualityComparer; using il2cpp::metadata::Il2CppTypeHash; template struct ReflectionMapHash { size_t operator()(const T& ea) const { return ((size_t)(intptr_t)(ea.first)) >> 3; } }; template struct ReflectionMapLess { bool operator()(const T& ea, const T& eb) const { if (ea.first < eb.first) return true; if (ea.second < eb.second) return true; return false; } }; template struct ReflectionMap : public il2cpp::gc::AppendOnlyGCHashMap > { }; typedef ReflectionMap, Il2CppReflectionAssembly*> AssemblyMap; typedef ReflectionMap, Il2CppReflectionField*> FieldMap; typedef ReflectionMap, Il2CppReflectionProperty*> PropertyMap; typedef ReflectionMap, Il2CppReflectionEvent*> EventMap; typedef ReflectionMap, Il2CppReflectionMethod*> MethodMap; typedef ReflectionMap, Il2CppReflectionModule*> ModuleMap; typedef ReflectionMap, Il2CppArray*> ParametersMap; typedef il2cpp::gc::AppendOnlyGCHashMap TypeMap; typedef Il2CppHashMap > MonoGenericParameterMap; typedef Il2CppHashMap > MonoAssemblyNameMap; // these needs to be pointers and allocated after GC is initialized since it uses GC Allocator static AssemblyMap* s_AssemblyMap; static FieldMap* s_FieldMap; static PropertyMap* s_PropertyMap; static EventMap* s_EventMap; static MethodMap* s_MethodMap; static ModuleMap* s_ModuleMap; static ParametersMap* s_ParametersMap; static TypeMap* s_TypeMap; static MonoGenericParameterMap* s_MonoGenericParamterMap; static MonoAssemblyNameMap* s_MonoAssemblyNameMap; namespace il2cpp { namespace vm { static il2cpp::os::FastMutex s_ReflectionICallsMutex; Il2CppReflectionAssembly* Reflection::GetAssemblyObject(const Il2CppAssembly *assembly) { static Il2CppClass *System_Reflection_Assembly; Il2CppReflectionAssembly *res; il2cpp::os::FastAutoLock lock(&s_ReflectionICallsMutex); AssemblyMap::key_type::wrapped_type key(assembly, (Il2CppClass*)NULL); AssemblyMap::data_type value = NULL; if (s_AssemblyMap->TryGetValue(key, &value)) return value; if (!System_Reflection_Assembly) #if !NET_4_0 System_Reflection_Assembly = il2cpp_defaults.assembly_class; #else System_Reflection_Assembly = il2cpp_defaults.mono_assembly_class; #endif res = (Il2CppReflectionAssembly*)Object::New(System_Reflection_Assembly); res->assembly = assembly; s_AssemblyMap->Add(key, res); return res; } Il2CppReflectionAssemblyName* Reflection::GetAssemblyNameObject(const Il2CppAssemblyName *assemblyName) { std::string fullAssemblyName = vm::AssemblyName::AssemblyNameToString(*assemblyName); Il2CppReflectionAssemblyName* reflectionAssemblyName = (Il2CppReflectionAssemblyName*)Object::New(il2cpp_defaults.assembly_name_class); vm::AssemblyName::ParseName(reflectionAssemblyName, fullAssemblyName); return reflectionAssemblyName; } Il2CppReflectionField* Reflection::GetFieldObject(Il2CppClass *klass, FieldInfo *field) { Il2CppReflectionField *res; static Il2CppClass *monofield_klass; il2cpp::os::FastAutoLock lock(&s_ReflectionICallsMutex); FieldMap::key_type::wrapped_type key(field, klass); FieldMap::data_type value = NULL; if (s_FieldMap->TryGetValue(key, &value)) return value; if (!monofield_klass) monofield_klass = Class::FromName(il2cpp_defaults.corlib, "System.Reflection", "MonoField"); res = (Il2CppReflectionField*)Object::New(monofield_klass); res->klass = klass; res->field = field; IL2CPP_OBJECT_SETREF(res, name, String::New(Field::GetName(field))); res->attrs = field->type->attrs; IL2CPP_OBJECT_SETREF(res, type, GetTypeObject(field->type)); s_FieldMap->Add(key, res); return res; } /* * We use the same C representation for methods and constructors, but the type * name in C# is different. */ static Il2CppClass *System_Reflection_MonoMethod = NULL; static Il2CppClass *System_Reflection_MonoCMethod = NULL; static Il2CppClass *System_Reflection_MonoGenericCMethod = NULL; static Il2CppClass *System_Reflection_MonoGenericMethod = NULL; Il2CppReflectionMethod* Reflection::GetMethodObject(const MethodInfo *method, Il2CppClass *refclass) { Il2CppClass *klass; Il2CppReflectionMethod *ret; il2cpp::os::FastAutoLock lock(&s_ReflectionICallsMutex); if (method->is_inflated) { refclass = method->declaring_type; MethodMap::key_type::wrapped_type key(method, refclass); MethodMap::data_type value = NULL; if (s_MethodMap->TryGetValue(key, &value)) return value; if ((*method->name == '.') && (!strcmp(method->name, ".ctor") || !strcmp(method->name, ".cctor"))) { if (!System_Reflection_MonoGenericCMethod) System_Reflection_MonoGenericCMethod = Class::FromName(il2cpp_defaults.corlib, "System.Reflection", "MonoGenericCMethod"); klass = System_Reflection_MonoGenericCMethod; } else { if (!System_Reflection_MonoGenericMethod) System_Reflection_MonoGenericMethod = Class::FromName(il2cpp_defaults.corlib, "System.Reflection", "MonoGenericMethod"); klass = System_Reflection_MonoGenericMethod; } Il2CppReflectionGenericMethod *gret = (Il2CppReflectionGenericMethod*)Object::New(klass); gret->base.method = method; IL2CPP_OBJECT_SETREF(gret, base.name, String::New(method->name)); IL2CPP_OBJECT_SETREF(gret, base.reftype, GetTypeObject(refclass->byval_arg)); ret = &gret->base; s_MethodMap->Add(key, ret); return ret; } if (!refclass) refclass = method->declaring_type; MethodMap::key_type::wrapped_type key(method, refclass); MethodMap::data_type value = NULL; if (s_MethodMap->TryGetValue(key, &value)) return value; if (*method->name == '.' && (strcmp(method->name, ".ctor") == 0 || strcmp(method->name, ".cctor") == 0)) { if (!System_Reflection_MonoCMethod) System_Reflection_MonoCMethod = Class::FromName(il2cpp_defaults.corlib, "System.Reflection", "MonoCMethod"); klass = System_Reflection_MonoCMethod; } else { if (!System_Reflection_MonoMethod) System_Reflection_MonoMethod = Class::FromName(il2cpp_defaults.corlib, "System.Reflection", "MonoMethod"); klass = System_Reflection_MonoMethod; } ret = (Il2CppReflectionMethod*)Object::New(klass); ret->method = method; IL2CPP_OBJECT_SETREF(ret, reftype, GetTypeObject(refclass->byval_arg)); s_MethodMap->Add(key, ret); return ret; } Il2CppReflectionModule* Reflection::GetModuleObject(const Il2CppImage *image) { static Il2CppClass *System_Reflection_Module; Il2CppReflectionModule *res; //char* basename; il2cpp::os::FastAutoLock lock(&s_ReflectionICallsMutex); ModuleMap::key_type::wrapped_type key(image, (Il2CppClass*)NULL); ModuleMap::data_type value = NULL; if (s_ModuleMap->TryGetValue(key, &value)) return value; if (!System_Reflection_Module) { #if !NET_4_0 System_Reflection_Module = Class::FromName(il2cpp_defaults.corlib, "System.Reflection", "Module"); #else System_Reflection_Module = Class::FromName(il2cpp_defaults.corlib, "System.Reflection", "MonoModule"); #endif } res = (Il2CppReflectionModule*)Object::New(System_Reflection_Module); res->image = image; IL2CPP_OBJECT_SETREF(res, assembly, (Il2CppReflectionAssembly*)Reflection::GetAssemblyObject(MetadataCache::GetAssemblyFromIndex(image->assemblyIndex))); IL2CPP_OBJECT_SETREF(res, fqname, String::New(image->name)); NOT_IMPLEMENTED_ICALL_NO_ASSERT(Reflection::GetModuleObject, "Missing Module fields need set"); //basename = g_path_get_basename (image->name); //IL2CPP_OBJECT_SETREF (res, name, String::New (basename)); IL2CPP_OBJECT_SETREF(res, name, String::New(image->name)); IL2CPP_OBJECT_SETREF(res, scopename, String::New(image->nameNoExt)); //g_free (basename); /*if (image->assembly->image == image) { res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1); } else { int i; res->token = 0; if (image->assembly->image->modules) { for (i = 0; i < image->assembly->image->module_count; i++) { if (image->assembly->image->modules [i] == image) res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1); } IL2CPP_ASSERT(res->token); } }*/ s_ModuleMap->Add(key, res); return res; } Il2CppReflectionProperty* Reflection::GetPropertyObject(Il2CppClass *klass, const PropertyInfo *property) { Il2CppReflectionProperty *res; static Il2CppClass *monoproperty_klass; il2cpp::os::FastAutoLock lock(&s_ReflectionICallsMutex); PropertyMap::key_type::wrapped_type key(property, klass); PropertyMap::data_type value = NULL; if (s_PropertyMap->TryGetValue(key, &value)) return value; if (!monoproperty_klass) monoproperty_klass = Class::FromName(il2cpp_defaults.corlib, "System.Reflection", "MonoProperty"); res = (Il2CppReflectionProperty*)Object::New(monoproperty_klass); res->klass = klass; res->property = property; s_PropertyMap->Add(key, res); return res; } Il2CppReflectionEvent* Reflection::GetEventObject(Il2CppClass* klass, const EventInfo* event) { Il2CppReflectionEvent* result; static Il2CppClass* monoproperty_klass = Class::FromName(il2cpp_defaults.corlib, "System.Reflection", "MonoEvent"); il2cpp::os::FastAutoLock lock(&s_ReflectionICallsMutex); EventMap::key_type::wrapped_type key(event, klass); EventMap::data_type value = NULL; if (s_EventMap->TryGetValue(key, &value)) return value; Il2CppReflectionMonoEvent* monoEvent = reinterpret_cast(Object::New(monoproperty_klass)); monoEvent->eventInfo = event; monoEvent->reflectedType = Reflection::GetTypeObject(klass->byval_arg); result = reinterpret_cast(monoEvent); s_EventMap->Add(key, result); return result; } Il2CppReflectionType* Reflection::GetTypeObject(const Il2CppType *type) { il2cpp::os::FastAutoLock lock(&s_ReflectionICallsMutex); Il2CppReflectionType* object = NULL; if (s_TypeMap->TryGetValue(type, &object)) return object; Il2CppReflectionType* typeObject = (Il2CppReflectionType*)Object::New(il2cpp_defaults.monotype_class); typeObject->type = type; s_TypeMap->Add(type, typeObject); return typeObject; } Il2CppObject* Reflection::GetDBNullObject() { Il2CppObject* valueFieldValue; static FieldInfo *dbNullValueField = NULL; if (!dbNullValueField) { dbNullValueField = Class::GetFieldFromName(il2cpp_defaults.dbnull_class, "Value"); IL2CPP_ASSERT(dbNullValueField); } valueFieldValue = Field::GetValueObject(dbNullValueField, NULL); IL2CPP_ASSERT(valueFieldValue); return valueFieldValue; } static Il2CppObject* GetReflectionMissingObject() { Il2CppObject* valueFieldValue; static FieldInfo *reflectionMissingField = NULL; if (!reflectionMissingField) { Il2CppClass* klass = Image::ClassFromName(il2cpp_defaults.corlib, "System.Reflection", "Missing"); Class::Init(klass); reflectionMissingField = Class::GetFieldFromName(klass, "Value"); IL2CPP_ASSERT(reflectionMissingField); } valueFieldValue = Field::GetValueObject(reflectionMissingField, NULL); IL2CPP_ASSERT(valueFieldValue); return valueFieldValue; } static Il2CppObject* GetObjectForMissingDefaultValue(uint32_t parameterAttributes) { if (parameterAttributes & PARAM_ATTRIBUTE_OPTIONAL) return GetReflectionMissingObject(); else return Reflection::GetDBNullObject(); } Il2CppArray* Reflection::GetParamObjects(const MethodInfo *method, Il2CppClass *refclass) { static Il2CppClass *System_Reflection_ParameterInfo; static Il2CppClass *System_Reflection_ParameterInfo_array; Il2CppArray *res = NULL; Il2CppReflectionMethod *member = NULL; il2cpp::os::FastAutoLock lock(&s_ReflectionICallsMutex); NOT_IMPLEMENTED_NO_ASSERT(Reflection::GetParamObjects, "Work in progress!"); if (!System_Reflection_ParameterInfo_array) { Il2CppClass *klass; #if !NET_4_0 klass = il2cpp_defaults.parameter_info_class; #else klass = il2cpp_defaults.mono_parameter_info_class; #endif //mono_memory_barrier (); System_Reflection_ParameterInfo = klass; klass = Class::GetArrayClass(klass, 1); //mono_memory_barrier (); System_Reflection_ParameterInfo_array = klass; } if (!method->parameters_count) return Array::NewSpecific(System_Reflection_ParameterInfo_array, 0); // Mono caches based on the address of the method pointer in the MethodInfo // since they put everything in one cache and the MethodInfo is already used as key for GetMethodObject caching // However, since we have distinct maps for the different types we can use MethodInfo as the key again ParametersMap::key_type::wrapped_type key(method, refclass); ParametersMap::data_type value; if (s_ParametersMap->TryGetValue(key, &value)) return value; member = GetMethodObject(method, refclass); res = Array::NewSpecific(System_Reflection_ParameterInfo_array, method->parameters_count); for (int i = 0; i < method->parameters_count; ++i) { Il2CppReflectionParameter* param = (Il2CppReflectionParameter*)Object::New(System_Reflection_ParameterInfo); IL2CPP_OBJECT_SETREF(param, ClassImpl, GetTypeObject(method->parameters[i].parameter_type)); IL2CPP_OBJECT_SETREF(param, MemberImpl, (Il2CppObject*)member); IL2CPP_OBJECT_SETREF(param, NameImpl, method->parameters[i].name ? String::New(method->parameters[i].name) : NULL); param->PositionImpl = i; param->AttrsImpl = method->parameters[i].parameter_type->attrs; Il2CppObject* defaultValue = NULL; if (param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT) { bool isExplicitySetNullDefaultValue = false; defaultValue = Parameter::GetDefaultParameterValueObject(method, &method->parameters[i], &isExplicitySetNullDefaultValue); if (defaultValue == NULL && !isExplicitySetNullDefaultValue) defaultValue = GetObjectForMissingDefaultValue(param->AttrsImpl); } else { defaultValue = GetObjectForMissingDefaultValue(param->AttrsImpl); } IL2CPP_OBJECT_SETREF(param, DefaultValueImpl, defaultValue); il2cpp_array_setref(res, i, param); } s_ParametersMap->Add(key, res); return res; } // TODO: move this somewhere else bool Reflection::IsType(Il2CppObject *obj) { if (obj->klass->image == il2cpp_defaults.corlib) return strcmp(obj->klass->name, "MonoType") == 0 && strcmp(obj->klass->namespaze, "System") == 0; return false; } static bool IsMethod(Il2CppObject *obj) { if (obj->klass->image == il2cpp_defaults.corlib) return strcmp(obj->klass->name, "MonoMethod") == 0 && strcmp(obj->klass->namespaze, "System.Reflection") == 0; return false; } static bool IsCMethod(Il2CppObject *obj) { if (obj->klass->image == il2cpp_defaults.corlib) return strcmp(obj->klass->name, "MonoCMethod") == 0 && strcmp(obj->klass->namespaze, "System.Reflection") == 0; return false; } static bool IsGenericMethod(Il2CppObject *obj) { if (obj->klass->image == il2cpp_defaults.corlib) return strcmp(obj->klass->name, "MonoGenericMethod") == 0 && strcmp(obj->klass->namespaze, "System.Reflection") == 0; return false; } static bool IsGenericCMethod(Il2CppObject *obj) { if (obj->klass->image == il2cpp_defaults.corlib) return strcmp(obj->klass->name, "MonoGenericCMethod") == 0 && strcmp(obj->klass->namespaze, "System.Reflection") == 0; return false; } bool Reflection::IsAnyMethod(Il2CppObject *obj) { return IsMethod(obj) || IsCMethod(obj) || IsGenericMethod(obj) || IsGenericCMethod(obj); } bool Reflection::IsField(Il2CppObject *obj) { if (obj->klass->image == il2cpp_defaults.corlib) return strcmp(obj->klass->name, "MonoField") == 0 && strcmp(obj->klass->namespaze, "System.Reflection") == 0; return false; } bool Reflection::IsProperty(Il2CppObject *obj) { if (obj->klass->image == il2cpp_defaults.corlib) return strcmp(obj->klass->name, "MonoProperty") == 0 && strcmp(obj->klass->namespaze, "System.Reflection") == 0; return false; } bool Reflection::IsEvent(Il2CppObject *obj) { if (obj->klass->image == il2cpp_defaults.corlib) return strcmp(obj->klass->name, "MonoEvent") == 0 && strcmp(obj->klass->namespaze, "System.Reflection") == 0; return false; } static bool IsParameter(Il2CppObject *obj) { if (obj->klass->image == il2cpp_defaults.corlib) #if !NET_4_0 return obj->klass == il2cpp_defaults.parameter_info_class; #else return obj->klass == il2cpp_defaults.mono_parameter_info_class; #endif return false; } static bool IsAssembly(Il2CppObject *obj) { if (obj->klass->image == il2cpp_defaults.corlib) #if !NET_4_0 return obj->klass == il2cpp_defaults.assembly_class; #else return obj->klass == il2cpp_defaults.mono_assembly_class; #endif return false; } CustomAttributesCache* Reflection::GetCustomAttributesCacheFor(Il2CppClass *klass) { return MetadataCache::GenerateCustomAttributesCache(klass->customAttributeIndex); } CustomAttributesCache* Reflection::GetCustomAttributesCacheFor(const MethodInfo *method) { return MetadataCache::GenerateCustomAttributesCache(method->customAttributeIndex); } CustomAttributesCache* Reflection::GetCustomAttributesCacheFor(const PropertyInfo *property) { return MetadataCache::GenerateCustomAttributesCache(property->customAttributeIndex); } CustomAttributesCache* Reflection::GetCustomAttributesCacheFor(FieldInfo *field) { return MetadataCache::GenerateCustomAttributesCache(field->customAttributeIndex); } CustomAttributesCache* Reflection::GetCustomAttributesCacheFor(const EventInfo *event) { return MetadataCache::GenerateCustomAttributesCache(event->customAttributeIndex); } CustomAttributesCache* Reflection::GetCustomAttributesCacheFor(Il2CppReflectionParameter *parameter) { Il2CppReflectionMethod* method = (Il2CppReflectionMethod*)parameter->MemberImpl; if (method->method->parameters == NULL) return NULL; NOT_IMPLEMENTED_NO_ASSERT(Reflection::GetCustomAttributesCacheFor, "-1 represents the return value. Need to emit custom attribute information for that.") if (parameter->PositionImpl == -1) return NULL; const ::ParameterInfo* info = &method->method->parameters[parameter->PositionImpl]; return MetadataCache::GenerateCustomAttributesCache(info->customAttributeIndex); } CustomAttributeTypeCache* Reflection::GetCustomAttributeTypeCacheFor(Il2CppReflectionParameter *parameter) { Il2CppReflectionMethod* method = (Il2CppReflectionMethod*)parameter->MemberImpl; if (method->method->parameters == NULL) return NULL; NOT_IMPLEMENTED_NO_ASSERT(Reflection::GetCustomAttributeTypeCacheFor, "-1 represents the return value. Need to emit custom attribute information for that.") if (parameter->PositionImpl == -1) return NULL; const ::ParameterInfo* info = &method->method->parameters[parameter->PositionImpl]; return MetadataCache::GenerateCustomAttributeTypeCache(info->customAttributeIndex); } CustomAttributesCache* Reflection::GetCustomAttributesCacheFor(const Il2CppAssembly *assembly) { return MetadataCache::GenerateCustomAttributesCache(assembly->customAttributeIndex); } CustomAttributesCache* Reflection::GetCustomAttrsInfo(Il2CppObject *obj) { if (IsMethod(obj) || IsCMethod(obj) || IsGenericMethod(obj) || IsGenericCMethod(obj)) return GetCustomAttributesCacheFor(((Il2CppReflectionMethod*)obj)->method); if (IsProperty(obj)) return GetCustomAttributesCacheFor(((Il2CppReflectionProperty*)obj)->property); if (IsField(obj)) return GetCustomAttributesCacheFor(((Il2CppReflectionField*)obj)->field); if (IsEvent(obj)) return GetCustomAttributesCacheFor(((Il2CppReflectionMonoEvent*)obj)->eventInfo); if (IsParameter(obj)) return GetCustomAttributesCacheFor(((Il2CppReflectionParameter*)obj)); if (IsAssembly(obj)) return GetCustomAttributesCacheFor(((Il2CppReflectionAssembly*)obj)->assembly); Il2CppClass *klass = IsType(obj) ? Class::FromSystemType((Il2CppReflectionType*)obj) : obj->klass; return GetCustomAttributesCacheFor(klass); } CustomAttributeTypeCache* Reflection::GetCustomAttrsTypeInfo(Il2CppObject *obj) { if (IsMethod(obj) || IsCMethod(obj) || IsGenericMethod(obj) || IsGenericCMethod(obj)) return MetadataCache::GenerateCustomAttributeTypeCache((((Il2CppReflectionMethod*)obj)->method)->customAttributeIndex); if (IsProperty(obj)) return MetadataCache::GenerateCustomAttributeTypeCache((((Il2CppReflectionProperty*)obj)->property)->customAttributeIndex); if (IsField(obj)) return MetadataCache::GenerateCustomAttributeTypeCache((((Il2CppReflectionField*)obj)->field)->customAttributeIndex); if (IsEvent(obj)) return MetadataCache::GenerateCustomAttributeTypeCache((((Il2CppReflectionMonoEvent*)obj)->eventInfo)->customAttributeIndex); if (IsParameter(obj)) return GetCustomAttributeTypeCacheFor((Il2CppReflectionParameter*)obj); if (IsAssembly(obj)) return MetadataCache::GenerateCustomAttributeTypeCache((((Il2CppReflectionAssembly*)obj)->assembly)->customAttributeIndex); Il2CppClass *klass = IsType(obj) ? Class::FromSystemType((Il2CppReflectionType*)obj) : obj->klass; return MetadataCache::GenerateCustomAttributeTypeCache(klass->customAttributeIndex); } void Reflection::Initialize() { s_AssemblyMap = new AssemblyMap(); s_FieldMap = new FieldMap(); s_PropertyMap = new PropertyMap(); s_EventMap = new EventMap(); s_MethodMap = new MethodMap(); s_ModuleMap = new ModuleMap(); s_ParametersMap = new ParametersMap(); s_TypeMap = new TypeMap(); s_MonoGenericParamterMap = new MonoGenericParameterMap(); s_MonoAssemblyNameMap = new MonoAssemblyNameMap(); } bool Reflection::CustomAttrsHasAttr(CustomAttributeTypeCache *ainfo, Il2CppClass *attr_klass) { IL2CPP_ASSERT(ainfo); IL2CPP_ASSERT(attr_klass); int i; Il2CppClass *klass; for (i = 0; i < ainfo->count; ++i) { klass = ainfo->attributeTypes[i]; if (Class::HasParent(klass, attr_klass) || (Class::IsInterface(attr_klass) && Class::IsAssignableFrom(attr_klass, klass))) return true; } return false; } bool Reflection::HasAttribute(Il2CppObject *obj, Il2CppClass *attribute) { CustomAttributeTypeCache* attrs = GetCustomAttrsTypeInfo(obj); if (!attrs) return false; return CustomAttrsHasAttr(attrs, attribute); } bool Reflection::HasAttribute(FieldInfo *field, Il2CppClass *attribute) { CustomAttributeTypeCache* attrs = MetadataCache::GenerateCustomAttributeTypeCache(field->customAttributeIndex); if (!attrs) return false; return CustomAttrsHasAttr(attrs, attribute); } bool Reflection::HasAttribute(const MethodInfo *method, Il2CppClass *attribute) { CustomAttributeTypeCache* attrs = MetadataCache::GenerateCustomAttributeTypeCache(method->customAttributeIndex); if (!attrs) return false; return CustomAttrsHasAttr(attrs, attribute); } bool Reflection::HasAttribute(Il2CppClass *klass, Il2CppClass *attribute) { CustomAttributeTypeCache* attrs = MetadataCache::GenerateCustomAttributeTypeCache(klass->customAttributeIndex); if (!attrs) return false; return CustomAttrsHasAttr(attrs, attribute); } Il2CppClass* Reflection::TypeGetHandle(Il2CppReflectionType* ref) { if (!ref) return NULL; return Class::FromSystemType(ref); } const MonoGenericParameterInfo* Reflection::GetMonoGenericParameterInfo(const Il2CppGenericParameter *param) { MonoGenericParameterMap::const_iterator it = s_MonoGenericParamterMap->find(param); if (it == s_MonoGenericParamterMap->end()) return NULL; return it->second; } void Reflection::SetMonoGenericParameterInfo(const Il2CppGenericParameter *param, const MonoGenericParameterInfo *monoParam) { s_MonoGenericParamterMap->insert(std::make_pair(param, monoParam)); } const Il2CppMonoAssemblyName* Reflection::GetMonoAssemblyName(const Il2CppAssembly *assembly) { MonoAssemblyNameMap::const_iterator it = s_MonoAssemblyNameMap->find(assembly); if (it == s_MonoAssemblyNameMap->end()) return NULL; return it->second; } void Reflection::SetMonoAssemblyName(const Il2CppAssembly *assembly, const Il2CppMonoAssemblyName *aname) { s_MonoAssemblyNameMap->insert(std::make_pair(assembly, aname)); } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Reflection.h ================================================ #pragma once #include #include "il2cpp-config.h" struct Il2CppString; struct Il2CppArray; struct Il2CppReflectionAssembly; struct Il2CppReflectionAssemblyName; struct Il2CppReflectionField; struct Il2CppReflectionMethod; struct Il2CppReflectionModule; struct Il2CppReflectionProperty; struct Il2CppReflectionEvent; struct Il2CppReflectionType; struct Il2CppReflectionParameter; struct Il2CppClass; struct FieldInfo; struct MethodInfo; struct PropertyInfo; struct EventInfo; struct Il2CppClass; struct CustomAttributesCache; struct CustomAttributeTypeCache; struct Il2CppAssembly; struct Il2CppAssemblyName; struct Il2CppImage; struct Il2CppType; struct Il2CppObject; struct MonoGenericParameterInfo; struct Il2CppGenericParameter; struct Il2CppMonoAssemblyName; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API Reflection { // exported public: static Il2CppReflectionAssembly* GetAssemblyObject(const Il2CppAssembly *assembly); static Il2CppReflectionAssemblyName* GetAssemblyNameObject(const Il2CppAssemblyName *assemblyName); static Il2CppReflectionField* GetFieldObject(Il2CppClass *klass, FieldInfo *field); static Il2CppReflectionProperty* GetPropertyObject(Il2CppClass *klass, const PropertyInfo *property); static Il2CppReflectionEvent* GetEventObject(Il2CppClass *klass, const EventInfo *event); static Il2CppReflectionMethod* GetMethodObject(const MethodInfo *method, Il2CppClass *refclass); static Il2CppReflectionModule* GetModuleObject(const Il2CppImage *image); static Il2CppReflectionType* GetTypeObject(const Il2CppType *type); static Il2CppArray* GetParamObjects(const MethodInfo *method, Il2CppClass *refclass); static CustomAttributesCache* GetCustomAttrsInfo(Il2CppObject *obj); static const MonoGenericParameterInfo* GetMonoGenericParameterInfo(const Il2CppGenericParameter *param); static void SetMonoGenericParameterInfo(const Il2CppGenericParameter *param, const MonoGenericParameterInfo *monoParam); static const Il2CppMonoAssemblyName* GetMonoAssemblyName(const Il2CppAssembly *assembly); static void SetMonoAssemblyName(const Il2CppAssembly *assembly, const Il2CppMonoAssemblyName *aname); static bool HasAttribute(Il2CppObject *obj, Il2CppClass *attribute); static bool HasAttribute(FieldInfo *field, Il2CppClass *attribute); static bool HasAttribute(const MethodInfo *method, Il2CppClass *attribute); static bool HasAttribute(Il2CppClass *klass, Il2CppClass *attribute); static bool IsType(Il2CppObject *obj); static bool IsField(Il2CppObject *obj); static bool IsAnyMethod(Il2CppObject *obj); static bool IsProperty(Il2CppObject *obj); static bool IsEvent(Il2CppObject *obj); // internal public: static void Initialize(); static bool CustomAttrsHasAttr(CustomAttributeTypeCache *ainfo, Il2CppClass *attr_klass); static Il2CppClass* TypeGetHandle(Il2CppReflectionType* ref); static Il2CppObject* GetDBNullObject(); private: static CustomAttributeTypeCache* GetCustomAttrsTypeInfo(Il2CppObject *obj); static CustomAttributeTypeCache* GetCustomAttributeTypeCacheFor(Il2CppReflectionParameter *parameter); static CustomAttributesCache* GetCustomAttributesCacheFor(Il2CppClass *klass); static CustomAttributesCache* GetCustomAttributesCacheFor(const MethodInfo *method); static CustomAttributesCache* GetCustomAttributesCacheFor(const PropertyInfo *property); static CustomAttributesCache* GetCustomAttributesCacheFor(FieldInfo *field); static CustomAttributesCache* GetCustomAttributesCacheFor(const EventInfo *event); static CustomAttributesCache* GetCustomAttributesCacheFor(Il2CppReflectionParameter *param); static CustomAttributesCache* GetCustomAttributesCacheFor(const Il2CppAssembly *assembly); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Runtime.cpp ================================================ #include "il2cpp-config.h" #include "os/Environment.h" #include "os/File.h" #include "os/Image.h" #include "os/Initialize.h" #include "os/LibraryLoader.h" #include "os/Locale.h" #include "os/MemoryMappedFile.h" #include "os/Mutex.h" #include "os/Path.h" #include "os/Thread.h" #include "os/Socket.h" #include "vm/Array.h" #include "vm/Assembly.h" #include "vm/Class.h" #include "vm/Domain.h" #include "vm/Exception.h" #include "vm/Field.h" #include "vm/Image.h" #include "vm/LastError.h" #include "vm/MetadataAlloc.h" #include "vm/MetadataCache.h" #include "vm/MetadataLock.h" #include "vm/Method.h" #include "vm/Reflection.h" #include "vm/Runtime.h" #include "vm/Thread.h" #include "vm/ThreadPool.h" #include "vm/Type.h" #include "vm/String.h" #include "vm/Object.h" #include #include #include "class-internals.h" #include "object-internals.h" #include "tabledefs.h" #include "gc/GarbageCollector.h" #include "vm/InternalCalls.h" #include "utils/Collections.h" #include "utils/Memory.h" #include "utils/RegisterRuntimeInitializeAndCleanup.h" #include "utils/StringUtils.h" #include "utils/PathUtils.h" #include "utils/Runtime.h" #include "utils/Environment.h" #include "mono/ThreadPool/threadpool-ms.h" #include "mono/ThreadPool/threadpool-ms-io.h" //#include "icalls/mscorlib/System.Reflection/Assembly.h" #if IL2CPP_DEBUGGER_ENABLED #include "il2cpp-debugger.h" #endif using il2cpp::metadata::GenericMethod; using il2cpp::utils::StringUtils; Il2CppIntPtr Il2CppIntPtr::Zero; Il2CppDefaults il2cpp_defaults; bool g_il2cpp_is_fully_initialized = false; static bool shutting_down = false; namespace il2cpp { namespace vm { il2cpp::os::FastMutex g_MetadataLock; static std::string s_ConfigDir; static const char *s_FrameworkVersion = 0; static const char *s_BundledMachineConfig = 0; static Il2CppRuntimeUnhandledExceptionPolicy s_UnhandledExceptionPolicy = IL2CPP_UNHANDLED_POLICY_CURRENT; #define DEFAULTS_INIT(field, ns, n) do { il2cpp_defaults.field = Class::FromName (il2cpp_defaults.corlib, ns, n);\ IL2CPP_ASSERT(il2cpp_defaults.field); } while (0) #define DEFAULTS_INIT_TYPE(field, ns, n, nativetype) do { DEFAULTS_INIT(field, ns, n); \ IL2CPP_ASSERT(il2cpp_defaults.field->instance_size == sizeof(nativetype) + (il2cpp_defaults.field->valuetype ? sizeof(Il2CppObject) : 0)); } while (0) char* basepath(const char* path) { std::string original_path(path); size_t position_of_last_separator = original_path.find_last_of(IL2CPP_DIR_SEPARATOR); return il2cpp::utils::StringUtils::StringDuplicate(original_path.substr(position_of_last_separator + 1).c_str()); } static const char *framework_version_for(const char *runtime_version) { IL2CPP_ASSERT(runtime_version && "Invalid runtime version"); #if NET_4_0 IL2CPP_ASSERT((strstr(runtime_version, "v4.0") == runtime_version) && "Invalid runtime version"); return "4.0"; #else IL2CPP_ASSERT((strstr(runtime_version, "v2.0") == runtime_version) && "Invalid runtime version"); return "2.0"; #endif } static void SanityChecks() { #if IL2CPP_ENABLE_INTERLOCKED_64_REQUIRED_ALIGNMENT IL2CPP_ASSERT(ALIGN_OF(int64_t) == 8); #endif } #if NET_4_0 static inline void InitializeStringEmpty() { Class::Init(il2cpp_defaults.string_class); FieldInfo* stringEmptyField = Class::GetFieldFromName(il2cpp_defaults.string_class, "Empty"); Field::StaticSetValue(stringEmptyField, String::Empty()); } #endif void Runtime::Init(const char* filename, const char *runtime_version) { SanityChecks(); os::Initialize(); os::Locale::Initialize(); MetadataAllocInitialize(); s_FrameworkVersion = framework_version_for(runtime_version); os::Thread::Init(); il2cpp::utils::RegisterRuntimeInitializeAndCleanup::ExecuteInitializations(); MetadataCache::Initialize(); Assembly::Initialize(); gc::GarbageCollector::Initialize(); // Thread needs GC initialized Thread::Initialize(); // Reflection needs GC initialized Reflection::Initialize(); memset(&il2cpp_defaults, 0, sizeof(Il2CppDefaults)); const Il2CppAssembly* assembly = Assembly::Load("mscorlib.dll"); // It is not possible to use DEFAULTS_INIT_TYPE for managed types for which we have a native struct, if the // native struct does not map the complete managed type. // Which is the case for: Il2CppThread, Il2CppAppDomain, Il2CppCultureInfo, Il2CppReflectionProperty, // Il2CppDateTimeFormatInfo, Il2CppNumberFormatInfo il2cpp_defaults.corlib = Assembly::GetImage(assembly); DEFAULTS_INIT(object_class, "System", "Object"); DEFAULTS_INIT(void_class, "System", "Void"); DEFAULTS_INIT_TYPE(boolean_class, "System", "Boolean", bool); DEFAULTS_INIT_TYPE(byte_class, "System", "Byte", uint8_t); DEFAULTS_INIT_TYPE(sbyte_class, "System", "SByte", int8_t); DEFAULTS_INIT_TYPE(int16_class, "System", "Int16", int16_t); DEFAULTS_INIT_TYPE(uint16_class, "System", "UInt16", uint16_t); DEFAULTS_INIT_TYPE(int32_class, "System", "Int32", int32_t); DEFAULTS_INIT_TYPE(uint32_class, "System", "UInt32", uint32_t); DEFAULTS_INIT(uint_class, "System", "UIntPtr"); DEFAULTS_INIT_TYPE(int_class, "System", "IntPtr", Il2CppIntPtr); DEFAULTS_INIT_TYPE(int64_class, "System", "Int64", int64_t); DEFAULTS_INIT_TYPE(uint64_class, "System", "UInt64", uint64_t); DEFAULTS_INIT_TYPE(single_class, "System", "Single", float); DEFAULTS_INIT_TYPE(double_class, "System", "Double", double); DEFAULTS_INIT_TYPE(char_class, "System", "Char", Il2CppChar); DEFAULTS_INIT(string_class, "System", "String"); DEFAULTS_INIT(enum_class, "System", "Enum"); DEFAULTS_INIT(array_class, "System", "Array"); DEFAULTS_INIT_TYPE(delegate_class, "System", "Delegate", Il2CppDelegate); #if !NET_4_0 DEFAULTS_INIT(multicastdelegate_class, "System", "MulticastDelegate"); #else DEFAULTS_INIT_TYPE(multicastdelegate_class, "System", "MulticastDelegate", Il2CppMulticastDelegate); #endif DEFAULTS_INIT(asyncresult_class, "System.Runtime.Remoting.Messaging", "AsyncResult"); DEFAULTS_INIT_TYPE(async_call_class, "System", "MonoAsyncCall", Il2CppAsyncCall); DEFAULTS_INIT(manualresetevent_class, "System.Threading", "ManualResetEvent"); //DEFAULTS_INIT(typehandle_class, "System", "RuntimeTypeHandle"); //DEFAULTS_INIT(methodhandle_class, "System", "RuntimeMethodHandle"); //DEFAULTS_INIT(fieldhandle_class, "System", "RuntimeFieldHandle"); DEFAULTS_INIT(systemtype_class, "System", "Type"); DEFAULTS_INIT_TYPE(monotype_class, "System", "MonoType", Il2CppReflectionMonoType); //DEFAULTS_INIT(exception_class, "System", "Exception"); //DEFAULTS_INIT(threadabortexcepXtion_class, "System.Threading", "ThreadAbortException"); DEFAULTS_INIT_TYPE(thread_class, "System.Threading", "Thread", Il2CppThread); #if NET_4_0 DEFAULTS_INIT_TYPE(internal_thread_class, "System.Threading", "InternalThread", Il2CppInternalThread); DEFAULTS_INIT_TYPE(runtimetype_class, "System", "RuntimeType", Il2CppReflectionRuntimeType); #endif DEFAULTS_INIT(appdomain_class, "System", "AppDomain"); DEFAULTS_INIT(appdomain_setup_class, "System", "AppDomainSetup"); DEFAULTS_INIT(field_info_class, "System.Reflection", "FieldInfo"); DEFAULTS_INIT(method_info_class, "System.Reflection", "MethodInfo"); DEFAULTS_INIT(property_info_class, "System.Reflection", "PropertyInfo"); DEFAULTS_INIT_TYPE(event_info_class, "System.Reflection", "EventInfo", Il2CppReflectionEvent); DEFAULTS_INIT_TYPE(mono_event_info_class, "System.Reflection", "MonoEventInfo", Il2CppReflectionMonoEventInfo); DEFAULTS_INIT_TYPE(stringbuilder_class, "System.Text", "StringBuilder", Il2CppStringBuilder); DEFAULTS_INIT_TYPE(stack_frame_class, "System.Diagnostics", "StackFrame", Il2CppStackFrame); DEFAULTS_INIT(stack_trace_class, "System.Diagnostics", "StackTrace"); DEFAULTS_INIT_TYPE(typed_reference_class, "System", "TypedReference", Il2CppTypedRef); DEFAULTS_INIT(generic_ilist_class, "System.Collections.Generic", "IList`1"); DEFAULTS_INIT(generic_icollection_class, "System.Collections.Generic", "ICollection`1"); DEFAULTS_INIT(generic_ienumerable_class, "System.Collections.Generic", "IEnumerable`1"); #if NET_4_0 DEFAULTS_INIT(generic_ireadonlylist_class, "System.Collections.Generic", "IReadOnlyList`1"); DEFAULTS_INIT(generic_ireadonlycollection_class, "System.Collections.Generic", "IReadOnlyCollection`1"); #endif DEFAULTS_INIT(generic_nullable_class, "System", "Nullable`1"); DEFAULTS_INIT(version, "System", "Version"); DEFAULTS_INIT(culture_info, "System.Globalization", "CultureInfo"); DEFAULTS_INIT_TYPE(assembly_class, "System.Reflection", "Assembly", Il2CppReflectionAssembly); DEFAULTS_INIT_TYPE(assembly_name_class, "System.Reflection", "AssemblyName", Il2CppReflectionAssemblyName); #if NET_4_0 DEFAULTS_INIT_TYPE(mono_assembly_class, "System.Reflection", "MonoAssembly", Il2CppReflectionAssembly); #endif #if !NET_4_0 DEFAULTS_INIT_TYPE(enum_info_class, "System", "MonoEnumInfo", Il2CppEnumInfo); #endif DEFAULTS_INIT_TYPE(mono_field_class, "System.Reflection", "MonoField", Il2CppReflectionField); DEFAULTS_INIT_TYPE(mono_method_class, "System.Reflection", "MonoMethod", Il2CppReflectionMethod); DEFAULTS_INIT_TYPE(mono_method_info_class, "System.Reflection", "MonoMethodInfo", Il2CppMethodInfo); DEFAULTS_INIT_TYPE(mono_property_info_class, "System.Reflection", "MonoPropertyInfo", Il2CppPropertyInfo); DEFAULTS_INIT_TYPE(parameter_info_class, "System.Reflection", "ParameterInfo", Il2CppReflectionParameter); #if NET_4_0 DEFAULTS_INIT_TYPE(mono_parameter_info_class, "System.Reflection", "MonoParameterInfo", Il2CppReflectionParameter); #endif DEFAULTS_INIT_TYPE(module_class, "System.Reflection", "Module", Il2CppReflectionModule); DEFAULTS_INIT_TYPE(marshal_class, "System.Reflection.Emit", "UnmanagedMarshal", Il2CppReflectionMarshal); DEFAULTS_INIT_TYPE(pointer_class, "System.Reflection", "Pointer", Il2CppReflectionPointer); DEFAULTS_INIT_TYPE(exception_class, "System", "Exception", Il2CppException); DEFAULTS_INIT_TYPE(system_exception_class, "System", "SystemException", Il2CppSystemException); DEFAULTS_INIT_TYPE(argument_exception_class, "System", "ArgumentException", Il2CppArgumentException); DEFAULTS_INIT_TYPE(marshalbyrefobject_class, "System", "MarshalByRefObject", Il2CppMarshalByRefObject); DEFAULTS_INIT_TYPE(il2cpp_com_object_class, "System", "__Il2CppComObject", Il2CppComObject); DEFAULTS_INIT_TYPE(safe_handle_class, "System.Runtime.InteropServices", "SafeHandle", Il2CppSafeHandle); DEFAULTS_INIT_TYPE(sort_key_class, "System.Globalization", "SortKey", Il2CppSortKey); DEFAULTS_INIT(dbnull_class, "System", "DBNull"); DEFAULTS_INIT_TYPE(error_wrapper_class, "System.Runtime.InteropServices", "ErrorWrapper", Il2CppErrorWrapper); DEFAULTS_INIT(missing_class, "System.Reflection", "Missing"); DEFAULTS_INIT(customattribute_data_class, "System.Reflection", "CustomAttributeData"); DEFAULTS_INIT(value_type_class, "System", "ValueType"); DEFAULTS_INIT(key_value_pair_class, "System.Collections.Generic", "KeyValuePair`2"); #if NET_4_0 DEFAULTS_INIT(threadpool_wait_callback_class, "System.Threading", "_ThreadPoolWaitCallback"); DEFAULTS_INIT(mono_method_message_class, "System.Runtime.Remoting.Messaging", "MonoMethodMessage"); il2cpp_defaults.threadpool_perform_wait_callback_method = (MethodInfo*)vm::Class::GetMethodFromName( il2cpp_defaults.threadpool_wait_callback_class, "PerformWaitCallback", 0); #endif const Il2CppAssembly* systemDll = Assembly::Load("System"); if (systemDll != NULL) il2cpp_defaults.system_uri_class = Class::FromName(Assembly::GetImage(systemDll), "System", "Uri"); // This will only exist if there was at least 1 winmd file present during conversion const Il2CppAssembly* windowsRuntimeMetadataAssembly = Assembly::Load("WindowsRuntimeMetadata"); if (windowsRuntimeMetadataAssembly != NULL) { const Il2CppImage* windowsRuntimeMetadataImage = Assembly::GetImage(windowsRuntimeMetadataAssembly); il2cpp_defaults.ireference_class = Class::FromName(windowsRuntimeMetadataImage, "Windows.Foundation", "IReference`1"); il2cpp_defaults.ikey_value_pair_class = Class::FromName(windowsRuntimeMetadataImage, "Windows.Foundation.Collections", "IKeyValuePair`2"); il2cpp_defaults.ikey_value_pair_class = Class::FromName(windowsRuntimeMetadataImage, "Windows.Foundation.Collections", "IKeyValuePair`2"); il2cpp_defaults.windows_foundation_uri_class = Class::FromName(windowsRuntimeMetadataImage, "Windows.Foundation", "Uri"); il2cpp_defaults.windows_foundation_iuri_runtime_class_class = Class::FromName(windowsRuntimeMetadataImage, "Windows.Foundation", "IUriRuntimeClass"); } Class::Init(il2cpp_defaults.string_class); Il2CppDomain* domain = Domain::GetCurrent(); Thread::Attach(domain); Il2CppAppDomainSetup* setup = (Il2CppAppDomainSetup*)Object::NewPinned(il2cpp_defaults.appdomain_setup_class); Il2CppAppDomain* ad = (Il2CppAppDomain*)Object::NewPinned(il2cpp_defaults.appdomain_class); ad->data = domain; domain->domain = ad; domain->setup = setup; domain->domain_id = 1; // Only have a single domain ATM. domain->friendly_name = basepath(filename); #if IL2CPP_DEBUGGER_ENABLED // The current thread needs to be attached before sending any debugger event. il2cpp_debugger_notify_appdomain_create(domain); #endif LastError::InitializeLastErrorThreadStatic(); gc::GarbageCollector::InitializeFinalizer(); MetadataCache::InitializeGCSafe(); #if !NET_4_0 ThreadPool::Initialize(); #endif String::InitializeEmptyString(il2cpp_defaults.string_class); #if NET_4_0 // .NET 2.0 mscorlib does it with a static constructor InitializeStringEmpty(); #endif os::Socket::Startup(); g_il2cpp_is_fully_initialized = true; // Force binary serialization in Mono to use reflection instead of code generation. #undef SetEnvironmentVariable // Get rid of windows.h #define. os::Environment::SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes"); os::Environment::SetEnvironmentVariable("MONO_XMLSERIALIZER_THS", "no"); Domain::ContextInit(domain); Domain::ContextSet(domain->default_context); VerifyApiVersion(); } void Runtime::Shutdown() { shutting_down = true; #if !NET_4_0 ThreadPool::Shutdown(); #endif #if NET_4_0 threadpool_ms_cleanup(); #endif // Foreground threads will make us wait here. Background threads // will get terminated abruptly. Thread::KillAllBackgroundThreadsAndWaitForForegroundThreads(); os::Socket::Cleanup(); String::CleanupEmptyString(); il2cpp::gc::GarbageCollector::UninitializeFinalizers(); // after the gc cleanup so the finalizer thread can unregister itself Thread::UnInitialize(); os::Thread::Shutdown(); // We need to do this after thread shut down because it is freeing GC fixed memory il2cpp::gc::GarbageCollector::UninitializeGC(); // This needs to happen after no managed code can run anymore, including GC finalizers os::LibraryLoader::CleanupLoadedLibraries(); vm::Image::ClearCachedResourceData(); MetadataAllocCleanup(); os::Locale::UnInitialize(); os::Uninitialize(); } bool Runtime::IsShuttingDown() { return shutting_down; } void Runtime::SetConfigDir(const char *path) { s_ConfigDir = path; } static void SetConfigStr(const std::string& executablePath) { Il2CppDomain* domain = vm::Domain::GetCurrent(); std::string configFileName = utils::PathUtils::Basename(executablePath); configFileName.append(".config"); std::string appBase = utils::PathUtils::DirectoryName(executablePath); IL2CPP_OBJECT_SETREF(domain->setup, application_base, vm::String::New(appBase.c_str())); IL2CPP_OBJECT_SETREF(domain->setup, configuration_file, vm::String::New(configFileName.c_str())); } void Runtime::SetConfigUtf16(const Il2CppChar* executablePath) { IL2CPP_ASSERT(executablePath); std::string exePathUtf8 = il2cpp::utils::StringUtils::Utf16ToUtf8(executablePath); SetConfigStr(exePathUtf8); } void Runtime::SetConfig(const char* executablePath) { IL2CPP_ASSERT(executablePath); std::string executablePathStr(executablePath); SetConfigStr(executablePathStr); } const char *Runtime::GetFrameworkVersion() { return s_FrameworkVersion; } std::string Runtime::GetConfigDir() { if (s_ConfigDir.size() > 0) return s_ConfigDir; return utils::PathUtils::Combine(utils::Runtime::GetDataDir(), utils::StringView("etc")); } const MethodInfo* Runtime::GetDelegateInvoke(Il2CppClass* klass) { const MethodInfo* invoke = Class::GetMethodFromName(klass, "Invoke", -1); IL2CPP_ASSERT(invoke); return invoke; } Il2CppObject* Runtime::DelegateInvoke(Il2CppDelegate *delegate, void **params, Il2CppException **exc) { const MethodInfo* invoke = GetDelegateInvoke(delegate->object.klass); return Invoke(invoke, delegate, params, exc); } const MethodInfo* Runtime::GetGenericVirtualMethod(const MethodInfo* methodDefinition, const MethodInfo* inflatedMethod) { NOT_IMPLEMENTED_NO_ASSERT(GetGenericVirtualMethod, "We should only do the following slow method lookup once and then cache on type itself."); const Il2CppGenericInst* classInst = NULL; if (methodDefinition->is_inflated) { classInst = methodDefinition->genericMethod->context.class_inst; methodDefinition = methodDefinition->genericMethod->methodDefinition; } const Il2CppGenericMethod* gmethod = MetadataCache::GetGenericMethod(const_cast(methodDefinition), classInst, inflatedMethod->genericMethod->context.method_inst); const MethodInfo* method = metadata::GenericMethod::GetMethod(gmethod); RaiseExecutionEngineExceptionIfMethodIsNotFound(method, gmethod); return method; } void Runtime::RaiseExecutionEngineExceptionIfMethodIsNotFound(const MethodInfo* method) { if (method->methodPointer == NULL) { if (Method::GetClass(method)) RaiseExecutionEngineException(Method::GetFullName(method).c_str()); else RaiseExecutionEngineException(Method::GetName(method)); } } void Runtime::AlwaysRaiseExecutionEngineException(const MethodInfo* method) { if (Method::GetClass(method)) RaiseExecutionEngineException(Method::GetFullName(method).c_str()); else RaiseExecutionEngineException(Method::GetName(method)); } Il2CppObject* Runtime::Invoke(const MethodInfo *method, void *obj, void **params, Il2CppException **exc) { if (exc) *exc = NULL; // we wrap invoker call in try/catch here, rather than emitting a try/catch // in every invoke call as that blows up the code size. try { RaiseExecutionEngineExceptionIfMethodIsNotFound(method); return (Il2CppObject*)method->invoker_method(method->methodPointer, method, obj, params); } catch (Il2CppExceptionWrapper& ex) { if (exc) *exc = ex.ex; return NULL; } } Il2CppObject* Runtime::InvokeWithThrow(const MethodInfo *method, void *obj, void **params) { RaiseExecutionEngineExceptionIfMethodIsNotFound(method); return (Il2CppObject*)method->invoker_method(method->methodPointer, method, obj, params); } Il2CppObject* Runtime::InvokeArray(const MethodInfo *method, void *obj, Il2CppArray *params, Il2CppException **exc) { if (params == NULL) return InvokeConvertArgs(method, obj, NULL, 0, exc); // TO DO: when changing GC to one that moves managed objects around, mark params array local variable as pinned! return InvokeConvertArgs(method, obj, reinterpret_cast(Array::GetFirstElementAddress(params)), Array::GetLength(params), exc); } void Runtime::ObjectInit(Il2CppObject *object) { ObjectInitException(object, NULL); } void Runtime::ObjectInitException(Il2CppObject *object, Il2CppException **exc) { const MethodInfo *method = NULL; Il2CppClass *klass = object->klass; method = Class::GetMethodFromName(klass, ".ctor", 0); IL2CPP_ASSERT(method != NULL && "ObjectInit; no default constructor for object is found"); if (method->declaring_type->valuetype) object = (Il2CppObject*)Object::Unbox(object); Invoke(method, object, NULL, exc); } void Runtime::SetUnhandledExceptionPolicy(Il2CppRuntimeUnhandledExceptionPolicy value) { s_UnhandledExceptionPolicy = value; } Il2CppRuntimeUnhandledExceptionPolicy Runtime::GetUnhandledExceptionPolicy() { return s_UnhandledExceptionPolicy; } void Runtime::UnhandledException(Il2CppException* exc) { Il2CppDomain *currentDomain = Domain::GetCurrent(); Il2CppDomain *rootDomain = Domain::GetRoot(); FieldInfo *field; Il2CppObject *current_appdomain_delegate = NULL; Il2CppObject *root_appdomain_delegate = NULL; field = Class::GetFieldFromName(il2cpp_defaults.appdomain_class, "UnhandledException"); IL2CPP_ASSERT(field); Il2CppObject* excObject = (Il2CppObject*)exc; if (excObject->klass != il2cpp_defaults.threadabortexception_class) { //bool abort_process = (Thread::Current () == Thread::Main ()) || // (Runtime::GetUnhandledExceptionPolicy () == IL2CPP_UNHANDLED_POLICY_CURRENT); Field::GetValue((Il2CppObject*)rootDomain->domain, field, &root_appdomain_delegate); NOT_IMPLEMENTED_NO_ASSERT(Runtime::UnhandledException, "We don't have runtime version info yet"); //if (currentDomain != rootDomain && (mono_framework_version () >= 2)) { // Field::GetValue ((Il2CppObject*)currentDomain->domain, field, ¤t_appdomain_delegate); //} //else //{ // current_appdomain_delegate = NULL; //} ///* set exitcode only if we will abort the process */ //if (abort_process) // mono_environment_exitcode_set (1); //if ((current_appdomain_delegate == NULL) && (root_appdomain_delegate == NULL) //{ // mono_print_unhandled_exception (exc); //} //else { if (root_appdomain_delegate) { CallUnhandledExceptionDelegate(rootDomain, (Il2CppDelegate*)root_appdomain_delegate, exc); } if (current_appdomain_delegate) { CallUnhandledExceptionDelegate(currentDomain, (Il2CppDelegate*)current_appdomain_delegate, exc); } } } } static inline Il2CppObject* InvokeConvertThis(const MethodInfo* method, void* thisArg, void** convertedParameters, Il2CppException** exception) { Il2CppClass* thisType = method->declaring_type; // If it's not a constructor, just invoke directly if (strcmp(method->name, ".ctor") != 0 || method->declaring_type == il2cpp_defaults.string_class) return Runtime::Invoke(method, thisArg, convertedParameters, exception); // If it is a construction, we need to construct a return value and allocate object if needed Il2CppObject* instance; if (thisArg == NULL) { thisArg = instance = Object::New(thisType); Runtime::Invoke(method, thisArg, convertedParameters, exception); } else { // thisArg is pointer to data in case of a value type // We need to invoke the constructor first, passing point to the value // Since the constructor may modify the value, we need to box the result // AFTER the constructor was invoked Runtime::Invoke(method, thisArg, convertedParameters, exception); instance = Object::Box(thisType, thisArg); } return instance; } Il2CppObject* Runtime::InvokeConvertArgs(const MethodInfo *method, void* thisArg, Il2CppObject** parameters, int paramCount, Il2CppException** exception) { void** convertedParameters = NULL; bool hasByRefNullables = false; // Convert parameters if they are not null if (parameters != NULL) { convertedParameters = (void**)alloca(sizeof(void*) * paramCount); for (int i = 0; i < paramCount; i++) { bool passedByReference = method->parameters[i].parameter_type->byref; Il2CppClass* parameterType = Class::FromIl2CppType(method->parameters[i].parameter_type); Class::Init(parameterType); if (parameterType->valuetype) { if (Class::IsNullable(parameterType)) { // Since we don't really store boxed nullables, we need to create a new one. void* nullableStorage = alloca(parameterType->instance_size - sizeof(Il2CppObject)); Object::UnboxNullable(parameters[i], Class::GetNullableArgument(parameterType), nullableStorage); convertedParameters[i] = nullableStorage; hasByRefNullables |= passedByReference; } else if (passedByReference) { // If value type is passed by reference, just pass pointer to value directly // If null was passed in, create a new boxed value type in its place if (parameters[i] == NULL) parameters[i] = Object::New(parameterType); convertedParameters[i] = Object::Unbox(parameters[i]); } else if (parameters[i] == NULL) // If value type is passed by value, we need to pass pointer to its value { // If null was passed in, allocate a new value with default value uint32_t valueSize = parameterType->instance_size - sizeof(Il2CppObject); convertedParameters[i] = alloca(valueSize); memset(convertedParameters[i], 0, valueSize); } else { // Otherwise, pass the original convertedParameters[i] = Object::Unbox(parameters[i]); } } else if (passedByReference) { convertedParameters[i] = ¶meters[i]; // Reference type passed by reference } else if (parameterType->byval_arg->type == IL2CPP_TYPE_PTR) { if (parameters[i] != NULL) { IL2CPP_ASSERT(parameters[i]->klass == il2cpp_defaults.int_class); convertedParameters[i] = static_cast(Object::Unbox(parameters[i]))->m_value; } else { convertedParameters[i] = NULL; } } else { convertedParameters[i] = parameters[i]; // Reference type passed by value } } } Il2CppObject* result = InvokeConvertThis(method, thisArg, convertedParameters, exception); if (hasByRefNullables) { // We need to copy by reference nullables back to original argument array for (int i = 0; i < paramCount; i++) { if (!method->parameters[i].parameter_type->byref) continue; Il2CppClass* parameterType = Class::FromIl2CppType(method->parameters[i].parameter_type); if (Class::IsNullable(parameterType)) parameters[i] = Object::Box(parameterType, convertedParameters[i]); } } if (method->return_type->type == IL2CPP_TYPE_PTR) { static Il2CppClass* pointerClass = Class::FromName(il2cpp_defaults.corlib, "System.Reflection", "Pointer"); Il2CppReflectionPointer* pointer = reinterpret_cast(Object::New(pointerClass)); pointer->data = result; pointer->type = Reflection::GetTypeObject(method->return_type); result = reinterpret_cast(pointer); } return result; } void Runtime::CallUnhandledExceptionDelegate(Il2CppDomain* domain, Il2CppDelegate* delegate, Il2CppException* exc) { Il2CppException *e = NULL; void* pa[2]; pa[0] = domain->domain; pa[1] = CreateUnhandledExceptionEventArgs(exc); DelegateInvoke(delegate, pa, &e); IL2CPP_ASSERT(!e); } static il2cpp::os::FastMutex s_TypeInitializationLock; // We currently call Runtime::ClassInit in 4 places: // 1. Just after we allocate storage for a new object (Object::NewAllocSpecific) // 2. Just before reading any static field // 3. Just before calling any static method // 4. Just before calling class instance constructor from a derived class instance constructor void Runtime::ClassInit(Il2CppClass *klass) { // Nothing to do if class has no static constructor. if (!klass->has_cctor) return; // Nothing to do if class constructor already ran. if (os::Atomic::CompareExchange(&klass->cctor_finished, 1, 1) == 1) return; s_TypeInitializationLock.Lock(); // See if some thread ran it while we acquired the lock. if (os::Atomic::CompareExchange(&klass->cctor_finished, 1, 1) == 1) { s_TypeInitializationLock.Unlock(); return; } // See if some other thread got there first and already started running the constructor. if (os::Atomic::CompareExchange(&klass->cctor_started, 1, 1) == 1) { s_TypeInitializationLock.Unlock(); // May have been us and we got here through recursion. os::Thread::ThreadId currentThread = os::Thread::CurrentThreadId(); if (os::Atomic::CompareExchange64(&klass->cctor_thread, currentThread, currentThread) == currentThread) return; // Wait for other thread to finish executing the constructor. while (os::Atomic::CompareExchange(&klass->cctor_finished, 1, 1) == 0) { os::Thread::Sleep(1); } } else { // Let others know we have started executing the constructor. os::Atomic::Exchange64(&klass->cctor_thread, os::Thread::CurrentThreadId()); os::Atomic::Exchange(&klass->cctor_started, 1); s_TypeInitializationLock.Unlock(); // Run it. Il2CppException* exception = NULL; const MethodInfo* cctor = Class::GetCCtor(klass); if (cctor != NULL) { vm::Runtime::Invoke(cctor, NULL, NULL, &exception); } // Let other threads know we finished. os::Atomic::Exchange(&klass->cctor_finished, 1); os::Atomic::Exchange64(&klass->cctor_thread, 0); // Deal with exceptions. if (exception != NULL) { const Il2CppType *type = Class::GetType(klass); std::string n = StringUtils::Printf("The type initializer for '%s' threw an exception.", Type::GetName(type, IL2CPP_TYPE_NAME_FORMAT_IL).c_str()); Il2CppException* typeInitializationException = Exception::GetTypeInitializationException(n.c_str(), exception); Exception::Raise(typeInitializationException); } } } struct ConstCharCompare { bool operator()(char const *a, char const *b) const { return strcmp(a, b) < 0; } }; Il2CppObject* Runtime::CreateUnhandledExceptionEventArgs(Il2CppException *exc) { Il2CppClass *klass; void* args[2]; const MethodInfo *method = NULL; bool is_terminating = true; Il2CppObject *obj; klass = Class::FromName(il2cpp_defaults.corlib, "System", "UnhandledExceptionEventArgs"); IL2CPP_ASSERT(klass); Class::Init(klass); /* UnhandledExceptionEventArgs only has 1 public ctor with 2 args */ method = Class::GetMethodFromNameFlags(klass, ".ctor", 2, METHOD_ATTRIBUTE_PUBLIC); IL2CPP_ASSERT(method); args[0] = exc; args[1] = &is_terminating; obj = Object::New(klass); Runtime::Invoke(method, obj, args, NULL); return obj; } const char *Runtime::GetBundledMachineConfig() { return s_BundledMachineConfig; } void Runtime::RegisterBundledMachineConfig(const char *config_xml) { s_BundledMachineConfig = config_xml; } void Runtime::VerifyApiVersion() { #if IL2CPP_DEBUG Il2CppClass *klass = Class::FromName(il2cpp_defaults.corlib, "System", "Environment"); Class::Init(klass); FieldInfo *field = Class::GetFieldFromName(klass, "mono_corlib_version"); int32_t value; Field::StaticGetValue(field, &value); #if !NET_4_0 IL2CPP_ASSERT(value == 82); #else IL2CPP_ASSERT(value == 156); #endif #endif } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Runtime.h ================================================ #pragma once #include #include #include #include "il2cpp-config.h" #include "il2cpp-metadata.h" #include "object-internals.h" #include "metadata/GenericMethod.h" #include "vm/Exception.h" #include "vm/Class.h" #include "vm/MetadataCache.h" #include "utils/StringUtils.h" struct Il2CppArray; struct Il2CppDelegate; struct Il2CppObject; struct MethodInfo; struct Il2CppClass; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API Runtime { public: static void Init(const char* filename, const char *runtime_version); static void Shutdown(); static bool IsShuttingDown(); static void SetConfigDir(const char *path); static void SetConfigUtf16(const Il2CppChar* executablePath); static void SetConfig(const char* executablePath); static std::string GetConfigDir(); static const char *GetFrameworkVersion(); static const MethodInfo* GetDelegateInvoke(Il2CppClass* klass); static Il2CppObject* DelegateInvoke(Il2CppDelegate *obj, void **params, Il2CppException **exc); static Il2CppObject* Invoke(const MethodInfo *method, void *obj, void **params, Il2CppException **exc); static Il2CppObject* InvokeWithThrow(const MethodInfo *method, void *obj, void **params); static Il2CppObject* InvokeConvertArgs(const MethodInfo *method, void *obj, Il2CppObject **params, int paramCount, Il2CppException **exc); static Il2CppObject* InvokeArray(const MethodInfo *method, void *obj, Il2CppArray *params, Il2CppException **exc); static void ObjectInit(Il2CppObject* object); static void ObjectInitException(Il2CppObject* object, Il2CppException **exc); static void SetUnhandledExceptionPolicy(Il2CppRuntimeUnhandledExceptionPolicy value); static const MethodInfo* GetGenericVirtualMethod(const MethodInfo* methodDefinition, const MethodInfo* inflatedMethod); static void RaiseExecutionEngineExceptionIfMethodIsNotFound(const MethodInfo* method); static void AlwaysRaiseExecutionEngineException(const MethodInfo* method); public: // internal static Il2CppRuntimeUnhandledExceptionPolicy GetUnhandledExceptionPolicy(); static void UnhandledException(Il2CppException* exc); static void ClassInit(Il2CppClass *klass); static const char *GetBundledMachineConfig(); static void RegisterBundledMachineConfig(const char *config_xml); private: static void CallUnhandledExceptionDelegate(Il2CppDomain* domain, Il2CppDelegate* delegate, Il2CppException* exc); static Il2CppObject* CreateUnhandledExceptionEventArgs(Il2CppException* exc); static void VerifyApiVersion(); static inline void RaiseExecutionEngineExceptionIfMethodIsNotFound(const MethodInfo* method, const Il2CppGenericMethod* genericMethod) { if (method->methodPointer == NULL) RaiseExecutionEngineException(metadata::GenericMethod::GetFullName(genericMethod).c_str()); } static inline void RaiseExecutionEngineException(const char* methodFullName) { Exception::Raise(Exception::GetExecutionEngineException(utils::StringUtils::Printf("Attempting to call method '%s' for which no ahead of time (AOT) code was generated.", methodFullName).c_str())); } }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/StackTrace.cpp ================================================ #include "il2cpp-config.h" #include "StackTrace.h" #include "il2cpp-debugger.h" #include "object-internals.h" #include "os/Event.h" #include "os/StackTrace.h" #include "os/Thread.h" #include "os/ThreadLocalValue.h" #include "vm-utils/NativeSymbol.h" namespace il2cpp { namespace vm { #if IL2CPP_ENABLE_STACKTRACES class MethodStack { protected: os::ThreadLocalValue s_StackFrames; inline StackFrames* GetStackFramesRaw() { StackFrames* stackFrames; os::ErrorCode result = s_StackFrames.GetValue(reinterpret_cast(&stackFrames)); Assert(result == os::kErrorCodeSuccess); return stackFrames; } public: inline void InitializeForCurrentThread() { if (GetStackFramesRaw() != NULL) return; StackFrames* stackFrames = new StackFrames(); stackFrames->reserve(64); os::ErrorCode result = s_StackFrames.SetValue(stackFrames); Assert(result == os::kErrorCodeSuccess); } inline void CleanupForCurrentThread() { StackFrames* frames = GetStackFramesRaw(); if (frames == NULL) return; delete frames; os::ErrorCode result = s_StackFrames.SetValue(NULL); Assert(result == os::kErrorCodeSuccess); } }; #if IL2CPP_ENABLE_STACKTRACE_SENTRIES class StacktraceSentryMethodStack : public MethodStack { public: inline const StackFrames* GetStackFrames() { return GetStackFramesRaw(); } inline bool GetStackFrameAt(int32_t depth, Il2CppStackFrameInfo& frame) { const StackFrames& frames = *GetStackFramesRaw(); if (static_cast(frames.size()) + depth < 1) return false; frame = frames[frames.size() - 1 + depth]; return true; } inline void PushFrame(Il2CppStackFrameInfo& frame) { GetStackFramesRaw()->push_back(frame); #if IL2CPP_DEBUGGER_ENABLED il2cpp_debugger_method_entry(frame); #endif } inline void PopFrame() { StackFrames* stackFrames = GetStackFramesRaw(); #if IL2CPP_DEBUGGER_ENABLED Il2CppStackFrameInfo frame = stackFrames->back(); #endif stackFrames->pop_back(); #if IL2CPP_DEBUGGER_ENABLED il2cpp_debugger_method_exit(frame); #endif } }; #endif // IL2CPP_ENABLE_STACKTRACE_SENTRIES #if IL2CPP_ENABLE_NATIVE_STACKTRACES class NativeMethodStack : public MethodStack { static bool GetStackFramesCallback(Il2CppMethodPointer frame, void* context) { const MethodInfo* method = il2cpp::utils::NativeSymbol::GetMethodFromNativeSymbol(frame); StackFrames* stackFrames = static_cast(context); if (method != NULL) { Il2CppStackFrameInfo frameInfo = { 0 }; frameInfo.method = method; stackFrames->push_back(frameInfo); } return true; } struct GetStackFrameAtContext { int32_t currentDepth; const MethodInfo* method; }; static bool GetStackFrameAtCallback(Il2CppMethodPointer frame, void* context) { const MethodInfo* method = il2cpp::utils::NativeSymbol::GetMethodFromNativeSymbol(frame); GetStackFrameAtContext* ctx = static_cast(context); if (method != NULL) { if (ctx->currentDepth == 0) { ctx->method = method; return false; } ctx->currentDepth++; } return true; } public: inline const StackFrames* GetStackFrames() { StackFrames* stackFrames = GetStackFramesRaw(); stackFrames->clear(); os::StackTrace::WalkStack(&NativeMethodStack::GetStackFramesCallback, stackFrames, os::StackTrace::kFirstCalledToLastCalled); return stackFrames; } inline bool GetStackFrameAt(int32_t depth, Il2CppStackFrameInfo& frame) { GetStackFrameAtContext context = { depth, NULL }; os::StackTrace::WalkStack(&NativeMethodStack::GetStackFrameAtCallback, &context, os::StackTrace::kLastCalledToFirstCalled); if (context.method != NULL) { frame.method = context.method; return true; } return false; } inline void PushFrame(Il2CppStackFrameInfo& frame) { } inline void PopFrame() { } }; #endif // IL2CPP_ENABLE_NATIVE_STACKTRACES #else static StackFrames s_EmptyStack; class NoOpMethodStack { public: inline void InitializeForCurrentThread() { } inline void CleanupForCurrentThread() { } inline const StackFrames* GetStackFrames() { return &s_EmptyStack; } inline bool GetStackFrameAt(int32_t depth, Il2CppStackFrameInfo& frame) { return false; } inline void PushFrame(Il2CppStackFrameInfo& frame) { } inline void PopFrame() { } }; #endif // IL2CPP_ENABLE_STACKTRACES #if IL2CPP_ENABLE_STACKTRACES #if IL2CPP_ENABLE_STACKTRACE_SENTRIES StacktraceSentryMethodStack s_MethodStack; #elif IL2CPP_ENABLE_NATIVE_STACKTRACES NativeMethodStack s_MethodStack; #endif #else NoOpMethodStack s_MethodStack; #endif // IL2CPP_ENABLE_STACKTRACES // Current thread functions void StackTrace::InitializeStackTracesForCurrentThread() { s_MethodStack.InitializeForCurrentThread(); } void StackTrace::CleanupStackTracesForCurrentThread() { s_MethodStack.CleanupForCurrentThread(); } const StackFrames* StackTrace::GetStackFrames() { return s_MethodStack.GetStackFrames(); } bool StackTrace::GetStackFrameAt(int32_t depth, Il2CppStackFrameInfo& frame) { Assert(depth <= 0 && "Frame depth must be 0 or less"); return s_MethodStack.GetStackFrameAt(depth, frame); } void StackTrace::WalkFrameStack(Il2CppFrameWalkFunc callback, void* context) { const StackFrames& frames = *GetStackFrames(); for (StackFrames::const_iterator it = frames.begin(); it != frames.end(); it++) callback(&*it, context); } void StackTrace::PushFrame(Il2CppStackFrameInfo& frame) { s_MethodStack.PushFrame(frame); } void StackTrace::PopFrame() { s_MethodStack.PopFrame(); } // Remote thread functions struct GetThreadFrameAtContext { il2cpp::os::Event apcDoneEvent; int32_t depth; Il2CppStackFrameInfo* frame; bool hasResult; }; struct WalkThreadFrameStackContext { il2cpp::os::Event apcDoneEvent; Il2CppFrameWalkFunc callback; void* userContext; }; struct GetThreadStackDepthContext { il2cpp::os::Event apcDoneEvent; int32_t stackDepth; }; struct GetThreadTopFrameContext { il2cpp::os::Event apcDoneEvent; Il2CppStackFrameInfo* frame; bool hasResult; }; static void STDCALL GetThreadFrameAtCallback(void* context) { GetThreadFrameAtContext* ctx = static_cast(context); ctx->hasResult = StackTrace::GetStackFrameAt(ctx->depth, *ctx->frame); ctx->apcDoneEvent.Set(); } bool StackTrace::GetThreadStackFrameAt(Il2CppThread* thread, int32_t depth, Il2CppStackFrameInfo& frame) { #if IL2CPP_ENABLE_STACKTRACES GetThreadFrameAtContext apcContext; apcContext.depth = depth; apcContext.frame = &frame; thread->GetInternalThread()->handle->QueueUserAPC(GetThreadFrameAtCallback, &apcContext); apcContext.apcDoneEvent.Wait(); return apcContext.hasResult; #else return false; #endif } static void STDCALL WalkThreadFrameStackCallback(void* context) { WalkThreadFrameStackContext* ctx = static_cast(context); StackTrace::WalkFrameStack(ctx->callback, ctx->userContext); ctx->apcDoneEvent.Set(); } void StackTrace::WalkThreadFrameStack(Il2CppThread* thread, Il2CppFrameWalkFunc callback, void* context) { #if IL2CPP_ENABLE_STACKTRACES WalkThreadFrameStackContext apcContext; apcContext.callback = callback; apcContext.userContext = context; thread->GetInternalThread()->handle->QueueUserAPC(WalkThreadFrameStackCallback, &apcContext); apcContext.apcDoneEvent.Wait(); #endif } static void STDCALL GetThreadStackDepthCallback(void* context) { GetThreadStackDepthContext* ctx = static_cast(context); ctx->stackDepth = static_cast(StackTrace::GetStackDepth()); ctx->apcDoneEvent.Set(); } int32_t StackTrace::GetThreadStackDepth(Il2CppThread* thread) { #if IL2CPP_ENABLE_STACKTRACES GetThreadStackDepthContext apcContext; thread->GetInternalThread()->handle->QueueUserAPC(GetThreadStackDepthCallback, &apcContext); apcContext.apcDoneEvent.Wait(); return apcContext.stackDepth; #else return 0; #endif } static void STDCALL GetThreadTopFrameCallback(void* context) { GetThreadTopFrameContext* ctx = static_cast(context); ctx->hasResult = StackTrace::GetTopStackFrame(*ctx->frame); ctx->apcDoneEvent.Set(); } bool StackTrace::GetThreadTopStackFrame(Il2CppThread* thread, Il2CppStackFrameInfo& frame) { #if IL2CPP_ENABLE_STACKTRACES GetThreadTopFrameContext apcContext; apcContext.frame = &frame; thread->GetInternalThread()->handle->QueueUserAPC(GetThreadTopFrameCallback, &apcContext); apcContext.apcDoneEvent.Wait(); return apcContext.hasResult; #else return false; #endif } } } ================================================ FILE: unity_decoder/libil2cpp/vm/StackTrace.h ================================================ #pragma once #include #include #include "il2cpp-config.h" #include "il2cpp-metadata.h" #if IL2CPP_ENABLE_NATIVE_STACKTRACES struct MethodDefinitionKey { Il2CppMethodPointer method; MethodIndex methodIndex; }; #endif namespace il2cpp { namespace vm { typedef std::vector StackFrames; class LIBIL2CPP_CODEGEN_API StackTrace { public: static void InitializeStackTracesForCurrentThread(); static void CleanupStackTracesForCurrentThread(); // Current thread functions static const StackFrames* GetStackFrames(); static bool GetStackFrameAt(int32_t depth, Il2CppStackFrameInfo& frame); static void WalkFrameStack(Il2CppFrameWalkFunc callback, void* context); inline static size_t GetStackDepth() { return GetStackFrames()->size(); } inline static bool GetTopStackFrame(Il2CppStackFrameInfo& frame) { return GetStackFrameAt(0, frame); } static void PushFrame(Il2CppStackFrameInfo& frame); static void PopFrame(); // Remote thread functions static bool GetThreadStackFrameAt(Il2CppThread* thread, int32_t depth, Il2CppStackFrameInfo& frame); static void WalkThreadFrameStack(Il2CppThread* thread, Il2CppFrameWalkFunc callback, void* context); static int32_t GetThreadStackDepth(Il2CppThread* thread); static bool GetThreadTopStackFrame(Il2CppThread* thread, Il2CppStackFrameInfo& frame); }; } } ================================================ FILE: unity_decoder/libil2cpp/vm/String.cpp ================================================ #include "il2cpp-config.h" #include "gc/Allocator.h" #include "gc/GarbageCollector.h" #include "gc/GCHandle.h" #include "os/Mutex.h" #include "vm/Exception.h" #include "vm/String.h" #include "vm/Object.h" #include "vm/Profiler.h" #include "gc/AppendOnlyGCHashMap.h" #include "utils/StringUtils.h" #include #include #include "class-internals.h" #include "object-internals.h" namespace il2cpp { namespace vm { static Il2CppString* s_EmptyString; void String::InitializeEmptyString(Il2CppClass* stringClass) { IL2CPP_ASSERT(s_EmptyString == NULL && "Empty string was already initialized"); // size for string and null terminator s_EmptyString = static_cast(gc::GarbageCollector::AllocateFixed(sizeof(Il2CppString) + 2, 0)); s_EmptyString->object.klass = stringClass; s_EmptyString->length = 0; s_EmptyString->chars[0] = 0; } void String::CleanupEmptyString() { IL2CPP_ASSERT(s_EmptyString && "Empty string was not yet initialized"); gc::GarbageCollector::FreeFixed(s_EmptyString); s_EmptyString = NULL; } Il2CppString* String::Empty() { IL2CPP_ASSERT(s_EmptyString && "Empty string was not yet initialized"); return s_EmptyString; } int32_t String::GetHash(Il2CppString* str) { const Il2CppChar* p = utils::StringUtils::GetChars(str); int i, len = utils::StringUtils::GetLength(str); uint32_t h = 0; for (i = 0; i < len; i++) { h = (h << 5) - h + *p; p++; } return h; } Il2CppString* String::New(const char* str) { return NewLen(str, (uint32_t)strlen(str)); } Il2CppString* String::NewWrapper(const char* str) { return New(str); } Il2CppString* String::NewLen(const char* str, uint32_t length) { UTF16String utf16Chars = il2cpp::utils::StringUtils::Utf8ToUtf16(str, length); return NewUtf16(utf16Chars.c_str(), (uint32_t)utf16Chars.length()); } Il2CppString* String::NewUtf16(const Il2CppChar* text, int32_t len) { Il2CppString *s; s = NewSize(len); IL2CPP_ASSERT(s != NULL); memcpy(utils::StringUtils::GetChars(s), text, len * 2); return s; } Il2CppString* String::NewUtf16(const utils::StringView& text) { assert(text.Length() < static_cast(std::numeric_limits::max())); return NewUtf16(text.Str(), static_cast(text.Length())); } Il2CppString* String::NewSize(int32_t len) { if (len == 0) return Empty(); Il2CppString *s; IL2CPP_ASSERT(len >= 0); size_t size = (sizeof(Il2CppString) + ((len + 1) * 2)); /* overflow ? can't fit it, can't allocate it! */ if (static_cast(len) > size) Exception::RaiseOutOfMemoryException(); s = reinterpret_cast(Object::AllocatePtrFree(size, il2cpp_defaults.string_class)); s->length = len; #if NEED_TO_ZERO_PTRFREE s->chars[len] = 0; #endif #if IL2CPP_ENABLE_PROFILER if (Profiler::ProfileAllocations()) Profiler::Allocation((Il2CppObject*)s, il2cpp_defaults.string_class); #endif return s; } struct InternedString { int32_t length; const Il2CppChar* chars; }; class InternedStringHash { public: size_t operator()(const InternedString& ea) const { return utils::StringUtils::Hash(ea.chars, ea.length); } }; class InternedStringCompare { public: bool operator()(const InternedString& ea, const InternedString& eb) const { return (ea.length == eb.length) && (0 == memcmp(ea.chars, eb.chars, sizeof(Il2CppChar) * ea.length)); } }; typedef il2cpp::gc::AppendOnlyGCHashMap InternedStringMap; static os::FastMutex s_InternedStringMapMutex; static InternedStringMap* s_InternedStringMap; Il2CppString* String::Intern(Il2CppString* str) { os::FastAutoLock lockMap(&s_InternedStringMapMutex); // allocate this are runtime since it uses GC allocator to keep managed strings alive and needs GC initialized if (s_InternedStringMap == NULL) s_InternedStringMap = new InternedStringMap(); InternedString internedString = { str->length, str->chars }; Il2CppString* value = NULL; if (s_InternedStringMap->TryGetValue(internedString, &value)) return value; internedString.chars = utils::StringUtils::GetChars(str); s_InternedStringMap->Add(internedString, str); return str; } Il2CppString* String::IsInterned(Il2CppString* str) { os::FastAutoLock lockMap(&s_InternedStringMapMutex); // if this is NULL, it means we have no interned strings if (s_InternedStringMap == NULL) return NULL; InternedString internedString = { str->length, str->chars }; Il2CppString* value = NULL; if (s_InternedStringMap->TryGetValue(internedString, &value)) return value; return NULL; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/String.h ================================================ #pragma once #include #include "il2cpp-config.h" #include "utils/StringView.h" struct Il2CppString; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API String { public: //exported static Il2CppString* Empty(); static int32_t GetLength(Il2CppString* str); static int32_t GetHash(Il2CppString* str); static Il2CppString* New(const char* str); static Il2CppString* NewWrapper(const char* str); static Il2CppString* NewLen(const char* str, uint32_t length); static Il2CppString* NewSize(int32_t len); static Il2CppString* NewUtf16(const Il2CppChar *text, int32_t len); static Il2CppString* NewUtf16(const utils::StringView& text); public: static void InitializeEmptyString(Il2CppClass* stringClass); static void CleanupEmptyString(); static Il2CppString* Intern(Il2CppString* str); static Il2CppString* IsInterned(Il2CppString* str); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Thread.cpp ================================================ #include "il2cpp-config.h" #include "os/Atomic.h" #include "os/Mutex.h" #include "os/Thread.h" #include "os/ThreadLocalValue.h" #include "os/StackTrace.h" #include "os/Semaphore.h" #include "vm/Domain.h" #include "vm/Exception.h" #include "vm/Object.h" #include "vm/Object.h" #include "vm/Runtime.h" #include "vm/StackTrace.h" #include "vm/Thread.h" #include "vm/String.h" #include "gc/Allocator.h" #include "gc/GarbageCollector.h" #include "gc/GCHandle.h" #include "utils/Memory.h" #include "utils/StringUtils.h" #include "class-internals.h" #include "object-internals.h" #include #include #if IL2CPP_DEBUGGER_ENABLED #include "../il2cpp-debugger.h" #endif using namespace il2cpp::os; using il2cpp::gc::GarbageCollector; using il2cpp::os::FastMutex; namespace il2cpp { namespace vm { Il2CppThread* Thread::s_MainThread = NULL; typedef std::vector > GCTrackedThreadVector; // we need to allocate this ourselves so the CRT does not initialize it and try to allocate GC memory on startup before the GC is initialized static GCTrackedThreadVector* s_AttachedThreads; static bool s_BlockNewThreads = false; #define AUTO_LOCK_THREADS() \ il2cpp::os::FastAutoLock lock(&s_ThreadMutex) static FastMutex s_ThreadMutex; static std::vector s_ThreadStaticSizes; static ThreadLocalValue s_CurrentThread; static volatile int32_t s_NextManagedThreadId = 0; static void thread_cleanup_on_cancel(void* arg) { Thread::Detach((Il2CppThread*)arg); } void Thread::Initialize() { #if IL2CPP_HAS_NATIVE_THREAD_CLEANUP os::Thread::SetNativeThreadCleanup(&thread_cleanup_on_cancel); #endif s_AttachedThreads = new GCTrackedThreadVector(); } void Thread::UnInitialize() { #if IL2CPP_HAS_NATIVE_THREAD_CLEANUP os::Thread::SetNativeThreadCleanup(NULL); #endif delete s_AttachedThreads; s_AttachedThreads = NULL; } Il2CppThread* Thread::Attach(Il2CppDomain *domain) { Il2CppThread* thread = Current(); if (thread != NULL) return thread; int temp = 0; if (!GarbageCollector::RegisterThread(&temp)) IL2CPP_ASSERT(0 && "GarbageCollector::RegisterThread failed"); StackTrace::InitializeStackTracesForCurrentThread(); // Get/create OS thread representing the current thread. For pre-existing threads such as // the main thread, this will create an OS thread instance on demand. For threads that have // been started through our OS layer, there will already be an instance. os::Thread* osThread = os::Thread::GetOrCreateCurrentThread(); // Create managed object representing the current thread. thread = (Il2CppThread*)Object::New(il2cpp_defaults.thread_class); #if NET_4_0 thread->internal_thread = (Il2CppInternalThread*)Object::New(il2cpp_defaults.internal_thread_class); #endif thread->GetInternalThread()->handle = osThread; thread->GetInternalThread()->state = kThreadStateRunning; thread->GetInternalThread()->tid = osThread->Id(); thread->GetInternalThread()->managed_id = GetNewManagedId(); Setup(thread); Initialize(thread, domain); return thread; } void Thread::Setup(Il2CppThread* thread) { thread->GetInternalThread()->synch_cs = new il2cpp::os::FastMutex(); thread->GetInternalThread()->apartment_state = kApartmentStateUnknown; } void Thread::Initialize(Il2CppThread* thread, Il2CppDomain* domain) { IL2CPP_ASSERT(thread->GetInternalThread()->handle != NULL); IL2CPP_ASSERT(thread->GetInternalThread()->synch_cs != NULL); s_CurrentThread.SetValue(thread); Domain::ContextSet(domain->default_context); Register(thread); AdjustStaticData(); #if IL2CPP_DEBUGGER_ENABLED il2cpp_debugger_notify_thread_attach(thread); #endif // Sync thread name. if (thread->GetInternalThread()->name) { std::string utf8Name = il2cpp::utils::StringUtils::Utf16ToUtf8(thread->GetInternalThread()->name); thread->GetInternalThread()->handle->SetName(utf8Name); } // Sync thread apartment state. thread->GetInternalThread()->apartment_state = thread->GetInternalThread()->handle->GetApartment(); #if IL2CPP_HAS_NATIVE_THREAD_CLEANUP // register us for platform specific cleanup attempt in case thread is not exited cleanly os::Thread::RegisterCurrentThreadForCleanup(thread); #endif // If an interrupt has been requested before the thread was started, re-request // the interrupt now. if (thread->GetInternalThread()->interruption_requested) RequestInterrupt(thread); } void Thread::Uninitialize(Il2CppThread *thread) { #if IL2CPP_HAS_NATIVE_THREAD_CLEANUP // unregister from special cleanup since we are doing it now os::Thread::UnregisterCurrentThreadForCleanup(); #endif if (!GarbageCollector::UnregisterThread()) IL2CPP_ASSERT(0 && "GarbageCollector::UnregisterThread failed"); #if IL2CPP_DEBUGGER_ENABLED il2cpp_debugger_notify_thread_detach(thread); #endif Unregister(thread); FreeThreadStaticData(thread); #if !NET_4_0 delete[] thread->GetInternalThread()->serialized_culture_info; #endif os::Thread::DetachCurrentThread(); s_CurrentThread.SetValue(NULL); } Il2CppThread* Thread::Current() { void* value = NULL; s_CurrentThread.GetValue(&value); return (Il2CppThread*)value; } Il2CppThread** Thread::GetAllAttachedThreads(size_t &size) { size = s_AttachedThreads->size(); return &(*s_AttachedThreads)[0]; } static void STDCALL TerminateBackgroundThread(void* context) { // We throw a dummy exception to make sure things clean up properly // and we don't leave any locks behind (such as global locks in the allocator which // would then deadlock other threads). This could work off ThreadAbortException // but we don't want to deal with a managed exception here. So we use a C++ exception. throw Thread::NativeThreadAbortException(); } void Thread::KillAllBackgroundThreadsAndWaitForForegroundThreads() { #if IL2CPP_SUPPORT_THREADS Il2CppThread* gcFinalizerThread = NULL; Il2CppThread* currentThread = Current(); IL2CPP_ASSERT(currentThread != NULL && "No current thread!"); s_ThreadMutex.Lock(); s_BlockNewThreads = true; GCTrackedThreadVector attachedThreadsCopy = *s_AttachedThreads; s_ThreadMutex.Unlock(); std::vector backgroundThreads; std::vector foregroundThreads; // Kill all threads but the finalizer and current one. We temporarily flush out // the entire list and then just put the two threads back. while (attachedThreadsCopy.size()) { Il2CppThread* thread = attachedThreadsCopy.back(); os::Thread* osThread = thread->GetInternalThread()->handle; if (GarbageCollector::IsFinalizerThread(thread)) { IL2CPP_ASSERT(gcFinalizerThread == NULL && "There seems to be more than one finalizer thread!"); gcFinalizerThread = thread; } else if (thread != currentThread) { // If it's a background thread, request it to kill itself. if (GetState(thread) & kThreadStateBackground) { ////TODO: use Thread.Abort() instead osThread->QueueUserAPC(TerminateBackgroundThread, NULL); backgroundThreads.push_back(osThread); } else foregroundThreads.push_back(osThread); } attachedThreadsCopy.pop_back(); } ////FIXME: While we don't have stable thread abortion in place yet, work around problems in //// the current implementation by repeatedly requesting threads to terminate. This works around //// race condition to some extent. while (backgroundThreads.size()) { os::Thread* osThread = backgroundThreads.back(); // Wait for the thread. if (osThread->Join(10) == kWaitStatusSuccess) backgroundThreads.pop_back(); else { ////TODO: use Thread.Abort() instead osThread->QueueUserAPC(TerminateBackgroundThread, NULL); } } for (unsigned i = 0; i < foregroundThreads.size(); ++i) { foregroundThreads[i]->Join(); } AUTO_LOCK_THREADS(); s_AttachedThreads->clear(); // Put finalizer and current thread back in list. IL2CPP_ASSERT(gcFinalizerThread != NULL && "GC finalizer thread was not found in list of attached threads!"); if (gcFinalizerThread) s_AttachedThreads->push_back(gcFinalizerThread); if (currentThread) s_AttachedThreads->push_back(currentThread); #endif } void Thread::Detach(Il2CppThread *thread) { IL2CPP_ASSERT(thread != NULL && "Cannot detach a NULL thread"); Uninitialize(thread); il2cpp::vm::StackTrace::CleanupStackTracesForCurrentThread(); } Il2CppThread* Thread::Main() { return s_MainThread; } void Thread::SetMain(Il2CppThread* thread) { s_MainThread = thread; } void Thread::SetState(Il2CppThread *thread, ThreadState value) { il2cpp::os::FastAutoLock lock(thread->GetInternalThread()->synch_cs); thread->GetInternalThread()->state |= value; } #if NET_4_0 void Thread::ClrState(Il2CppInternalThread* thread, ThreadState clr) { il2cpp::os::FastAutoLock lock(thread->synch_cs); thread->state &= ~clr; } void Thread::SetState(Il2CppInternalThread *thread, ThreadState value) { il2cpp::os::FastAutoLock lock(thread->synch_cs); thread->state |= value; } ThreadState Thread::GetState(Il2CppInternalThread *thread) { il2cpp::os::FastAutoLock lock(thread->synch_cs); return (ThreadState)thread->state; } bool Thread::TestState(Il2CppInternalThread* thread, ThreadState value) { il2cpp::os::FastAutoLock lock(thread->synch_cs); return (thread->state & value) != 0; } Il2CppInternalThread* Thread::CurrentInternal() { return Current()->GetInternalThread(); } #endif ThreadState Thread::GetState(Il2CppThread *thread) { il2cpp::os::FastAutoLock lock(thread->GetInternalThread()->synch_cs); return (ThreadState)thread->GetInternalThread()->state; } void Thread::ClrState(Il2CppThread* thread, ThreadState state) { il2cpp::os::FastAutoLock lock(thread->GetInternalThread()->synch_cs); thread->GetInternalThread()->state &= ~state; } const int32_t kMaxThreadStaticSlots = 2048; void Thread::AdjustStaticData() { AUTO_LOCK_THREADS(); size_t index = 0; Il2CppThread* thread = Current(); if (!thread->GetInternalThread()->static_data) thread->GetInternalThread()->static_data = (void**)IL2CPP_CALLOC(kMaxThreadStaticSlots, sizeof(void*)); for (std::vector::const_iterator iter = s_ThreadStaticSizes.begin(); iter != s_ThreadStaticSizes.end(); ++iter) { if (!thread->GetInternalThread()->static_data[index]) thread->GetInternalThread()->static_data[index] = GarbageCollector::AllocateFixed(*iter, NULL); index++; } } int32_t Thread::AllocThreadStaticData(int32_t size) { AUTO_LOCK_THREADS(); int32_t index = (int32_t)s_ThreadStaticSizes.size(); IL2CPP_ASSERT(index < kMaxThreadStaticSlots); s_ThreadStaticSizes.push_back(size); for (GCTrackedThreadVector::const_iterator iter = s_AttachedThreads->begin(); iter != s_AttachedThreads->end(); ++iter) { Il2CppThread* thread = *iter; if (!thread->GetInternalThread()->static_data) thread->GetInternalThread()->static_data = (void**)IL2CPP_CALLOC(kMaxThreadStaticSlots, sizeof(void*)); thread->GetInternalThread()->static_data[index] = GarbageCollector::AllocateFixed(size, NULL); } return index; } void Thread::FreeThreadStaticData(Il2CppThread *thread) { AUTO_LOCK_THREADS(); size_t index = 0; for (std::vector::const_iterator iter = s_ThreadStaticSizes.begin(); iter != s_ThreadStaticSizes.end(); ++iter) { if (thread->GetInternalThread()->static_data[index]) GarbageCollector::FreeFixed(thread->GetInternalThread()->static_data[index]); index++; } IL2CPP_FREE(thread->GetInternalThread()->static_data); thread->GetInternalThread()->static_data = NULL; } void* Thread::GetThreadStaticData(int32_t offset) { // No lock. We allocate static_data once with a fixed size so we can read it // safely without a lock here. IL2CPP_ASSERT(offset >= 0 && static_cast(offset) < s_ThreadStaticSizes.size()); return Current()->GetInternalThread()->static_data[offset]; } void Thread::Register(Il2CppThread *thread) { AUTO_LOCK_THREADS(); if (s_BlockNewThreads) TerminateBackgroundThread(NULL); else s_AttachedThreads->push_back(thread); } void Thread::Unregister(Il2CppThread *thread) { AUTO_LOCK_THREADS(); GCTrackedThreadVector::iterator it = std::find(s_AttachedThreads->begin(), s_AttachedThreads->end(), thread); IL2CPP_ASSERT(it != s_AttachedThreads->end() && "Vm thread not found in list of attached threads."); s_AttachedThreads->erase(it); } bool Thread::IsVmThread(Il2CppThread *thread) { return !GarbageCollector::IsFinalizerThread(thread); } char *Thread::GetName(uint32_t *len) { *len = 0; // TODO: not implemented return NULL; } void Thread::SetName(Il2CppThread* thread, Il2CppString* name) { il2cpp::os::FastAutoLock lock(thread->GetInternalThread()->synch_cs); // Throw if already set. if (thread->GetInternalThread()->name_len != 0) il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetInvalidOperationException("Thread name can only be set once.")); // Store name. thread->GetInternalThread()->name_len = utils::StringUtils::GetLength(name); thread->GetInternalThread()->name = il2cpp::utils::StringUtils::StringDuplicate(utils::StringUtils::GetChars(name), thread->GetInternalThread()->name_len); // Hand over to OS layer, if thread has been started already. if (thread->GetInternalThread()->handle) { std::string utf8Name = il2cpp::utils::StringUtils::Utf16ToUtf8(thread->GetInternalThread()->name); thread->GetInternalThread()->handle->SetName(utf8Name); } } #if NET_4_0 void Thread::SetName(Il2CppInternalThread* thread, Il2CppString* name) { il2cpp::os::FastAutoLock lock(thread->synch_cs); // Throw if already set. if (thread->name_len != 0) il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetInvalidOperationException("Thread name can only be set once.")); // Store name. thread->name_len = utils::StringUtils::GetLength(name); thread->name = il2cpp::utils::StringUtils::StringDuplicate(utils::StringUtils::GetChars(name), thread->name_len); // Hand over to OS layer, if thread has been started already. if (thread->handle) { std::string utf8Name = il2cpp::utils::StringUtils::Utf16ToUtf8(thread->name); thread->handle->SetName(utf8Name); } } #endif static void STDCALL CheckCurrentThreadForInterruptCallback(void* context) { Thread::CheckCurrentThreadForInterruptAndThrowIfNecessary(); } void Thread::RequestInterrupt(Il2CppThread* thread) { il2cpp::os::FastAutoLock lock(thread->GetInternalThread()->synch_cs); thread->GetInternalThread()->interruption_requested = true; // If thread has already been started, queue an interrupt now. il2cpp::os::Thread* osThread = thread->GetInternalThread()->handle; if (osThread) osThread->QueueUserAPC(CheckCurrentThreadForInterruptCallback, NULL); } void Thread::CheckCurrentThreadForInterruptAndThrowIfNecessary() { Il2CppThread* currentThread = il2cpp::vm::Thread::Current(); if (!currentThread) return; il2cpp::os::FastAutoLock lock(currentThread->GetInternalThread()->synch_cs); // Don't throw if thread is not currently in waiting state or if there's // no pending interrupt. if (!currentThread->GetInternalThread()->interruption_requested || !(il2cpp::vm::Thread::GetState(currentThread) & il2cpp::vm::kThreadStateWaitSleepJoin)) return; // Mark the current thread as being unblocked. currentThread->GetInternalThread()->interruption_requested = false; il2cpp::vm::Thread::ClrState(currentThread, il2cpp::vm::kThreadStateWaitSleepJoin); // Throw interrupt exception. il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetThreadInterruptedException()); } static void STDCALL CheckCurrentThreadForAbortCallback(void* context) { Thread::CheckCurrentThreadForAbortAndThrowIfNecessary(); } bool Thread::RequestAbort(Il2CppThread* thread) { il2cpp::os::FastAutoLock lock(thread->GetInternalThread()->synch_cs); ThreadState state = il2cpp::vm::Thread::GetState(thread); if (state & kThreadStateAbortRequested || state & kThreadStateStopped || state & kThreadStateStopRequested) return false; il2cpp::os::Thread* osThread = thread->GetInternalThread()->handle; if (osThread) { // If thread has already been started, queue an abort now. Thread::SetState(thread, kThreadStateAbortRequested); osThread->QueueUserAPC(CheckCurrentThreadForAbortCallback, NULL); } else { // If thread has not started, put it in the aborted state. Thread::SetState(thread, kThreadStateAborted); } return true; } #if NET_4_0 bool Thread::RequestAbort(Il2CppInternalThread* thread) { il2cpp::os::FastAutoLock lock(thread->synch_cs); ThreadState state = il2cpp::vm::Thread::GetState(thread); if (state & kThreadStateAbortRequested || state & kThreadStateStopped || state & kThreadStateStopRequested) return false; il2cpp::os::Thread* osThread = thread->handle; if (osThread) { // If thread has already been started, queue an abort now. Thread::SetState(thread, kThreadStateAbortRequested); osThread->QueueUserAPC(CheckCurrentThreadForAbortCallback, NULL); } else { // If thread has not started, put it in the aborted state. Thread::SetState(thread, kThreadStateAborted); } return true; } void Thread::SetPriority(Il2CppThread* thread, int32_t priority) { Il2CppInternalThread* internalThread = thread->GetInternalThread(); il2cpp::os::FastAutoLock lock(internalThread->synch_cs); internalThread->handle->SetPriority((ThreadPriority)priority); } int32_t Thread::GetPriority(Il2CppThread* thread) { Il2CppInternalThread* internalThread = thread->GetInternalThread(); il2cpp::os::FastAutoLock lock(internalThread->synch_cs); return internalThread->handle->GetPriority(); } struct StartDataInternal { Il2CppThread* m_Thread; Il2CppDomain* m_Domain; void* m_Delegate; void* m_StartArg; il2cpp::os::Semaphore* m_Semaphore; }; static void ThreadStart(void* arg) { StartDataInternal* startData = (StartDataInternal*)arg; startData->m_Semaphore->Wait(); { int temp = 0; if (!GarbageCollector::RegisterThread(&temp)) IL2CPP_ASSERT(0 && "GarbageCollector::RegisterThread failed"); il2cpp::vm::StackTrace::InitializeStackTracesForCurrentThread(); il2cpp::vm::Thread::Initialize(startData->m_Thread, startData->m_Domain); il2cpp::vm::Thread::SetState(startData->m_Thread, kThreadStateRunning); try { try { ((void(*)(void*))startData->m_Delegate)(startData->m_StartArg); } catch (Il2CppExceptionWrapper& ex) { Runtime::UnhandledException(ex.ex); } } catch (il2cpp::vm::Thread::NativeThreadAbortException) { // Nothing to do. We've successfully aborted the thread. il2cpp::vm::Thread::SetState(startData->m_Thread, kThreadStateAborted); } il2cpp::vm::Thread::ClrState(startData->m_Thread, kThreadStateRunning); il2cpp::vm::Thread::SetState(startData->m_Thread, kThreadStateStopped); il2cpp::vm::Thread::Uninitialize(startData->m_Thread); il2cpp::vm::StackTrace::CleanupStackTracesForCurrentThread(); } delete startData->m_Semaphore; GarbageCollector::FreeFixed(startData); } Il2CppInternalThread* Thread::CreateInternal(void(*func)(void*), void* arg, bool threadpool_thread, uint32_t stack_size) { os::Thread* osThread = new os::Thread(); Il2CppThread* thread = (Il2CppThread*)Object::New(il2cpp_defaults.thread_class); Il2CppInternalThread* internal = (Il2CppInternalThread*)Object::New(il2cpp_defaults.internal_thread_class); thread->internal_thread = internal; internal->state = kThreadStateUnstarted; internal->handle = osThread; internal->synch_cs = new il2cpp::os::FastMutex(); internal->apartment_state = il2cpp::os::kApartmentStateUnknown; internal->threadpool_thread = threadpool_thread; // use fixed GC memory since we are storing managed object pointers StartDataInternal* startData = (StartDataInternal*)GarbageCollector::AllocateFixed(sizeof(StartDataInternal), NULL); startData->m_Thread = thread; startData->m_Domain = Domain::GetCurrent(); startData->m_Delegate = (void*)func; startData->m_StartArg = arg; startData->m_Semaphore = new il2cpp::os::Semaphore(0); osThread->SetStackSize(stack_size); osThread->SetExplicitApartment(static_cast(internal->apartment_state)); il2cpp::os::ErrorCode status = osThread->Run(&ThreadStart, startData); if (status != il2cpp::os::kErrorCodeSuccess) { delete osThread; return NULL; } internal->state &= ~kThreadStateUnstarted; internal->tid = osThread->Id(); internal->managed_id = GetNewManagedId(); startData->m_Semaphore->Post(1, NULL); return internal; } void Thread::Stop(Il2CppInternalThread* thread) { IL2CPP_ASSERT(thread != CurrentInternal()); if (!RequestAbort(thread)) return; os::Thread* osThread = thread->handle; ////FIXME: While we don't have stable thread abortion in place yet, work around problems in //// the current implementation by repeatedly requesting threads to terminate. This works around //// race condition to some extent. while (true) { // If it's a background thread, request it to kill itself. if (GetState(thread) & kThreadStateBackground) { ////TODO: use Thread.Abort() instead osThread->QueueUserAPC(TerminateBackgroundThread, NULL); } // Wait for the thread. if (osThread->Join(10) == kWaitStatusSuccess) break; } } void Thread::Sleep(uint32_t ms) { CurrentInternal()->handle->Sleep(ms); } bool Thread::YieldInternal() { return os::Thread::YieldInternal(); } #endif void Thread::CheckCurrentThreadForAbortAndThrowIfNecessary() { Il2CppThread* currentThread = il2cpp::vm::Thread::Current(); if (!currentThread) return; il2cpp::os::FastAutoLock lock(currentThread->GetInternalThread()->synch_cs); ThreadState state = il2cpp::vm::Thread::GetState(currentThread); if (!(state & kThreadStateAbortRequested)) return; // Mark the current thread as being unblocked. il2cpp::vm::Thread::ClrState(currentThread, kThreadStateAbortRequested); // Throw interrupt exception. Il2CppException* abortException = il2cpp::vm::Exception::GetThreadAbortException(); IL2CPP_OBJECT_SETREF(currentThread->GetInternalThread(), abort_exc, (Il2CppObject*)abortException); il2cpp::vm::Exception::Raise(abortException); } void Thread::ResetAbort(Il2CppThread* thread) { il2cpp::vm::Thread::ClrState(thread, kThreadStateAbortRequested); if (thread->GetInternalThread()->abort_exc == NULL) il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetThreadStateException("Unable to reset abort because no abort was requested.")); } void Thread::MemoryBarrier() { os::Atomic::MemoryBarrier(); } int32_t Thread::GetNewManagedId() { return os::Atomic::Increment(&s_NextManagedThreadId); } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Thread.h ================================================ #pragma once #include #include #include "il2cpp-config.h" #include "utils/NonCopyable.h" struct MethodInfo; struct Il2CppArray; struct Il2CppDomain; struct Il2CppObject; struct Il2CppThread; struct Il2CppInternalThread; struct Il2CppString; namespace il2cpp { namespace vm { // System.Threading.ThreadState enum ThreadState { kThreadStateRunning = 0x00000000, kThreadStateStopRequested = 0x00000001, kThreadStateSuspendRequested = 0x00000002, kThreadStateBackground = 0x00000004, kThreadStateUnstarted = 0x00000008, kThreadStateStopped = 0x00000010, kThreadStateWaitSleepJoin = 0x00000020, kThreadStateSuspended = 0x00000040, kThreadStateAbortRequested = 0x00000080, kThreadStateAborted = 0x00000100 }; // System.Threading.ApartmentState enum ThreadApartmentState { kThreadApartmentStateSTA = 0x00000000, kThreadApartmentStateMTA = 0x00000001, kThreadApartmentStateUnknown = 0x00000002 }; class LIBIL2CPP_CODEGEN_API Thread { public: static char *GetName(uint32_t *len); static void SetName(Il2CppThread* thread, Il2CppString* name); static void SetName(Il2CppInternalThread* thread, Il2CppString* name); static Il2CppThread* Current(); static Il2CppThread* Attach(Il2CppDomain *domain); static void Detach(Il2CppThread *thread); static void WalkFrameStack(Il2CppThread *thread, Il2CppFrameWalkFunc func, void *user_data); static Il2CppThread** GetAllAttachedThreads(size_t &size); static void KillAllBackgroundThreadsAndWaitForForegroundThreads(); static Il2CppThread* Main(); static bool IsVmThread(Il2CppThread *thread); static void RequestInterrupt(Il2CppThread* thread); static void CheckCurrentThreadForInterruptAndThrowIfNecessary(); static bool RequestAbort(Il2CppThread* thread); static void CheckCurrentThreadForAbortAndThrowIfNecessary(); static void ResetAbort(Il2CppThread* thread); #if NET_4_0 static bool RequestAbort(Il2CppInternalThread* thread); static void SetPriority(Il2CppThread* thread, int32_t priority); static int32_t GetPriority(Il2CppThread* thread); #endif struct NativeThreadAbortException {}; public: // internal static void Initialize(); static void UnInitialize(); static void AdjustStaticData(); static int32_t AllocThreadStaticData(int32_t size); static void FreeThreadStaticData(Il2CppThread *thread); static void* GetThreadStaticData(int32_t offset); static void Register(Il2CppThread *thread); static void Unregister(Il2CppThread *thread); static void Setup(Il2CppThread* thread); /// Initialize and register thread. /// NOTE: Must be called on thread! static void Initialize(Il2CppThread *thread, Il2CppDomain* domain); static void Uninitialize(Il2CppThread *thread); static void SetMain(Il2CppThread* thread); static void SetState(Il2CppThread *thread, ThreadState value); static ThreadState GetState(Il2CppThread *thread); static void ClrState(Il2CppThread* thread, ThreadState clr); static void MemoryBarrier(); static int32_t GetNewManagedId(); #if NET_4_0 static Il2CppInternalThread* CurrentInternal(); static void ClrState(Il2CppInternalThread* thread, ThreadState clr); static void SetState(Il2CppInternalThread *thread, ThreadState value); static ThreadState GetState(Il2CppInternalThread *thread); static bool TestState(Il2CppInternalThread* thread, ThreadState value); static Il2CppInternalThread* CreateInternal(void(*func)(void*), void* arg, bool threadpool_thread, uint32_t stack_size); static void Stop(Il2CppInternalThread* thread); static void Sleep(uint32_t ms); static bool YieldInternal(); #endif private: static Il2CppThread* s_MainThread; }; class ThreadAttacher : il2cpp::utils::NonCopyable { public: ThreadAttacher(Il2CppDomain *domain) { m_Thread = Thread::Attach(domain); } ~ThreadAttacher() { Thread::Detach(m_Thread); } private: Il2CppThread* m_Thread; }; class ThreadStateSetter : il2cpp::utils::NonCopyable { public: ThreadStateSetter(ThreadState state) : m_State(state) { m_Thread = il2cpp::vm::Thread::Current(); Thread::SetState(m_Thread, m_State); } ~ThreadStateSetter() { Thread::ClrState(m_Thread, m_State); } private: ThreadState m_State; Il2CppThread* m_Thread; }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/ThreadPool.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "il2cpp-api.h" #include "object-internals.h" #include "vm/Array.h" #include "vm/Class.h" #include "vm/Exception.h" #include "vm/Image.h" #include "vm/Object.h" #include "vm/Thread.h" #include "vm/ThreadPool.h" #include "vm/WaitHandle.h" #include "os/Atomic.h" #include "os/Environment.h" #include "os/Event.h" #include "os/Mutex.h" #include "os/Semaphore.h" #include "os/Socket.h" #include "os/Thread.h" #include "gc/Allocator.h" #include "gc/GCHandle.h" #include "utils/Memory.h" #include "icalls/System/System.Net.Sockets/Socket.h" #include #include #include #include #include #if IL2CPP_TARGET_POSIX #include #include "os/Posix/PosixHelpers.h" #elif IL2CPP_TARGET_WINDOWS #include "os/Win32/WindowsHeaders.h" #include "os/Win32/ThreadImpl.h" #include #endif #if IL2CPP_USE_SOCKET_MULTIPLEX_IO #include "MultiplexIO.h" #endif ////TODO: Currently the pool uses a single global lock for each compartment; doesn't scale well and provides room for optimization. namespace il2cpp { namespace vm { enum { THREADS_PER_CORE = 10 }; typedef gc::Allocator AsyncResultAllocator; typedef std::list AsyncResultList; typedef std::vector AsyncResultVector; typedef std::queue AsyncResultQueue; static const Il2CppClass* g_SocketAsyncCallClass; static const Il2CppClass* g_ProcessAsyncCallClass; static const Il2CppClass* g_WriteDelegateClass; static const Il2CppClass* g_ReadDelegateClass; ////TODO: add System.Net.Sockets.Socket.SendFileHandler? static bool IsInstanceOfDelegateClass(Il2CppDelegate* delegate, const char* delegateClassName, const char* outerClassName, const Il2CppClass*& cachePtr) { Il2CppClass* klass = delegate->object.klass; Il2CppClass* declaringType = Class::GetDeclaringType(klass); if (cachePtr == 0 && strcmp(klass->name, delegateClassName) == 0 && (strcmp(vm::Image::GetName(klass->image), "System") == 0 || strcmp(vm::Image::GetName(klass->image), "System.dll") == 0) && declaringType && strcmp(declaringType->name, outerClassName) == 0) { cachePtr = klass; } return (klass == cachePtr); } static bool IsSocketAsyncCall(Il2CppDelegate* delegate) { return IsInstanceOfDelegateClass(delegate, "SocketAsyncCall", "Socket", g_SocketAsyncCallClass); } static bool IsProcessAsyncCall(Il2CppDelegate* delegate) { return IsInstanceOfDelegateClass(delegate, "AsyncReadHandler", "Process", g_ProcessAsyncCallClass); } static bool IsFileStreamAsyncCall(Il2CppDelegate* delegate) { return IsInstanceOfDelegateClass(delegate, "WriteDelegate", "FileStream", g_WriteDelegateClass) || IsInstanceOfDelegateClass(delegate, "ReadDelegate", "FileStream", g_ReadDelegateClass); } /// Socket operations enumeration taken from Mono. (Mostly) corresponds /// to System.Net.Sockets.Socket.SocketOperation. enum { AIO_OP_FIRST, AIO_OP_ACCEPT = 0, AIO_OP_CONNECT, AIO_OP_RECEIVE, AIO_OP_RECEIVEFROM, AIO_OP_SEND, AIO_OP_SENDTO, AIO_OP_RECV_JUST_CALLBACK, AIO_OP_SEND_JUST_CALLBACK, AIO_OP_READPIPE, AIO_OP_LAST }; /// We use a dedicated thread to pre-screen sockets for activity and only then handing them /// on to the pool. This avoids having async I/O threads being hogged by single long-running /// network requests. It's basically a separate staging step for socket AsyncResults. struct SocketPollingThread { os::FastMutex mutex; AsyncResultQueue queue; os::Thread* thread; os::Event threadStartupAcknowledged; #if IL2CPP_USE_SOCKET_MULTIPLEX_IO Sockets::MultiplexIO multiplexIO; // container class to allow access to multiplex io socket functions #elif IL2CPP_TARGET_POSIX || IL2CPP_TARGET_WINDOWS /// On POSIX, we have no way to interrupt polls() with user APCs in a way that isn't prone /// to race conditions so what we do instead is create a pipe that we include in the poll() /// call and then write to that in order to interrupt an ongoing poll(). /// /// On Windows, we used to do QueueUserAPC and throw an exception in order to interrupt poll(), /// however, that is not safe and corrupts memory/leaves dangling pointers to the stack as /// WinSock2 is not exception safe. So we do it in a similar way as POSIX, but instead of pipes /// we use sockets. enum { kMessageTerminate, kMessageNewAsyncResult }; #if IL2CPP_TARGET_POSIX typedef int PipeType; #elif IL2CPP_TARGET_WINDOWS typedef SOCKET PipeType; #endif PipeType readPipe; PipeType writePipe; static inline void WritePipe(PipeType pipe, char message) { #if IL2CPP_TARGET_POSIX write(pipe, &message, 1); #elif IL2CPP_TARGET_WINDOWS send(pipe, &message, 1, 0); #endif } static inline char ReadPipe(PipeType pipe, char* message, int length) { #if IL2CPP_TARGET_POSIX return read(pipe, message, length); #elif IL2CPP_TARGET_WINDOWS return recv(pipe, message, length, 0); #endif } #endif SocketPollingThread() : threadStartupAcknowledged(true) , thread(NULL) #if !IL2CPP_USE_SOCKET_MULTIPLEX_IO && (IL2CPP_TARGET_POSIX || IL2CPP_TARGET_WINDOWS) , readPipe(0) , writePipe(0) #endif { } void QueueRequest(Il2CppAsyncResult* asyncResult) { // Put in queue. { os::FastAutoLock lock(&mutex); queue.push(asyncResult); } // Interrupt polling thread to pick up new request. #if IL2CPP_USE_SOCKET_MULTIPLEX_IO multiplexIO.InterruptPoll(); // causes the current blocking poll to abort and recheck the queue #elif IL2CPP_TARGET_POSIX || IL2CPP_TARGET_WINDOWS char message = static_cast(kMessageNewAsyncResult); WritePipe(writePipe, message); #endif } Il2CppAsyncResult* DequeueRequest() { os::FastAutoLock lock(&mutex); if (queue.empty()) return NULL; Il2CppAsyncResult* asyncResult = queue.front(); queue.pop(); return asyncResult; } bool ResultReady() { os::FastAutoLock lock(&mutex); return !queue.empty(); } void RunLoop(); void Terminate(); }; /// Data for a single pool of threads. We compartmentalize the pool to deal with async I/O and "normal" work /// items separately. struct ThreadPoolCompartment { /// Human readable name of the compartment (mostly for debugging). const char* compartmentName; /// Minimum number of threads to be kept around. This is the number that the pool will /// actively try to maintain. Actual thread count can be less during startup of pool. /// NOTE: Can be changed without locking. int minThreads; /// Maximum number of threads the pool will ever have running at the same time. /// NOTE: Can be changed without locking. int maxThreads; /// Number of threads currently waiting for new work. /// NOTE: Changed atomically. volatile int32_t numIdleThreads; /// Semaphore that worker threads listen on. os::Semaphore signalThreads; /// Mutex for queue and threads vector. os::FastMutex mutex; /// Queue of pending items. /// NOTE: Requires lock on mutex. AsyncResultQueue queue; /// List of threads in the pool. Worker threads register and unregister themselves here. /// NOTE: Requires lock on mutex. std::vector threads; ThreadPoolCompartment() : compartmentName(NULL) , minThreads(0) , maxThreads(4) , signalThreads(0, std::numeric_limits::max()) , numIdleThreads(0) { } void QueueWorkItem(Il2CppAsyncResult* asyncResult); Il2CppAsyncResult* DequeueNextWorkItem(); int AttachThread(Il2CppThread* thread) { os::FastAutoLock lock(&mutex); threads.push_back(thread); return (int)threads.size(); } void DetachThread(Il2CppThread* thread) { os::FastAutoLock lock(&mutex); threads.erase(std::remove(threads.begin(), threads.end(), thread), threads.end()); } void SignalAllThreads() { signalThreads.Post((int32_t)threads.size()); } void SpawnNewWorkerThread(); void WorkerThreadRunLoop(); enum { /// Time (in milliseconds) that a worker thread will wait before terminating after finding /// that the pool already has enough threads. kGracePeriodBeforeExtranenousWorkerThreadTerminates = 5000 }; }; enum { kWorkerThreadPool, kAsyncIOPool, kNumThreadPoolCompartments }; static ThreadPoolCompartment* g_ThreadPoolCompartments[kNumThreadPoolCompartments]; static SocketPollingThread* g_SocketPollingThread; #if IL2CPP_TARGET_POSIX && !IL2CPP_USE_SOCKET_MULTIPLEX_IO typedef pollfd NativePollRequest; #else typedef os::PollRequest NativePollRequest; #endif static Il2CppSocketAsyncResult* GetSocketAsyncResult(Il2CppAsyncResult* asyncResult) { ////TODO: assert return reinterpret_cast(asyncResult->async_state); } static bool IsSocketAsyncOperation(Il2CppAsyncResult* asyncResult) { int32_t operation = GetSocketAsyncResult(asyncResult)->operation; return (operation >= AIO_OP_FIRST && operation <= AIO_OP_LAST); } static void InitPollRequest(NativePollRequest& request, Il2CppSocketAsyncResult* socketAsyncResult, os::SocketHandleWrapper& socketHandle) { request.revents = os::kPollFlagsNone; #if IL2CPP_TARGET_POSIX && !IL2CPP_USE_SOCKET_MULTIPLEX_IO request.events = 0xFFFF; #else request.events = os::kPollFlagsNone; switch (socketAsyncResult->operation) { case AIO_OP_ACCEPT: case AIO_OP_RECEIVE: case AIO_OP_RECV_JUST_CALLBACK: case AIO_OP_RECEIVEFROM: case AIO_OP_READPIPE: request.events |= os::kPollFlagsIn; break; case AIO_OP_SEND: case AIO_OP_SEND_JUST_CALLBACK: case AIO_OP_SENDTO: case AIO_OP_CONNECT: request.events |= os::kPollFlagsOut; break; default: // Should never happen IL2CPP_ASSERT(false && "Unrecognized socket async I/O operation"); break; } #endif #if !NET_4_0 // Acquire socket. socketHandle.Acquire(os::PointerToSocketHandle(socketAsyncResult->handle.m_value)); #else IL2CPP_ASSERT(false && "Todo .net 4"); #endif request.fd = socketHandle.IsValid() ? socketHandle.GetSocket()->GetDescriptor() : -1; } void SocketPollingThread::RunLoop() { #if !IL2CPP_USE_SOCKET_MULTIPLEX_IO && !IL2CPP_TARGET_POSIX && !IL2CPP_TARGET_WINDOWS IL2CPP_ASSERT(false && "Platform has no SocketPollingThread mechanism. This function WILL deadlock."); #endif #if IL2CPP_TARGET_POSIX && !IL2CPP_USE_SOCKET_MULTIPLEX_IO const short kNativePollIn = POLLIN; #else const os::PollFlags kNativePollIn = os::kPollFlagsIn; #endif // List of poll requests that we pass to os::Socket::Poll(). std::vector pollRequests; // List of AsyncResults corresponding to pollRequests. Needs to be its own list as // this is memory that we need the GC to scan. AsyncResultVector asyncResults; // List of socket handles we're currently using. If destructed, will automatically // release all sockets. std::vector socketHandles; #if !IL2CPP_USE_SOCKET_MULTIPLEX_IO && (IL2CPP_TARGET_POSIX || IL2CPP_TARGET_WINDOWS) { NativePollRequest pollRequest; pollRequest.fd = readPipe; pollRequest.events = kNativePollIn; pollRequest.revents = os::kPollFlagsNone; pollRequests.push_back(pollRequest); // Push back dummy values to asyncResults and socketHandles so their indices match pollrequest indices asyncResults.push_back(NULL); socketHandles.push_back(os::SocketHandleWrapper()); } #endif // Let other threads know we're ready to take requests. threadStartupAcknowledged.Set(); while (true) { // See if there's anything new in the queue. while (ResultReady()) { // Grab next request. Il2CppAsyncResult* asyncResult = DequeueRequest(); if (!asyncResult) break; Il2CppSocketAsyncResult* socketAsyncResult = GetSocketAsyncResult(asyncResult); // Add socket handle. socketHandles.push_back(os::SocketHandleWrapper()); os::SocketHandleWrapper& socketHandle = socketHandles.back(); asyncResults.push_back(asyncResult); // Add the request to the list. NativePollRequest pollRequest; InitPollRequest(pollRequest, socketAsyncResult, socketHandle); pollRequests.push_back(pollRequest); } // Poll the list. #if IL2CPP_USE_SOCKET_MULTIPLEX_IO int32_t errorCode = 0; int32_t results = 0; multiplexIO.Poll(pollRequests, -1, &results, &errorCode); #elif IL2CPP_TARGET_POSIX || IL2CPP_TARGET_WINDOWS #if IL2CPP_TARGET_POSIX os::posix::Poll(pollRequests.data(), pollRequests.size(), -1); #else int32_t result, error; os::Socket::Poll(pollRequests, -1, &result, &error); #endif if (pollRequests[0].revents != os::kPollFlagsNone) { char message; if (ReadPipe(readPipe, &message, 1) == 1 && message == kMessageTerminate) throw vm::Thread::NativeThreadAbortException(); } #endif // Go through our requests and see which ones we can forward, which ones are // obsolete, and which ones still need to be waited on. #if IL2CPP_USE_SOCKET_MULTIPLEX_IO || (!IL2CPP_TARGET_POSIX && !IL2CPP_TARGET_WINDOWS) const size_t startIndex = 0; #else const size_t startIndex = 1; #endif for (size_t i = startIndex; i < pollRequests.size();) { // See if there's been some activity that allows us to forward the request // to the thread pool. We don't care what event(s) exactly happened on the // socket and the socket may even have been closed already. All we want is // to forward a socket to the pool as soon as there is some activity and then // have the normal processing chain sort out what kind of activity that was. if (pollRequests[i].revents) { // Yes. g_ThreadPoolCompartments[kAsyncIOPool]->QueueWorkItem(asyncResults[i]); pollRequests.erase(pollRequests.begin() + i); asyncResults.erase(asyncResults.begin() + i); socketHandles.erase(socketHandles.begin() + i); } else { ++i; } } } } static void FreeThreadHandle(void* data) { uint32_t handle = (uint32_t)(uintptr_t)data; gc::GCHandle::Free(handle); } #if IL2CPP_TARGET_WINDOWS struct ConnectToSocketArgs { SOCKET s; const sockaddr_in* socketAddress; }; static void ConnectToSocket(void* arg) { ConnectToSocketArgs* connectArgs = static_cast(arg); const int kRetryCount = 3; for (int i = 0; i < kRetryCount; i++) { int connectResult = connect(connectArgs->s, reinterpret_cast(connectArgs->socketAddress), sizeof(sockaddr_in)); if (connectResult == 0) return; Sleep(100); } IL2CPP_ASSERT(false && "Failed to connect to socket"); } #endif static void SocketPollingThreadEntryPoint(void* data) { SocketPollingThread* pollingThread = reinterpret_cast(data); // Properly attach us to the VM and mark us as a background thread. Il2CppThread* managedThread = vm::Thread::Attach(il2cpp_domain_get()); uint32_t handle = gc::GCHandle::New((Il2CppObject*)managedThread, true); vm::Thread::SetState(managedThread, kThreadStateBackground); managedThread->GetInternalThread()->handle->SetName("Socket I/O Polling Thread"); managedThread->GetInternalThread()->handle->SetPriority(os::kThreadPriorityLow); managedThread->GetInternalThread()->handle->SetCleanupFunction(&FreeThreadHandle, (void*)(uintptr_t)handle); // The socket polling thread is not technically a worker pool thread but for all // intents and purposes it is part of the async I/O thread pool. It is important to // mark it as a thread pool thread so that the queueing logic correctly detects // when it is necessary to spin up a new thread to avoid deadlocks. managedThread->GetInternalThread()->threadpool_thread = true; #if IL2CPP_USE_SOCKET_MULTIPLEX_IO #elif IL2CPP_TARGET_POSIX int pipeHandles[2]; if (::pipe(pipeHandles) != 0) { vm::Exception::Raise(vm::Exception::GetExecutionEngineException("Initialization socket polling thread for thread pool failed!")); } pollingThread->readPipe = pipeHandles[0]; pollingThread->writePipe = pipeHandles[1]; #elif IL2CPP_TARGET_WINDOWS { SOCKET server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); IL2CPP_ASSERT(server != INVALID_SOCKET); sockaddr_in serverAddress; int serverAddressLength = sizeof(serverAddress); ZeroMemory(&serverAddress, sizeof(serverAddress)); serverAddress.sin_family = AF_INET; serverAddress.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); int bindResult = bind(server, reinterpret_cast(&serverAddress), serverAddressLength); IL2CPP_ASSERT(bindResult == 0); int getsocknameResult = getsockname(server, reinterpret_cast(&serverAddress), &serverAddressLength); IL2CPP_ASSERT(getsocknameResult == 0); int listenResult = listen(server, 1); IL2CPP_ASSERT(listenResult == 0); pollingThread->writePipe = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); IL2CPP_ASSERT(pollingThread->writePipe != INVALID_SOCKET); os::Thread connectThread; ConnectToSocketArgs args = { pollingThread->writePipe, &serverAddress }; connectThread.Run(ConnectToSocket, &args); sockaddr_in clientAddress = {}; int clientAddressLength = sizeof(clientAddress); pollingThread->readPipe = accept(server, reinterpret_cast(&clientAddress), &clientAddressLength); if (pollingThread->readPipe == INVALID_SOCKET) { int error = WSAGetLastError(); wchar_t errorMessage[512]; FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errorMessage, 256, NULL); OutputDebugStringW(errorMessage); OutputDebugStringW(L"\r\n"); IL2CPP_ASSERT(false && "Failed to accept poll interrupt socket connection"); } connectThread.Join(); closesocket(server); } #endif // Do work. try { pollingThread->RunLoop(); } catch (Thread::NativeThreadAbortException) { // Runtime cleanup asked us to exit. // Cleanup pipes/sockets that we created #if IL2CPP_USE_SOCKET_MULTIPLEX_IO #elif IL2CPP_TARGET_POSIX close(pollingThread->readPipe); close(pollingThread->writePipe); #elif IL2CPP_TARGET_WINDOWS closesocket(pollingThread->readPipe); closesocket(pollingThread->writePipe); #endif } // Clean up. vm::Thread::Detach(managedThread); } static void SpawnSocketPollingThreadIfNeeded() { if (g_SocketPollingThread->thread) return; // Spawn thread. { os::FastAutoLock lock(&g_SocketPollingThread->mutex); // Double-check after lock to avoid race condition. if (!g_SocketPollingThread->thread) { g_SocketPollingThread->thread = new os::Thread(); g_SocketPollingThread->thread->Run(SocketPollingThreadEntryPoint, g_SocketPollingThread); } } // Wait for thread to have started up so we can queue requests on it. g_SocketPollingThread->threadStartupAcknowledged.Wait(); } void SocketPollingThread::Terminate() { #if IL2CPP_TARGET_WINDOWS || IL2CPP_TARGET_POSIX if (!g_SocketPollingThread->thread) return; #if !IL2CPP_USE_SOCKET_MULTIPLEX_IO WritePipe(writePipe, static_cast(kMessageTerminate)); #endif g_SocketPollingThread->thread->Join(); #endif } static bool IsCurrentThreadAWorkerThread() { Il2CppThread* thread = vm::Thread::Current(); return thread->GetInternalThread()->threadpool_thread; } void ThreadPoolCompartment::QueueWorkItem(Il2CppAsyncResult* asyncResult) { bool forceNewThread = false; // Put the item in the queue. { os::FastAutoLock lock(&mutex); queue.push(asyncResult); IL2CPP_ASSERT(numIdleThreads >= 0); if (queue.size() > static_cast(numIdleThreads)) forceNewThread = true; } // If all our worker threads are tied up and we have room to grow, spawn a // new worker thread. Also, if an item is queued from within a work item that // is currently being processed and we don't have idle threads, force a new // thread to be spawned even if we are at max capacity. This prevents deadlocks // if the code queuing the item then goes and waits on the item it just queued. IL2CPP_ASSERT(maxThreads >= 0); if (forceNewThread && (threads.size() < static_cast(maxThreads) || IsCurrentThreadAWorkerThread())) { SpawnNewWorkerThread(); } else { // Signal existing thread. signalThreads.Post(); } } Il2CppAsyncResult* ThreadPoolCompartment::DequeueNextWorkItem() { os::FastAutoLock lock(&mutex); if (queue.empty()) return NULL; Il2CppAsyncResult* result = queue.front(); queue.pop(); return result; } static void WorkerThreadEntryPoint(void* data); void ThreadPoolCompartment::SpawnNewWorkerThread() { os::Thread* thread = new os::Thread(); thread->Run(WorkerThreadEntryPoint, this); } static void HandleSocketAsyncOperation(Il2CppAsyncResult* asyncResult) { Il2CppSocketAsyncResult* socketAsyncResult = GetSocketAsyncResult(asyncResult); const icalls::System::System::Net::Sockets::SocketFlags flags = static_cast(socketAsyncResult->socket_flags); Il2CppArray* buffer = socketAsyncResult->buffer; int32_t offset = socketAsyncResult->offset; int32_t count = socketAsyncResult->size; #if !NET_4_0 // Perform send/receive. switch (socketAsyncResult->operation) { case AIO_OP_RECEIVE: socketAsyncResult->total = icalls::System::System::Net::Sockets::Socket::Receive (socketAsyncResult->handle, buffer, offset, count, flags, &socketAsyncResult->error); break; case AIO_OP_SEND: socketAsyncResult->total = icalls::System::System::Net::Sockets::Socket::Send (socketAsyncResult->handle, buffer, offset, count, flags, &socketAsyncResult->error); break; } #else IL2CPP_ASSERT(false && "TO DO .net 4"); #endif } void ThreadPoolCompartment::WorkerThreadRunLoop() { bool waitingToTerminate = false; // Pump AsyncResults until we're killed. while (true) { // Grab next work item. Il2CppAsyncResult* asyncResult = DequeueNextWorkItem(); if (!asyncResult) { // There's no work for us to do so decide what to do. // If we've exceeded the normal number of threads for the pool (minThreads), // wait around for a bit and then, if there is no work to do, // terminate. IL2CPP_ASSERT(minThreads >= 0); if (threads.size() > static_cast(minThreads)) { if (waitingToTerminate) { // We've already waited so now is the time to go. break; } waitingToTerminate = true; } // No item so wait for signal. We need to allow interruptions here as we don't yet // have proper abort support and the runtime currently uses interruptions to get // background threads to exit. os::Atomic::Increment(&numIdleThreads); if (waitingToTerminate) signalThreads.Wait(kGracePeriodBeforeExtranenousWorkerThreadTerminates, true); else signalThreads.Wait(true); os::Atomic::Decrement(&numIdleThreads); // Try again. continue; } waitingToTerminate = false; // See if it's a socket async call and if so, do whatever I/O we need to // do before invoking the delegate. Il2CppDelegate* delegate = asyncResult->async_delegate; const bool isSocketAsyncCall = IsSocketAsyncCall(delegate); if (isSocketAsyncCall) HandleSocketAsyncOperation(asyncResult); // Invoke delegate. Il2CppAsyncCall* asyncCall = asyncResult->object_data; Il2CppException* exception = NULL; uint32_t argsGCHandle = (uint32_t)((uintptr_t)asyncResult->data); Il2CppArray* args = (Il2CppArray*)gc::GCHandle::GetTarget(argsGCHandle); const uint8_t paramsCount = delegate->method->parameters_count; uint8_t byRefArgsCount = 0; for (uint8_t i = 0; i < paramsCount; ++i) { const Il2CppType* paramType = (Il2CppType*)delegate->method->parameters[i].parameter_type; if (paramType->byref) ++byRefArgsCount; } void** byRefArgs = 0; if (byRefArgsCount > 0) { asyncCall->out_args = vm::Array::New(il2cpp_defaults.object_class, byRefArgsCount); byRefArgs = (void**)il2cpp_array_addr(asyncCall->out_args, Il2CppObject*, 0); } void** argsPtr = (void**)il2cpp_array_addr(args, Il2CppObject*, 0); void** params = (void**)IL2CPP_MALLOC(paramsCount * sizeof(void*)); int byRefIndex = 0; for (uint8_t i = 0; i < paramsCount; ++i) { Il2CppType* paramType = (Il2CppType*)delegate->method->parameters[i].parameter_type; const Il2CppClass* paramClass = il2cpp_class_from_type(paramType); const bool isValueType = il2cpp_class_is_valuetype(paramClass); if (paramType->byref) { if (isValueType) { // Value types are always boxed byRefArgs[byRefIndex] = il2cpp_object_unbox((Il2CppObject*)argsPtr[i]); params[i] = byRefArgs[byRefIndex++]; } else { byRefArgs[byRefIndex] = argsPtr[i]; params[i] = &byRefArgs[byRefIndex++]; } } else { params[i] = isValueType ? il2cpp_object_unbox((Il2CppObject*)argsPtr[i]) // Value types are always boxed : argsPtr[i]; } } Il2CppObject* result = il2cpp_runtime_invoke(delegate->method, delegate->target, params, &exception); IL2CPP_FREE(params); gc::GCHandle::Free(argsGCHandle); // Store result. asyncCall->res = result; #if !NET_4_0 asyncCall->msg = exception; #else asyncCall->msg = (Il2CppMethodMessage*)exception; #endif os::Atomic::MemoryBarrier(); asyncResult->completed = true; // Invoke callback, if we have one. Il2CppDelegate* asyncCallback = asyncCall->cb_target; if (asyncCallback) { void* args[1] = { asyncResult }; il2cpp_runtime_invoke(asyncCallback->method, asyncCallback->target, args, &exception); #if !NET_4_0 asyncCall->msg = exception; #else asyncCall->msg = (Il2CppMethodMessage*)exception; #endif } // Signal wait handle, if there's one. il2cpp_monitor_enter(&asyncResult->base); if (asyncResult->handle) { os::Handle* osHandle = vm::WaitHandle::GetPlatformHandle(asyncResult->handle); osHandle->Signal(); } il2cpp_monitor_exit(&asyncResult->base); } } static void WorkerThreadEntryPoint(void* data) { ThreadPoolCompartment* compartment = reinterpret_cast(data); Il2CppThread* managedThread = NULL; // Do work. try { // Properly attach us to the VM and mark us as a background // worker thread. managedThread = vm::Thread::Attach(il2cpp_domain_get()); uint32_t handle = gc::GCHandle::New((Il2CppObject*)managedThread, true); vm::Thread::SetState(managedThread, kThreadStateBackground); managedThread->GetInternalThread()->threadpool_thread = true; int threadCount = compartment->AttachThread(managedThread); // Configure OS thread. char name[2048]; sprintf(name, "%s Thread #%i", compartment->compartmentName, threadCount - 1); managedThread->GetInternalThread()->handle->SetName(name); managedThread->GetInternalThread()->handle->SetPriority(os::kThreadPriorityLow); managedThread->GetInternalThread()->handle->SetCleanupFunction(&FreeThreadHandle, (void*)(uintptr_t)handle); compartment->WorkerThreadRunLoop(); } catch (Thread::NativeThreadAbortException) { // Nothing to do. Runtime cleanup asked us to exit. } catch (Il2CppExceptionWrapper e) { // Only eat a ThreadAbortException, as it may have been thrown by the runtime // when there was managed code on the stack, but that managed code exited already. if (strcmp(e.ex->klass->name, "ThreadAbortException") != 0) throw; } // Clean up. if (managedThread) { compartment->DetachThread(managedThread); vm::Thread::Detach(managedThread); } } void ThreadPool::Initialize() { #if NET_4_0 NOT_SUPPORTED_IL2CPP(ThreadPool::Initialize, "vm::ThreadPool is not supported in .NET 4.5, use threadpool-ms instead"); #else g_SocketPollingThread = new SocketPollingThread(); g_ThreadPoolCompartments[kWorkerThreadPool] = new ThreadPoolCompartment(); g_ThreadPoolCompartments[kAsyncIOPool] = new ThreadPoolCompartment(); g_ThreadPoolCompartments[kWorkerThreadPool]->compartmentName = "Worker Pool"; g_ThreadPoolCompartments[kAsyncIOPool]->compartmentName = "Async I/O Pool"; int numCores = os::Environment::GetProcessorCount(); g_ThreadPoolCompartments[kWorkerThreadPool]->minThreads = numCores; g_ThreadPoolCompartments[kWorkerThreadPool]->maxThreads = 20 + THREADS_PER_CORE * numCores; g_ThreadPoolCompartments[kAsyncIOPool]->minThreads = g_ThreadPoolCompartments[kWorkerThreadPool]->minThreads; g_ThreadPoolCompartments[kAsyncIOPool]->maxThreads = g_ThreadPoolCompartments[kWorkerThreadPool]->maxThreads; #endif } void ThreadPool::Shutdown() { #if NET_4_0 NOT_SUPPORTED_IL2CPP(ThreadPool::Shutdown, "vm::ThreadPool is not supported in .NET 4.5, use threadpool-ms instead"); #else g_SocketPollingThread->Terminate(); // avoid cleaning up until we properly handle race condition from other threads queueing jobs // delete g_SocketPollingThread; // g_SocketPollingThread = NULL; #endif } ThreadPool::Configuration ThreadPool::GetConfiguration() { #if NET_4_0 NOT_SUPPORTED_IL2CPP(ThreadPool::GetConfiguration, "vm::ThreadPool is not supported in .NET 4.5, use threadpool-ms instead"); IL2CPP_UNREACHABLE; return Configuration(); #else Configuration configuration; configuration.availableThreads = g_ThreadPoolCompartments[kWorkerThreadPool]->numIdleThreads; configuration.availableAsyncIOThreads = g_ThreadPoolCompartments[kAsyncIOPool]->numIdleThreads; configuration.minThreads = g_ThreadPoolCompartments[kWorkerThreadPool]->minThreads; configuration.maxThreads = g_ThreadPoolCompartments[kWorkerThreadPool]->maxThreads; configuration.minAsyncIOThreads = g_ThreadPoolCompartments[kAsyncIOPool]->minThreads; configuration.maxAsyncIOThreads = g_ThreadPoolCompartments[kAsyncIOPool]->maxThreads; return configuration; #endif } void ThreadPool::SetConfiguration(const Configuration& configuration) { #if NET_4_0 NOT_SUPPORTED_IL2CPP(ThreadPool::SetConfiguration, "vm::ThreadPool is not supported in .NET 4.5, use threadpool-ms instead"); #else IL2CPP_ASSERT(configuration.maxThreads >= configuration.minThreads && "Invalid configuration"); IL2CPP_ASSERT(configuration.maxAsyncIOThreads >= configuration.minAsyncIOThreads && "Invalid configuration"); IL2CPP_ASSERT(configuration.minThreads > 0 && "Invalid configuration"); IL2CPP_ASSERT(configuration.minAsyncIOThreads > 0 && "Invalid configuration"); IL2CPP_ASSERT(configuration.maxThreads > 0 && "Invalid configuration"); IL2CPP_ASSERT(configuration.maxAsyncIOThreads > 0 && "Invalid configuration"); g_ThreadPoolCompartments[kWorkerThreadPool]->minThreads = configuration.minThreads; g_ThreadPoolCompartments[kWorkerThreadPool]->maxThreads = configuration.maxThreads; g_ThreadPoolCompartments[kAsyncIOPool]->minThreads = configuration.minAsyncIOThreads; g_ThreadPoolCompartments[kAsyncIOPool]->maxThreads = configuration.maxAsyncIOThreads; // Get our worker threads to respond and exit, if necessary. // The method here isn't very smart and in fact won't even work reliably as idle worker // threads will steal the signal from threads that are currently busy. g_ThreadPoolCompartments[kWorkerThreadPool]->SignalAllThreads(); g_ThreadPoolCompartments[kAsyncIOPool]->SignalAllThreads(); #endif } Il2CppAsyncResult* ThreadPool::Queue(Il2CppDelegate* delegate, void** params, Il2CppDelegate* asyncCallback, Il2CppObject* state) { #if NET_4_0 NOT_SUPPORTED_IL2CPP(ThreadPool::Queue, "vm::ThreadPool is not supported in .NET 4.5, use threadpool-ms instead"); IL2CPP_UNREACHABLE; return NULL; #else // Create AsyncCall. Il2CppAsyncCall* asyncCall = (Il2CppAsyncCall*)il2cpp::vm::Object::New(il2cpp_defaults.async_call_class); asyncCall->cb_target = asyncCallback; asyncCall->state = state; // Copy arguments. const uint8_t parametersCount = delegate->method->parameters_count; IL2CPP_ASSERT(!params[parametersCount] && "Expecting NULL as last element of the params array!"); Il2CppArray* args = vm::Array::New(il2cpp_defaults.object_class, parametersCount); for (uint8_t i = 0; i < parametersCount; ++i) il2cpp_array_setref(args, i, params[i]); // Create AsyncResult. Il2CppAsyncResult* asyncResult = (Il2CppAsyncResult*)il2cpp::vm::Object::New(il2cpp_defaults.asyncresult_class); asyncResult->async_delegate = delegate; // NOTE: we store a GC handle here because .data is an IntPtr on the managed side and it won't be scanned by the GC. asyncResult->data = (void*)(uintptr_t)gc::GCHandle::New((Il2CppObject*)args, true); asyncResult->object_data = asyncCall; asyncResult->async_state = state; // See which compartment we should process this request with and whether we // need to first pipe it through the socket polling stage. if (IsProcessAsyncCall(delegate)) { NOT_SUPPORTED_IL2CPP(AsyncReadHandler, "Async Process operations are not supported by Il2Cpp"); } else if (IsSocketAsyncCall(delegate)) { Il2CppSocketAsyncResult* socketAsyncResult = GetSocketAsyncResult(asyncResult); socketAsyncResult->ares = asyncResult; // Apparently, using poll/WSAPoll to listen for connect() isn't reliable, so // we bypass the polling stage in that case. // Also, Mono has some AIO_OP_xxx operations that are only defined in C# and are not // meant to go through the polling stage. if ((socketAsyncResult->operation == AIO_OP_CONNECT && socketAsyncResult->blocking) || !IsSocketAsyncOperation(asyncResult)) { g_ThreadPoolCompartments[kAsyncIOPool]->QueueWorkItem(asyncResult); } else { // Give it to polling thread. SpawnSocketPollingThreadIfNeeded(); g_SocketPollingThread->QueueRequest(asyncResult); } } else if (IsFileStreamAsyncCall(delegate)) { g_ThreadPoolCompartments[kAsyncIOPool]->QueueWorkItem(asyncResult); } else { g_ThreadPoolCompartments[kWorkerThreadPool]->QueueWorkItem(asyncResult); } return asyncResult; #endif } Il2CppObject* ThreadPool::Wait(Il2CppAsyncResult* asyncResult, void** outArgs) { #if NET_4_0 NOT_SUPPORTED_IL2CPP(ThreadPool::Wait, "vm::ThreadPool is not supported in .NET 4.5, use threadpool-ms instead"); IL2CPP_UNREACHABLE; return NULL; #else // Need lock already here to ensure only a single call to EndInvoke() gets to be the first one. il2cpp_monitor_enter(&asyncResult->base); // Throw if this result has already been waited on. if (asyncResult->endinvoke_called) { il2cpp_monitor_exit(&asyncResult->base); Exception::Raise(Exception::GetInvalidOperationException ("Cannot call EndInvoke() repeatedly or concurrently on the same AsyncResult!")); } asyncResult->endinvoke_called = 1; // Wait if the AsyncResult hasn't yet been processed. if (!asyncResult->completed) { if (!asyncResult->handle) asyncResult->handle = WaitHandle::NewManualResetEvent(false); os::Handle* osHandle = WaitHandle::GetPlatformHandle(asyncResult->handle); il2cpp_monitor_exit(&asyncResult->base); osHandle->Wait(); } else il2cpp_monitor_exit(&asyncResult->base); // Raise exception now if the delegate threw while we were running it on // the worker thread. Il2CppAsyncCall* asyncCall = asyncResult->object_data; if (asyncCall->msg != NULL) il2cpp_raise_exception((Il2CppException*)asyncCall->msg); // Copy out arguments. if (asyncCall->out_args != NULL) { void** outArgsPtr = (void**)il2cpp_array_addr(asyncCall->out_args, Il2CppObject*, 0); Il2CppDelegate* delegate = asyncResult->async_delegate; const uint8_t paramsCount = delegate->method->parameters_count; uint8_t index = 0; for (uint8_t i = 0; i < paramsCount; ++i) { Il2CppType* paramType = (Il2CppType*)delegate->method->parameters[i].parameter_type; const Il2CppClass* paramClass = il2cpp_class_from_type(paramType); if (!paramType->byref) continue; const bool isValueType = il2cpp_class_is_valuetype(paramClass); if (isValueType) { IL2CPP_ASSERT(paramClass->native_size > 0 && "EndInvoke: Invalid native_size found when trying to copy a value type in the out_args."); // NOTE(gab): in case of value types, we need to copy the data over. memcpy(outArgs[index], outArgsPtr[index], paramClass->native_size); } else { *((void**)outArgs[index]) = outArgsPtr[index]; } ++index; } } return asyncResult->object_data->res; #endif } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/ThreadPool.h ================================================ #pragma once #include "il2cpp-config.h" struct Il2CppObject; struct Il2CppDelegate; struct Il2CppAsyncResult; #if NET_4_0 /* Keep in sync with System.IOOperation in mcs/class/System/System/IOSelector.cs */ enum Il2CppIOOperation { EVENT_IN = 1 << 0, EVENT_OUT = 1 << 1, EVENT_ERR = 1 << 2, /* not in managed */ }; #endif namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API ThreadPool { public: struct Configuration { int minThreads; int maxThreads; int minAsyncIOThreads; int maxAsyncIOThreads; // These are read-only. int availableThreads; int availableAsyncIOThreads; }; #if NET_4_0 typedef struct { bool(*init)(int wakeup_pipe_fd); void(*register_fd)(int fd, int events, bool is_new); void(*remove_fd)(int fd); int(*event_wait)(void(*callback)(int fd, int events, void* user_data), void* user_data); } ThreadPoolIOBackend; #endif static void Initialize(); static void Shutdown(); /// On a thread, call the given delegate with 'params' as arguments. Upon completion, /// call 'asyncCallback'. static Il2CppAsyncResult* Queue(Il2CppDelegate* delegate, void** params, Il2CppDelegate* asyncCallback, Il2CppObject* state); /// Wait for the execution of the given asynchronous call to have completed and return /// the value returned by the delegate wrapped in the call (or null if the delegate has /// a void return type). /// NOTE: Any AsyncResult can only be waited on once! Repeated or concurrent calls to Wait() on the same AsyncResult /// will throw InvalidOperationExceptions. static Il2CppObject* Wait(Il2CppAsyncResult* asyncResult, void** outArgs); static Configuration GetConfiguration(); static void SetConfiguration(const Configuration& configuration); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/ThreadPoolMs.cpp ================================================ #if NET_4_0 #include "il2cpp-api.h" #include "utils/dynamic_array.h" #include "vm/ThreadPoolMs.h" #include "vm/Domain.h" #include "vm/Array.h" #include "vm/Object.h" #include "vm/Runtime.h" #include "os/Atomic.h" #include "gc/WriteBarrier.h" #include "mono/ThreadPool/threadpool-ms.h" namespace il2cpp { namespace vm { Il2CppAsyncResult* ThreadPoolMs::DelegateBeginInvoke(Il2CppDelegate* delegate, void** params, Il2CppDelegate* asyncCallback, Il2CppObject* state) { int numParams = delegate->method->parameters_count; il2cpp::utils::dynamic_array newParams(numParams + 2); for (int i = 0; i < numParams; ++i) newParams[i] = params[i]; newParams[numParams] = asyncCallback; newParams[numParams + 1] = state; return threadpool_ms_begin_invoke(il2cpp::vm::Domain::GetCurrent(), (Il2CppObject*)delegate, const_cast(delegate->method), newParams.data()); } Il2CppObject* ThreadPoolMs::DelegateEndInvoke(Il2CppAsyncResult* asyncResult, void **out_args) { Il2CppArray *arrayOutArgs; Il2CppObject *exc, *retVal; retVal = threadpool_ms_end_invoke(asyncResult, &arrayOutArgs, &exc); if (exc) il2cpp_raise_exception((Il2CppException*)exc); if (out_args) { const MethodInfo *method = asyncResult->async_delegate->method; void** outArgsPtr = (void**)il2cpp_array_addr(arrayOutArgs, Il2CppObject*, 0); for (int i = 0; i < arrayOutArgs->max_length; ++i) { const Il2CppType* paramType = method->parameters[i].parameter_type; if (!paramType->byref) continue; Il2CppClass *paramClass = il2cpp_class_from_type(paramType); if (paramClass->valuetype) { IL2CPP_ASSERT(paramClass->native_size > 0 && "EndInvoke: Invalid native_size found when trying to copy a value type in the out_args."); // NOTE(gab): in case of value types, we need to copy the data over. memcpy(out_args[i], il2cpp::vm::Object::Unbox((Il2CppObject*)outArgsPtr[i]), paramClass->native_size); } else { *((void**)out_args[i]) = outArgsPtr[i]; } } } return retVal; } Il2CppObject* ThreadPoolMs::MessageInvoke(Il2CppObject *target, Il2CppMethodMessage *msg, Il2CppObject **exc, Il2CppArray **out_args) { static Il2CppClass *object_array_klass = NULL; MethodInfo *method; Il2CppObject *ret; Il2CppArray *arr; int i, j, outarg_count = 0; method = (MethodInfo*)msg->method->method; for (i = 0; i < method->parameters_count; i++) { if (method->parameters[i].parameter_type->byref) outarg_count++; } if (!object_array_klass) { Il2CppClass *klass; klass = il2cpp_array_class_get(il2cpp_defaults.object_class, 1); IL2CPP_ASSERT(klass); os::Atomic::MemoryBarrier(); object_array_klass = klass; } arr = il2cpp_array_new(object_array_klass, outarg_count); il2cpp::gc::WriteBarrier::GenericStore(out_args, (Il2CppObject*)arr); *exc = NULL; ret = vm::Runtime::InvokeArray(method, method->declaring_type->valuetype ? il2cpp_object_unbox(target) : target, method->parameters_count > 0 ? msg->args : NULL, (Il2CppException**)exc); for (i = 0, j = 0; i < method->parameters_count; i++) { if (method->parameters[i].parameter_type->byref) { Il2CppObject* arg; arg = (Il2CppObject*)il2cpp_array_get(msg->args, void*, i); il2cpp_array_setref(*out_args, j, arg); j++; } } return ret; } } /* namespace vm */ } /* namespace il2cpp */ #endif ================================================ FILE: unity_decoder/libil2cpp/vm/ThreadPoolMs.h ================================================ #pragma once #if NET_4_0 #include "il2cpp-config.h" #include "object-internals.h" #include "class-internals.h" namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API ThreadPoolMs { public: static Il2CppAsyncResult* DelegateBeginInvoke(Il2CppDelegate* delegate, void** params, Il2CppDelegate* asyncCallback, Il2CppObject* state); static Il2CppObject* DelegateEndInvoke(Il2CppAsyncResult* asyncResult, void **out_args); static Il2CppObject* MessageInvoke(Il2CppObject *target, Il2CppMethodMessage *msg, Il2CppObject **exc, Il2CppArray **out_args); }; } /* namespace vm */ } /* namespace il2cpp */ #endif ================================================ FILE: unity_decoder/libil2cpp/vm/Type.cpp ================================================ #include "il2cpp-config.h" #include #include #include #include #include "utils/StringUtils.h" #include "vm/Assembly.h" #include "vm/AssemblyName.h" #include "vm/Class.h" #include "vm/GenericClass.h" #include "vm/GenericContainer.h" #include "vm/MetadataCache.h" #include "vm/Reflection.h" #include "vm/String.h" #include "vm/Type.h" #include "class-internals.h" #include "object-internals.h" #include "tabledefs.h" #include "vm/Array.h" static char* copy_name(const char* name) { const size_t len = strlen(name); char* cname = new char[len + 1]; strncpy(cname, name, len); cname[len] = '\0'; return cname; } namespace il2cpp { namespace vm { TypeNameParser::TypeNameParser(std::string &name, TypeNameParseInfo &info, bool is_nested) : _info(info), _is_nested(is_nested), _accept_assembly_name(true), _p(name.begin()), _end(name.end()) { } TypeNameParser::TypeNameParser(std::string::const_iterator &begin, std::string::const_iterator &end, TypeNameParseInfo &info, bool is_nested) : _info(info), _is_nested(is_nested), _accept_assembly_name(true), _p(begin), _end(end) { } bool TypeNameParser::Parse(bool acceptAssemblyName) { _accept_assembly_name = acceptAssemblyName; int32_t arity = 0; InitializeParser(); if (IsEOL()) return false; if (!ParseTypeName(arity)) return false; if (!ParseNestedTypeOptional(arity)) return false; if (!ParseTypeArgumentsOptional(arity)) return false; if (!ParsePointerModifiersOptional()) return false; if (!ParseArrayModifierOptional()) return false; if (!ParseByRefModifiersOptional()) return false; if (!ParseAssemblyNameOptional()) return false; return (_p == _end) || _is_nested; } bool TypeNameParser::ParseAssembly() { InitializeParser(); if (IsEOL()) return false; if (!ParseAssemblyName()) return false; return true; } bool TypeNameParser::ParseTypeName(int32_t &arity) { std::string::const_iterator begin = _p; std::string::const_iterator last_dot = _end; while (true) { ConsumeIdentifier(); if (!CurrentIs('.')) break; last_dot = _p; if (!Next()) return false; // Invalid format } if (CurrentIs('`')) { if (!Next()) return false; // Invalid format if (!ConsumeNumber(arity)) return false; // Invalid format } if (last_dot == _end) { _info._name.assign(begin, _p); } else { _info._namespace.assign(begin, last_dot); _info._name.assign(last_dot + 1, _p); } return true; } bool TypeNameParser::ParseNestedTypeOptional(int32_t &arity) { while (CurrentIs('+')) { if (!Next()) return false; // Invalid format std::string::const_iterator begin = _p; ConsumeIdentifier(); if (CurrentIs('`')) { if (!Next()) return false; // Invalid format int32_t nested_arity = 0; if (!ConsumeNumber(nested_arity)) return false; // Invalid format arity += nested_arity; } _info._nested.push_back(std::string(begin, _p)); } return true; } bool TypeNameParser::ParsePointerModifiersOptional() { if (IsEOL()) return true; while (CurrentIs('*')) { _info._modifiers.push_back(-1); if (!Next(true)) break; } return true; } bool TypeNameParser::ParseByRefModifiersOptional() { if (IsEOL()) return true; if (CurrentIs('&')) { if (std::find(_info._modifiers.begin(), _info._modifiers.end(), 0) != _info._modifiers.end()) return false; // Invalid format, already marked as reference _info._modifiers.push_back(0); Next(true); } return true; } bool TypeNameParser::ParseTypeArgumentsOptional(int32_t &arity) { SkipWhites(); if (IsEOL()) return true; if (!CurrentIs('[')) return true; if (NextWillBe(']', true) || NextWillBe(',', true) || NextWillBe('*', true)) return true; if (!Next(true)) return false; // Invalid format _info._type_arguments.reserve(arity); while (true) { bool acceptAssemblyName = false; if (CurrentIs('[')) { acceptAssemblyName = true; if (!Next(true)) return false; // Invalid format } TypeNameParseInfo info; TypeNameParser parser(_p, _end, info, true); if (!parser.Parse(acceptAssemblyName)) return false; // Invalid format _p = parser._p; _info._type_arguments.push_back(info); SkipWhites(); if (IsEOL()) return false; // Invalid format if (acceptAssemblyName) { if (!CurrentIs(']')) return false; // Invalid format if (!Next(true)) return false; // Invalid format } if (CurrentIs(']')) break; if (CurrentIs(',')) { if (!Next(true)) return false; // Invalid format } else { return false; // Invalid format } } if (_info._type_arguments.size() != arity) return false; // Invalid format Next(true); return true; } bool TypeNameParser::ParseArrayModifierOptional() { SkipWhites(); if (IsEOL()) return true; if (!CurrentIs('[')) return true; if (!NextWillBe(']', true) && !NextWillBe(',', true) && !NextWillBe('*', true)) return true; if (!Next(true)) return false; // Invalid format int32_t rank = 1; while (true) { if (CurrentIs(']')) { Next(true); break; } else if (CurrentIs(',')) { ++rank; if (!Next(true)) return false; // invalid format } else if (CurrentIs('*')) { _info._modifiers.push_back(-2); if (!Next(true)) return false; // invalid format } else { return false; // invalid format } } _info._modifiers.push_back(rank); // This is to support arrays of array return ParseArrayModifierOptional(); } bool TypeNameParser::ParseAssemblyNameOptional() { if (!_accept_assembly_name) return true; if (!CurrentIs(',')) return true; if (!Next()) return false; // Invalid format SkipWhites(); return ParseAssemblyName(); } bool TypeNameParser::ParseAssemblyName() { std::string::const_iterator begin = _p; ConsumeAssemblyIdentifier(); _info._assembly_name.name.assign(begin, _p); SkipWhites(); ParsePropertiesOptional(); return true; } bool TypeNameParser::ParsePropertiesOptional() { while (CurrentIs(',')) { if (!Next(true)) return false; // Invalid format std::string::const_iterator begin = _p; ConsumePropertyIdentifier(); std::string propertyName(begin, _p); if (!CurrentIs('=')) return false; if (!Next()) return false; // Invalid format begin = _p; ConsumePropertyValue(); std::string propertyValue(begin, _p); if (propertyName == "Version") { if (!ParseVersion(propertyValue, _info._assembly_name.major, _info._assembly_name.minor, _info._assembly_name.build, _info._assembly_name.revision)) return false; } else if (propertyName == "PublicKey") { if (propertyValue != "null") _info._assembly_name.public_key = propertyValue; } else if (propertyName == "PublicKeyToken") { if (propertyValue != "null") { if ((kPublicKeyTokenLength - 1) != propertyValue.size()) return false; strncpy(_info._assembly_name.public_key_token, propertyValue.c_str(), kPublicKeyTokenLength); } } else if (propertyName == "Culture") { _info._assembly_name.culture = propertyValue; } else { return false; } } return true; } bool TypeNameParser::ParseVersion(const std::string& version, uint16_t& major, uint16_t& minor, uint16_t& build, uint16_t& revision) { size_t start = 0; size_t index = version.find('.'); if (-1 == index) return false; std::string component = version.substr(start, index - start); major = atoi(component.c_str()); start = index + 1; index = version.find('.', start); if (-1 == index) return false; component = version.substr(start, index - start); minor = atoi(component.c_str()); start = index + 1; index = version.find('.', start); if (-1 == index) return false; component = version.substr(start, index - start); build = atoi(component.c_str()); start = index + 1; component = version.substr(start, version.size() - start); revision = atoi(component.c_str()); return true; } bool TypeNameParser::NextWillBe(char v, bool skipWhites) const { if (IsEOL()) return false; int32_t i = 1; if (skipWhites) { if ((*(_p + i) == ' ') || (*(_p + i) == '\t')) ++i; if ((_p + i) >= _end) return false; } return *(_p + i) == v; } bool TypeNameParser::ConsumeNumber(int32_t &value) { if (!isdigit(*_p)) return false; std::string::const_iterator begin = _p; while (isdigit(*_p)) { if (!Next()) break; } value = (int32_t)strtol(&(*begin), NULL, 10); return true; } void TypeNameParser::ConsumeAssemblyIdentifier() { do { switch (*_p) { case ',': case '+': case '&': case '*': case '[': case ']': case '=': case '"': case '`': return; case '\\': Next(); break; } } while (Next()); } void TypeNameParser::ConsumePropertyIdentifier() { do { switch (*_p) { case '=': return; } } while (Next()); } void TypeNameParser::ConsumePropertyValue() { do { switch (*_p) { case ',': case ']': return; } } while (Next()); } void TypeNameParser::ConsumeIdentifier() { do { switch (*_p) { case ',': case '+': case '&': case '*': case '[': case ']': case '.': case '=': case '"': case '`': return; case '\\': Next(); break; } } while (Next()); } void TypeNameParser::InitializeParser() { SkipWhites(); } void TypeNameParser::SkipWhites() { while ((CurrentIs(' ') || CurrentIs('\t')) && !IsEOL()) ++_p; } TypeNameParseInfo::TypeNameParseInfo() { } TypeNameParseInfo::~TypeNameParseInfo() { _type_arguments.clear(); _modifiers.clear(); _nested.clear(); } int Type::GetType(const Il2CppType *type) { return type->type; } void Type::GetNameInternal(std::string &str, const Il2CppType *type, Il2CppTypeNameFormat format, bool is_nested) { switch (type->type) { case IL2CPP_TYPE_ARRAY: { Il2CppClass* arrayClass = Class::FromIl2CppType(type); Il2CppClass* elementClass = Class::GetElementClass(arrayClass); Type::GetNameInternal( str, elementClass->byval_arg, format == IL2CPP_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ? IL2CPP_TYPE_NAME_FORMAT_FULL_NAME : format, false); str += '['; if (arrayClass->rank == 1) str += '*'; for (int32_t i = 1; i < arrayClass->rank; i++) str += ','; str += ']'; if (type->byref) str += '&'; if (format == IL2CPP_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) { const Il2CppAssembly *ta = MetadataCache::GetAssemblyFromIndex(elementClass->image->assemblyIndex); str += ", " + vm::AssemblyName::AssemblyNameToString(ta->aname); } break; } case IL2CPP_TYPE_SZARRAY: { Il2CppClass* elementClass = Class::FromIl2CppType(type->data.type); Type::GetNameInternal( str, elementClass->byval_arg, format == IL2CPP_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ? IL2CPP_TYPE_NAME_FORMAT_FULL_NAME : format, false); str += "[]"; if (type->byref) str += '&'; if (format == IL2CPP_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) { const Il2CppAssembly *ta = MetadataCache::GetAssemblyFromIndex(elementClass->image->assemblyIndex); str += ", " + vm::AssemblyName::AssemblyNameToString(ta->aname); } break; } case IL2CPP_TYPE_PTR: { Type::GetNameInternal( str, type->data.type, format == IL2CPP_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ? IL2CPP_TYPE_NAME_FORMAT_FULL_NAME : format, false); str += '*'; if (type->byref) str += '&'; if (format == IL2CPP_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) { const Il2CppAssembly *ta = MetadataCache::GetAssemblyFromIndex(Class::FromIl2CppType(type->data.type)->image->assemblyIndex); str += ", " + vm::AssemblyName::AssemblyNameToString(ta->aname); } break; } case IL2CPP_TYPE_VAR: case IL2CPP_TYPE_MVAR: str += MetadataCache::GetStringFromIndex(Type::GetGenericParameter(type)->nameIndex); if (type->byref) str += '&'; break; default: { Il2CppClass *klass = Class::FromIl2CppType(type); Class::Init(klass); Il2CppClass* declaringType = Class::GetDeclaringType(klass); if (declaringType) { Type::GetNameInternal(str, declaringType->byval_arg, format, true); str += (format == IL2CPP_TYPE_NAME_FORMAT_IL ? '.' : '+'); } else if (*klass->namespaze) { str += klass->namespaze; str += '.'; } if (format == IL2CPP_TYPE_NAME_FORMAT_IL) { const char *s = strchr(klass->name, '`'); str += (s ? std::string(klass->name, s) : klass->name); } else str += klass->name; if (is_nested) break; if (klass->generic_class) { Il2CppGenericClass *gclass = klass->generic_class; const Il2CppGenericInst *inst = gclass->context.class_inst; Il2CppTypeNameFormat nested_format; nested_format = format == IL2CPP_TYPE_NAME_FORMAT_FULL_NAME ? IL2CPP_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format; str += (format == IL2CPP_TYPE_NAME_FORMAT_IL ? '<' : '['); for (uint32_t i = 0; i < inst->type_argc; i++) { const Il2CppType *t = inst->type_argv[i]; if (i) str += ','; if ((nested_format == IL2CPP_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) && (t->type != IL2CPP_TYPE_VAR) && (type->type != IL2CPP_TYPE_MVAR)) str += '['; Type::GetNameInternal(str, inst->type_argv[i], nested_format, false); if ((nested_format == IL2CPP_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) && (t->type != IL2CPP_TYPE_VAR) && (type->type != IL2CPP_TYPE_MVAR)) str += ']'; } str += (format == IL2CPP_TYPE_NAME_FORMAT_IL ? '>' : ']'); } else if (Class::IsGeneric(klass) && (format != IL2CPP_TYPE_NAME_FORMAT_FULL_NAME) && (format != IL2CPP_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) { const Il2CppGenericContainer* container = Class::GetGenericContainer(klass); str += (format == IL2CPP_TYPE_NAME_FORMAT_IL ? '<' : '['); for (int32_t i = 0; i < container->type_argc; i++) { if (i) str += ','; str += MetadataCache::GetStringFromIndex(GenericContainer::GetGenericParameter(container, i)->nameIndex); } str += (format == IL2CPP_TYPE_NAME_FORMAT_IL ? '>' : ']'); } if (type->byref) str += '&'; if ((format == IL2CPP_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) && (type->type != IL2CPP_TYPE_VAR) && (type->type != IL2CPP_TYPE_MVAR)) { const Il2CppAssembly *ta = MetadataCache::GetAssemblyFromIndex(klass->image->assemblyIndex); str += ", " + vm::AssemblyName::AssemblyNameToString(ta->aname); } break; } } } std::string Type::GetName(const Il2CppType *type, Il2CppTypeNameFormat format) { std::string str; Type::GetNameInternal(str, type, format, false); return str; } Il2CppClass* Type::GetClassOrElementClass(const Il2CppType *type) { // This is a weird function to mimic old mono behaviour. // We incorrectly used the analogous mono function in Unity. // Expectations: Return class if type is not an array. Return element type if it is an array. if (type->type == IL2CPP_TYPE_ARRAY) return Class::FromIl2CppType(type->data.array->etype); if (type->type == IL2CPP_TYPE_SZARRAY) return Class::FromIl2CppType(type->data.type); // IL2CPP_TYPE_SZARRAY stores element class in klass return MetadataCache::GetTypeInfoFromTypeDefinitionIndex(type->data.klassIndex); } const Il2CppType* Type::GetUnderlyingType(const Il2CppType *type) { if (type->type == IL2CPP_TYPE_VALUETYPE && MetadataCache::GetTypeInfoFromTypeDefinitionIndex(type->data.klassIndex)->enumtype && !type->byref) return Class::GetEnumBaseType(MetadataCache::GetTypeInfoFromTypeDefinitionIndex(type->data.klassIndex)); if (IsGenericInstance(type)) { Il2CppClass* definition = GenericClass::GetTypeDefinition(type->data.generic_class); if (definition != NULL && definition->enumtype && !type->byref) return Class::GetEnumBaseType(definition); } return type; } bool Type::IsGenericInstance(const Il2CppType* type) { return type->type == IL2CPP_TYPE_GENERICINST; } Il2CppReflectionType* Type::GetDeclaringType(const Il2CppType* type) { Il2CppClass *typeInfo = NULL; if (type->byref) return NULL; if (type->type == IL2CPP_TYPE_VAR || type->type == IL2CPP_TYPE_MVAR) { const Il2CppGenericParameter* genericParameter = GetGenericParameter(type); const Il2CppGenericContainer* container = MetadataCache::GetGenericContainerFromIndex(genericParameter->ownerIndex); typeInfo = GenericContainer::GetDeclaringType(container); } else { typeInfo = Class::GetDeclaringType(Class::FromIl2CppType(type)); } return typeInfo ? Reflection::GetTypeObject(typeInfo->byval_arg) : NULL; } Il2CppArray* Type::GetGenericArgumentsInternal(Il2CppReflectionType* type, bool runtimeArray) { Il2CppArray *res; Il2CppClass *klass, *pklass; klass = Class::FromIl2CppType(type->type); #if NET_4_0 Il2CppClass *arrType = runtimeArray ? il2cpp_defaults.runtimetype_class : il2cpp_defaults.systemtype_class; #else Il2CppClass *arrType = il2cpp_defaults.systemtype_class; #endif if (Class::IsGeneric(klass)) { const Il2CppGenericContainer *container = MetadataCache::GetGenericContainerFromIndex(klass->genericContainerIndex); res = Array::New(arrType, container->type_argc); for (int32_t i = 0; i < container->type_argc; ++i) { pklass = Class::FromGenericParameter(GenericContainer::GetGenericParameter(container, i)); il2cpp_array_setref(res, i, Reflection::GetTypeObject(pklass->byval_arg)); } } else if (klass->generic_class) { const Il2CppGenericInst *inst = klass->generic_class->context.class_inst; res = Array::New(arrType, inst->type_argc); for (uint32_t i = 0; i < inst->type_argc; ++i) il2cpp_array_setref(res, i, Reflection::GetTypeObject(inst->type_argv[i])); } else { res = Array::New(arrType, 0); } return res; } uint32_t Type::GetToken(const Il2CppType *type) { if (IsGenericInstance(type)) return GenericClass::GetTypeDefinition(type->data.generic_class)->token; return GetClass(type)->token; } bool Type::IsReference(const Il2CppType* type) { if (!type) return false; if (type->type == IL2CPP_TYPE_STRING || type->type == IL2CPP_TYPE_SZARRAY || type->type == IL2CPP_TYPE_CLASS || type->type == IL2CPP_TYPE_OBJECT || type->type == IL2CPP_TYPE_ARRAY) return true; if (IsGenericInstance(type) && !GenericClass::IsValueType(type->data.generic_class)) return true; return false; } bool Type::IsStruct(const Il2CppType* type) { if (type->byref) return false; if (type->type == IL2CPP_TYPE_VALUETYPE && !MetadataCache::GetTypeInfoFromTypeDefinitionIndex(type->data.klassIndex)->enumtype) return true; if (type->type == IL2CPP_TYPE_TYPEDBYREF) return true; if (IsGenericInstance(type) && GenericClass::IsValueType(type->data.generic_class) && !GenericClass::IsEnum(type->data.generic_class)) return true; return false; } bool Type::GenericInstIsValuetype(const Il2CppType* type) { IL2CPP_ASSERT(IsGenericInstance(type)); return GenericClass::IsValueType(type->data.generic_class); } bool Type::IsEnum(const Il2CppType *type) { if (type->type != IL2CPP_TYPE_VALUETYPE) return false; Il2CppClass* klass = GetClass(type); return klass->enumtype; } bool Type::IsValueType(const Il2CppType *type) { Il2CppClass* klass = GetClass(type); return klass->valuetype; } bool Type::IsEmptyType(const Il2CppType *type) { return IsGenericInstance(type) && type->data.generic_class->typeDefinitionIndex == kTypeIndexInvalid; } bool Type::IsSystemDBNull(const Il2CppType *type) { Il2CppClass* klass = GetClass(type); return (klass->image == il2cpp_defaults.corlib && strcmp(klass->namespaze, "System") == 0 && strcmp(klass->name, "DBNull") == 0); } bool Type::IsSystemDateTime(const Il2CppType *type) { Il2CppClass* klass = GetClass(type); return (klass->image == il2cpp_defaults.corlib && strcmp(klass->namespaze, "System") == 0 && strcmp(klass->name, "DateTime") == 0); } bool Type::IsSystemDecimal(const Il2CppType *type) { Il2CppClass* klass = GetClass(type); return (klass->image == il2cpp_defaults.corlib && strcmp(klass->namespaze, "System") == 0 && strcmp(klass->name, "Decimal") == 0); } Il2CppClass* Type::GetClass(const Il2CppType *type) { IL2CPP_ASSERT(type->type == IL2CPP_TYPE_CLASS || type->type == IL2CPP_TYPE_VALUETYPE); return MetadataCache::GetTypeInfoFromTypeDefinitionIndex(type->data.klassIndex); } const Il2CppGenericParameter* Type::GetGenericParameter(const Il2CppType *type) { IL2CPP_ASSERT(type->type == IL2CPP_TYPE_VAR || type->type == IL2CPP_TYPE_MVAR); return MetadataCache::GetGenericParameterFromIndex(type->data.genericParameterIndex); } /** * Type::ConstructDelegate: * @delegate: pointer to an uninitialized delegate object * @target: target object * @addr: pointer to native code * @method: method * * Initialize a delegate and set a specific method, not the one * associated with addr. This is useful when sharing generic code. * In that case addr will most probably not be associated with the * correct instantiation of the method. */ void Type::ConstructDelegate(Il2CppDelegate* delegate, Il2CppObject* target, Il2CppMethodPointer addr, const MethodInfo* method) { IL2CPP_ASSERT(delegate); if (method) delegate->method = method; delegate->method_ptr = addr; if (target != NULL) IL2CPP_OBJECT_SETREF(delegate, target, target); delegate->invoke_impl = method->invoker_method; //TODO:figure out if this is needed at all } Il2CppString* Type::AppendAssemblyNameIfNecessary(Il2CppString* typeName, const char* assemblyName) { if (typeName != NULL) { std::string name = utils::StringUtils::Utf16ToUtf8(utils::StringUtils::GetChars(typeName)); il2cpp::vm::TypeNameParseInfo info; il2cpp::vm::TypeNameParser parser(name, info, false); if (parser.Parse()) { if (info.assembly_name().name.empty()) { std::string assemblyQualifiedName; assemblyQualifiedName = name + ", " + assemblyName; return vm::String::New(assemblyQualifiedName.c_str()); } } } return typeName; } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/Type.h ================================================ #pragma once #include #include #include #include #include #include "il2cpp-config.h" #include "class-internals.h" #ifdef major # undef major # undef minor #endif struct FieldInfo; struct Il2CppType; struct Il2CppClass; struct Il2CppGenericParameter; struct Il2CppString; namespace il2cpp { namespace vm { static const int32_t kPublicKeyTokenLength = 17; class TypeNameParseInfo { public: struct AssemblyName { std::string name; std::string culture; std::string hash_value; std::string public_key; char public_key_token[kPublicKeyTokenLength]; uint32_t hash_alg; uint32_t hash_len; uint32_t flags; uint16_t major; uint16_t minor; uint16_t build; uint16_t revision; AssemblyName() : hash_alg(0), hash_len(0), flags(0), major(0), minor(0), build(0), revision(0) { memset(public_key_token, 0, kPublicKeyTokenLength); } }; TypeNameParseInfo(); ~TypeNameParseInfo(); inline const std::string &ns() const { return _namespace; } inline const std::string &name() const { return _name; } inline const AssemblyName &assembly_name() const { return _assembly_name; } inline const std::vector &modifiers() const { return _modifiers; } inline const std::vector &type_arguments() const { return _type_arguments; } inline const std::vector &nested() const { return _nested; } inline bool is_byref() const { return std::find(_modifiers.begin(), _modifiers.end(), 0) != _modifiers.end(); } inline bool has_generic_arguments() const { return _type_arguments.size() > 0; } inline bool is_pointer() const { return std::find(_modifiers.begin(), _modifiers.end(), -1) != _modifiers.end(); } inline bool is_bounded() const { return std::find(_modifiers.begin(), _modifiers.end(), -2) != _modifiers.end(); } inline bool is_array() const { std::vector::const_iterator it = _modifiers.begin(); while (it != _modifiers.end()) { if (*it > 0) return true; ++it; } return false; } private: std::string _namespace; std::string _name; AssemblyName _assembly_name; std::vector _modifiers; std::vector _type_arguments; std::vector _nested; friend class TypeNameParser; }; class TypeNameParser { public: TypeNameParser(std::string &name, TypeNameParseInfo &info, bool is_nested); TypeNameParser(std::string::const_iterator &begin, std::string::const_iterator &end, TypeNameParseInfo &info, bool is_nested); bool Parse(bool acceptAssemblyName = true); bool ParseAssembly(); private: inline bool IsEOL() const { return _p >= _end; } inline bool CurrentIs(char v) const { if (IsEOL()) return false; return *_p == v; } inline bool Next(bool skipWhites = false) { ++_p; if (skipWhites) SkipWhites(); return !IsEOL(); } bool NextWillBe(char v, bool skipWhites = false) const; void InitializeParser(); void SkipWhites(); void ConsumeIdentifier(); void ConsumeAssemblyIdentifier(); void ConsumePropertyIdentifier(); void ConsumePropertyValue(); bool ConsumeNumber(int32_t &value); bool ParseTypeName(int32_t &arity); bool ParseNestedTypeOptional(int32_t &arity); bool ParseTypeArgumentsOptional(int32_t &arity); bool ParseAssemblyNameOptional(); bool ParseAssemblyName(); bool ParsePropertiesOptional(); bool ParseArrayModifierOptional(); bool ParsePointerModifiersOptional(); bool ParseByRefModifiersOptional(); static bool ParseVersion(const std::string& version, uint16_t& major, uint16_t& minor, uint16_t& build, uint16_t& revision); TypeNameParseInfo &_info; bool _is_nested; bool _accept_assembly_name; std::string::const_iterator _p; std::string::const_iterator _end; }; class LIBIL2CPP_CODEGEN_API Type { public: // exported static std::string GetName(const Il2CppType *type, Il2CppTypeNameFormat format); static int GetType(const Il2CppType *type); static Il2CppClass* GetClassOrElementClass(const Il2CppType *type); static const Il2CppType* GetUnderlyingType(const Il2CppType *type); static uint32_t GetToken(const Il2CppType *type); static bool IsGenericInstance(const Il2CppType *type); static Il2CppReflectionType* GetDeclaringType(const Il2CppType* type); static Il2CppArray* GetGenericArgumentsInternal(Il2CppReflectionType* type, bool runtimeArray); public: // internal static void GetNameInternal(std::string &oss, const Il2CppType *type, Il2CppTypeNameFormat format, bool is_nested); static bool IsReference(const Il2CppType* type); static bool IsStruct(const Il2CppType* type); static bool GenericInstIsValuetype(const Il2CppType* type); static bool IsEnum(const Il2CppType *type); static bool IsValueType(const Il2CppType *type); static bool IsEmptyType(const Il2CppType *type); static bool IsSystemDBNull(const Il2CppType *type); static bool IsSystemDateTime(const Il2CppType *type); static bool IsSystemDecimal(const Il2CppType *type); static Il2CppClass* GetClass(const Il2CppType *type); static const Il2CppGenericParameter* GetGenericParameter(const Il2CppType *type); static void ConstructDelegate(Il2CppDelegate* delegate, Il2CppObject* target, Il2CppMethodPointer addr, const MethodInfo* method); static Il2CppString* AppendAssemblyNameIfNecessary(Il2CppString* typeName, const char* assemblyName); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/VisualizerHelpers.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #if _MSC_VER // These structs aren't actually used anywhere, but they are used by the VS debugger visualizer to help visualize various types namespace VisualizerHelpers { struct Il2CppRawTypeName { Il2CppClass t; }; struct Il2CppRawTypeNameWithoutDeclaringType { Il2CppClass t; }; struct Il2CppGenericParameters_DeclaringTypeHas0Parameters { Il2CppGenericContainer c; }; struct Il2CppGenericParameters_DeclaringTypeHas1Parameters { Il2CppGenericContainer c; }; struct Il2CppGenericParameters_DeclaringTypeHas2Parameters { Il2CppGenericContainer c; }; struct Il2CppGenericParameters_DeclaringTypeHas3Parameters { Il2CppGenericContainer c; }; struct Il2CppGenericParameters_DeclaringTypeHas4Parameters { Il2CppGenericContainer c; }; struct Il2CppGenericParameters_DeclaringTypeHas5Parameters { Il2CppGenericContainer c; }; struct Il2CppGenericParameters { Il2CppGenericContainer c; }; struct Il2CppGenericArguments_DeclaringTypeHas0Arguments { Il2CppGenericInst gi; }; struct Il2CppGenericArguments_DeclaringTypeHas1Arguments { Il2CppGenericInst gi; }; struct Il2CppGenericArguments_DeclaringTypeHas2Arguments { Il2CppGenericInst gi; }; struct Il2CppGenericArguments_DeclaringTypeHas3Arguments { Il2CppGenericInst gi; }; struct Il2CppGenericArguments_DeclaringTypeHas4Arguments { Il2CppGenericInst gi; }; struct Il2CppGenericArguments_DeclaringTypeHas5Arguments { Il2CppGenericInst gi; }; struct Il2CppGenericArguments { Il2CppGenericClass gi; }; struct Il2CppMethodParameters { MethodInfo m; }; struct Il2CppMethodGenericParameters { MethodInfo m; }; struct PreventLinkerFromStrippingTypesFromDebugInfo { Il2CppRawTypeName* ___rawTypeName; Il2CppRawTypeNameWithoutDeclaringType* ___rawTypeNameWithoutDeclaringType; Il2CppGenericParameters_DeclaringTypeHas0Parameters* ___genericParameters0; Il2CppGenericParameters_DeclaringTypeHas1Parameters* ___genericParameters1; Il2CppGenericParameters_DeclaringTypeHas2Parameters* ___genericParameters2; Il2CppGenericParameters_DeclaringTypeHas3Parameters* ___genericParameters3; Il2CppGenericParameters_DeclaringTypeHas4Parameters* ___genericParameters4; Il2CppGenericParameters_DeclaringTypeHas5Parameters* ___genericParameters5; Il2CppGenericParameters* ___genericParameters; Il2CppGenericArguments_DeclaringTypeHas0Arguments* ___genericArguments0; Il2CppGenericArguments_DeclaringTypeHas1Arguments* ___genericArguments1; Il2CppGenericArguments_DeclaringTypeHas2Arguments* ___genericArguments2; Il2CppGenericArguments_DeclaringTypeHas3Arguments* ___genericArguments3; Il2CppGenericArguments_DeclaringTypeHas4Arguments* ___genericArguments4; Il2CppGenericArguments_DeclaringTypeHas5Arguments* ___genericArguments5; Il2CppGenericArguments* ___genericArguments; Il2CppMethodParameters* ___methodParameters; Il2CppMethodGenericParameters* ___methodGenericParameters; }; } // We need to declare a global variable, otherwise compiler strips all type information from PDBs, and in result debugger can't visualize them extern "C" VisualizerHelpers::PreventLinkerFromStrippingTypesFromDebugInfo * ____visualizerHelpersPreventLinkerStripping = NULL; #endif ================================================ FILE: unity_decoder/libil2cpp/vm/WaitHandle.cpp ================================================ #include "il2cpp-config.h" #include "class-internals.h" #include "object-internals.h" #include "vm/WaitHandle.h" #include "vm/Class.h" #include "vm/Field.h" #include "vm/Object.h" #include "vm/Runtime.h" namespace il2cpp { namespace vm { Il2CppWaitHandle* WaitHandle::NewManualResetEvent(bool initialState) { static const MethodInfo* constructor = NULL; if (!constructor) constructor = Class::GetMethodFromName(il2cpp_defaults.manualresetevent_class, ".ctor", 1); Il2CppObject* instance = Object::New(il2cpp_defaults.manualresetevent_class); void* args[1] = { &initialState }; // NOTE: passing NULL here as Mono does, as long as the WaitHandle ctor will never throw an exception. Runtime::Invoke(constructor, instance, args, NULL); return reinterpret_cast(instance); } os::Handle* WaitHandle::GetPlatformHandle(Il2CppWaitHandle* waitHandle) { static FieldInfo *s_osHandle; static FieldInfo *s_safeHandle; if (!s_osHandle && !s_safeHandle) { #if !NET_4_0 s_osHandle = vm::Class::GetFieldFromName(il2cpp_defaults.manualresetevent_class, "os_handle"); s_safeHandle = vm::Class::GetFieldFromName(il2cpp_defaults.manualresetevent_class, "safe_wait_handle"); #else s_osHandle = vm::Class::GetFieldFromName(il2cpp_defaults.manualresetevent_class, "Handle"); s_safeHandle = vm::Class::GetFieldFromName(il2cpp_defaults.manualresetevent_class, "safeWaitHandle"); #endif } Il2CppIntPtr retval; if (s_osHandle) { vm::Field::GetValue((Il2CppObject*)waitHandle, s_osHandle, &retval); } else { Il2CppSafeHandle *sh; vm::Field::GetValue((Il2CppObject*)waitHandle, s_safeHandle, &sh); retval.m_value = sh->handle; } return static_cast(retval.m_value); } } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/WaitHandle.h ================================================ #pragma once struct Il2CppWaitHandle; namespace il2cpp { namespace os { class Handle; } } namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API WaitHandle { public: static Il2CppWaitHandle* NewManualResetEvent(bool initialState); static os::Handle* GetPlatformHandle(Il2CppWaitHandle* waitHandle); }; } /* namespace vm */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm/WindowsRuntime.cpp ================================================ #include "il2cpp-config.h" #include "metadata/GenericMetadata.h" #include "os/LibraryLoader.h" #include "os/WindowsRuntime.h" #include "utils/Il2CppHStringReference.h" #include "utils/StringUtils.h" #include "vm/Class.h" #include "vm/Exception.h" #include "vm/GenericClass.h" #include "vm/MetadataCache.h" #include "vm/WindowsRuntime.h" using namespace il2cpp::metadata; namespace il2cpp { namespace vm { Il2CppIActivationFactory* WindowsRuntime::GetActivationFactory(const utils::StringView& runtimeClassName) { utils::Il2CppHStringReference className(runtimeClassName); Il2CppIActivationFactory* factory = NULL; il2cpp_hresult_t hr = os::WindowsRuntime::GetActivationFactory(className, &factory); if (IL2CPP_HR_SUCCEEDED(hr)) return factory; if (hr != IL2CPP_REGDB_E_CLASSNOTREG) Exception::Raise(hr, false); // If GetActivationFactory doesn't find the class, we can still try to find it manually // All Windows runtime classes must be in namespaces, and that class has to be in a DLL // that is named after the namespace of a part of it. // For example, MyNamespace.MySubNamespace.MyClass can be in either // MyNamespace.MySubNamespace.dll or MyNamespace.dll IL2CPP_ASSERT(runtimeClassName.Length() > 1); size_t namespaceEnd = runtimeClassName.Length() - 1; do { namespaceEnd--; } while (namespaceEnd > 0 && runtimeClassName[namespaceEnd] != '.'); Il2CppNativeChar* nativeDll = static_cast(alloca((namespaceEnd + 5) * sizeof(Il2CppNativeChar))); memcpy(nativeDll, runtimeClassName.Str(), namespaceEnd * sizeof(Il2CppNativeChar)); while (namespaceEnd > 0) { memcpy(nativeDll + namespaceEnd, IL2CPP_NATIVE_STRING(".dll"), 4 * sizeof(Il2CppNativeChar)); nativeDll[namespaceEnd + 4] = 0; void* dynamicLibrary = os::LibraryLoader::LoadDynamicLibrary(utils::StringView(nativeDll, namespaceEnd + 4)); if (dynamicLibrary != NULL) { typedef il2cpp_hresult_t(STDCALL * DllGetActivationFactory)(Il2CppHString activatableClassId, Il2CppIActivationFactory** factory); DllGetActivationFactory dllGetActivationFactory = reinterpret_cast(os::LibraryLoader::GetFunctionPointer(dynamicLibrary, "DllGetActivationFactory")); if (dllGetActivationFactory != NULL) { hr = dllGetActivationFactory(className, &factory); if (IL2CPP_HR_SUCCEEDED(hr)) return factory; if (hr != IL2CPP_REGDB_E_CLASSNOTREG) Exception::Raise(hr, false); } } do { namespaceEnd--; } while (namespaceEnd > 0 && runtimeClassName[namespaceEnd] != '.'); } Exception::Raise(IL2CPP_REGDB_E_CLASSNOTREG, false); return NULL; } } } ================================================ FILE: unity_decoder/libil2cpp/vm/WindowsRuntime.h ================================================ #pragma once #include "il2cpp-vm-support.h" #include "os/WindowsRuntime.h" #include "vm/Exception.h" #include "utils/StringView.h" struct Il2CppIActivationFactory; namespace il2cpp { namespace vm { class LIBIL2CPP_CODEGEN_API WindowsRuntime { public: static Il2CppIActivationFactory* GetActivationFactory(const utils::StringView& runtimeClassName); static inline void CreateHStringReference(const utils::StringView& str, Il2CppHStringHeader* header, Il2CppHString* hstring) { il2cpp_hresult_t hr = os::WindowsRuntime::CreateHStringReference(str, header, hstring); IL2CPP_VM_RAISE_IF_FAILED(hr, false); } static inline Il2CppHString CreateHString(Il2CppString* str) { Il2CppHString result; il2cpp_hresult_t hr = os::WindowsRuntime::CreateHString(utils::StringView(str->chars, str->length), &result); IL2CPP_VM_RAISE_IF_FAILED(hr, false); return result; } static inline void DeleteHString(Il2CppHString hstring) { il2cpp_hresult_t hr = os::WindowsRuntime::DeleteHString(hstring); IL2CPP_VM_RAISE_IF_FAILED(hr, false); } static inline Il2CppString* HStringToManagedString(Il2CppHString hstring) { return os::WindowsRuntime::HStringToManagedString(hstring); } }; } } ================================================ FILE: unity_decoder/libil2cpp/vm-utils/BlobReader.cpp ================================================ #include "il2cpp-config.h" #include #include "BlobReader.h" #include "utils/MemoryRead.h" #include "object-internals.h" #include "il2cpp-vm-support.h" namespace il2cpp { namespace utils { int BlobReader::GetConstantValueFromBlob(Il2CppTypeEnum type, const char *blob, void *value) { int retval = 0; const char *p = blob; switch (type) { case IL2CPP_TYPE_BOOLEAN: case IL2CPP_TYPE_U1: case IL2CPP_TYPE_I1: *(uint8_t*)value = *p; break; case IL2CPP_TYPE_CHAR: *(Il2CppChar*)value = ReadChar(p); break; case IL2CPP_TYPE_U2: case IL2CPP_TYPE_I2: *(uint16_t*)value = Read16(p); break; case IL2CPP_TYPE_U4: case IL2CPP_TYPE_I4: *(uint32_t*)value = Read32(p); break; case IL2CPP_TYPE_U8: case IL2CPP_TYPE_I8: *(uint64_t*)value = Read64(p); break; case IL2CPP_TYPE_R4: *(float*)value = ReadFloat(p); break; case IL2CPP_TYPE_R8: *(double*)value = ReadDouble(p); break; case IL2CPP_TYPE_STRING: { *(void**)value = NULL; if (p != NULL) { // int32_t length followed by non-null terminated utf-8 byte stream uint32_t length = Read32(p); *(VmString**)value = IL2CPP_VM_STRING_NEW_LEN(p + sizeof(uint32_t), length); } break; } case IL2CPP_TYPE_CLASS: case IL2CPP_TYPE_OBJECT: case IL2CPP_TYPE_GENERICINST: case IL2CPP_TYPE_SZARRAY: IL2CPP_ASSERT(p == NULL); *(void**)value = NULL; break; default: retval = -1; IL2CPP_ASSERT(0); } return retval; } } /* utils */ } /* il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm-utils/BlobReader.h ================================================ #pragma once #include "../blob.h" namespace il2cpp { namespace utils { class BlobReader { public: // internal static int GetConstantValueFromBlob(Il2CppTypeEnum type, const char *blob, void *value); }; } /* utils */ } /* il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm-utils/NativeDelegateMethodCache.cpp ================================================ #include "NativeDelegateMethodCache.h" namespace il2cpp { namespace utils { il2cpp::os::FastMutex NativeDelegateMethodCache::m_CacheMutex; NativeDelegateMap NativeDelegateMethodCache::m_NativeDelegateMethods; const VmMethod* NativeDelegateMethodCache::GetNativeDelegate(Il2CppMethodPointer nativeFunctionPointer) { os::FastAutoLock lock(&m_CacheMutex); NativeDelegateMap::iterator i = m_NativeDelegateMethods.find(nativeFunctionPointer); if (i == m_NativeDelegateMethods.end()) return NULL; return i->second; } void NativeDelegateMethodCache::AddNativeDelegate(Il2CppMethodPointer nativeFunctionPointer, const VmMethod* managedMethodInfo) { os::FastAutoLock lock(&m_CacheMutex); m_NativeDelegateMethods.insert(std::make_pair(nativeFunctionPointer, managedMethodInfo)); } } // namespace utils } // namespace il2cpp ================================================ FILE: unity_decoder/libil2cpp/vm-utils/NativeDelegateMethodCache.h ================================================ #pragma once #include "il2cpp-api-types.h" #include "il2cpp-vm-support.h" #include "os/Mutex.h" #include namespace il2cpp { namespace utils { typedef std::map NativeDelegateMap; class NativeDelegateMethodCache { public: static const VmMethod* GetNativeDelegate(Il2CppMethodPointer nativeFunctionPointer); static void AddNativeDelegate(Il2CppMethodPointer nativeFunctionPointer, const VmMethod* managedMethodInfo); private: static il2cpp::os::FastMutex m_CacheMutex; static NativeDelegateMap m_NativeDelegateMethods; }; } // namespace utils } // namespace il2cpp ================================================ FILE: unity_decoder/libil2cpp/vm-utils/NativeSymbol.cpp ================================================ #include "il2cpp-config.h" #include "os/Environment.h" #include "os/File.h" #include "os/Image.h" #include "os/Initialize.h" #include "os/LibraryLoader.h" #include "os/Locale.h" #include "os/MemoryMappedFile.h" #include "os/Path.h" #include "NativeSymbol.h" #include "utils/Collections.h" #include "utils/PathUtils.h" #include "utils/Runtime.h" #include namespace il2cpp { namespace utils { #if IL2CPP_ENABLE_NATIVE_STACKTRACES static Il2CppMethodPointer MaskSpareBits(const Il2CppMethodPointer method) { return (Il2CppMethodPointer)((size_t)method & ~IL2CPP_POINTER_SPARE_BITS); } struct MethodInfoToMethodPointerConverter { Il2CppMethodPointer operator()(const MethodDefinitionKey& methodInfo) const { return MaskSpareBits(methodInfo.method); } }; typedef il2cpp::utils::collections::ArrayValueMap NativeMethodMap; static NativeMethodMap s_NativeMethods; void NativeSymbol::RegisterMethods(const std::vector& managedMethods) { s_NativeMethods.assign(managedMethods); } #pragma pack(push, p1, 4) struct SymbolInfo { uint64_t address; uint32_t length; }; #pragma pack(pop, p1) static int32_t s_SymbolCount; static SymbolInfo* s_SymbolInfos; static void* s_ImageBase; static void* LoadSymbolInfoFileFrom(const std::string& path) { int error; il2cpp::os::FileHandle* handle = il2cpp::os::File::Open(path, kFileModeOpen, kFileAccessRead, kFileShareRead, kFileOptionsNone, &error); if (error != 0) return NULL; // Note that we won't unmap this file, we'll leave it open the entire lifetime of the process. void* mappedFile = il2cpp::os::MemoryMappedFile::Map(handle); il2cpp::os::File::Close(handle, &error); IL2CPP_ASSERT(error == 0); return mappedFile; } static void* LoadSymbolInfoFile() { #if IL2CPP_TARGET_ANDROID #if defined(__i386__) std::string symbolMapFileName = "SymbolMap-x86"; #else std::string symbolMapFileName = "SymbolMap-ARMv7"; #endif #else #if !IL2CPP_CAN_USE_MULTIPLE_SYMBOL_MAPS std::string symbolMapFileName = "SymbolMap"; #elif IL2CPP_SIZEOF_VOID_P == 4 std::string symbolMapFileName = "SymbolMap-32"; #elif IL2CPP_SIZEOF_VOID_P == 8 std::string symbolMapFileName = "SymbolMap-64"; #else #error Unknown symbol map file name #endif #endif void* result = LoadSymbolInfoFileFrom(il2cpp::utils::PathUtils::Combine(il2cpp::utils::PathUtils::DirectoryName(il2cpp::os::Path::GetExecutablePath()), symbolMapFileName)); if (result != NULL) return result; return LoadSymbolInfoFileFrom(il2cpp::utils::PathUtils::Combine(utils::Runtime::GetDataDir(), symbolMapFileName)); } static void InitializeSymbolInfos() { s_ImageBase = il2cpp::os::Image::GetImageBase(); void* fileBuffer = LoadSymbolInfoFile(); if (fileBuffer == NULL) return; s_SymbolCount = *((int32_t*)fileBuffer); s_SymbolInfos = (SymbolInfo*)((uint8_t*)fileBuffer + sizeof(s_SymbolCount)); } static bool CompareEndOfSymbols(const SymbolInfo &a, const SymbolInfo &b) { return a.address + a.length < b.address + b.length; } static bool s_TriedToInitializeSymbolInfo = false; const VmMethod* NativeSymbol::GetMethodFromNativeSymbol(Il2CppMethodPointer nativeMethod) { if (!s_TriedToInitializeSymbolInfo) { // Only attempt to initialize the symbol information once. If it is not present the first time, // it likely won't be there later either. Repeated chcecking can cause performance problems. s_TriedToInitializeSymbolInfo = true; InitializeSymbolInfos(); } // address has to be above our base address if ((void*)nativeMethod < (void*)s_ImageBase) return NULL; if (s_SymbolCount > 0) { SymbolInfo* end = s_SymbolInfos + s_SymbolCount; // our 'key' could be anywhere within a symbol. Our comparison function compares the end address // of the symbols. By doing this, upper bound returns the first symbol whose end address is greater // than our 'key'. This is our symbol since our end is the first end above an interior value. SymbolInfo interiorSymbol = { (size_t)((char*)nativeMethod - (char*)s_ImageBase), 0 }; SymbolInfo* containingSymbol = std::upper_bound(s_SymbolInfos, end, interiorSymbol, &CompareEndOfSymbols); if (containingSymbol == end) return NULL; // We only include managed methods in the symbol data. A lookup for a native method might find the // previous or next managed method in the data. This will be incorrect, so check the start and the size, // to make sure the interior symbol is really within the method found in the containing symbol. if ((interiorSymbol.address != containingSymbol->address) && ((interiorSymbol.address < containingSymbol->address) || (interiorSymbol.address - containingSymbol->address > containingSymbol->length))) return NULL; nativeMethod = (Il2CppMethodPointer)((char*)s_ImageBase + containingSymbol->address); // We can't assume that the map file is aligned. // We must use the same masking/no masking logic used to insert into the data structure for the lookup. // If we don't, the find will try to look up unmasked in a table full of masked values. // do exact lookup based on the symbol start address, as that is our key NativeMethodMap::iterator iter = s_NativeMethods.find_first(MaskSpareBits(nativeMethod)); if (iter != s_NativeMethods.end()) { return IL2CPP_VM_METHOD_METADATA_FROM_INDEX(iter->isGeneric, iter->methodIndex); } } else { // get the first symbol greater than the one we want NativeMethodMap::iterator iter = s_NativeMethods.upper_bound(nativeMethod); // This will cause it to fail to pickup the last method, but we cannot do anything about it if (iter != s_NativeMethods.begin() && iter != s_NativeMethods.end()) { // go back one to get the symbol we actually want iter--; return IL2CPP_VM_METHOD_METADATA_FROM_INDEX(iter->isGeneric, iter->methodIndex); } } return NULL; } #endif } /* namespace utils */ } /* namespace il2cpp */ ================================================ FILE: unity_decoder/libil2cpp/vm-utils/NativeSymbol.h ================================================ #pragma once #include #include #include "il2cpp-vm-support.h" namespace il2cpp { namespace utils { class NativeSymbol { public: #if IL2CPP_ENABLE_NATIVE_STACKTRACES static void RegisterMethods(const std::vector& managedMethods); static const VmMethod* GetMethodFromNativeSymbol(Il2CppMethodPointer nativeMethod); #endif }; } /* namespace vm */ } /* namespace mono */ ================================================ FILE: unity_decoder/libil2cpp/vm-utils/VmStringUtils.cpp ================================================ #include "VmStringUtils.h" #include "../object-internals.h" #include "../char-conversions.h" #include "utils/Functional.h" #include "utils/StringUtils.h" #include "utils/utf8-cpp/source/utf8/unchecked.h" namespace il2cpp { namespace utils { Il2CppChar VmStringUtils::Utf16ToLower(Il2CppChar c) { const Il2CppChar kDataLowThreshold = 9423; const Il2CppChar kDataHighThreshold = 65313; if (c <= kDataLowThreshold) { c = ToLowerDataLow[c]; } else if (c >= kDataHighThreshold) { c = ToLowerDataHigh[c - kDataHighThreshold]; } return c; } bool VmStringUtils::CaseSensitiveComparer::operator()(const std::string& left, const std::string& right) const { return left == right; } bool VmStringUtils::CaseSensitiveComparer::operator()(const std::string& left, const char* right) const { return left.compare(right) == 0; } bool VmStringUtils::CaseSensitiveComparer::operator()(const char* left, const std::string& right) const { return right.compare(left) == 0; } bool VmStringUtils::CaseSensitiveComparer::operator()(const char* left, const char* right) const { return strcmp(left, right) == 0; } static inline void Utf32CharToSurrogatePair(uint32_t c, Il2CppChar(&surrogatePair)[2]) { const Il2CppChar kLeadOffset = 55232; const Il2CppChar kTrailSurrogateMin = 56320; if (c > 0xffff) { surrogatePair[0] = static_cast((c >> 10) + kLeadOffset); surrogatePair[1] = static_cast((c & 0x3ff) + kTrailSurrogateMin); } else { surrogatePair[0] = static_cast(c); surrogatePair[1] = 0; } } static inline bool Utf16CharEqualsIgnoreCase(Il2CppChar left, Il2CppChar right) { return VmStringUtils::Utf16ToLower(left) == VmStringUtils::Utf16ToLower(right); } bool VmStringUtils::CaseInsensitiveComparer::operator()(const std::string& left, const std::string& right) const { return operator()(left.c_str(), right.c_str()); } bool VmStringUtils::CaseInsensitiveComparer::operator()(const std::string& left, const char* right) const { return operator()(left.c_str(), right); } bool VmStringUtils::CaseInsensitiveComparer::operator()(const char* left, const std::string& right) const { return operator()(left, right.c_str()); } bool VmStringUtils::CaseInsensitiveComparer::operator()(const char* left, const char* right) const { #if IL2CPP_DEBUG // Invalid UTF8 strings shouldn't be passed here, so let's assert in debug mode IL2CPP_ASSERT(utf8::is_valid(left, left + strlen(left))); IL2CPP_ASSERT(utf8::is_valid(right, right + strlen(right))); #endif Il2CppChar utf16Left[2]; Il2CppChar utf16Right[2]; while (*left && *right) { Utf32CharToSurrogatePair(utf8::unchecked::next(left), utf16Left); Utf32CharToSurrogatePair(utf8::unchecked::next(right), utf16Right); if (!Utf16CharEqualsIgnoreCase(utf16Left[0], utf16Right[0]) || !Utf16CharEqualsIgnoreCase(utf16Left[1], utf16Right[1])) { return false; } } return *left == '\0' && *right == '\0'; } bool VmStringUtils::CaseSensitiveEquals(Il2CppString* left, const char* right) { std::string leftString = StringUtils::Utf16ToUtf8(left->chars); functional::Filter equalsLeft(leftString.c_str()); return equalsLeft(right); } bool VmStringUtils::CaseSensitiveEquals(const char* left, const char* right) { functional::Filter equalsLeft(left); return equalsLeft(right); } bool VmStringUtils::CaseInsensitiveEquals(Il2CppString* left, const char* right) { std::string leftString = StringUtils::Utf16ToUtf8(left->chars); functional::Filter equalsLeft(leftString.c_str()); return equalsLeft(right); } bool VmStringUtils::CaseInsensitiveEquals(const char* left, const char* right) { functional::Filter equalsLeft(left); return equalsLeft(right); } } } ================================================ FILE: unity_decoder/libil2cpp/vm-utils/VmStringUtils.h ================================================ #pragma once #include "il2cpp-config.h" #include namespace il2cpp { namespace utils { class LIBIL2CPP_CODEGEN_API VmStringUtils { public: static Il2CppChar Utf16ToLower(Il2CppChar c); static bool CaseSensitiveEquals(Il2CppString* left, const char* right); static bool CaseSensitiveEquals(const char* left, const char* right); static bool CaseInsensitiveEquals(Il2CppString* left, const char* right); static bool CaseInsensitiveEquals(const char* left, const char* right); struct CaseSensitiveComparer { bool operator()(const std::string& left, const std::string& right) const; bool operator()(const std::string& left, const char* right) const; bool operator()(const char* left, const std::string& right) const; bool operator()(const char* left, const char* right) const; }; struct CaseInsensitiveComparer { bool operator()(const std::string& left, const std::string& right) const; bool operator()(const std::string& left, const char* right) const; bool operator()(const char* left, const std::string& right) const; bool operator()(const char* left, const char* right) const; }; }; } // namespace utils } // namespace il2cpp ================================================ FILE: unity_decoder/main.cpp ================================================ #include "core.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //Define file names const char *MetadataFileName = "./global-metadata.dat"; const char *StringLiteralFileName = "./string_literal.txt"; const char *MethodNameFileName = "./method_name.txt"; static Il2CppGlobalMetadataHeader* s_GlobalMetadataHeader; static void* s_GlobalMetadata; #define MAX_META_COUNT 100000 char *g_metadataUsages[MAX_META_COUNT] = { NULL }; //Il2CppMethodPointer g_methodPointers[MAX_META_COUNT] = { NULL }; Il2CppClass* g_classes[MAX_META_COUNT] = { NULL }; char *g_methodNames[MAX_META_COUNT] = { NULL }; char* removeAllChars(char* str, char c) { char *pr = str, *pw = str; while (*pr) { *pw = *pr++; pw += (*pw != c); } *pw = '\0'; return str; } const char* GetStringFromIndex(StringIndex index) { assert(index <= s_GlobalMetadataHeader->stringCount); const char* strings = ((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->stringOffset) + index; return strings; } static Il2CppClass* FromTypeDefinition(TypeDefinitionIndex index) { assert(index >= 0 && static_cast(index) < s_GlobalMetadataHeader->typeDefinitionsCount / sizeof(Il2CppTypeDefinition)); const Il2CppTypeDefinition* typeDefinitions = (const Il2CppTypeDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->typeDefinitionsOffset); const Il2CppTypeDefinition* typeDefinition = typeDefinitions + index; //const Il2CppTypeDefinitionSizes* typeDefinitionSizes = s_Il2CppMetadataRegistration->typeDefinitionsSizes + index; Il2CppClass* typeInfo = (Il2CppClass*)malloc(sizeof(Il2CppClass)); //typeInfo->image = GetImageForTypeDefinitionIndex(index); typeInfo->name = GetStringFromIndex(typeDefinition->nameIndex); typeInfo->namespaze = GetStringFromIndex(typeDefinition->namespaceIndex); typeInfo->customAttributeIndex = typeDefinition->customAttributeIndex; //typeInfo->byval_arg = MetadataCache::GetIl2CppTypeFromIndex(typeDefinition->byvalTypeIndex); //typeInfo->this_arg = MetadataCache::GetIl2CppTypeFromIndex(typeDefinition->byrefTypeIndex); typeInfo->typeDefinition = typeDefinition; typeInfo->genericContainerIndex = typeDefinition->genericContainerIndex; //typeInfo->instance_size = typeDefinitionSizes->instance_size; //typeInfo->actualSize = typeDefinitionSizes->instance_size; // actualySize is instance_size for compiler generated values //typeInfo->native_size = typeDefinitionSizes->native_size; //typeInfo->static_fields_size = typeDefinitionSizes->static_fields_size; //typeInfo->thread_static_fields_size = typeDefinitionSizes->thread_static_fields_size; typeInfo->thread_static_fields_offset = -1; typeInfo->flags = typeDefinition->flags; //typeInfo->valuetype = (typeDefinition->bitfield >> (kBitIsValueType - 1)) & 0x1; //typeInfo->enumtype = (typeDefinition->bitfield >> (kBitIsEnum - 1)) & 0x1; typeInfo->is_generic = typeDefinition->genericContainerIndex != kGenericContainerIndexInvalid; // generic if we have a generic container //typeInfo->has_finalize = (typeDefinition->bitfield >> (kBitHasFinalizer - 1)) & 0x1; //typeInfo->has_cctor = (typeDefinition->bitfield >> (kBitHasStaticConstructor - 1)) & 0x1; //typeInfo->is_blittable = (typeDefinition->bitfield >> (kBitIsBlittable - 1)) & 0x1; //typeInfo->is_import_or_windows_runtime = (typeDefinition->bitfield >> (kBitIsImportOrWindowsRuntime - 1)) & 0x1; //typeInfo->packingSize = ConvertPackingSizeEnumToValue(static_cast((typeDefinition->bitfield >> (kPackingSize - 1)) & 0xF)); typeInfo->method_count = typeDefinition->method_count; typeInfo->property_count = typeDefinition->property_count; typeInfo->field_count = typeDefinition->field_count; typeInfo->event_count = typeDefinition->event_count; typeInfo->nested_type_count = typeDefinition->nested_type_count; typeInfo->vtable_count = typeDefinition->vtable_count; typeInfo->interfaces_count = typeDefinition->interfaces_count; typeInfo->interface_offsets_count = typeDefinition->interface_offsets_count; typeInfo->token = typeDefinition->token; /* if (typeDefinition->parentIndex != kTypeIndexInvalid) typeInfo->parent = Class::FromIl2CppType(MetadataCache::GetIl2CppTypeFromIndex(typeDefinition->parentIndex)); if (typeDefinition->declaringTypeIndex != kTypeIndexInvalid) typeInfo->declaringType = Class::FromIl2CppType(MetadataCache::GetIl2CppTypeFromIndex(typeDefinition->declaringTypeIndex)); typeInfo->castClass = typeInfo->element_class = typeInfo; if (typeInfo->enumtype) typeInfo->castClass = typeInfo->element_class = Class::FromIl2CppType(MetadataCache::GetIl2CppTypeFromIndex(typeDefinition->elementTypeIndex)); */ return typeInfo; } const Il2CppMethodDefinition* GetMethodDefinitionFromIndex(MethodIndex index) { assert(index >= 0 && static_cast(index) <= s_GlobalMetadataHeader->methodsCount / sizeof(Il2CppMethodDefinition)); const Il2CppMethodDefinition* methods = (const Il2CppMethodDefinition*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->methodsOffset); return methods + index; } void SetupMethods(Il2CppClass *klass) { if (klass->method_count == 0) { klass->methods = NULL; return; } klass->methods = (const MethodInfo**)malloc(klass->method_count * sizeof(MethodInfo*)); MethodInfo* methods = (MethodInfo*)malloc(klass->method_count * sizeof(MethodInfo)); memset(methods, 0, klass->method_count * sizeof(MethodInfo)); MethodInfo* newMethod = methods; MethodIndex start = klass->typeDefinition->methodStart; assert(start != kFieldIndexInvalid); MethodIndex end = start + klass->method_count; for (MethodIndex index = start; index < end; ++index) { const Il2CppMethodDefinition* methodDefinition = GetMethodDefinitionFromIndex(index); newMethod->name = GetStringFromIndex(methodDefinition->nameIndex); //newMethod->methodPointer = GetMethodPointerFromIndex(methodDefinition->methodIndex); //newMethod->invoker_method = GetMethodInvokerFromIndex(methodDefinition->invokerIndex); newMethod->declaring_type = klass; //newMethod->return_type = GetIl2CppTypeFromIndex(methodDefinition->returnType); /* ParameterInfo* parameters = (ParameterInfo*)malloc(methodDefinition->parameterCount * sizeof(ParameterInfo)); ParameterInfo* newParameter = parameters; for (uint16_t paramIndex = 0; paramIndex < methodDefinition->parameterCount; ++paramIndex) { const Il2CppParameterDefinition* parameterDefinition = GetParameterDefinitionFromIndex(methodDefinition->parameterStart + paramIndex); newParameter->name = GetStringFromIndex(parameterDefinition->nameIndex); newParameter->position = paramIndex; newParameter->token = parameterDefinition->token; newParameter->customAttributeIndex = parameterDefinition->customAttributeIndex; newParameter->parameter_type = GetIl2CppTypeFromIndex(parameterDefinition->typeIndex); newParameter++; } newMethod->parameters = parameters; newMethod->customAttributeIndex = methodDefinition->customAttributeIndex; newMethod->flags = methodDefinition->flags; newMethod->iflags = methodDefinition->iflags; newMethod->slot = methodDefinition->slot; newMethod->parameters_count = static_cast(methodDefinition->parameterCount); newMethod->is_inflated = false; newMethod->token = methodDefinition->token; newMethod->methodDefinition = methodDefinition; newMethod->genericContainer = GetGenericContainerFromIndex(methodDefinition->genericContainerIndex); */ if (newMethod->genericContainer) newMethod->is_generic = true; klass->methods[index - start] = newMethod; if (methodDefinition->methodIndex >= 0 && newMethod->name != NULL) { int totalLen = strlen(klass->name) + strlen(newMethod->name) + 3; char *name = new char[totalLen]; snprintf(name, totalLen, "%s$$%s\0", klass->name, newMethod->name); g_methodNames[methodDefinition->methodIndex] = name; } newMethod++; } } Il2CppClass* GetTypeInfoFromTypeDefinitionIndex(TypeDefinitionIndex index) { if (index == kTypeIndexInvalid) return NULL; assert(index >= 0 && static_cast(index) < s_GlobalMetadataHeader->typeDefinitionsCount / sizeof(Il2CppTypeDefinition)); return FromTypeDefinition(index); } char* GetStringLiteralFromIndex(StringLiteralIndex index) { assert(index >= 0 && static_cast(index) < s_GlobalMetadataHeader->stringLiteralCount / sizeof(Il2CppStringLiteral) && "Invalid string literal index "); const Il2CppStringLiteral* stringLiteral = (const Il2CppStringLiteral*)((const char*)s_GlobalMetadata + s_GlobalMetadataHeader->stringLiteralOffset) + index; const char* srcStr = (const char*)s_GlobalMetadata + s_GlobalMetadataHeader->stringLiteralDataOffset + stringLiteral->dataIndex; char *dstStr = new char[stringLiteral->length+1]; snprintf(dstStr, stringLiteral->length+1, "%s", srcStr); dstStr = removeAllChars(dstStr, '\r'); dstStr = removeAllChars(dstStr, '\n'); return dstStr; } template static T MetadataOffset(void* metadata, size_t sectionOffset, size_t itemIndex) { return reinterpret_cast (reinterpret_cast (metadata) + sectionOffset) + itemIndex; } void InitializeMethodMetadata(uint32_t index) { assert(s_GlobalMetadataHeader->metadataUsageListsCount >= 0 && index <= static_cast(s_GlobalMetadataHeader->metadataUsageListsCount)); const Il2CppMetadataUsageList* metadataUsageLists = MetadataOffset(s_GlobalMetadata, s_GlobalMetadataHeader->metadataUsageListsOffset, index); uint32_t start = metadataUsageLists->start; uint32_t count = metadataUsageLists->count; for (uint32_t i = 0; i < count; i++) { uint32_t offset = start + i; assert(s_GlobalMetadataHeader->metadataUsagePairsCount >= 0 && offset <= static_cast(s_GlobalMetadataHeader->metadataUsagePairsCount)); const Il2CppMetadataUsagePair* metadataUsagePairs = MetadataOffset(s_GlobalMetadata, s_GlobalMetadataHeader->metadataUsagePairsOffset, offset); uint32_t destinationIndex = metadataUsagePairs->destinationIndex; uint32_t encodedSourceIndex = metadataUsagePairs->encodedSourceIndex; Il2CppMetadataUsage usage = GetEncodedIndexType(encodedSourceIndex); uint32_t decodedIndex = GetDecodedMethodIndex(encodedSourceIndex); switch (usage) { case kIl2CppMetadataUsageTypeInfo: //metadataUsages[destinationIndex] = GetTypeInfoFromTypeIndex(decodedIndex); break; case kIl2CppMetadataUsageIl2CppType: //metadataUsages[destinationIndex] = const_cast(GetIl2CppTypeFromIndex(decodedIndex)); //break; case kIl2CppMetadataUsageMethodDef: //metadataUsages_method[destinationIndex] = const_cast(GetMethodInfoFromMethodDefinitionIndex(encodedSourceIndex)); break; case kIl2CppMetadataUsageMethodRef: //metadataUsages_method[destinationIndex] = const_cast(GetMethodInfoFromMethodDefinitionIndex(encodedSourceIndex)); //metadataUsages[destinationIndex] = const_cast(GetMethodInfoFromIndex(encodedSourceIndex)); break; case kIl2CppMetadataUsageFieldInfo: //metadataUsages[destinationIndex] = GetFieldInfoFromIndex(decodedIndex); break; case kIl2CppMetadataUsageStringLiteral: g_metadataUsages[destinationIndex] = GetStringLiteralFromIndex(decodedIndex); break; default: //std::cout << "not implemented" << std::endl; break; } } } int main() { std::ofstream stringLiteralFile, methodNameFile; std::ifstream metadataFile; metadataFile.open(MetadataFileName, std::ios::binary | std::ios::ate); std::streamsize size = metadataFile.tellg(); metadataFile.seekg(0, std::ios::beg); char *addr = (char*)malloc(size + 1); metadataFile.read(&addr[0], size); addr[size] = 0; s_GlobalMetadata = addr; s_GlobalMetadataHeader = (Il2CppGlobalMetadataHeader*)addr; std::cout << "metadata version is: " << s_GlobalMetadataHeader->version << std::endl; assert(s_GlobalMetadataHeader->sanity == 0xFAB11BAF); assert(s_GlobalMetadataHeader->version == 24); stringLiteralFile.open(StringLiteralFileName); int usagePairCount = s_GlobalMetadataHeader->metadataUsageListsCount / sizeof(Il2CppMetadataUsagePair); for (int i = 0; i < usagePairCount; i++) { InitializeMethodMetadata(i); } int strCount = s_GlobalMetadataHeader->stringLiteralCount / sizeof(Il2CppStringLiteral); /* for (int i = MAX_META_COUNT - 1 ; i >= 0 ; i--) { if (g_metadataUsages[i] != NULL) { stringLiteralFile << g_metadataUsages[i] << std::endl; } } */ int skip = 0; int i = 0; for (i = 0; i < MAX_META_COUNT; i++) { if (g_metadataUsages[i] == NULL) { skip++; } else { break; } } int totalStrNum = skip + strCount; stringLiteralFile << totalStrNum << std::endl << strCount << std::endl; for (; i < MAX_META_COUNT; i++) { if (g_metadataUsages[i] == NULL) { break; } stringLiteralFile << g_metadataUsages[i] << std::endl; } stringLiteralFile.close(); methodNameFile.open(MethodNameFileName); int typeCount = s_GlobalMetadataHeader->typeDefinitionsCount / sizeof(Il2CppTypeDefinition); for (int i = 0; i < typeCount; i++) { g_classes[i] = GetTypeInfoFromTypeDefinitionIndex(i); SetupMethods(g_classes[i]); } int methodCount = 0; for (int i = 0; i < MAX_META_COUNT; i++) { if (g_methodNames[i] != NULL) { methodCount++; } } methodNameFile << methodCount << std::endl; for (int i = 0; i < MAX_META_COUNT; i++) { if (g_methodNames[i] != NULL) { methodNameFile << g_methodNames[i] << std::endl; } } methodNameFile.close(); return 0; } ================================================ FILE: unity_decoder/unity_decoder.vcxproj ================================================  Debug Win32 Release Win32 Debug x64 Release x64 {326A24E3-C74E-4B12-9BFE-E69F0C6493D4} Win32Proj unity_decoder 8.1 Application true v141 Unicode Application false v140 true Unicode Application true v141 Unicode Application false v141 true Unicode true $(IncludePath) $(LibraryPath) true D:\vs_project\unity_decoder\unity_decoder\libil2cpp;D:\local\boost_1_61_0;$(IncludePath) D:\local\boost_1_61_0\lib64-msvc-14.0;$(LibraryPath) D:\vs_project\unity_decoder\unity_decoder\libil2cpp;$(SourcePath) false $(WindowsSdkDir)\include;$(ProjectDir)\libil2cpp;$(IncludePath) false Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true .\libil2cpp;%(AdditionalIncludeDirectories) MultiThreadedDebugDLL Console true %(AdditionalDependencies) %(AdditionalLibraryDirectories) Level3 Disabled _DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true Console true Level3 MaxSpeed true true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true Console true true true Level3 MaxSpeed true true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true Console true true true ================================================ FILE: unity_decoder/unity_decoder.vcxproj.filters ================================================  {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms ソース ファイル ヘッダー ファイル ================================================ FILE: unity_decoder/unity_decoder.vcxproj.user ================================================  true ================================================ FILE: unity_decoder.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unity_decoder", "unity_decoder\unity_decoder.vcxproj", "{326A24E3-C74E-4B12-9BFE-E69F0C6493D4}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {326A24E3-C74E-4B12-9BFE-E69F0C6493D4}.Debug|x64.ActiveCfg = Debug|x64 {326A24E3-C74E-4B12-9BFE-E69F0C6493D4}.Debug|x64.Build.0 = Debug|x64 {326A24E3-C74E-4B12-9BFE-E69F0C6493D4}.Debug|x86.ActiveCfg = Debug|Win32 {326A24E3-C74E-4B12-9BFE-E69F0C6493D4}.Debug|x86.Build.0 = Debug|Win32 {326A24E3-C74E-4B12-9BFE-E69F0C6493D4}.Release|x64.ActiveCfg = Release|x64 {326A24E3-C74E-4B12-9BFE-E69F0C6493D4}.Release|x64.Build.0 = Release|x64 {326A24E3-C74E-4B12-9BFE-E69F0C6493D4}.Release|x86.ActiveCfg = Release|Win32 {326A24E3-C74E-4B12-9BFE-E69F0C6493D4}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: unity_loader.py ================================================ import os, sys import re import random import idaapi import idc import idautils INFO = idaapi.get_inf_structure() if INFO.is_64bit(): BITS = 64 elif INFO.is_32bit(): BITS = 32 else: BITS = 16 ENUM_FILE_TYPE =\ [ "f_EXE_old", #// MS DOS EXE File "f_COM_old", #// MS DOS COM File "f_BIN", #// Binary File "f_DRV", #// MS DOS Driver "f_WIN", #// New Executable (NE) "f_HEX", #// Intel Hex Object File "f_MEX", #// MOS Technology Hex Object File "f_LX", #// Linear Executable (LX) "f_LE", #// Linear Executable (LE) "f_NLM", #// Netware Loadable Module (NLM) "f_COFF", #// Common Object File Format (COFF) "f_PE", #// Portable Executable (PE) "f_OMF", #// Object Module Format "f_SREC", #// R-records "f_ZIP", #// ZIP file (this file is never loaded to IDA database) "f_OMFLIB", #// Library of OMF Modules "f_AR", #// ar library "f_LOADER", #// file is loaded using LOADER DLL "f_ELF", #// Executable and Linkable Format (ELF) "f_W32RUN", #// Watcom DOS32 Extender (W32RUN) "f_AOUT", #// Linux a.out (AOUT) "f_PRC", #// PalmPilot program file "f_EXE", #// MS DOS EXE File "f_COM", #// MS DOS COM File "f_AIXAR", #// AIX ar library "f_MACHO", #// Max OS X ]; FILE_TYPE = ENUM_FILE_TYPE[INFO.filetype] def IncreaseAddr(addr): if BITS == 64: return addr+8 elif BITS == 32: return addr+4 def DecreaseAddr(addr): if BITS == 64: return addr-8 elif BITS == 32: return addr-4 def GetVarFromAddr(addr): if BITS == 64: return idc.Qword(addr) elif BITS == 32: return idc.Dword(addr) def GetMethodFromAddr(addr): return GetVarFromAddr(addr) & 0xFFFFFFFE def IsCode(addr): return idc.isCode(idc.GetFlags(addr)) def IsData(addr): return idc.isData(idc.GetFlags(addr)) def IsSubFollowing(addr): i = 0 while i < 20: pAddr = GetMethodFromAddr(addr) if not IsCode(pAddr): return False; addr = idc.NextHead(addr) i = i + 1 return True def IsDataFollowing(addr): i = 0 while i < 20: pAddr = GetVarFromAddr(addr) if not IsData(addr): return False; addr = idc.NextHead(addr) i = i + 1 return True def LocateMethodPointers(): seg = idc.FirstSeg() initArrayAddr = 0 while seg != idc.BADADDR: seg = idc.NextSeg(seg) segName = idc.SegName(seg) if segName == ".data.rel.ro": data_rel_ro = idc.SegStart(seg) break addr = data_rel_ro referedVars = [] while idc.SegName(addr) == ".data.rel.ro": for r in idautils.XrefsTo(addr,0): #print "is refered: 0x%x" % addr referedVars.append(addr) break addr += 4 candidateMethodPointers = [] for var in referedVars: if IsSubFollowing(var): candidateMethodPointers.append(var) for candidate in candidateMethodPointers: for referedVar in referedVars: if referedVar == candidate: nextVar = referedVars[referedVars.index(referedVar)+1] print "candidate: 0x%x, candidate end: 0x%x, method numbers: %d" % (candidate, nextVar, (nextVar-candidate)/4) break def LocateStringLiterals(): seg = idc.FirstSeg() initArrayAddr = 0 while seg != idc.BADADDR: seg = idc.NextSeg(seg) segName = idc.SegName(seg) if segName == ".data.rel.ro": data_rel_ro = idc.SegStart(seg) break addr = data_rel_ro referedVars = [] while idc.SegName(addr) == ".data.rel.ro": for r in idautils.XrefsTo(addr,0): referedVars.append(addr) break addr += 4 candidateMetadaUsages = [] for idx, var in enumerate(referedVars): if idx < (len(referedVars)-1) and (referedVars[idx+1]-referedVars[idx]) >= 1024: if idc.Dword(var) == 0x0: continue if IsDataFollowing(var) and idc.SegName(idc.Dword(var) ) == '.bss': candidateMetadaUsages.append(var) for candidate in candidateMetadaUsages: for referedVar in referedVars: if referedVar == candidate: nextVar = referedVars[referedVars.index(referedVar)+1] print "candidate: 0x%x, candidate end: 0x%x, data numbers: %d" % (candidate, nextVar, (nextVar-candidate)/4) break def LoadMethods(ea = None): if ea is None: ea = ScreenEA(); path = os.getcwd() os.system(path+'/unity_decoder.exe') file = open('./method_name.txt') str_count = file.readline() i = 0; for line in file: line = line.strip(' ').replace('\r', '').replace('\n', '') new_line = re.sub(r'[^a-zA-Z0-9_$]', '_', line) i = 0; addr = GetMethodFromAddr(ea) ret = idc.MakeNameEx(addr, str(new_line), SN_NOWARN) while ret == 0 and i < 5: # failed new_line_rand = new_line + '_' + str(random.randint(0, 99999)) ret = idc.MakeNameEx(addr, str(new_line_rand), SN_NOWARN) idc.MakeComm(ea, str(line)) i = i + 1 ea = IncreaseAddr(ea) file.close() def LoadStringLiterals(ea = None): if ea is None: ea = ScreenEA(); path = os.getcwd() os.system(path+'/unity_decoder.exe') file = open('./string_literal.txt') total_count = file.readline() str_count = file.readline() skip_count = int(total_count) - int(str_count) ea += int(skip_count) * 0x4 for line in file: line = line.strip(' ').replace('\r', '').replace('\n', '') new_line = re.sub(r'[^a-zA-Z0-9_]', '_', line) new_line = 'StringLiteral_' + new_line i = 0; addr = GetVarFromAddr(ea) ret = idc.MakeNameEx(addr, str(new_line), SN_NOWARN) #ret = idc.MakeNameEx(addr, "", SN_NOWARN) while ret == 0 and i < 5: # failed new_line_rand = new_line + '_' + str(random.randint(0, 99999)) ret = idc.MakeNameEx(addr, str(new_line_rand), SN_NOWARN) i = i + 1 idc.MakeComm(ea, str(line)) #idc.MakeComm(ea, "") ea = IncreaseAddr(ea) file.close() print "Type LocateMethodPointers() to print suggested candidate for method pointers" print "Click the location where you believe the method pointers start, type LoadMethods()" print "Type LocateStringLiterals() to print suggested candidate for string literals" print "Click the location where you believe the string literals start, type LoadStringLiterals()"