Changeset 79562 in vbox
- Timestamp:
- Jul 5, 2019 8:37:19 PM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 131852
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/mangling.h
r79559 r79562 2064 2064 # define RTStrCmp RT_MANGLER(RTStrCmp) 2065 2065 # define RTStrConvertHexBytes RT_MANGLER(RTStrConvertHexBytes) 2066 # define RTStrConvertHexBytesEx RT_MANGLER(RTStrConvertHexBytesEx) 2066 2067 # define RTStrCopy RT_MANGLER(RTStrCopy) 2067 2068 # define RTStrCopyEx RT_MANGLER(RTStrCopyEx) -
trunk/include/iprt/string.h
r79013 r79562 3143 3143 * @param pv Output buffer. 3144 3144 * @param cb The size of the output buffer. 3145 * @param fFlags Must be zero, reserved for future use.3145 * @param fFlags RTSTRCONVERTHEXBYTES_F_XXX. 3146 3146 */ 3147 3147 RTDECL(int) RTStrConvertHexBytes(char const *pszHex, void *pv, size_t cb, uint32_t fFlags); 3148 3149 /** @name RTSTRCONVERTHEXBYTES_F_XXX - Flags for RTStrConvertHexBytes() and RTStrConvertHexBytesEx(). 3150 * @{ */ 3151 /** Accept colon as a byte separator. */ 3152 #define RTSTRCONVERTHEXBYTES_F_SEP_COLON RT_BIT(0) 3153 /** @} */ 3154 3155 /** 3156 * Converts a string of hex bytes back into binary data, extended version. 3157 * 3158 * @returns IPRT status code. 3159 * @retval VERR_INVALID_POINTER if any of the pointers are wrong. 3160 * @retval VERR_BUFFER_OVERFLOW if the string contains too many hex bytes. 3161 * @retval VERR_BUFFER_UNDERFLOW if there aren't enough hex bytes to fill up 3162 * the output buffer and *pcbReturned is NULL. 3163 * @retval VINF_BUFFER_UNDERFLOW if there aren't enough hex bytes to fill up 3164 * the output buffer and *pcbReturned is not NULL, *pcbReturned holds 3165 * the actual number of bytes. 3166 * @retval VERR_UNEVEN_INPUT if the input contains a half byte. 3167 * @retval VERR_NO_DIGITS 3168 * @retval VWRN_TRAILING_CHARS 3169 * @retval VWRN_TRAILING_SPACES 3170 * 3171 * @param pszHex The string containing the hex bytes. 3172 * @param pv Output buffer. 3173 * @param cb The size of the output buffer. 3174 * @param fFlags RTSTRCONVERTHEXBYTES_F_XXX. 3175 * @param ppszNext Set to point at where we stopped decoding hex bytes. 3176 * Optional. 3177 * @param pcbReturned Where to return the number of bytes found. Optional. 3178 */ 3179 RTDECL(int) RTStrConvertHexBytesEx(char const *pszHex, void *pv, size_t cb, uint32_t fFlags, 3180 const char **ppszNext, size_t *pcbReturned); 3148 3181 3149 3182 /** @} */ -
trunk/src/VBox/Runtime/common/string/strtonum.cpp
r76553 r79562 40 40 * Global Variables * 41 41 *********************************************************************************************************************************/ 42 /** 8-bit char -> digit. */ 42 /** 8-bit char -> digit. 43 * Non-digits have values 255 (most), 254 (zero), 253 (colon) and 252 (space). 44 */ 43 45 static const unsigned char g_auchDigits[256] = 44 46 { 45 25 5,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,46 25 5,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,255,255,255,255,255,255,47 254,255,255,255,255,255,255,255,255,252,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 48 252,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,253,255,255,255,255,255, 47 49 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,255,255,255,255,255, 48 50 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,255,255,255,255,255, … … 52 54 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 53 55 }; 56 54 57 /** Approximated overflow shift checks. */ 55 58 static const char g_auchShift[36] = … … 75 78 else if (i >= 'A' && i <= 'Z') 76 79 ch = i - 'A' + 10; 80 else if (i == 0) 81 ch = 254; 82 else if (i == ':') 83 ch = 253; 84 else if (i == ' ' || i == '\t') 85 ch = 252; 77 86 if (i == 0) 78 87 printf("\n %3d", ch); … … 973 982 974 983 984 RTDECL(int) RTStrConvertHexBytesEx(char const *pszHex, void *pv, size_t cb, uint32_t fFlags, 985 const char **ppszNext, size_t *pcbReturned) 986 { 987 size_t cbDst = cb; 988 uint8_t *pbDst = (uint8_t *)pv; 989 const unsigned char *pszSrc = (const unsigned char *)pszHex; 990 unsigned char uchDigit; 991 992 if (pcbReturned) 993 *pcbReturned = 0; 994 if (ppszNext) 995 *ppszNext = NULL; 996 AssertPtrReturn(pszHex, VERR_INVALID_POINTER); 997 AssertReturn(!(fFlags & ~RTSTRCONVERTHEXBYTES_F_SEP_COLON), VERR_INVALID_FLAGS); 998 999 if (fFlags & RTSTRCONVERTHEXBYTES_F_SEP_COLON) 1000 { 1001 /* 1002 * Optional colon separators. 1003 */ 1004 bool fPrevColon = true; /* leading colon is taken to mean leading zero byte */ 1005 for (;;) 1006 { 1007 /* Pick the next two digit from the string. */ 1008 uchDigit = g_auchDigits[*pszSrc++]; 1009 if (uchDigit >= 16) 1010 { 1011 if (uchDigit == 253 /* colon */) 1012 { 1013 Assert(pszSrc[-1] == ':'); 1014 if (!fPrevColon) 1015 fPrevColon = true; 1016 /* Add zero byte if there is room. */ 1017 else if (cbDst > 0) 1018 { 1019 cbDst--; 1020 *pbDst++ = 0; 1021 } 1022 else 1023 { 1024 if (pcbReturned) 1025 *pcbReturned = pbDst - (uint8_t *)pv; 1026 if (ppszNext) 1027 *ppszNext = (const char *)pszSrc - 1; 1028 return VERR_BUFFER_OVERFLOW; 1029 } 1030 continue; 1031 } 1032 else 1033 break; 1034 } 1035 else 1036 { 1037 /* Got one digit, check what comes next: */ 1038 unsigned char const uchDigit2 = g_auchDigits[*pszSrc++]; 1039 if (uchDigit2 < 16) 1040 { 1041 if (cbDst > 0) 1042 { 1043 *pbDst++ = (uchDigit << 4) | uchDigit2; 1044 cbDst--; 1045 fPrevColon = false; 1046 } 1047 else 1048 { 1049 if (pcbReturned) 1050 *pcbReturned = pbDst - (uint8_t *)pv; 1051 if (ppszNext) 1052 *ppszNext = (const char *)pszSrc - 1; 1053 return VERR_BUFFER_OVERFLOW; 1054 } 1055 } 1056 /* Lone digits are only allowed if following a colon or at the very start, because 1057 if there is more than one byte it ambigious whether it is the lead or tail byte 1058 that only has one digit in it. 1059 Note! This also ensures better compatibility with the no-separator variant 1060 (except for single digit strings, which are accepted here but not below). */ 1061 else if (fPrevColon) 1062 { 1063 if (cbDst > 0) 1064 { 1065 *pbDst++ = uchDigit; 1066 cbDst--; 1067 } 1068 else 1069 { 1070 if (pcbReturned) 1071 *pcbReturned = pbDst - (uint8_t *)pv; 1072 if (ppszNext) 1073 *ppszNext = (const char *)pszSrc - 1; 1074 return VERR_BUFFER_OVERFLOW; 1075 } 1076 if (uchDigit2 == 253 /* colon */) 1077 { 1078 Assert(pszSrc[-1] == ':'); 1079 fPrevColon = true; 1080 } 1081 else 1082 { 1083 fPrevColon = false; 1084 uchDigit = uchDigit2; 1085 break; 1086 } 1087 } 1088 else 1089 { 1090 if (pcbReturned) 1091 *pcbReturned = pbDst - (uint8_t *)pv; 1092 if (ppszNext) 1093 *ppszNext = (const char *)pszSrc - 2; 1094 return VERR_UNEVEN_INPUT; 1095 } 1096 } 1097 } 1098 1099 /* Trailing colon means trailing zero byte: */ 1100 if (fPrevColon) 1101 { 1102 if (cbDst > 0) 1103 { 1104 *pbDst++ = 0; 1105 cbDst--; 1106 } 1107 else 1108 { 1109 if (pcbReturned) 1110 *pcbReturned = pbDst - (uint8_t *)pv; 1111 if (ppszNext) 1112 *ppszNext = (const char *)pszSrc - 1; 1113 return VERR_BUFFER_OVERFLOW; 1114 } 1115 } 1116 } 1117 else 1118 { 1119 /* 1120 * No separators. 1121 */ 1122 for (;;) 1123 { 1124 /* Pick the next two digit from the string. */ 1125 uchDigit = g_auchDigits[*pszSrc++]; 1126 if (uchDigit < 16) 1127 { 1128 unsigned char const uchDigit2 = g_auchDigits[*pszSrc++]; 1129 if (uchDigit2 < 16) 1130 { 1131 /* Add the byte to the output buffer. */ 1132 if (cbDst) 1133 { 1134 cbDst--; 1135 *pbDst++ = (uchDigit << 4) | uchDigit2; 1136 } 1137 else 1138 { 1139 if (pcbReturned) 1140 *pcbReturned = pbDst - (uint8_t *)pv; 1141 if (ppszNext) 1142 *ppszNext = (const char *)pszSrc - 2; 1143 return VERR_BUFFER_OVERFLOW; 1144 } 1145 } 1146 else 1147 { 1148 if (pcbReturned) 1149 *pcbReturned = pbDst - (uint8_t *)pv; 1150 if (ppszNext) 1151 *ppszNext = (const char *)pszSrc - 2; 1152 return VERR_UNEVEN_INPUT; 1153 } 1154 } 1155 else 1156 break; 1157 } 1158 } 1159 1160 /* 1161 * End of hex bytes, look what comes next and figure out what to return. 1162 */ 1163 if (pcbReturned) 1164 *pcbReturned = pbDst - (uint8_t *)pv; 1165 if (ppszNext) 1166 *ppszNext = (const char *)pszSrc - 1; 1167 1168 if (uchDigit == 254) 1169 { 1170 Assert(pszSrc[-1] == '\0'); 1171 if (cbDst == 0) 1172 return VINF_SUCCESS; 1173 return pcbReturned ? VINF_BUFFER_UNDERFLOW : VERR_BUFFER_UNDERFLOW; 1174 } 1175 Assert(pszSrc[-1] != '\0'); 1176 1177 if (cbDst != 0 && !pcbReturned) 1178 return VERR_BUFFER_UNDERFLOW; 1179 1180 while (uchDigit == 252) 1181 { 1182 Assert(pszSrc[-1] == ' ' || pszSrc[-1] == '\t'); 1183 uchDigit = g_auchDigits[*pszSrc++]; 1184 } 1185 1186 Assert(pszSrc[-1] == '\0' ? uchDigit == 254 : uchDigit != 254); 1187 return uchDigit == 254 ? VWRN_TRAILING_CHARS : VWRN_TRAILING_SPACES; 1188 1189 } 1190 RT_EXPORT_SYMBOL(RTStrConvertHexBytesEx); 1191 1192 975 1193 RTDECL(int) RTStrConvertHexBytes(char const *pszHex, void *pv, size_t cb, uint32_t fFlags) 976 1194 { 977 size_t cbDst; 978 uint8_t *pbDst; 979 const char *pszSrc; 980 981 AssertPtrReturn(pszHex, VERR_INVALID_POINTER); 982 AssertReturn(!fFlags, VERR_INVALID_PARAMETER); 983 984 cbDst = cb; 985 pbDst = (uint8_t *)pv; 986 pszSrc = pszHex; 987 for (;;) 988 { 989 /* Pick the next two digit from the string. */ 990 char ch = *pszSrc++; 991 unsigned char uchDigit1 = g_auchDigits[(unsigned char)ch]; 992 unsigned char uchDigit2; 993 if (uchDigit1 >= 16) 994 { 995 if (!ch) 996 return cbDst == 0 ? VINF_SUCCESS : VERR_BUFFER_UNDERFLOW; 997 998 while (ch == ' ' || ch == '\t') 999 ch = *pszSrc++; 1000 return ch ? VWRN_TRAILING_CHARS : VWRN_TRAILING_SPACES; 1001 } 1002 1003 ch = *pszSrc++; 1004 uchDigit2 = g_auchDigits[(unsigned char)ch]; 1005 if (uchDigit2 >= 16) 1006 return VERR_UNEVEN_INPUT; 1007 1008 /* Add the byte to the output buffer. */ 1009 if (!cbDst) 1010 return VERR_BUFFER_OVERFLOW; 1011 cbDst--; 1012 *pbDst++ = (uchDigit1 << 4) | uchDigit2; 1013 } 1195 return RTStrConvertHexBytesEx(pszHex, pv, cb, fFlags, NULL /*ppszNext*/, NULL /*pcbReturned*/); 1196 1014 1197 } 1015 1198 RT_EXPORT_SYMBOL(RTStrConvertHexBytes); -
trunk/src/VBox/Runtime/testcase/tstStrToNum.cpp
r76553 r79562 25 25 */ 26 26 27 #include <iprt/initterm.h> 27 28 /********************************************************************************************************************************* 29 * Header Files * 30 *********************************************************************************************************************************/ 31 #include <iprt/test.h> 28 32 #include <iprt/string.h> 29 33 #include <iprt/stream.h> … … 69 73 int rc = Fun(Test.psz, NULL, Test.uBase, &Result); \ 70 74 if (Result != Test.Result) \ 71 { \ 72 RTPrintf("failure: '%s' -> " Fmt " expected " Fmt ". (%s/%u)\n", Test.psz, Result, Test.Result, #Fun, iTest); \ 73 cErrors++; \ 74 } \ 75 RTTestIFailed("'%s' -> " Fmt " expected " Fmt ". (%s/%u)\n", Test.psz, Result, Test.Result, #Fun, iTest); \ 75 76 else if (rc != Test.rc) \ 76 { \ 77 RTPrintf("failure: '%s' -> rc=%Rrc expected %Rrc. (%s/%u)\n", Test.psz, rc, Test.rc, #Fun, iTest); \ 78 cErrors++; \ 79 } \ 77 RTTestIFailed("'%s' -> rc=%Rrc expected %Rrc. (%s/%u)\n", Test.psz, rc, Test.rc, #Fun, iTest); \ 80 78 } while (0) 81 79 … … 92 90 int main() 93 91 { 94 RTR3InitExeNoArguments(0); 95 96 int cErrors = 0; 92 RTTEST hTest; 93 RTEXITCODE rcExit = RTTestInitAndCreate("tstRTStrToNum", &hTest); 94 if (rcExit != RTEXITCODE_SUCCESS) 95 return rcExit; 96 97 97 static const struct TstU64 aTstU64[] = 98 98 { … … 159 159 160 160 161 162 161 static const struct TstI32 aTstI32[] = 163 162 { … … 223 222 RUN_TESTS(aTstU32, uint32_t, "%#x", RTStrToUInt32Ex); 224 223 224 225 /* 226 * Test the some hex stuff too. 227 */ 228 static const struct 229 { 230 const char *pszHex; 231 size_t cbOut; 232 size_t offNext; 233 uint8_t bLast; 234 bool fColon; 235 int rc; 236 } s_aConvertHexTests[] = 237 { 238 { "00", 1, 2, 0x00, true, VINF_SUCCESS }, 239 { "00", 1, 2, 0x00, false, VINF_SUCCESS }, 240 { "000102", 3, 6, 0x02, true, VINF_SUCCESS }, 241 { "00019", 2, 4, 0x01, false, VERR_UNEVEN_INPUT }, 242 { "00019", 2, 4, 0x01, true, VERR_UNEVEN_INPUT }, 243 { "0001:9", 3, 6, 0x09, true, VINF_SUCCESS}, 244 { "000102", 3, 6, 0x02, false, VINF_SUCCESS }, 245 { "0:1", 2, 3, 0x01, true, VINF_SUCCESS }, 246 { ":", 2, 1, 0x00, true, VINF_SUCCESS }, 247 { "0:01", 2, 4, 0x01, true, VINF_SUCCESS }, 248 { "00:01", 2, 5, 0x01, true, VINF_SUCCESS }, 249 { ":1:2:3:4:5", 6, 10, 0x05, true, VINF_SUCCESS }, 250 { ":1:2:3::5", 6, 9, 0x05, true, VINF_SUCCESS }, 251 { ":1:2:3:4:", 6, 9, 0x00, true, VINF_SUCCESS }, 252 }; 253 for (unsigned i = 0; i < RT_ELEMENTS(s_aConvertHexTests); i++) 254 { 255 uint8_t abBuf[1024]; 256 memset(abBuf, 0xf6, sizeof(abBuf)); 257 const char *pszExpectNext = &s_aConvertHexTests[i].pszHex[s_aConvertHexTests[i].offNext]; 258 const char *pszNext = ""; 259 size_t cbReturned = 77777; 260 int rc = RTStrConvertHexBytesEx(s_aConvertHexTests[i].pszHex, abBuf, s_aConvertHexTests[i].cbOut, 261 s_aConvertHexTests[i].fColon ? RTSTRCONVERTHEXBYTES_F_SEP_COLON : 0, 262 &pszNext, &cbReturned); 263 if ( rc != s_aConvertHexTests[i].rc 264 || pszNext != pszExpectNext 265 || abBuf[s_aConvertHexTests[i].cbOut - 1] != s_aConvertHexTests[i].bLast 266 ) 267 RTTestFailed(hTest, "RTStrConvertHexBytesEx/#%u %s -> %Rrc %p %#zx %#02x, expected %Rrc %p %#zx %#02x\n", 268 i, s_aConvertHexTests[i].pszHex, 269 rc, pszNext, cbReturned, abBuf[s_aConvertHexTests[i].cbOut - 1], 270 s_aConvertHexTests[i].rc, pszExpectNext, s_aConvertHexTests[i].cbOut, s_aConvertHexTests[i].bLast); 271 } 272 273 225 274 /* 226 275 * Summary. 227 276 */ 228 if (!cErrors) 229 RTPrintf("tstStrToNum: SUCCESS\n"); 230 else 231 RTPrintf("tstStrToNum: FAILURE - %d errors\n", cErrors); 232 return !!cErrors; 277 return RTTestSummaryAndDestroy(hTest); 233 278 }
Note:
See TracChangeset
for help on using the changeset viewer.