Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / platform / GeneralUtils.cpp
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *    Copyright (c) 2018 Nest Labs, Inc.
5  *    All rights reserved.
6  *
7  *    Licensed under the Apache License, Version 2.0 (the "License");
8  *    you may not use this file except in compliance with the License.
9  *    You may obtain a copy of the License at
10  *
11  *        http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *    Unless required by applicable law or agreed to in writing, software
14  *    distributed under the License is distributed on an "AS IS" BASIS,
15  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *    See the License for the specific language governing permissions and
17  *    limitations under the License.
18  */
19
20 /**
21  *    @file
22  *          General utility functions available on all platforms.
23  */
24
25 #include <platform/internal/CHIPDeviceLayerInternal.h>
26 #include <support/CodeUtils.h>
27
28 namespace chip {
29 namespace DeviceLayer {
30
31 CHIP_ERROR ParseCompilerDateStr(const char * dateStr, uint16_t & year, uint8_t & month, uint8_t & dayOfMonth)
32 {
33     CHIP_ERROR err = CHIP_NO_ERROR;
34     char monthStr[4];
35     const char * p;
36     char * endptr;
37
38     static const char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
39
40     VerifyOrExit(strlen(dateStr) == 11, err = CHIP_ERROR_INVALID_ARGUMENT);
41
42     memcpy(monthStr, dateStr, 3);
43     monthStr[3] = 0;
44
45     p = strstr(months, monthStr);
46     VerifyOrExit(p != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
47
48     // Safe to cast because "months" is not too long.
49     static_assert(sizeof(months) < UINT8_MAX, "Too many months");
50     month = static_cast<uint8_t>(((p - months) / 3) + 1);
51
52     // Cast does not lose information, because we then check that we only parsed
53     // 2 digits, so our number can't be bigger than 99.
54     dayOfMonth = static_cast<uint8_t>(strtoul(dateStr + 4, &endptr, 10));
55     VerifyOrExit(endptr == dateStr + 6, err = CHIP_ERROR_INVALID_ARGUMENT);
56
57     // Cast does not lose information, because we then check that we only parsed
58     // 4 digits, so our number can't be bigger than 9999.
59     year = static_cast<uint16_t>(strtoul(dateStr + 7, &endptr, 10));
60     VerifyOrExit(endptr == dateStr + 11, err = CHIP_ERROR_INVALID_ARGUMENT);
61
62 exit:
63     return err;
64 }
65
66 CHIP_ERROR Parse24HourTimeStr(const char * timeStr, uint8_t & hour, uint8_t & minute, uint8_t & second)
67 {
68     CHIP_ERROR err = CHIP_NO_ERROR;
69     char * p;
70
71     VerifyOrExit(strlen(timeStr) == 8, err = CHIP_ERROR_INVALID_ARGUMENT);
72
73     // Cast does not lose information, because we then check that we only parsed
74     // 2 digits, so our number can't be bigger than 99.
75     hour = static_cast<uint8_t>(strtoul(timeStr, &p, 10));
76     VerifyOrExit(p == timeStr + 2, err = CHIP_ERROR_INVALID_ARGUMENT);
77
78     // Cast does not lose information, because we then check that we only parsed
79     // 2 digits, so our number can't be bigger than 99.
80     minute = static_cast<uint8_t>(strtoul(timeStr + 3, &p, 10));
81     VerifyOrExit(p == timeStr + 5, err = CHIP_ERROR_INVALID_ARGUMENT);
82
83     // Cast does not lose information, because we then check that we only parsed
84     // 2 digits, so our number can't be bigger than 99.
85     second = static_cast<uint8_t>(strtoul(timeStr + 6, &p, 10));
86     VerifyOrExit(p == timeStr + 8, err = CHIP_ERROR_INVALID_ARGUMENT);
87
88 exit:
89     return err;
90 }
91
92 /**
93  * Register a text error formatter for Device Layer errors.
94  */
95 void RegisterDeviceLayerErrorFormatter()
96 {
97     static ErrorFormatter sDeviceLayerErrorFormatter = { FormatDeviceLayerError, nullptr };
98
99     RegisterErrorFormatter(&sDeviceLayerErrorFormatter);
100 }
101
102 /**
103  * Given Device Layer error, returns a human-readable NULL-terminated C string
104  * describing the error.
105  *
106  * @param[in] buf                   Buffer into which the error string will be placed.
107  * @param[in] bufSize               Size of the supplied buffer in bytes.
108  * @param[in] err                   The error to be described.
109  *
110  * @return true                     If a descriptions string was written into the supplied buffer.
111  * @return false                    If the supplied error was not a Device Layer error.
112  *
113  */
114 bool FormatDeviceLayerError(char * buf, uint16_t bufSize, int32_t err)
115 {
116     const char * desc = nullptr;
117
118     if (err < CHIP_DEVICE_ERROR_MIN || err > CHIP_DEVICE_ERROR_MAX)
119     {
120         return false;
121     }
122
123 #if !CHIP_CONFIG_SHORT_ERROR_STR
124     switch (err)
125     {
126     case CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND:
127         desc = "Config not found";
128         break;
129     case CHIP_DEVICE_ERROR_NOT_SERVICE_PROVISIONED:
130         desc = "Not service provisioned";
131         break;
132     }
133 #endif // !CHIP_CONFIG_SHORT_ERROR_STR
134
135     FormatError(buf, bufSize, "Device Layer", err, desc);
136
137     return true;
138 }
139
140 const char * CharacterizeIPv6Address(const chip::Inet::IPAddress & ipAddr)
141 {
142     if (ipAddr.IsIPv6LinkLocal())
143     {
144         return "IPv6 link-local address";
145     }
146
147     if (ipAddr.IsIPv6ULA())
148     {
149         return "IPv6 unique local address";
150     }
151
152     if (ipAddr.IsIPv6GlobalUnicast())
153     {
154         return "IPv6 global unicast address";
155     }
156
157     return "IPv6 address";
158 }
159
160 } // namespace DeviceLayer
161 } // namespace chip