1*993b0882SAndroid Build Coastguard Worker /*
2*993b0882SAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project
3*993b0882SAndroid Build Coastguard Worker *
4*993b0882SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*993b0882SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*993b0882SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*993b0882SAndroid Build Coastguard Worker *
8*993b0882SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*993b0882SAndroid Build Coastguard Worker *
10*993b0882SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*993b0882SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*993b0882SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*993b0882SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*993b0882SAndroid Build Coastguard Worker * limitations under the License.
15*993b0882SAndroid Build Coastguard Worker */
16*993b0882SAndroid Build Coastguard Worker
17*993b0882SAndroid Build Coastguard Worker #include "utils/checksum.h"
18*993b0882SAndroid Build Coastguard Worker #include "utils/strings/numbers.h"
19*993b0882SAndroid Build Coastguard Worker
20*993b0882SAndroid Build Coastguard Worker namespace libtextclassifier3 {
21*993b0882SAndroid Build Coastguard Worker
VerifyLuhnChecksum(const std::string & input,bool ignore_whitespace)22*993b0882SAndroid Build Coastguard Worker bool VerifyLuhnChecksum(const std::string& input, bool ignore_whitespace) {
23*993b0882SAndroid Build Coastguard Worker int sum = 0;
24*993b0882SAndroid Build Coastguard Worker int num_digits = 0;
25*993b0882SAndroid Build Coastguard Worker bool is_odd = true;
26*993b0882SAndroid Build Coastguard Worker
27*993b0882SAndroid Build Coastguard Worker // http://en.wikipedia.org/wiki/Luhn_algorithm
28*993b0882SAndroid Build Coastguard Worker static const int kPrecomputedSumsOfDoubledDigits[] = {0, 2, 4, 6, 8,
29*993b0882SAndroid Build Coastguard Worker 1, 3, 5, 7, 9};
30*993b0882SAndroid Build Coastguard Worker for (int i = input.size() - 1; i >= 0; i--) {
31*993b0882SAndroid Build Coastguard Worker const char c = input[i];
32*993b0882SAndroid Build Coastguard Worker if (ignore_whitespace && c == ' ') {
33*993b0882SAndroid Build Coastguard Worker continue;
34*993b0882SAndroid Build Coastguard Worker }
35*993b0882SAndroid Build Coastguard Worker if (!isdigit(c)) {
36*993b0882SAndroid Build Coastguard Worker return false;
37*993b0882SAndroid Build Coastguard Worker }
38*993b0882SAndroid Build Coastguard Worker ++num_digits;
39*993b0882SAndroid Build Coastguard Worker const int digit = c - '0';
40*993b0882SAndroid Build Coastguard Worker if (is_odd) {
41*993b0882SAndroid Build Coastguard Worker sum += digit;
42*993b0882SAndroid Build Coastguard Worker } else {
43*993b0882SAndroid Build Coastguard Worker sum += kPrecomputedSumsOfDoubledDigits[digit];
44*993b0882SAndroid Build Coastguard Worker }
45*993b0882SAndroid Build Coastguard Worker is_odd = !is_odd;
46*993b0882SAndroid Build Coastguard Worker }
47*993b0882SAndroid Build Coastguard Worker return (num_digits > 1 && sum % 10 == 0);
48*993b0882SAndroid Build Coastguard Worker }
49*993b0882SAndroid Build Coastguard Worker
50*993b0882SAndroid Build Coastguard Worker } // namespace libtextclassifier3
51