FieldNameLookup.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. //------------------------------------------------------------------------------
  2. // <copyright file="FieldNameLookup.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. // <owner current="true" primary="true">Microsoft</owner>
  6. // <owner current="true" primary="false">Microsoft</owner>
  7. //------------------------------------------------------------------------------
  8. namespace System.Data.ProviderBase {
  9. using System;
  10. using System.Collections;
  11. using System.ComponentModel;
  12. using System.Data;
  13. using System.Data.Common;
  14. using System.Diagnostics;
  15. using System.Globalization;
  16. using System.Text;
  17. internal sealed class FieldNameLookup { // V1.2.3300, MDAC 69015, 71470
  18. // hashtable stores the index into the _fieldNames, match via case-sensitive
  19. private Hashtable _fieldNameLookup;
  20. // original names for linear searches when exact matches fail
  21. private string[] _fieldNames;
  22. // if _defaultLocaleID is -1 then _compareInfo is initialized with InvariantCulture CompareInfo
  23. // otherwise it is specified by the server? for the correct compare info
  24. private CompareInfo _compareInfo;
  25. private int _defaultLocaleID;
  26. public FieldNameLookup(string[] fieldNames, int defaultLocaleID) { // V1.2.3300
  27. if (null == fieldNames) {
  28. throw ADP.ArgumentNull("fieldNames");
  29. }
  30. _fieldNames = fieldNames;
  31. _defaultLocaleID = defaultLocaleID;
  32. }
  33. public FieldNameLookup(System.Collections.ObjectModel.ReadOnlyCollection<string> columnNames, int defaultLocaleID) {
  34. int length = columnNames.Count;
  35. string[] fieldNames = new string[length];
  36. for (int i = 0; i < length; ++i) {
  37. fieldNames[i] = columnNames[i];
  38. Debug.Assert(null != fieldNames[i], "MDAC 66681");
  39. }
  40. _fieldNames = fieldNames;
  41. _defaultLocaleID = defaultLocaleID;
  42. GenerateLookup();
  43. }
  44. public FieldNameLookup(IDataRecord reader, int defaultLocaleID) { // V1.2.3300
  45. int length = reader.FieldCount;
  46. string[] fieldNames = new string[length];
  47. for (int i = 0; i < length; ++i) {
  48. fieldNames[i] = reader.GetName(i);
  49. Debug.Assert(null != fieldNames[i], "MDAC 66681");
  50. }
  51. _fieldNames = fieldNames;
  52. _defaultLocaleID = defaultLocaleID;
  53. }
  54. public int GetOrdinal(string fieldName) { // V1.2.3300
  55. if (null == fieldName) {
  56. throw ADP.ArgumentNull("fieldName");
  57. }
  58. int index = IndexOf(fieldName);
  59. if (-1 == index) {
  60. throw ADP.IndexOutOfRange(fieldName);
  61. }
  62. return index;
  63. }
  64. public int IndexOfName(string fieldName) { // V1.2.3300
  65. if (null == _fieldNameLookup) {
  66. GenerateLookup();
  67. }
  68. // via case sensitive search, first match with lowest ordinal matches
  69. object value = _fieldNameLookup[fieldName];
  70. return ((null != value) ? (int) value : -1);
  71. }
  72. public int IndexOf(string fieldName) { // V1.2.3300
  73. if (null == _fieldNameLookup) {
  74. GenerateLookup();
  75. }
  76. int index;
  77. object value = _fieldNameLookup[fieldName];
  78. if (null != value) {
  79. // via case sensitive search, first match with lowest ordinal matches
  80. index = (int) value;
  81. }
  82. else {
  83. // via case insensitive search, first match with lowest ordinal matches
  84. index = LinearIndexOf(fieldName, CompareOptions.IgnoreCase);
  85. if (-1 == index) {
  86. // do the slow search now (kana, width insensitive comparison)
  87. index = LinearIndexOf(fieldName, ADP.compareOptions);
  88. }
  89. }
  90. return index;
  91. }
  92. private int LinearIndexOf(string fieldName, CompareOptions compareOptions) {
  93. CompareInfo compareInfo = _compareInfo;
  94. if (null == compareInfo) {
  95. if (-1 != _defaultLocaleID) {
  96. compareInfo = CompareInfo.GetCompareInfo(_defaultLocaleID);
  97. }
  98. if (null == compareInfo) {
  99. compareInfo = CultureInfo.InvariantCulture.CompareInfo;
  100. }
  101. _compareInfo = compareInfo;
  102. }
  103. int length = _fieldNames.Length;
  104. for (int i = 0; i < length; ++i) {
  105. if (0 == compareInfo.Compare(fieldName, _fieldNames[i], compareOptions)) {
  106. _fieldNameLookup[fieldName] = i; // add an exact match for the future
  107. return i;
  108. }
  109. }
  110. return -1;
  111. }
  112. // RTM common code for generating Hashtable from array of column names
  113. private void GenerateLookup() {
  114. int length = _fieldNames.Length;
  115. Hashtable hash = new Hashtable(length);
  116. // via case sensitive search, first match with lowest ordinal matches
  117. for (int i = length-1; 0 <= i; --i) {
  118. string fieldName = _fieldNames[i];
  119. hash[fieldName] = i;
  120. }
  121. _fieldNameLookup = hash;
  122. }
  123. }
  124. }