OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 library convert.utils; |
| 6 |
| 7 import 'package:charcode/ascii.dart'; |
| 8 |
| 9 /// Returns the digit (0 through 15) corresponding to the hexadecimal code unit |
| 10 /// at index [i] in [codeUnits]. |
| 11 /// |
| 12 /// If the given code unit isn't valid hexadecimal, throws a [FormatException]. |
| 13 int digitForCodeUnit(List<int> codeUnits, int index) { |
| 14 // If the code unit is a numeral, get its value. XOR works because 0 in ASCII |
| 15 // is `0b110000` and the other numerals come after it in ascending order and |
| 16 // take up at most four bits. |
| 17 // |
| 18 // We check for digits first because it ensures there's only a single branch |
| 19 // for 10 out of 16 of the expected cases. We don't count the `digit >= 0` |
| 20 // check because branch prediction will always work on it for valid data. |
| 21 var codeUnit = codeUnits[index]; |
| 22 var digit = $0 ^ codeUnit; |
| 23 if (digit <= 9) { |
| 24 if (digit >= 0) return digit; |
| 25 } else { |
| 26 // If the code unit is an uppercase letter, convert it to lowercase. This |
| 27 // works because uppercase letters in ASCII are exactly `0b100000 = 0x20` |
| 28 // less than lowercase letters, so if we ensure that that bit is 1 we ensure |
| 29 // that the letter is lowercase. |
| 30 var letter = 0x20 | codeUnit; |
| 31 if ($a <= letter && letter <= $f) return letter - $a + 10; |
| 32 } |
| 33 |
| 34 throw new FormatException( |
| 35 "Invalid hexadecimal code unit " |
| 36 "U+${codeUnit.toRadixString(16).padLeft(4, '0')}.", |
| 37 codeUnits, index); |
| 38 } |
| 39 |
OLD | NEW |