xref: /aosp_15_r20/external/libtextclassifier/native/utils/checksum.cc (revision 993b0882672172b81d12fad7a7ac0c3e5c824a12)
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