//
// MetadataRowReader.cs
//
// Author:
//   Jb Evain (jbevain@gmail.com)
//
// Generated by /CodeGen/cecil-gen.rb do not edit
// Thu Sep 29 22:11:54 CEST 2005
//
// (C) 2005 Jb Evain
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

namespace Mono.Cecil.Metadata {

	using System;
	using System.Collections;
	using System.IO;

	using Mono.Cecil.Binary;

	class MetadataRowReader : BaseMetadataRowVisitor {

		MetadataTableReader m_mtrv;
		BinaryReader m_binaryReader;
		MetadataRoot m_metadataRoot;
		IDictionary m_ciCache;

		int m_blobHeapIdxSz;
		int m_stringsHeapIdxSz;
		int m_guidHeapIdxSz;

		public MetadataRowReader (MetadataTableReader mtrv)
		{
			m_mtrv = mtrv;
			m_binaryReader = mtrv.GetReader ();
			m_metadataRoot = mtrv.GetMetadataRoot ();
			m_ciCache = new Hashtable ();
		}

		int GetIndexSize (Type table)
		{
			return m_mtrv.GetNumberOfRows (table) < (1 << 16) ? 2 : 4;
		}

		int GetCodedIndexSize (CodedIndex ci)
		{
			return Utilities.GetCodedIndexSize (ci,
				new Utilities.TableRowCounter (m_mtrv.GetNumberOfRows), m_ciCache);
		}

		uint ReadByIndexSize (int size)
		{
			if (size == 2) {
				return (uint) m_binaryReader.ReadUInt16 ();
			} else if (size == 4) {
				return m_binaryReader.ReadUInt32 ();
			} else {
				throw new MetadataFormatException ("Non valid size for indexing");
			}
		}

		public override void VisitRowCollection (RowCollection coll)
		{
			m_blobHeapIdxSz = m_metadataRoot.Streams.BlobHeap != null ?
				m_metadataRoot.Streams.BlobHeap.IndexSize : 2;
			m_stringsHeapIdxSz = m_metadataRoot.Streams.StringsHeap != null ?
				m_metadataRoot.Streams.StringsHeap.IndexSize : 2;
			m_guidHeapIdxSz = m_metadataRoot.Streams.GuidHeap != null ?
				m_metadataRoot.Streams.GuidHeap.IndexSize : 2;
		}

		public override void VisitAssemblyRow (AssemblyRow row)
		{
			row.HashAlgId = (Mono.Cecil.AssemblyHashAlgorithm) m_binaryReader.ReadUInt32 ();
			row.MajorVersion = m_binaryReader.ReadUInt16 ();
			row.MinorVersion = m_binaryReader.ReadUInt16 ();
			row.BuildNumber = m_binaryReader.ReadUInt16 ();
			row.RevisionNumber = m_binaryReader.ReadUInt16 ();
			row.Flags = (Mono.Cecil.AssemblyFlags) m_binaryReader.ReadUInt32 ();
			row.PublicKey = ReadByIndexSize (m_blobHeapIdxSz);
			row.Name = ReadByIndexSize (m_stringsHeapIdxSz);
			row.Culture = ReadByIndexSize (m_stringsHeapIdxSz);
		}

		public override void VisitAssemblyOSRow (AssemblyOSRow row)
		{
			row.OSPlatformID = m_binaryReader.ReadUInt32 ();
			row.OSMajorVersion = m_binaryReader.ReadUInt32 ();
			row.OSMinorVersion = m_binaryReader.ReadUInt32 ();
		}

		public override void VisitAssemblyProcessorRow (AssemblyProcessorRow row)
		{
			row.Processor = m_binaryReader.ReadUInt32 ();
		}

		public override void VisitAssemblyRefRow (AssemblyRefRow row)
		{
			row.MajorVersion = m_binaryReader.ReadUInt16 ();
			row.MinorVersion = m_binaryReader.ReadUInt16 ();
			row.BuildNumber = m_binaryReader.ReadUInt16 ();
			row.RevisionNumber = m_binaryReader.ReadUInt16 ();
			row.Flags = (Mono.Cecil.AssemblyFlags) m_binaryReader.ReadUInt32 ();
			row.PublicKeyOrToken = ReadByIndexSize (m_blobHeapIdxSz);
			row.Name = ReadByIndexSize (m_stringsHeapIdxSz);
			row.Culture = ReadByIndexSize (m_stringsHeapIdxSz);
			row.HashValue = ReadByIndexSize (m_blobHeapIdxSz);
		}

