xref: /aosp_15_r20/hardware/ril/include/telephony/ril_mnc.h (revision 062a843b36e31144e02d312b6b2de34642e6750e)
1*062a843bSAndroid Build Coastguard Worker /*
2*062a843bSAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*062a843bSAndroid Build Coastguard Worker  *
4*062a843bSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*062a843bSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*062a843bSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*062a843bSAndroid Build Coastguard Worker  *
8*062a843bSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*062a843bSAndroid Build Coastguard Worker  *
10*062a843bSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*062a843bSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*062a843bSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*062a843bSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*062a843bSAndroid Build Coastguard Worker  * limitations under the License.
15*062a843bSAndroid Build Coastguard Worker  */
16*062a843bSAndroid Build Coastguard Worker 
17*062a843bSAndroid Build Coastguard Worker #ifndef RIL_MNC_H
18*062a843bSAndroid Build Coastguard Worker #define RIL_MNC_H
19*062a843bSAndroid Build Coastguard Worker 
20*062a843bSAndroid Build Coastguard Worker #include <climits>
21*062a843bSAndroid Build Coastguard Worker #include <cstdio>
22*062a843bSAndroid Build Coastguard Worker #include <string>
23*062a843bSAndroid Build Coastguard Worker 
24*062a843bSAndroid Build Coastguard Worker namespace ril {
25*062a843bSAndroid Build Coastguard Worker namespace util {
26*062a843bSAndroid Build Coastguard Worker namespace mnc {
27*062a843bSAndroid Build Coastguard Worker 
28*062a843bSAndroid Build Coastguard Worker /**
29*062a843bSAndroid Build Coastguard Worker  * Decode an MNC with an optional length indicator provided in the most-significant nibble.
30*062a843bSAndroid Build Coastguard Worker  *
31*062a843bSAndroid Build Coastguard Worker  * @param mnc an encoded MNC value; if no encoding is provided, then the string is returned
32*062a843bSAndroid Build Coastguard Worker  *     as a minimum length string representing the provided integer.
33*062a843bSAndroid Build Coastguard Worker  *
34*062a843bSAndroid Build Coastguard Worker  * @return string representation of an encoded MNC or an empty string if the MNC is not a valid
35*062a843bSAndroid Build Coastguard Worker  *     MNC value.
36*062a843bSAndroid Build Coastguard Worker  */
decode(int mnc)37*062a843bSAndroid Build Coastguard Worker static inline std::string decode(int mnc) {
38*062a843bSAndroid Build Coastguard Worker     if (mnc == INT_MAX || mnc < 0) return "";
39*062a843bSAndroid Build Coastguard Worker     unsigned umnc = mnc;
40*062a843bSAndroid Build Coastguard Worker     char mncNumDigits = (umnc >> (sizeof(int) * 8 - 4)) & 0xF;
41*062a843bSAndroid Build Coastguard Worker 
42*062a843bSAndroid Build Coastguard Worker     umnc = (umnc << 4) >> 4;
43*062a843bSAndroid Build Coastguard Worker     if (umnc > 999) return "";
44*062a843bSAndroid Build Coastguard Worker 
45*062a843bSAndroid Build Coastguard Worker     char mncStr[4] = {0};
46*062a843bSAndroid Build Coastguard Worker     switch (mncNumDigits) {
47*062a843bSAndroid Build Coastguard Worker         case 0:
48*062a843bSAndroid Build Coastguard Worker             // Legacy MNC report hasn't set the number of digits; preserve current
49*062a843bSAndroid Build Coastguard Worker             // behavior and make a string of the minimum number of required digits.
50*062a843bSAndroid Build Coastguard Worker             return std::to_string(umnc);
51*062a843bSAndroid Build Coastguard Worker 
52*062a843bSAndroid Build Coastguard Worker         case 2:
53*062a843bSAndroid Build Coastguard Worker             snprintf(mncStr, sizeof(mncStr), "%03.3u", umnc);
54*062a843bSAndroid Build Coastguard Worker             return mncStr + 1;
55*062a843bSAndroid Build Coastguard Worker 
56*062a843bSAndroid Build Coastguard Worker         case 3:
57*062a843bSAndroid Build Coastguard Worker             snprintf(mncStr, sizeof(mncStr), "%03.3u", umnc);
58*062a843bSAndroid Build Coastguard Worker             return mncStr;
59*062a843bSAndroid Build Coastguard Worker 
60*062a843bSAndroid Build Coastguard Worker         default:
61*062a843bSAndroid Build Coastguard Worker             // Error case
62*062a843bSAndroid Build Coastguard Worker             return "";
63*062a843bSAndroid Build Coastguard Worker     }
64*062a843bSAndroid Build Coastguard Worker 
65*062a843bSAndroid Build Coastguard Worker }
66*062a843bSAndroid Build Coastguard Worker 
67*062a843bSAndroid Build Coastguard Worker /**
68*062a843bSAndroid Build Coastguard Worker  * Encode an MNC of the given value and a given number of digits
69*062a843bSAndroid Build Coastguard Worker  *
70*062a843bSAndroid Build Coastguard Worker  * @param mnc an MNC value 0-999 or INT_MAX if unknown
71*062a843bSAndroid Build Coastguard Worker  * @param numDigits the number of MNC digits {2, 3} or 0 if unknown
72*062a843bSAndroid Build Coastguard Worker  *
73*062a843bSAndroid Build Coastguard Worker  * @return an encoded MNC with embedded length information
74*062a843bSAndroid Build Coastguard Worker  */
encode(int mnc,int numDigits)75*062a843bSAndroid Build Coastguard Worker static inline int encode(int mnc, int numDigits) {
76*062a843bSAndroid Build Coastguard Worker     if (mnc > 999 || mnc < 0) return INT_MAX;
77*062a843bSAndroid Build Coastguard Worker     switch (numDigits) {
78*062a843bSAndroid Build Coastguard Worker         case 0: // fall through
79*062a843bSAndroid Build Coastguard Worker         case 2: // fall through
80*062a843bSAndroid Build Coastguard Worker         case 3:
81*062a843bSAndroid Build Coastguard Worker             break;
82*062a843bSAndroid Build Coastguard Worker 
83*062a843bSAndroid Build Coastguard Worker         default:
84*062a843bSAndroid Build Coastguard Worker             return INT_MAX;
85*062a843bSAndroid Build Coastguard Worker     };
86*062a843bSAndroid Build Coastguard Worker 
87*062a843bSAndroid Build Coastguard Worker     return (numDigits << (sizeof(int) * 8 - 4)) | mnc;
88*062a843bSAndroid Build Coastguard Worker }
89*062a843bSAndroid Build Coastguard Worker 
90*062a843bSAndroid Build Coastguard Worker /**
91*062a843bSAndroid Build Coastguard Worker  * Encode an MNC of the given value
92*062a843bSAndroid Build Coastguard Worker  *
93*062a843bSAndroid Build Coastguard Worker  * @param mnc the string representation of the MNC, with the length equal to the length of the
94*062a843bSAndroid Build Coastguard Worker  *     provided string.
95*062a843bSAndroid Build Coastguard Worker  *
96*062a843bSAndroid Build Coastguard Worker  * @return an encoded MNC with embedded length information
97*062a843bSAndroid Build Coastguard Worker  */
encode(const std::string & mnc)98*062a843bSAndroid Build Coastguard Worker static inline int encode(const std::string & mnc) {
99*062a843bSAndroid Build Coastguard Worker     return encode(std::stoi(mnc), mnc.length());
100*062a843bSAndroid Build Coastguard Worker }
101*062a843bSAndroid Build Coastguard Worker 
102*062a843bSAndroid Build Coastguard Worker // echo -e "#include \"hardware/ril/include/telephony/ril_mnc.h\"\nint main()"\
103*062a843bSAndroid Build Coastguard Worker // "{ return ril::util::mnc::test(); }" > ril_test.cpp \
104*062a843bSAndroid Build Coastguard Worker // && g++ -o /tmp/ril_test -DTEST_RIL_MNC ril_test.cpp; \
105*062a843bSAndroid Build Coastguard Worker // rm ril_test.cpp; /tmp/ril_test && [ $? ] && echo "passed"
106*062a843bSAndroid Build Coastguard Worker #ifdef TEST_RIL_MNC
test()107*062a843bSAndroid Build Coastguard Worker static int test() {
108*062a843bSAndroid Build Coastguard Worker     const struct mnc_strings { const char * in; const char * out; } mncs[] = {
109*062a843bSAndroid Build Coastguard Worker         {"0001",""},
110*062a843bSAndroid Build Coastguard Worker         {"9999",""},
111*062a843bSAndroid Build Coastguard Worker         {"0",""},
112*062a843bSAndroid Build Coastguard Worker         {"9",""},
113*062a843bSAndroid Build Coastguard Worker         {"123","123"},
114*062a843bSAndroid Build Coastguard Worker         {"000","000"},
115*062a843bSAndroid Build Coastguard Worker         {"001","001"},
116*062a843bSAndroid Build Coastguard Worker         {"011","011"},
117*062a843bSAndroid Build Coastguard Worker         {"111","111"},
118*062a843bSAndroid Build Coastguard Worker         {"00","00"},
119*062a843bSAndroid Build Coastguard Worker         {"01","01"},
120*062a843bSAndroid Build Coastguard Worker         {"11","11"},
121*062a843bSAndroid Build Coastguard Worker         {"09","09"},
122*062a843bSAndroid Build Coastguard Worker         {"099","099"},
123*062a843bSAndroid Build Coastguard Worker         {"999", "999"}};
124*062a843bSAndroid Build Coastguard Worker 
125*062a843bSAndroid Build Coastguard Worker     for (int i=0; i< sizeof(mncs) / sizeof(struct mnc_strings); i++) {
126*062a843bSAndroid Build Coastguard Worker         if (decode(encode(mncs[i].in)).compare(mncs[i].out)) return 1;
127*062a843bSAndroid Build Coastguard Worker     }
128*062a843bSAndroid Build Coastguard Worker 
129*062a843bSAndroid Build Coastguard Worker     const struct mnc_ints { const int in; const char * out; } legacy_mncs[] = {
130*062a843bSAndroid Build Coastguard Worker         {INT_MAX, ""},
131*062a843bSAndroid Build Coastguard Worker         {1, "1"},
132*062a843bSAndroid Build Coastguard Worker         {11, "11"},
133*062a843bSAndroid Build Coastguard Worker         {111, "111"},
134*062a843bSAndroid Build Coastguard Worker         {0, "0"},
135*062a843bSAndroid Build Coastguard Worker         {9999, ""},
136*062a843bSAndroid Build Coastguard Worker     };
137*062a843bSAndroid Build Coastguard Worker 
138*062a843bSAndroid Build Coastguard Worker     for (int i=0; i < sizeof(legacy_mncs) / sizeof(struct mnc_ints); i++) {
139*062a843bSAndroid Build Coastguard Worker         if (decode(legacy_mncs[i].in).compare(legacy_mncs[i].out)) return 1;
140*062a843bSAndroid Build Coastguard Worker     }
141*062a843bSAndroid Build Coastguard Worker 
142*062a843bSAndroid Build Coastguard Worker     return 0;
143*062a843bSAndroid Build Coastguard Worker }
144*062a843bSAndroid Build Coastguard Worker #endif
145*062a843bSAndroid Build Coastguard Worker 
146*062a843bSAndroid Build Coastguard Worker }
147*062a843bSAndroid Build Coastguard Worker }
148*062a843bSAndroid Build Coastguard Worker }
149*062a843bSAndroid Build Coastguard Worker #endif /* !defined(RIL_MNC_H) */
150