Delete FriendAccessAllowedAttribute and associated dead code (#15101)
[platform/upstream/coreclr.git] / src / mscorlib / src / System / Number.CoreCLR.cs
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 using System.Globalization;
6 using System.Runtime.CompilerServices;
7
8 namespace System
9 {
10     // The Number class implements methods for formatting and parsing
11     // numeric values. To format and parse numeric values, applications should
12     // use the Format and Parse methods provided by the numeric
13     // classes (Byte, Int16, Int32, Int64,
14     // Single, Double, Currency, and Decimal). Those
15     // Format and Parse methods share a common implementation
16     // provided by this class, and are thus documented in detail here.
17     //
18     // Formatting
19     //
20     // The Format methods provided by the numeric classes are all of the
21     // form
22     //
23     //  public static String Format(XXX value, String format);
24     //  public static String Format(XXX value, String format, NumberFormatInfo info);
25     //
26     // where XXX is the name of the particular numeric class. The methods convert
27     // the numeric value to a string using the format string given by the
28     // format parameter. If the format parameter is null or
29     // an empty string, the number is formatted as if the string "G" (general
30     // format) was specified. The info parameter specifies the
31     // NumberFormatInfo instance to use when formatting the number. If the
32     // info parameter is null or omitted, the numeric formatting information
33     // is obtained from the current culture. The NumberFormatInfo supplies
34     // such information as the characters to use for decimal and thousand
35     // separators, and the spelling and placement of currency symbols in monetary
36     // values.
37     //
38     // Format strings fall into two categories: Standard format strings and
39     // user-defined format strings. A format string consisting of a single
40     // alphabetic character (A-Z or a-z), optionally followed by a sequence of
41     // digits (0-9), is a standard format string. All other format strings are
42     // used-defined format strings.
43     //
44     // A standard format string takes the form Axx, where A is an
45     // alphabetic character called the format specifier and xx is a
46     // sequence of digits called the precision specifier. The format
47     // specifier controls the type of formatting applied to the number and the
48     // precision specifier controls the number of significant digits or decimal
49     // places of the formatting operation. The following table describes the
50     // supported standard formats.
51     //
52     // C c - Currency format. The number is
53     // converted to a string that represents a currency amount. The conversion is
54     // controlled by the currency format information of the NumberFormatInfo
55     // used to format the number. The precision specifier indicates the desired
56     // number of decimal places. If the precision specifier is omitted, the default
57     // currency precision given by the NumberFormatInfo is used.
58     //
59     // D d - Decimal format. This format is
60     // supported for integral types only. The number is converted to a string of
61     // decimal digits, prefixed by a minus sign if the number is negative. The
62     // precision specifier indicates the minimum number of digits desired in the
63     // resulting string. If required, the number will be left-padded with zeros to
64     // produce the number of digits given by the precision specifier.
65     //
66     // E e Engineering (scientific) format.
67     // The number is converted to a string of the form
68     // "-d.ddd...E+ddd" or "-d.ddd...e+ddd", where each
69     // 'd' indicates a digit (0-9). The string starts with a minus sign if the
70     // number is negative, and one digit always precedes the decimal point. The
71     // precision specifier indicates the desired number of digits after the decimal
72     // point. If the precision specifier is omitted, a default of 6 digits after
73     // the decimal point is used. The format specifier indicates whether to prefix
74     // the exponent with an 'E' or an 'e'. The exponent is always consists of a
75     // plus or minus sign and three digits.
76     //
77     // F f Fixed point format. The number is
78     // converted to a string of the form "-ddd.ddd....", where each
79     // 'd' indicates a digit (0-9). The string starts with a minus sign if the
80     // number is negative. The precision specifier indicates the desired number of
81     // decimal places. If the precision specifier is omitted, the default numeric
82     // precision given by the NumberFormatInfo is used.
83     //
84     // G g - General format. The number is
85     // converted to the shortest possible decimal representation using fixed point
86     // or scientific format. The precision specifier determines the number of
87     // significant digits in the resulting string. If the precision specifier is
88     // omitted, the number of significant digits is determined by the type of the
89     // number being converted (10 for int, 19 for long, 7 for
90     // float, 15 for double, 19 for Currency, and 29 for
91     // Decimal). Trailing zeros after the decimal point are removed, and the
92     // resulting string contains a decimal point only if required. The resulting
93     // string uses fixed point format if the exponent of the number is less than
94     // the number of significant digits and greater than or equal to -4. Otherwise,
95     // the resulting string uses scientific format, and the case of the format
96     // specifier controls whether the exponent is prefixed with an 'E' or an
97     // 'e'.
98     //
99     // N n Number format. The number is
100     // converted to a string of the form "-d,ddd,ddd.ddd....", where
101     // each 'd' indicates a digit (0-9). The string starts with a minus sign if the
102     // number is negative. Thousand separators are inserted between each group of
103     // three digits to the left of the decimal point. The precision specifier
104     // indicates the desired number of decimal places. If the precision specifier
105     // is omitted, the default numeric precision given by the
106     // NumberFormatInfo is used.
107     //
108     // X x - Hexadecimal format. This format is
109     // supported for integral types only. The number is converted to a string of
110     // hexadecimal digits. The format specifier indicates whether to use upper or
111     // lower case characters for the hexadecimal digits above 9 ('X' for 'ABCDEF',
112     // and 'x' for 'abcdef'). The precision specifier indicates the minimum number
113     // of digits desired in the resulting string. If required, the number will be
114     // left-padded with zeros to produce the number of digits given by the
115     // precision specifier.
116     //
117     // Some examples of standard format strings and their results are shown in the
118     // table below. (The examples all assume a default NumberFormatInfo.)
119     //
120     // Value        Format  Result
121     // 12345.6789   C       $12,345.68
122     // -12345.6789  C       ($12,345.68)
123     // 12345        D       12345
124     // 12345        D8      00012345
125     // 12345.6789   E       1.234568E+004
126     // 12345.6789   E10     1.2345678900E+004
127     // 12345.6789   e4      1.2346e+004
128     // 12345.6789   F       12345.68
129     // 12345.6789   F0      12346
130     // 12345.6789   F6      12345.678900
131     // 12345.6789   G       12345.6789
132     // 12345.6789   G7      12345.68
133     // 123456789    G7      1.234568E8
134     // 12345.6789   N       12,345.68
135     // 123456789    N4      123,456,789.0000
136     // 0x2c45e      x       2c45e
137     // 0x2c45e      X       2C45E
138     // 0x2c45e      X8      0002C45E
139     //
140     // Format strings that do not start with an alphabetic character, or that start
141     // with an alphabetic character followed by a non-digit, are called
142     // user-defined format strings. The following table describes the formatting
143     // characters that are supported in user defined format strings.
144     //
145     // 
146     // 0 - Digit placeholder. If the value being
147     // formatted has a digit in the position where the '0' appears in the format
148     // string, then that digit is copied to the output string. Otherwise, a '0' is
149     // stored in that position in the output string. The position of the leftmost
150     // '0' before the decimal point and the rightmost '0' after the decimal point
151     // determines the range of digits that are always present in the output
152     // string.
153     //
154     // # - Digit placeholder. If the value being
155     // formatted has a digit in the position where the '#' appears in the format
156     // string, then that digit is copied to the output string. Otherwise, nothing
157     // is stored in that position in the output string.
158     //
159     // . - Decimal point. The first '.' character
160     // in the format string determines the location of the decimal separator in the
161     // formatted value; any additional '.' characters are ignored. The actual
162     // character used as a the decimal separator in the output string is given by
163     // the NumberFormatInfo used to format the number.
164     //
165     // , - Thousand separator and number scaling.
166     // The ',' character serves two purposes. First, if the format string contains
167     // a ',' character between two digit placeholders (0 or #) and to the left of
168     // the decimal point if one is present, then the output will have thousand
169     // separators inserted between each group of three digits to the left of the
170     // decimal separator. The actual character used as a the decimal separator in
171     // the output string is given by the NumberFormatInfo used to format the
172     // number. Second, if the format string contains one or more ',' characters
173     // immediately to the left of the decimal point, or after the last digit
174     // placeholder if there is no decimal point, then the number will be divided by
175     // 1000 times the number of ',' characters before it is formatted. For example,
176     // the format string '0,,' will represent 100 million as just 100. Use of the
177     // ',' character to indicate scaling does not also cause the formatted number
178     // to have thousand separators. Thus, to scale a number by 1 million and insert
179     // thousand separators you would use the format string '#,##0,,'.
180     //
181     // % - Percentage placeholder. The presence of
182     // a '%' character in the format string causes the number to be multiplied by
183     // 100 before it is formatted. The '%' character itself is inserted in the
184     // output string where it appears in the format string.
185     //
186     // E+ E- e+ e-   - Scientific notation.
187     // If any of the strings 'E+', 'E-', 'e+', or 'e-' are present in the format
188     // string and are immediately followed by at least one '0' character, then the
189     // number is formatted using scientific notation with an 'E' or 'e' inserted
190     // between the number and the exponent. The number of '0' characters following
191     // the scientific notation indicator determines the minimum number of digits to
192     // output for the exponent. The 'E+' and 'e+' formats indicate that a sign
193     // character (plus or minus) should always precede the exponent. The 'E-' and
194     // 'e-' formats indicate that a sign character should only precede negative
195     // exponents.
196     //
197     // \ - Literal character. A backslash character
198     // causes the next character in the format string to be copied to the output
199     // string as-is. The backslash itself isn't copied, so to place a backslash
200     // character in the output string, use two backslashes (\\) in the format
201     // string.
202     //
203     // 'ABC' "ABC" - Literal string. Characters
204     // enclosed in single or double quotation marks are copied to the output string
205     // as-is and do not affect formatting.
206     //
207     // ; - Section separator. The ';' character is
208     // used to separate sections for positive, negative, and zero numbers in the
209     // format string.
210     //
211     // Other - All other characters are copied to
212     // the output string in the position they appear.
213     //
214     // For fixed point formats (formats not containing an 'E+', 'E-', 'e+', or
215     // 'e-'), the number is rounded to as many decimal places as there are digit
216     // placeholders to the right of the decimal point. If the format string does
217     // not contain a decimal point, the number is rounded to the nearest
218     // integer. If the number has more digits than there are digit placeholders to
219     // the left of the decimal point, the extra digits are copied to the output
220     // string immediately before the first digit placeholder.
221     //
222     // For scientific formats, the number is rounded to as many significant digits
223     // as there are digit placeholders in the format string.
224     //
225     // To allow for different formatting of positive, negative, and zero values, a
226     // user-defined format string may contain up to three sections separated by
227     // semicolons. The results of having one, two, or three sections in the format
228     // string are described in the table below.
229     //
230     // Sections:
231     //
232     // One - The format string applies to all values.
233     //
234     // Two - The first section applies to positive values
235     // and zeros, and the second section applies to negative values. If the number
236     // to be formatted is negative, but becomes zero after rounding according to
237     // the format in the second section, then the resulting zero is formatted
238     // according to the first section.
239     //
240     // Three - The first section applies to positive
241     // values, the second section applies to negative values, and the third section
242     // applies to zeros. The second section may be left empty (by having no
243     // characters between the semicolons), in which case the first section applies
244     // to all non-zero values. If the number to be formatted is non-zero, but
245     // becomes zero after rounding according to the format in the first or second
246     // section, then the resulting zero is formatted according to the third
247     // section.
248     //
249     // For both standard and user-defined formatting operations on values of type
250     // float and double, if the value being formatted is a NaN (Not
251     // a Number) or a positive or negative infinity, then regardless of the format
252     // string, the resulting string is given by the NaNSymbol,
253     // PositiveInfinitySymbol, or NegativeInfinitySymbol property of
254     // the NumberFormatInfo used to format the number.
255     //
256     // Parsing
257     //
258     // The Parse methods provided by the numeric classes are all of the form
259     //
260     //  public static XXX Parse(String s);
261     //  public static XXX Parse(String s, int style);
262     //  public static XXX Parse(String s, int style, NumberFormatInfo info);
263     //
264     // where XXX is the name of the particular numeric class. The methods convert a
265     // string to a numeric value. The optional style parameter specifies the
266     // permitted style of the numeric string. It must be a combination of bit flags
267     // from the NumberStyles enumeration. The optional info parameter
268     // specifies the NumberFormatInfo instance to use when parsing the
269     // string. If the info parameter is null or omitted, the numeric
270     // formatting information is obtained from the current culture.
271     //
272     // Numeric strings produced by the Format methods using the Currency,
273     // Decimal, Engineering, Fixed point, General, or Number standard formats
274     // (the C, D, E, F, G, and N format specifiers) are guaranteed to be parseable
275     // by the Parse methods if the NumberStyles.Any style is
276     // specified. Note, however, that the Parse methods do not accept
277     // NaNs or Infinities.
278     internal static partial class Number
279     {
280         [MethodImpl(MethodImplOptions.InternalCall)]
281         public static extern string FormatDecimal(decimal value, string format, NumberFormatInfo info);
282
283         [MethodImpl(MethodImplOptions.InternalCall)]
284         public static extern string FormatDouble(double value, string format, NumberFormatInfo info);
285
286         [MethodImpl(MethodImplOptions.InternalCall)]
287         public static extern string FormatSingle(float value, string format, NumberFormatInfo info);
288
289         public static unsafe bool NumberBufferToDecimal(ref Number.NumberBuffer number, ref decimal value)
290         {
291             fixed (Number.NumberBuffer* numberPtr = &number)
292             {
293                 return NumberBufferToDecimal((byte*)numberPtr, ref value);
294             }
295         }
296
297         public static unsafe bool NumberBufferToDouble(ref Number.NumberBuffer number, ref double value)
298         {
299             fixed (Number.NumberBuffer* numberPtr = &number)
300             {
301                 return NumberBufferToDouble((byte*)numberPtr, ref value);
302             }
303         }
304
305         [MethodImpl(MethodImplOptions.InternalCall)]
306         private unsafe static extern bool NumberBufferToDecimal(byte* number, ref decimal value);
307
308         [MethodImpl(MethodImplOptions.InternalCall)]
309         private unsafe static extern bool NumberBufferToDouble(byte* number, ref double value);
310     }
311 }