		public override void VisitAssemblyRefOSRow (AssemblyRefOSRow row)
		{
			row.OSPlatformID = m_binaryReader.ReadUInt32 ();
			row.OSMajorVersion = m_binaryReader.ReadUInt32 ();
			row.OSMinorVersion = m_binaryReader.ReadUInt32 ();
			row.AssemblyRef = ReadByIndexSize (GetIndexSize (typeof (AssemblyRefTable)));
		}

		public override void VisitAssemblyRefProcessorRow (AssemblyRefProcessorRow row)
		{
			row.Processor = m_binaryReader.ReadUInt32 ();
			row.AssemblyRef = ReadByIndexSize (GetIndexSize (typeof (AssemblyRefTable)));
		}

		public override void VisitClassLayoutRow (ClassLayoutRow row)
		{
			row.PackingSize = m_binaryReader.ReadUInt16 ();
			row.ClassSize = m_binaryReader.ReadUInt32 ();
			row.Parent = ReadByIndexSize (GetIndexSize (typeof (TypeDefTable)));
		}

		public override void VisitConstantRow (ConstantRow row)
		{
			row.Type = (Mono.Cecil.Metadata.ElementType) m_binaryReader.ReadUInt16 ();
			row.Parent = Utilities.GetMetadataToken (CodedIndex.HasConstant,
				ReadByIndexSize (GetCodedIndexSize (CodedIndex.HasConstant)));
			row.Value = ReadByIndexSize (m_blobHeapIdxSz);
		}

		public override void VisitCustomAttributeRow (CustomAttributeRow row)
		{
			row.Parent = Utilities.GetMetadataToken (CodedIndex.HasCustomAttribute,
				ReadByIndexSize (GetCodedIndexSize (CodedIndex.HasCustomAttribute)));
			row.Type = Utilities.GetMetadataToken (CodedIndex.CustomAttributeType,
				ReadByIndexSize (GetCodedIndexSize (CodedIndex.CustomAttributeType)));
			row.Value = ReadByIndexSize (m_blobHeapIdxSz);
		}

		public override void VisitDeclSecurityRow (DeclSecurityRow row)
		{
			row.Action = (Mono.Cecil.SecurityAction) m_binaryReader.ReadInt16 ();
			row.Parent = Utilities.GetMetadataToken (CodedIndex.HasDeclSecurity,
				ReadByIndexSize (GetCodedIndexSize (CodedIndex.HasDeclSecurity)));
			row.PermissionSet = ReadByIndexSize (m_blobHeapIdxSz);
		}

		public override void VisitEventRow (EventRow row)
		{
			row.EventFlags = (Mono.Cecil.EventAttributes) m_binaryReader.ReadUInt16 ();
			row.Name = ReadByIndexSize (m_stringsHeapIdxSz);
			row.EventType = Utilities.GetMetadataToken (CodedIndex.TypeDefOrRef,
				ReadByIndexSize (GetCodedIndexSize (CodedIndex.TypeDefOrRef)));
		}

		public override void VisitEventMapRow (EventMapRow row)
		{
			row.Parent = ReadByIndexSize (GetIndexSize (typeof (TypeDefTable)));
			row.EventList = ReadByIndexSize (GetIndexSize (typeof (EventTable)));
		}

		public override void VisitExportedTypeRow (ExportedTypeRow row)
		{
			row.Flags = (Mono.Cecil.TypeAttributes) m_binaryReader.ReadUInt32 ();
			row.TypeDefId = m_binaryReader.ReadUInt32 ();
			row.TypeName = ReadByIndexSize (m_stringsHeapIdxSz);
			row.TypeNamespace = ReadByIndexSize (m_stringsHeapIdxSz);
			row.Implementation = Utilities.GetMetadataToken (CodedIndex.Implementation,
				ReadByIndexSize (GetCodedIndexSize (CodedIndex.Implementation)));
		}

		public override void VisitFieldRow (FieldRow row)
		{
			row.Flags = (Mono.Cecil.FieldAttributes) m_binaryReader.ReadUInt16 ();
			row.Name = ReadByIndexSize (m_stringsHeapIdxSz);
			row.Signature = ReadByIndexSize (m_blobHeapIdxSz);
		}

		public override void VisitFieldLayoutRow (FieldLayoutRow row)
		{
			row.Offset = m_binaryReader.ReadUInt32 ();
			row.Field = ReadByIndexSize (GetIndexSize (typeof (FieldTable)));
		}

