/Zelig/Zelig/CompileTime/MetaData/Importer/ArrayReader.cs

https://github.com/NETMF/llilum · C# · 564 lines · 409 code · 131 blank · 24 comment · 36 complexity · 8134dd459fe49f4bb26b4d2c426a4cc0 MD5 · raw file

  1. //
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Text;
  7. namespace Microsoft.Zelig.MetaData.Importer
  8. {
  9. public unsafe class ArrayReader
  10. {
  11. private static readonly System.Text.UTF8Encoding s_stringEncoding = new System.Text.UTF8Encoding();
  12. //
  13. // State
  14. //
  15. byte[] m_image;
  16. int m_startPosition;
  17. int m_currentPosition;
  18. int m_endPosition;
  19. GrowOnlySet< string > m_lookup;
  20. //
  21. // Constructor Methods
  22. //
  23. public ArrayReader( byte[] image )
  24. {
  25. m_image = image;
  26. m_startPosition = 0;
  27. m_currentPosition = 0;
  28. m_endPosition = image.Length;
  29. m_lookup = SetFactory.New< string >();
  30. }
  31. public ArrayReader( ArrayReader scanner ,
  32. int offset )
  33. {
  34. m_image = scanner.m_image;
  35. m_startPosition = scanner.m_currentPosition + offset;
  36. m_currentPosition = m_startPosition;
  37. m_endPosition = scanner.m_endPosition;
  38. m_lookup = scanner.m_lookup;
  39. if(m_startPosition < 0)
  40. {
  41. throw new IndexOutOfRangeException();
  42. }
  43. }
  44. public ArrayReader( ArrayReader scanner ,
  45. int offset ,
  46. int count )
  47. {
  48. m_image = scanner.m_image;
  49. m_startPosition = scanner.m_currentPosition + offset;
  50. m_currentPosition = m_startPosition;
  51. m_endPosition = m_startPosition + count;
  52. m_lookup = scanner.m_lookup;
  53. if(m_startPosition < 0 || m_endPosition > scanner.m_endPosition)
  54. {
  55. throw new IndexOutOfRangeException();
  56. }
  57. }
  58. //--//
  59. public override bool Equals( Object obj )
  60. {
  61. if(obj is ArrayReader)
  62. {
  63. ArrayReader other = (ArrayReader)obj;
  64. if(this.Length == other.Length)
  65. {
  66. int len = this.Length;
  67. while(len-- > 0)
  68. {
  69. if(m_image[m_startPosition+len] != other.m_image[other.m_startPosition+len])
  70. {
  71. return false;
  72. }
  73. }
  74. return true;
  75. }
  76. }
  77. return false;
  78. }
  79. public override int GetHashCode()
  80. {
  81. return (int)this.Length;
  82. }
  83. //--//
  84. private void CheckRange( int size )
  85. {
  86. if(size < 0 || m_currentPosition + size > m_endPosition)
  87. {
  88. throw new IndexOutOfRangeException();
  89. }
  90. }
  91. public bool ReadBoolean()
  92. {
  93. return (ReadUInt8() != 0);
  94. }
  95. public byte PeekUInt8()
  96. {
  97. CheckRange( 1 );
  98. return m_image[m_currentPosition];
  99. }
  100. public byte ReadUInt8()
  101. {
  102. CheckRange( 1 );
  103. byte res = m_image[m_currentPosition];
  104. m_currentPosition += 1;
  105. return res;
  106. }
  107. public ushort ReadUInt16()
  108. {
  109. CheckRange( 2 );
  110. ushort res = (ushort)(((uint)m_image[m_currentPosition ] ) |
  111. ((uint)m_image[m_currentPosition+1] << 8) );
  112. m_currentPosition += 2;
  113. return res;
  114. }
  115. public uint ReadUInt32()
  116. {
  117. CheckRange( 4 );
  118. uint res = (((uint)m_image[m_currentPosition ] ) |
  119. ((uint)m_image[m_currentPosition+1] << 8) |
  120. ((uint)m_image[m_currentPosition+2] << 16) |
  121. ((uint)m_image[m_currentPosition+3] << 24) );
  122. m_currentPosition += 4;
  123. return res;
  124. }
  125. public ulong ReadUInt64()
  126. {
  127. ulong res = (((ulong)ReadUInt32() ) |
  128. ((ulong)ReadUInt32() << 32) );
  129. return res;
  130. }
  131. public sbyte ReadInt8()
  132. {
  133. return (sbyte)ReadUInt8();
  134. }
  135. public short ReadInt16()
  136. {
  137. return (short)ReadUInt16();
  138. }
  139. public int ReadInt32()
  140. {
  141. return (int)ReadUInt32();
  142. }
  143. public long ReadInt64()
  144. {
  145. return (long)ReadUInt64();
  146. }
  147. public char ReadChar()
  148. {
  149. return (char)ReadUInt16();
  150. }
  151. public unsafe float ReadSingle()
  152. {
  153. uint tmpBuffer = ReadUInt32();
  154. return *((float*)&tmpBuffer);
  155. }
  156. public unsafe double ReadDouble()
  157. {
  158. ulong tmpBuffer = ReadUInt64();
  159. return *((double*)&tmpBuffer);
  160. }
  161. //--//
  162. public uint ReadCompressedUInt32()
  163. {
  164. byte firstByte = this.ReadUInt8();
  165. if((firstByte & 0x80) == 0)
  166. {
  167. // encoded in a single byte
  168. return firstByte;
  169. }
  170. else if((firstByte & 0x40) == 0)
  171. {
  172. // encoded in two bytes
  173. firstByte &= 0x3F;
  174. return (((uint)firstByte << 8) |
  175. ((uint)this.ReadUInt8() ) );
  176. }
  177. else
  178. {
  179. // encoded in four bytes
  180. firstByte &= 0x3F;
  181. return (((uint)firstByte << 24) |
  182. ((uint)this.ReadUInt8() << 16) |
  183. ((uint)this.ReadUInt8() << 8) |
  184. ((uint)this.ReadUInt8() ) );
  185. }
  186. }
  187. public string ReadCompressedString()
  188. {
  189. byte firstByte = this.ReadUInt8();
  190. if(firstByte == 0xFF)
  191. {
  192. return null;
  193. }
  194. m_currentPosition--;
  195. uint len = this.ReadCompressedUInt32();
  196. byte[] bytes = this.ReadUInt8Array( (int)len );
  197. return s_stringEncoding.GetString( bytes );
  198. }
  199. public int ReadCompressedToken()
  200. {
  201. uint codedToken = ReadCompressedUInt32();
  202. TokenType tokenType;
  203. switch(codedToken & 0x3)
  204. {
  205. case 0x0: tokenType = TokenType.TypeDef ; break;
  206. case 0x1: tokenType = TokenType.TypeRef ; break;
  207. case 0x2: tokenType = TokenType.TypeSpec; break;
  208. default : throw IllegalMetaDataFormatException.Create( "Bad signature token: {0}", codedToken );
  209. }
  210. return MetaData.PackToken( tokenType, (int)(codedToken >> 2) );
  211. }
  212. public Guid ReadGuid()
  213. {
  214. const int sizeOfGuid = 16;
  215. return new Guid( this.ReadUInt8Array( sizeOfGuid ) );
  216. }
  217. //--//
  218. public void CopyIntoArray( byte[] dst ,
  219. int offset ,
  220. int count )
  221. {
  222. CheckRange( count );
  223. Array.Copy( m_image, m_currentPosition, dst, offset, count );
  224. m_currentPosition += count;
  225. }
  226. public byte[] ReadUInt8Array( int count )
  227. {
  228. byte[] res = new byte[count];
  229. CopyIntoArray( res, 0, count );
  230. return res;
  231. }
  232. public byte[] ReadUInt8Array( int count ,
  233. int extraAlloc )
  234. {
  235. byte[] res = new byte[count + extraAlloc];
  236. CopyIntoArray( res, 0, count );
  237. return res;
  238. }
  239. public char[] ReadCharArray( int count )
  240. {
  241. char[] res = new char[count];
  242. for(int i = 0; i < count; i++)
  243. {
  244. res[i] = ReadChar();
  245. }
  246. return res;
  247. }
  248. public int[] ReadInt32Array( int count )
  249. {
  250. int[] res = new int[count];
  251. for(int i = 0; i < count; i++)
  252. {
  253. res[i] = ReadInt32();
  254. }
  255. return res;
  256. }
  257. public uint[] ReadUInt32Array( int count )
  258. {
  259. uint[] res = new uint[count];
  260. for(int i = 0; i < count; i++)
  261. {
  262. res[i] = ReadUInt32();
  263. }
  264. return res;
  265. }
  266. public string ReadZeroTerminatedUInt8String()
  267. {
  268. StringBuilder sb = new StringBuilder();
  269. while(true)
  270. {
  271. byte c = ReadUInt8();
  272. if(c == 0) break;
  273. sb.Append( (char)c );
  274. }
  275. return sb.ToString();
  276. }
  277. public string ReadZeroTerminatedUTF8String()
  278. {
  279. int start = m_currentPosition;
  280. int end = start;
  281. while(m_image[end] != 0)
  282. {
  283. end++;
  284. }
  285. CheckRange( end + 1 - start );
  286. m_currentPosition = end + 1;
  287. string res = s_stringEncoding.GetString( m_image, start, end - start );
  288. string res2;
  289. if(m_lookup.Contains( res, out res2 ))
  290. {
  291. return res2;
  292. }
  293. else
  294. {
  295. m_lookup.Insert( res );
  296. return res;
  297. }
  298. }
  299. public string ReadUInt8String( int count )
  300. {
  301. char[] res = new char[count];
  302. for(int i = 0; i < count; i++)
  303. {
  304. res[i] = (char)ReadUInt8();
  305. }
  306. return new String( res );
  307. }
  308. public string ReadUInt16String( int count )
  309. {
  310. char[] res = ReadCharArray( count );
  311. return new String( res );
  312. }
  313. //--//
  314. public ArrayReader CreateSubset( int count )
  315. {
  316. CheckRange( count );
  317. return new ArrayReader( this, 0, count );
  318. }
  319. public ArrayReader CreateSubsetAndAdvance( int count )
  320. {
  321. ArrayReader res = CreateSubset( count );
  322. m_currentPosition += count;
  323. return res;
  324. }
  325. // public uint ComputeCRC()
  326. // {
  327. // return CRC32.Compute( m_image, m_currentPosition, m_endPosition-m_currentPosition, 0 );
  328. // }
  329. //--//
  330. public void Seek( int offset )
  331. {
  332. SeekAbsolute( m_currentPosition + offset );
  333. }
  334. public void SeekAbsolute( int newPosition )
  335. {
  336. if(newPosition < m_startPosition || newPosition > m_endPosition)
  337. {
  338. throw new IndexOutOfRangeException();
  339. }
  340. m_currentPosition = newPosition;
  341. }
  342. public void Align( int count )
  343. {
  344. int rem = this.Position % count;
  345. if(rem != 0)
  346. {
  347. Seek( count - rem );
  348. }
  349. }
  350. public void AlignAbsolute( int count )
  351. {
  352. int rem = m_currentPosition % count;
  353. if(rem != 0)
  354. {
  355. Seek( count - rem );
  356. }
  357. }
  358. public void Rewind()
  359. {
  360. m_currentPosition = m_startPosition;
  361. }
  362. public bool IsEOF
  363. {
  364. get
  365. {
  366. return m_currentPosition == m_endPosition;
  367. }
  368. }
  369. public int Length
  370. {
  371. get
  372. {
  373. return m_endPosition - m_startPosition;
  374. }
  375. }
  376. public int Position
  377. {
  378. get
  379. {
  380. return m_currentPosition - m_startPosition;
  381. }
  382. set
  383. {
  384. int newPosition = m_startPosition + value;
  385. if(newPosition < m_startPosition || newPosition >= m_endPosition)
  386. {
  387. throw new IndexOutOfRangeException();
  388. }
  389. m_currentPosition = newPosition;
  390. }
  391. }
  392. //--//
  393. public override string ToString()
  394. {
  395. StringBuilder sb = new StringBuilder();
  396. AppendAsString( sb, true );
  397. return sb.ToString();
  398. }
  399. public void AppendAsString( StringBuilder sb ,
  400. bool whole )
  401. {
  402. int pos = whole ? m_startPosition : m_currentPosition;
  403. AppendAsString( sb, m_image, pos, m_endPosition - pos );
  404. }
  405. //--//
  406. public static void AppendAsString( StringBuilder sb ,
  407. byte[] buffer )
  408. {
  409. AppendAsString( sb, buffer, 0, buffer.Length );
  410. }
  411. public static void AppendAsString( StringBuilder sb ,
  412. byte[] buffer ,
  413. int offset ,
  414. int count )
  415. {
  416. int end = count + offset;
  417. bool fFirst = true;
  418. while(offset < end)
  419. {
  420. if(fFirst)
  421. {
  422. fFirst = false;
  423. }
  424. else
  425. {
  426. sb.Append( "," );
  427. }
  428. sb.Append( "0x" );
  429. sb.Append( buffer[offset++].ToString( "x2" ) );
  430. }
  431. }
  432. }
  433. }