@@ -152,33 +152,14 @@ public int getInt(int columnIndex) throws SQLException {
152152 case Value .Null n -> 0 ;
153153 case Value .Integer i -> (int ) i .value ();
154154 case Value .Float f -> (int ) f .value ();
155- case Value .Text t -> {
156- try {
157- yield Integer .parseInt (t .value ());
158- } catch (NumberFormatException e ) {
159- throw new SQLException ("Bad value for type Integer: " + t .value (), e );
160- }
161- }
162- case Value .Blob b -> 0 ;
155+ case Value .Text t -> (int ) parseSqliteLong (t .value ());
156+ case Value .Blob b -> (int ) parseSqliteLong (blobAsText (b ));
163157 };
164158 }
165159
166160 @ Override
167161 public long getLong (int columnIndex ) throws SQLException {
168- Value val = getCurrentValue (columnIndex );
169- return switch (val ) {
170- case Value .Null n -> 0L ;
171- case Value .Integer i -> i .value ();
172- case Value .Float f -> (long ) f .value ();
173- case Value .Text t -> {
174- try {
175- yield Long .parseLong (t .value ());
176- } catch (NumberFormatException e ) {
177- throw new SQLException ("Bad value for type Long: " + t .value (), e );
178- }
179- }
180- case Value .Blob b -> 0L ;
181- };
162+ return toLong (getCurrentValue (columnIndex ));
182163 }
183164
184165 @ Override
@@ -188,33 +169,139 @@ public float getFloat(int columnIndex) throws SQLException {
188169 case Value .Null n -> 0.0F ;
189170 case Value .Integer i -> (float ) i .value ();
190171 case Value .Float f -> (float ) f .value ();
191- case Value .Text t -> {
192- try {
193- yield Float .parseFloat (t .value ());
194- } catch (NumberFormatException e ) {
195- throw new SQLException ("Bad value for type Float: " + t .value (), e );
196- }
197- }
198- case Value .Blob b -> 0.0F ;
172+ case Value .Text t -> (float ) parseSqliteDouble (t .value ());
173+ case Value .Blob b -> (float ) parseSqliteDouble (blobAsText (b ));
199174 };
200175 }
201176
202177 @ Override
203178 public double getDouble (int columnIndex ) throws SQLException {
204- Value val = getCurrentValue (columnIndex );
179+ return toDouble (getCurrentValue (columnIndex ));
180+ }
181+
182+ private static long toLong (Value val ) {
183+ return switch (val ) {
184+ case Value .Null n -> 0L ;
185+ case Value .Integer i -> i .value ();
186+ case Value .Float f -> (long ) f .value ();
187+ case Value .Text t -> parseSqliteLong (t .value ());
188+ case Value .Blob b -> parseSqliteLong (blobAsText (b ));
189+ };
190+ }
191+
192+ private static double toDouble (Value val ) {
205193 return switch (val ) {
206194 case Value .Null n -> 0.0 ;
207195 case Value .Integer i -> (double ) i .value ();
208196 case Value .Float f -> f .value ();
209- case Value .Text t -> {
210- try {
211- yield Double .parseDouble (t .value ());
212- } catch (NumberFormatException e ) {
213- throw new SQLException ("Bad value for type Double: " + t .value (), e );
197+ case Value .Text t -> parseSqliteDouble (t .value ());
198+ case Value .Blob b -> parseSqliteDouble (blobAsText (b ));
199+ };
200+ }
201+
202+ private static String blobAsText (Value .Blob b ) {
203+ return new String (b .bytes (), java .nio .charset .StandardCharsets .UTF_8 );
204+ }
205+
206+ private static long parseSqliteLong (String text ) {
207+ int length = text .length ();
208+ int index = skipSqliteWhitespace (text , 0 );
209+ boolean negative = false ;
210+ if (index < length && (text .charAt (index ) == '+' || text .charAt (index ) == '-' )) {
211+ negative = text .charAt (index ) == '-' ;
212+ index ++;
213+ }
214+
215+ int digitsStart = index ;
216+ long value = 0L ;
217+ boolean overflow = false ;
218+ while (index < length ) {
219+ char c = text .charAt (index );
220+ if (c < '0' || c > '9' ) {
221+ break ;
222+ }
223+ if (!overflow ) {
224+ int digit = c - '0' ;
225+ if (value > (Long .MAX_VALUE - digit ) / 10 ) {
226+ overflow = true ;
227+ } else {
228+ value = value * 10 + digit ;
214229 }
215230 }
216- case Value .Blob b -> 0.0 ;
217- };
231+ index ++;
232+ }
233+
234+ if (index == digitsStart ) {
235+ return 0L ;
236+ }
237+ if (overflow ) {
238+ return negative ? Long .MIN_VALUE : Long .MAX_VALUE ;
239+ }
240+ return negative ? -value : value ;
241+ }
242+
243+ private static double parseSqliteDouble (String text ) {
244+ int length = text .length ();
245+ int index = skipSqliteWhitespace (text , 0 );
246+ int start = index ;
247+ if (index < length && (text .charAt (index ) == '+' || text .charAt (index ) == '-' )) {
248+ index ++;
249+ }
250+
251+ int digits = 0 ;
252+ while (index < length && isAsciiDigit (text .charAt (index ))) {
253+ index ++;
254+ digits ++;
255+ }
256+ if (index < length && text .charAt (index ) == '.' ) {
257+ index ++;
258+ while (index < length && isAsciiDigit (text .charAt (index ))) {
259+ index ++;
260+ digits ++;
261+ }
262+ }
263+
264+ if (digits == 0 ) {
265+ return 0.0 ;
266+ }
267+
268+ int end = index ;
269+ if (index < length && (text .charAt (index ) == 'e' || text .charAt (index ) == 'E' )) {
270+ int exponentIndex = index + 1 ;
271+ if (exponentIndex < length
272+ && (text .charAt (exponentIndex ) == '+' || text .charAt (exponentIndex ) == '-' )) {
273+ exponentIndex ++;
274+ }
275+ int exponentDigits = 0 ;
276+ while (exponentIndex < length && isAsciiDigit (text .charAt (exponentIndex ))) {
277+ exponentIndex ++;
278+ exponentDigits ++;
279+ }
280+ if (exponentDigits > 0 ) {
281+ end = exponentIndex ;
282+ }
283+ }
284+
285+ try {
286+ return Double .parseDouble (text .substring (start , end ));
287+ } catch (NumberFormatException e ) {
288+ return 0.0 ;
289+ }
290+ }
291+
292+ private static int skipSqliteWhitespace (String text , int index ) {
293+ while (index < text .length () && isSqliteWhitespace (text .charAt (index ))) {
294+ index ++;
295+ }
296+ return index ;
297+ }
298+
299+ private static boolean isSqliteWhitespace (char c ) {
300+ return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\u000b' || c == '\f' ;
301+ }
302+
303+ private static boolean isAsciiDigit (char c ) {
304+ return c >= '0' && c <= '9' ;
218305 }
219306
220307 @ Override
0 commit comments