		public override void VisitFieldMarshalRow (FieldMarshalRow row)
		{
			row.Parent = Utilities.GetMetadataToken (CodedIndex.HasFieldMarshal,
				ReadByIndexSize (GetCodedIndexSize (CodedIndex.HasFieldMarshal)));
			row.NativeType = ReadByIndexSize (m_blobHeapIdxSz);
		}

		public override void VisitFieldRVARow (FieldRVARow row)
		{
			row.RVA = new RVA (m_binaryReader.ReadUInt32 ());
			row.Field = ReadByIndexSize (GetIndexSize (typeof (FieldTable)));
		}

		public override void VisitFileRow (FileRow row)
		{
			row.Flags = (Mono.Cecil.FileAttributes) m_binaryReader.ReadUInt32 ();
			row.Name = ReadByIndexSize (m_stringsHeapIdxSz);
			row.HashValue = ReadByIndexSize (m_blobHeapIdxSz);
		}

		public override void VisitGenericParamRow (GenericParamRow row)
		{
			row.Number = m_binaryReader.ReadUInt16 ();
			row.Flags = (Mono.Cecil.GenericParamAttributes) m_binaryReader.ReadUInt16 ();
			row.Owner = Utilities.GetMetadataToken (CodedIndex.TypeOrMethodDef,
				ReadByIndexSize (GetCodedIndexSize (CodedIndex.TypeOrMethodDef)));
			row.Name = ReadByIndexSize (m_stringsHeapIdxSz);
		}

		public override void VisitGenericParamConstraintRow (GenericParamConstraintRow row)
		{
			row.Owner = ReadByIndexSize (GetIndexSize (typeof (GenericParamTable)));
			row.Constraint = Utilities.GetMetadataToken (CodedIndex.TypeDefOrRef,
				ReadByIndexSize (GetCodedIndexSize (CodedIndex.TypeDefOrRef)));
		}

		public override void VisitImplMapRow (ImplMapRow row)
		{
			row.MappingFlags = (Mono.Cecil.PInvokeAttributes) m_binaryReader.ReadUInt16 ();
			row.MemberForwarded = Utilities.GetMetadataToken (CodedIndex.MemberForwarded,
				ReadByIndexSize (GetCodedIndexSize (CodedIndex.MemberForwarded)));
			row.ImportName = ReadByIndexSize (m_stringsHeapIdxSz);
			row.ImportScope = ReadByIndexSize (GetIndexSize (typeof (ModuleRefTable)));
		}

		public override void VisitInterfaceImplRow (InterfaceImplRow row)
		{
			row.Class = ReadByIndexSize (GetIndexSize (typeof (TypeDefTable)));
			row.Interface = Utilities.GetMetadataToken (CodedIndex.TypeDefOrRef,
				ReadByIndexSize (GetCodedIndexSize (CodedIndex.TypeDefOrRef)));
		}

		public override void VisitManifestResourceRow (ManifestResourceRow row)
		{
			row.Offset = m_binaryReader.ReadUInt32 ();
			row.Flags = (Mono.Cecil.ManifestResourceAttributes) m_binaryReader.ReadUInt32 ();
			row.Name = ReadByIndexSize (m_stringsHeapIdxSz);
			row.Implementation = Utilities.GetMetadataToken (CodedIndex.Implementation,
				ReadByIndexSize (GetCodedIndexSize (CodedIndex.Implementation)));
		}

		public override void VisitMemberRefRow (MemberRefRow row)
		{
			row.Class = Utilities.GetMetadataToken (CodedIndex.MemberRefParent,
				ReadByIndexSize (GetCodedIndexSize (CodedIndex.MemberRefParent)));
			row.Name = ReadByIndexSize (m_stringsHeapIdxSz);
			row.Signature = ReadByIndexSize (m_blobHeapIdxSz);
		}

		public override void VisitMethodRow (MethodRow row)
		{
			row.RVA = new RVA (m_binaryReader.ReadUInt32 ());
			row.ImplFlags = (Mono.Cecil.MethodImplAttributes) m_binaryReader.ReadUInt16 ();
			row.Flags = (Mono.Cecil.MethodAttributes) m_binaryReader.ReadUInt16 ();
			row.Name = ReadByIndexSize (m_stringsHeapIdxSz);
			row.Signature = ReadByIndexSize (m_blobHeapIdxSz);
			row.ParamList = ReadByIndexSize (GetIndexSize (typeof (ParamTable)));
		}

