Line data Source code
1 0 : /*
2 : OOISNumberLiteral.m
3 :
4 : Copyright (C) 2008-2013 Jens Ayton
5 :
6 : Permission is hereby granted, free of charge, to any person obtaining a copy
7 : of this software and associated documentation files (the "Software"), to deal
8 : in the Software without restriction, including without limitation the rights
9 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 : copies of the Software, and to permit persons to whom the Software is
11 : furnished to do so, subject to the following conditions:
12 :
13 : The above copyright notice and this permission notice shall be included in all
14 : copies or substantial portions of the Software.
15 :
16 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 : SOFTWARE.
23 : */
24 :
25 : #import "OOIsNumberLiteral.h"
26 :
27 :
28 : #if 0
29 : #define FAIL(s) do { NSLog(@"OOIsNumberLiteral failed for \"%@\": %@.", string, @s); return NO; } while (0)
30 : #else
31 0 : #define FAIL(s) do { return NO; } while (0)
32 : #endif
33 :
34 :
35 0 : BOOL OOIsNumberLiteral(NSString *string, BOOL allowSpaces)
36 : {
37 : BOOL leadingSpace = allowSpaces,
38 : trailingSpace = NO,
39 : allowSign = YES,
40 : allowE = NO,
41 : hadE = NO,
42 : hadExp = NO,
43 : allowDec = YES,
44 : hadNumber = NO;
45 : NSUInteger i, count;
46 :
47 : if (string == nil) return NO;
48 :
49 : count = [string length];
50 : for (i = 0; i != count; ++i)
51 : {
52 : switch ([string characterAtIndex:i])
53 : {
54 : // <digit>
55 : case '0':
56 : case '1':
57 : case '2':
58 : case '3':
59 : case '4':
60 : case '5':
61 : case '6':
62 : case '7':
63 : case '8':
64 : case '9':
65 : leadingSpace = NO;
66 : if (trailingSpace) FAIL("Digit after trailing whitespace");
67 : if (!hadE) allowE = YES;
68 : else hadExp = YES;
69 : allowSign = NO;
70 : hadNumber = YES;
71 : break;
72 :
73 : // <whitespaceChar>
74 : case ' ':
75 : case '\t':
76 : if (leadingSpace || trailingSpace) break;
77 : if (hadNumber && allowSpaces)
78 : {
79 : trailingSpace = YES;
80 : allowSign = allowE = allowDec = NO;
81 : break;
82 : }
83 : FAIL("Space in unpermitted position");
84 :
85 : // <sign>
86 : case '-':
87 : case '+':
88 : leadingSpace = NO;
89 : if (allowSign)
90 : {
91 : allowSign = NO;
92 : break;
93 : }
94 : FAIL("Sign (+ or -) in unpermitted position");
95 :
96 : // <decimalPoint>
97 : case '.':
98 : leadingSpace = NO;
99 : if (allowDec)
100 : {
101 : allowDec = NO;
102 : continue;
103 : }
104 : FAIL("Sign (+ or -) in unpermitted position");
105 :
106 : // <e>
107 : case 'e':
108 : case 'E':
109 : leadingSpace = NO;
110 : if (allowE)
111 : {
112 : allowE = NO;
113 : allowSign = YES;
114 : allowDec = NO;
115 : hadE = YES;
116 : continue;
117 : }
118 : FAIL("E in unpermitted position");
119 :
120 : default:
121 : FAIL ("Unpermitted character");
122 : }
123 : }
124 :
125 : if (hadE && !hadExp) FAIL("E with no exponent");
126 : if (!hadNumber) FAIL("No digits in string");
127 :
128 : return YES;
129 : }
|