Lucene.Net  3.0.3
Lucene.Net is a port of the Lucene search engine library, written in C# and targeted at .NET runtime users.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Pages
NumberTools.cs
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 using System;
19 using Lucene.Net.Search;
20 using NumericUtils = Lucene.Net.Util.NumericUtils;
21 
22 namespace Lucene.Net.Documents
23 {
24 
25  // do not remove this class in 3.0, it may be needed to decode old indexes!
26 
27  /// <summary> Provides support for converting longs to Strings, and back again. The strings
28  /// are structured so that lexicographic sorting order is preserved.
29  ///
30  /// <p/>
31  /// That is, if l1 is less than l2 for any two longs l1 and l2, then
32  /// NumberTools.longToString(l1) is lexicographically less than
33  /// NumberTools.longToString(l2). (Similarly for "greater than" and "equals".)
34  ///
35  /// <p/>
36  /// This class handles <b>all</b> long values (unlike
37  /// <see cref="Lucene.Net.Documents.DateField" />).
38  ///
39  /// </summary>
40  /// <deprecated> For new indexes use <see cref="NumericUtils" /> instead, which
41  /// provides a sortable binary representation (prefix encoded) of numeric
42  /// values.
43  /// To index and efficiently query numeric values use <see cref="NumericField" />
44  /// and <see cref="NumericRangeQuery{T}" />.
45  /// This class is included for use with existing
46  /// indices and will be removed in a future release (possibly Lucene 4.0).
47  /// </deprecated>
48  [Obsolete("For new indexes use NumericUtils instead, which provides a sortable binary representation (prefix encoded) of numeric values. To index and efficiently query numeric values use NumericField and NumericRangeQuery. This class is included for use with existing indices and will be removed in a future release (possibly Lucene 4.0).")]
49  public class NumberTools
50  {
51 
52  private const int RADIX = 36;
53 
54  private const char NEGATIVE_PREFIX = '-';
55 
56  // NB: NEGATIVE_PREFIX must be < POSITIVE_PREFIX
57  private const char POSITIVE_PREFIX = '0';
58 
59  //NB: this must be less than
60  /// <summary> Equivalent to longToString(Long.MIN_VALUE)</summary>
61 #if !PRE_LUCENE_NET_2_0_0_COMPATIBLE
62  public static readonly System.String MIN_STRING_VALUE = NEGATIVE_PREFIX + "0000000000000";
63 #else
64  public static readonly System.String MIN_STRING_VALUE = NEGATIVE_PREFIX + "0000000000000000";
65 #endif
66 
67  /// <summary> Equivalent to longToString(Long.MAX_VALUE)</summary>
68 #if !PRE_LUCENE_NET_2_0_0_COMPATIBLE
69  public static readonly System.String MAX_STRING_VALUE = POSITIVE_PREFIX + "1y2p0ij32e8e7";
70 #else
71  public static readonly System.String MAX_STRING_VALUE = POSITIVE_PREFIX + "7fffffffffffffff";
72 #endif
73 
74  /// <summary> The length of (all) strings returned by <see cref="LongToString" /></summary>
75  public static readonly int STR_SIZE = MIN_STRING_VALUE.Length;
76 
77  /// <summary> Converts a long to a String suitable for indexing.</summary>
78  public static System.String LongToString(long l)
79  {
80 
81  if (l == System.Int64.MinValue)
82  {
83  // special case, because long is not symmetric around zero
84  return MIN_STRING_VALUE;
85  }
86 
87  System.Text.StringBuilder buf = new System.Text.StringBuilder(STR_SIZE);
88 
89  if (l < 0)
90  {
91  buf.Append(NEGATIVE_PREFIX);
92  l = System.Int64.MaxValue + l + 1;
93  }
94  else
95  {
96  buf.Append(POSITIVE_PREFIX);
97  }
98 #if !PRE_LUCENE_NET_2_0_0_COMPATIBLE
99  System.String num = ToString(l);
100 #else
101  System.String num = System.Convert.ToString(l, RADIX);
102 #endif
103 
104  int padLen = STR_SIZE - num.Length - buf.Length;
105  while (padLen-- > 0)
106  {
107  buf.Append('0');
108  }
109  buf.Append(num);
110 
111  return buf.ToString();
112  }
113 
114  /// <summary> Converts a String that was returned by <see cref="LongToString" /> back to a
115  /// long.
116  ///
117  /// </summary>
118  /// <throws> IllegalArgumentException </throws>
119  /// <summary> if the input is null
120  /// </summary>
121  /// <throws> NumberFormatException </throws>
122  /// <summary> if the input does not parse (it was not a String returned by
123  /// longToString()).
124  /// </summary>
125  public static long StringToLong(System.String str)
126  {
127  if (str == null)
128  {
129  throw new System.NullReferenceException("string cannot be null");
130  }
131  if (str.Length != STR_SIZE)
132  {
133  throw new System.FormatException("string is the wrong size");
134  }
135 
136  if (str.Equals(MIN_STRING_VALUE))
137  {
138  return System.Int64.MinValue;
139  }
140 
141  char prefix = str[0];
142 #if !PRE_LUCENE_NET_2_0_0_COMPATIBLE
143  long l = ToLong(str.Substring(1));
144 #else
145  long l = System.Convert.ToInt64(str.Substring(1), RADIX);
146 #endif
147 
148  if (prefix == POSITIVE_PREFIX)
149  {
150  // nop
151  }
152  else if (prefix == NEGATIVE_PREFIX)
153  {
154  l = l - System.Int64.MaxValue - 1;
155  }
156  else
157  {
158  throw new System.FormatException("string does not begin with the correct prefix");
159  }
160 
161  return l;
162  }
163 
164 #if !PRE_LUCENE_NET_2_0_0_COMPATIBLE
165  #region BASE36 OPS
166  static System.String digits = "0123456789abcdefghijklmnopqrstuvwxyz";
167  static long[] powersOf36 =
168  {
169  1L,
170  36L,
171  36L*36L,
172  36L*36L*36L,
173  36L*36L*36L*36L,
174  36L*36L*36L*36L*36L,
175  36L*36L*36L*36L*36L*36L,
176  36L*36L*36L*36L*36L*36L*36L,
177  36L*36L*36L*36L*36L*36L*36L*36L,
178  36L*36L*36L*36L*36L*36L*36L*36L*36L,
179  36L*36L*36L*36L*36L*36L*36L*36L*36L*36L,
180  36L*36L*36L*36L*36L*36L*36L*36L*36L*36L*36L,
181  36L*36L*36L*36L*36L*36L*36L*36L*36L*36L*36L*36L
182  };
183 
184  public static System.String ToString(long lval)
185  {
186  if (lval == 0)
187  {
188  return "0";
189  }
190 
191  int maxStrLen = powersOf36.Length;
192  long curval = lval;
193 
194  char[] tb = new char[maxStrLen];
195  int outpos = 0;
196  for (int i = 0; i < maxStrLen; i++)
197  {
198  long pval = powersOf36[maxStrLen - i - 1];
199  int pos = (int)(curval / pval);
200  tb[outpos++] = digits.Substring(pos, 1).ToCharArray()[0];
201  curval = curval % pval;
202  }
203  if (outpos == 0)
204  tb[outpos++] = '0';
205  return new System.String(tb, 0, outpos).TrimStart('0');
206  }
207 
208  public static long ToLong(System.String t)
209  {
210  long ival = 0;
211  char[] tb = t.ToCharArray();
212  for (int i = 0; i < tb.Length; i++)
213  {
214  ival += powersOf36[i] * digits.IndexOf(tb[tb.Length - i - 1]);
215  }
216  return ival;
217  }
218  #endregion
219 #endif
220  }
221 }