		public override void VisitMethodImplRow (MethodImplRow row)
		{
			row.Class = ReadByIndexSize (GetIndexSize (typeof (TypeDefTable)));
			row.MethodBody = Utilities.GetMetadataToken (CodedIndex.MethodDefOrRef,
				ReadByIndexSize (GetCodedIndexSize (CodedIndex.MethodDefOrRef)));
			row.MethodDeclaration = Utilities.GetMetadataToken (CodedIndex.MethodDefOrRef,
				ReadByIndexSize (GetCodedIndexSize (CodedIndex.MethodDefOrRef)));
		}

		public override void VisitMethodSemanticsRow (MethodSemanticsRow row)
		{
			row.Semantics = (Mono.Cecil.MethodSemanticsAttributes) m_binaryReader.ReadUInt16 ();
			row.Method = ReadByIndexSize (GetIndexSize (typeof (MethodTable)));
			row.Association = Utilities.GetMetadataToken (CodedIndex.HasSemantics,
				ReadByIndexSize (GetCodedIndexSize (CodedIndex.HasSemantics)));
		}

		public override void VisitMethodSpecRow (MethodSpecRow row)
		{
			row.Method = Utilities.GetMetadataToken (CodedIndex.MethodDefOrRef,
				ReadByIndexSize (GetCodedIndexSize (CodedIndex.MethodDefOrRef)));
			row.Instantiation = ReadByIndexSize (m_blobHeapIdxSz);
		}

		public override void VisitModuleRow (ModuleRow row)
		{
			row.Generation = m_binaryReader.ReadUInt16 ();
			row.Name = ReadByIndexSize (m_stringsHeapIdxSz);
			row.Mvid = ReadByIndexSize (m_guidHeapIdxSz);
			row.EncId = ReadByIndexSize (m_guidHeapIdxSz);
			row.EncBaseId = ReadByIndexSize (m_guidHeapIdxSz);
		}

		public override void VisitModuleRefRow (ModuleRefRow row)
		{
			row.Name = ReadByIndexSize (m_stringsHeapIdxSz);
		}

		public override void VisitNestedClassRow (NestedClassRow row)
		{
			row.NestedClass = ReadByIndexSize (GetIndexSize (typeof (TypeDefTable)));
			row.EnclosingClass = ReadByIndexSize (GetIndexSize (typeof (TypeDefTable)));
		}

		public override void VisitParamRow (ParamRow row)
		{
			row.Flags = (Mono.Cecil.ParamAttributes) m_binaryReader.ReadUInt16 ();
			row.Sequence = m_binaryReader.ReadUInt16 ();
			row.Name = ReadByIndexSize (m_stringsHeapIdxSz);
		}

		public override void VisitPropertyRow (PropertyRow row)
		{
			row.Flags = (Mono.Cecil.PropertyAttributes) m_binaryReader.ReadUInt16 ();
			row.Name = ReadByIndexSize (m_stringsHeapIdxSz);
			row.Type = ReadByIndexSize (m_blobHeapIdxSz);
		}

		public override void VisitPropertyMapRow (PropertyMapRow row)
		{
			row.Parent = ReadByIndexSize (GetIndexSize (typeof (TypeDefTable)));
			row.PropertyList = ReadByIndexSize (GetIndexSize (typeof (PropertyTable)));
		}

		public override void VisitStandAloneSigRow (StandAloneSigRow row)
		{
			row.Signature = ReadByIndexSize (m_blobHeapIdxSz);
		}

		public override void VisitTypeDefRow (TypeDefRow row)
		{
			row.Flags = (Mono.Cecil.TypeAttributes) m_binaryReader.ReadUInt32 ();
			row.Name = ReadByIndexSize (m_stringsHeapIdxSz);
			row.Namespace = ReadByIndexSize (m_stringsHeapIdxSz);
			row.Extends = Utilities.GetMetadataToken (CodedIndex.TypeDefOrRef,
				ReadByIndexSize (GetCodedIndexSize (CodedIndex.TypeDefOrRef)));
			row.FieldList = ReadByIndexSize (GetIndexSize (typeof (FieldTable)));
			row.MethodList = ReadByIndexSize (GetIndexSize (typeof (MethodTable)));
		}

		public override void VisitTypeRefRow (TypeRefRow row)
		{
			row.ResolutionScope = Utilities.GetMetadataToken (CodedIndex.ResolutionScope,
				ReadByIndexSize (GetCodedIndexSize (CodedIndex.ResolutionScope)));
			row.Name = ReadByIndexSize (m_stringsHeapIdxSz);
			row.Namespace = ReadByIndexSize (m_stringsHeapIdxSz);
		}

		public override void VisitTypeSpecRow (TypeSpecRow row)
		{
			row.Signature = ReadByIndexSize (m_blobHeapIdxSz);
		}

	}
}
