DbBuffer.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. //------------------------------------------------------------------------------
  2. // <copyright file="DbBuffer.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. // <owner current="true" primary="true">[....]</owner>
  6. //------------------------------------------------------------------------------
  7. namespace System.Data.ProviderBase
  8. {
  9. using System;
  10. using System.Data.Common;
  11. using System.Diagnostics;
  12. using System.Runtime.CompilerServices;
  13. using System.Runtime.ConstrainedExecution;
  14. using System.Runtime.InteropServices;
  15. using System.Security;
  16. using System.Security.Permissions;
  17. using System.Threading;
  18. // DbBuffer is abstract to require derived class to exist
  19. // so that when debugging, we can tell the difference between one DbBuffer and another
  20. internal abstract class DbBuffer : SafeHandle {
  21. internal const int LMEM_FIXED = 0x0000;
  22. internal const int LMEM_MOVEABLE = 0x0002;
  23. internal const int LMEM_ZEROINIT = 0x0040;
  24. private readonly int _bufferLength;
  25. private DbBuffer(int initialSize, bool zeroBuffer) : base(IntPtr.Zero, true) {
  26. if (0 < initialSize) {
  27. int flags = ((zeroBuffer) ? LMEM_ZEROINIT : LMEM_FIXED);
  28. _bufferLength = initialSize;
  29. RuntimeHelpers.PrepareConstrainedRegions();
  30. try {} finally {
  31. base.handle = SafeNativeMethods.LocalAlloc(flags, (IntPtr)initialSize);
  32. }
  33. if (IntPtr.Zero == base.handle) {
  34. throw new OutOfMemoryException();
  35. }
  36. }
  37. }
  38. protected DbBuffer(int initialSize) : this(initialSize, true) {
  39. }
  40. protected DbBuffer(IntPtr invalidHandleValue, bool ownsHandle) : base(invalidHandleValue, ownsHandle) {
  41. }
  42. private int BaseOffset { get { return 0; } }
  43. public override bool IsInvalid {
  44. get {
  45. return (IntPtr.Zero == base.handle);
  46. }
  47. }
  48. internal int Length {
  49. get {
  50. return _bufferLength;
  51. }
  52. }
  53. internal string PtrToStringUni(int offset) {
  54. offset += BaseOffset;
  55. Validate(offset, 2);
  56. Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment");
  57. string value = null;
  58. bool mustRelease = false;
  59. RuntimeHelpers.PrepareConstrainedRegions();
  60. try {
  61. DangerousAddRef(ref mustRelease);
  62. IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
  63. int length = UnsafeNativeMethods.lstrlenW(ptr);
  64. Validate(offset, (2*(length+1)));
  65. value = Marshal.PtrToStringUni(ptr, length);
  66. }
  67. finally {
  68. if (mustRelease) {
  69. DangerousRelease();
  70. }
  71. }
  72. return value;
  73. }
  74. internal String PtrToStringUni(int offset, int length) {
  75. offset += BaseOffset;
  76. Validate(offset, 2*length);
  77. Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment");
  78. string value = null;
  79. bool mustRelease = false;
  80. RuntimeHelpers.PrepareConstrainedRegions();
  81. try {
  82. DangerousAddRef(ref mustRelease);
  83. IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
  84. value = Marshal.PtrToStringUni(ptr, length);
  85. }
  86. finally {
  87. if (mustRelease) {
  88. DangerousRelease();
  89. }
  90. }
  91. return value;
  92. }
  93. internal byte ReadByte(int offset) {
  94. offset += BaseOffset;
  95. ValidateCheck(offset, 1);
  96. Debug.Assert(0 == offset%4, "invalid alignment");
  97. byte value;
  98. bool mustRelease = false;
  99. RuntimeHelpers.PrepareConstrainedRegions();
  100. try {
  101. DangerousAddRef(ref mustRelease);
  102. IntPtr ptr = DangerousGetHandle();
  103. value = Marshal.ReadByte(ptr, offset);
  104. }
  105. finally {
  106. if (mustRelease) {
  107. DangerousRelease();
  108. }
  109. }
  110. return value;
  111. }
  112. internal byte[] ReadBytes(int offset, int length) {
  113. byte[] value = new byte[length];
  114. return ReadBytes(offset, value, 0, length);
  115. }
  116. internal byte[] ReadBytes(int offset, byte[] destination, int startIndex, int length) {
  117. offset += BaseOffset;
  118. Validate(offset, length);
  119. Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment");
  120. Debug.Assert(null != destination, "null destination");
  121. Debug.Assert(startIndex + length <= destination.Length, "destination too small");
  122. bool mustRelease = false;
  123. RuntimeHelpers.PrepareConstrainedRegions();
  124. try {
  125. DangerousAddRef(ref mustRelease);
  126. IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
  127. Marshal.Copy(ptr, destination, startIndex, length);
  128. }
  129. finally {
  130. if (mustRelease) {
  131. DangerousRelease();
  132. }
  133. }
  134. return destination;
  135. }
  136. internal Char ReadChar(int offset) {
  137. short value = ReadInt16(offset);
  138. return unchecked((char)value);
  139. }
  140. internal char[] ReadChars(int offset, char[] destination, int startIndex, int length) {
  141. offset += BaseOffset;
  142. Validate(offset, 2*length);
  143. Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment");
  144. Debug.Assert(null != destination, "null destination");
  145. Debug.Assert(startIndex + length <= destination.Length, "destination too small");
  146. bool mustRelease = false;
  147. RuntimeHelpers.PrepareConstrainedRegions();
  148. try {
  149. DangerousAddRef(ref mustRelease);
  150. IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
  151. Marshal.Copy(ptr, destination, startIndex, length);
  152. }
  153. finally {
  154. if (mustRelease) {
  155. DangerousRelease();
  156. }
  157. }
  158. return destination;
  159. }
  160. internal Double ReadDouble(int offset) {
  161. Int64 value = ReadInt64(offset);
  162. return BitConverter.Int64BitsToDouble(value);
  163. }
  164. internal Int16 ReadInt16(int offset) {
  165. offset += BaseOffset;
  166. ValidateCheck(offset, 2);
  167. Debug.Assert(0 == offset%2, "invalid alignment");
  168. short value;
  169. bool mustRelease = false;
  170. RuntimeHelpers.PrepareConstrainedRegions();
  171. try {
  172. DangerousAddRef(ref mustRelease);
  173. IntPtr ptr = DangerousGetHandle();
  174. value = Marshal.ReadInt16(ptr, offset);
  175. }
  176. finally {
  177. if (mustRelease) {
  178. DangerousRelease();
  179. }
  180. }
  181. return value;
  182. }
  183. internal void ReadInt16Array(int offset, short[] destination, int startIndex, int length) {
  184. offset += BaseOffset;
  185. Validate(offset, 2*length);
  186. Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment");
  187. Debug.Assert(null != destination, "null destination");
  188. Debug.Assert(startIndex + length <= destination.Length, "destination too small");
  189. bool mustRelease = false;
  190. RuntimeHelpers.PrepareConstrainedRegions();
  191. try {
  192. DangerousAddRef(ref mustRelease);
  193. IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
  194. Marshal.Copy(ptr, destination, startIndex, length);
  195. }
  196. finally {
  197. if (mustRelease) {
  198. DangerousRelease();
  199. }
  200. }
  201. }
  202. internal Int32 ReadInt32(int offset) {
  203. offset += BaseOffset;
  204. ValidateCheck(offset, 4);
  205. Debug.Assert(0 == offset%4, "invalid alignment");
  206. int value;
  207. bool mustRelease = false;
  208. RuntimeHelpers.PrepareConstrainedRegions();
  209. try {
  210. DangerousAddRef(ref mustRelease);
  211. IntPtr ptr = DangerousGetHandle();
  212. value = Marshal.ReadInt32(ptr, offset);
  213. }
  214. finally {
  215. if (mustRelease) {
  216. DangerousRelease();
  217. }
  218. }
  219. return value;
  220. }
  221. internal void ReadInt32Array(int offset, int[] destination, int startIndex, int length) {
  222. offset += BaseOffset;
  223. Validate(offset, 4*length);
  224. Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment");
  225. Debug.Assert(null != destination, "null destination");
  226. Debug.Assert(startIndex + length <= destination.Length, "destination too small");
  227. bool mustRelease = false;
  228. RuntimeHelpers.PrepareConstrainedRegions();
  229. try {
  230. DangerousAddRef(ref mustRelease);
  231. IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
  232. Marshal.Copy(ptr, destination, startIndex, length);
  233. }
  234. finally {
  235. if (mustRelease) {
  236. DangerousRelease();
  237. }
  238. }
  239. }
  240. internal Int64 ReadInt64(int offset) {
  241. offset += BaseOffset;
  242. ValidateCheck(offset, 8);
  243. Debug.Assert(0 == offset%IntPtr.Size, "invalid alignment");
  244. long value;
  245. bool mustRelease = false;
  246. RuntimeHelpers.PrepareConstrainedRegions();
  247. try {
  248. DangerousAddRef(ref mustRelease);
  249. IntPtr ptr = DangerousGetHandle();
  250. value = Marshal.ReadInt64(ptr, offset);
  251. }
  252. finally {
  253. if (mustRelease) {
  254. DangerousRelease();
  255. }
  256. }
  257. return value;
  258. }
  259. internal IntPtr ReadIntPtr(int offset) {
  260. offset += BaseOffset;
  261. ValidateCheck(offset, IntPtr.Size);
  262. Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment");
  263. IntPtr value;
  264. bool mustRelease = false;
  265. RuntimeHelpers.PrepareConstrainedRegions();
  266. try {
  267. DangerousAddRef(ref mustRelease);
  268. IntPtr ptr = DangerousGetHandle();
  269. value = Marshal.ReadIntPtr(ptr, offset);
  270. }
  271. finally {
  272. if (mustRelease) {
  273. DangerousRelease();
  274. }
  275. }
  276. return value;
  277. }
  278. internal unsafe Single ReadSingle(int offset) {
  279. Int32 value = ReadInt32(offset);
  280. return *(Single*)&value;
  281. }
  282. override protected bool ReleaseHandle() {
  283. // NOTE: The SafeHandle class guarantees this will be called exactly once.
  284. IntPtr ptr = base.handle;
  285. base.handle = IntPtr.Zero;
  286. if (IntPtr.Zero != ptr) {
  287. SafeNativeMethods.LocalFree(ptr);
  288. }
  289. return true;
  290. }
  291. private void StructureToPtr(int offset, object structure) {
  292. Debug.Assert(null != structure, "null structure");
  293. offset += BaseOffset;
  294. ValidateCheck(offset, Marshal.SizeOf(structure.GetType()));
  295. Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment");
  296. bool mustRelease = false;
  297. RuntimeHelpers.PrepareConstrainedRegions();
  298. try {
  299. DangerousAddRef(ref mustRelease);
  300. IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
  301. Marshal.StructureToPtr(structure, ptr, false/*fDeleteOld*/);
  302. }
  303. finally {
  304. if (mustRelease) {
  305. DangerousRelease();
  306. }
  307. }
  308. }
  309. internal void WriteByte(int offset, byte value) {
  310. offset += BaseOffset;
  311. ValidateCheck(offset, 1);
  312. Debug.Assert(0 == offset%4, "invalid alignment");
  313. bool mustRelease = false;
  314. RuntimeHelpers.PrepareConstrainedRegions();
  315. try {
  316. DangerousAddRef(ref mustRelease);
  317. IntPtr ptr = DangerousGetHandle();
  318. Marshal.WriteByte(ptr, offset, value);
  319. }
  320. finally {
  321. if (mustRelease) {
  322. DangerousRelease();
  323. }
  324. }
  325. }
  326. internal void WriteBytes(int offset, byte[] source, int startIndex, int length) {
  327. offset += BaseOffset;
  328. Validate(offset, length);
  329. Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment");
  330. Debug.Assert(null != source, "null source");
  331. Debug.Assert(startIndex + length <= source.Length, "source too small");
  332. bool mustRelease = false;
  333. RuntimeHelpers.PrepareConstrainedRegions();
  334. try {
  335. DangerousAddRef(ref mustRelease);
  336. IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
  337. Marshal.Copy(source, startIndex, ptr, length);
  338. }
  339. finally {
  340. if (mustRelease) {
  341. DangerousRelease();
  342. }
  343. }
  344. }
  345. internal void WriteCharArray(int offset, char[] source, int startIndex, int length) {
  346. offset += BaseOffset;
  347. Validate(offset, 2*length);
  348. Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment");
  349. Debug.Assert(null != source, "null source");
  350. Debug.Assert(startIndex + length <= source.Length, "source too small");
  351. bool mustRelease = false;
  352. RuntimeHelpers.PrepareConstrainedRegions();
  353. try {
  354. DangerousAddRef(ref mustRelease);
  355. IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
  356. Marshal.Copy(source, startIndex, ptr, length);
  357. }
  358. finally {
  359. if (mustRelease) {
  360. DangerousRelease();
  361. }
  362. }
  363. }
  364. internal void WriteDouble(int offset, Double value) {
  365. WriteInt64(offset, BitConverter.DoubleToInt64Bits(value));
  366. }
  367. internal void WriteInt16(int offset, short value) {
  368. offset += BaseOffset;
  369. ValidateCheck(offset, 2);
  370. Debug.Assert(0 == offset%2, "invalid alignment");
  371. bool mustRelease = false;
  372. RuntimeHelpers.PrepareConstrainedRegions();
  373. try {
  374. DangerousAddRef(ref mustRelease);
  375. IntPtr ptr = DangerousGetHandle();
  376. Marshal.WriteInt16(ptr, offset, value);
  377. }
  378. finally {
  379. if (mustRelease) {
  380. DangerousRelease();
  381. }
  382. }
  383. }
  384. internal void WriteInt16Array(int offset, short[] source, int startIndex, int length) {
  385. offset += BaseOffset;
  386. Validate(offset, 2*length);
  387. Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment");
  388. Debug.Assert(null != source, "null source");
  389. Debug.Assert(startIndex + length <= source.Length, "source too small");
  390. bool mustRelease = false;
  391. RuntimeHelpers.PrepareConstrainedRegions();
  392. try {
  393. DangerousAddRef(ref mustRelease);
  394. IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
  395. Marshal.Copy(source, startIndex, ptr, length);
  396. }
  397. finally {
  398. if (mustRelease) {
  399. DangerousRelease();
  400. }
  401. }
  402. }
  403. internal void WriteInt32(int offset, int value) {
  404. offset += BaseOffset;
  405. ValidateCheck(offset, 4);
  406. Debug.Assert(0 == offset%4, "invalid alignment");
  407. bool mustRelease = false;
  408. RuntimeHelpers.PrepareConstrainedRegions();
  409. try {
  410. DangerousAddRef(ref mustRelease);
  411. IntPtr ptr = DangerousGetHandle();
  412. Marshal.WriteInt32(ptr, offset, value);
  413. }
  414. finally {
  415. if (mustRelease) {
  416. DangerousRelease();
  417. }
  418. }
  419. }
  420. internal void WriteInt32Array(int offset, int[] source, int startIndex, int length) {
  421. offset += BaseOffset;
  422. Validate(offset, 4*length);
  423. Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment");
  424. Debug.Assert(null != source, "null source");
  425. Debug.Assert(startIndex + length <= source.Length, "source too small");
  426. bool mustRelease = false;
  427. RuntimeHelpers.PrepareConstrainedRegions();
  428. try {
  429. DangerousAddRef(ref mustRelease);
  430. IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
  431. Marshal.Copy(source, startIndex, ptr, length);
  432. }
  433. finally {
  434. if (mustRelease) {
  435. DangerousRelease();
  436. }
  437. }
  438. }
  439. internal void WriteInt64(int offset, long value) {
  440. offset += BaseOffset;
  441. ValidateCheck(offset, 8);
  442. Debug.Assert(0 == offset%IntPtr.Size, "invalid alignment");
  443. bool mustRelease = false;
  444. RuntimeHelpers.PrepareConstrainedRegions();
  445. try {
  446. DangerousAddRef(ref mustRelease);
  447. IntPtr ptr = DangerousGetHandle();
  448. Marshal.WriteInt64(ptr, offset, value);
  449. }
  450. finally {
  451. if (mustRelease) {
  452. DangerousRelease();
  453. }
  454. }
  455. }
  456. internal void WriteIntPtr(int offset, IntPtr value) {
  457. offset += BaseOffset;
  458. ValidateCheck(offset, IntPtr.Size);
  459. Debug.Assert(0 == offset%IntPtr.Size, "invalid alignment");
  460. bool mustRelease = false;
  461. RuntimeHelpers.PrepareConstrainedRegions();
  462. try {
  463. DangerousAddRef(ref mustRelease);
  464. IntPtr ptr = DangerousGetHandle();
  465. Marshal.WriteIntPtr(ptr, offset, value);
  466. }
  467. finally {
  468. if (mustRelease) {
  469. DangerousRelease();
  470. }
  471. }
  472. }
  473. internal unsafe void WriteSingle(int offset, Single value) {
  474. WriteInt32(offset, *(Int32*)&value);
  475. }
  476. internal void ZeroMemory() {
  477. bool mustRelease = false;
  478. RuntimeHelpers.PrepareConstrainedRegions();
  479. try {
  480. DangerousAddRef(ref mustRelease);
  481. IntPtr ptr = DangerousGetHandle();
  482. SafeNativeMethods.ZeroMemory(ptr, (IntPtr)Length);
  483. }
  484. finally {
  485. if (mustRelease) {
  486. DangerousRelease();
  487. }
  488. }
  489. }
  490. internal Guid ReadGuid(int offset) {
  491. // faster than Marshal.PtrToStructure(offset, typeof(Guid))
  492. byte[] buffer = new byte[16];
  493. ReadBytes(offset, buffer, 0, 16);
  494. return new Guid(buffer);
  495. }
  496. internal void WriteGuid(int offset, Guid value) {
  497. // faster than Marshal.Copy(value.GetByteArray()
  498. StructureToPtr(offset, value);
  499. }
  500. internal DateTime ReadDate(int offset) {
  501. short[] buffer = new short[3];
  502. ReadInt16Array(offset, buffer, 0, 3);
  503. return new DateTime(
  504. unchecked((ushort)buffer[0]), // Year
  505. unchecked((ushort)buffer[1]), // Month
  506. unchecked((ushort)buffer[2])); // Day
  507. }
  508. internal void WriteDate(int offset, DateTime value) {
  509. short[] buffer = new short[3] {
  510. unchecked((short)value.Year),
  511. unchecked((short)value.Month),
  512. unchecked((short)value.Day),
  513. };
  514. WriteInt16Array(offset, buffer, 0, 3);
  515. }
  516. internal TimeSpan ReadTime(int offset) {
  517. short[] buffer = new short[3];
  518. ReadInt16Array(offset, buffer, 0, 3);
  519. return new TimeSpan(
  520. unchecked((ushort)buffer[0]), // Hours
  521. unchecked((ushort)buffer[1]), // Minutes
  522. unchecked((ushort)buffer[2])); // Seconds
  523. }
  524. internal void WriteTime(int offset, TimeSpan value) {
  525. short[] buffer = new short[3] {
  526. unchecked((short)value.Hours),
  527. unchecked((short)value.Minutes),
  528. unchecked((short)value.Seconds),
  529. };
  530. WriteInt16Array(offset, buffer, 0, 3);
  531. }
  532. internal DateTime ReadDateTime(int offset) {
  533. short[] buffer = new short[6];
  534. ReadInt16Array(offset, buffer, 0, 6);
  535. int ticks = ReadInt32(offset + 12);
  536. DateTime value = new DateTime(
  537. unchecked((ushort)buffer[0]), // Year
  538. unchecked((ushort)buffer[1]), // Month
  539. unchecked((ushort)buffer[2]), // Day
  540. unchecked((ushort)buffer[3]), // Hours
  541. unchecked((ushort)buffer[4]), // Minutes
  542. unchecked((ushort)buffer[5])); // Seconds
  543. return value.AddTicks(ticks / 100);
  544. }
  545. internal void WriteDateTime(int offset, DateTime value) {
  546. int ticks = (int)(value.Ticks % 10000000L)*100;
  547. short[] buffer = new short[6] {
  548. unchecked((short)value.Year),
  549. unchecked((short)value.Month),
  550. unchecked((short)value.Day),
  551. unchecked((short)value.Hour),
  552. unchecked((short)value.Minute),
  553. unchecked((short)value.Second),
  554. };
  555. WriteInt16Array(offset, buffer, 0, 6);
  556. WriteInt32(offset + 12, ticks);
  557. }
  558. internal Decimal ReadNumeric(int offset) {
  559. byte[] bits = new byte[20];
  560. ReadBytes(offset, bits, 1, 19);
  561. int[] buffer = new int[4];
  562. buffer[3] = ((int) bits[2]) << 16; // scale
  563. if (0 == bits[3]) {
  564. buffer[3] |= unchecked((int)0x80000000); //sign
  565. }
  566. buffer[0] = BitConverter.ToInt32(bits, 4); // low
  567. buffer[1] = BitConverter.ToInt32(bits, 8); // mid
  568. buffer[2] = BitConverter.ToInt32(bits, 12); // high
  569. if (0 != BitConverter.ToInt32(bits, 16)) {
  570. throw ADP.NumericToDecimalOverflow();
  571. }
  572. return new Decimal(buffer);
  573. }
  574. internal void WriteNumeric(int offset, Decimal value, byte precision) {
  575. int[] tmp = Decimal.GetBits(value);
  576. byte[] buffer = new byte[20];
  577. buffer[1] = precision;
  578. Buffer.BlockCopy(tmp, 14, buffer, 2, 2); // copy sign and scale
  579. buffer[3] = (Byte) ((0 == buffer[3]) ? 1 : 0); // flip sign for native
  580. Buffer.BlockCopy(tmp, 0, buffer, 4, 12);
  581. buffer[16] = 0;
  582. buffer[17] = 0;
  583. buffer[18] = 0;
  584. buffer[19] = 0;
  585. WriteBytes(offset, buffer, 1, 19);
  586. }
  587. [ConditionalAttribute("DEBUG")]
  588. protected void ValidateCheck(int offset, int count) {
  589. Validate(offset, count);
  590. }
  591. protected void Validate(int offset, int count) {
  592. if ((offset < 0) || (count < 0) || (Length < checked(offset + count))) {
  593. throw ADP.InternalError(ADP.InternalErrorCode.InvalidBuffer);
  594. }
  595. }
  596. }
  597. }