| 1228 | */ |
| 1229 | |
| 1230 | uint32 |
| 1231 | my_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, |
| 1232 | const char *from, uint32 from_length, |
| 1233 | CHARSET_INFO *from_cs, uint *errors) |
| 1234 | { |
| 1235 | uint32 length, length2; |
| 1236 | /* |
| 1237 | If any of the character sets is not ASCII compatible, |
| 1238 | immediately switch to slow mb_wc->wc_mb method. |
| 1239 | */ |
| 1240 | if ((to_cs->state | from_cs->state) & MY_CS_NONASCII) |
| 1241 | return my_convert_using_func(to, to_length, |
| 1242 | to_cs, to_cs->cset->wc_mb, |
| 1243 | from, from_length, |
| 1244 | from_cs, from_cs->cset->mb_wc, |
| 1245 | errors); |
| 1246 | |
| 1247 | length= length2= MY_MIN(to_length, from_length); |
| 1248 | |
| 1249 | #if SIZEOF_SIZE_T <= 8 |
| 1250 | for (size_t f; length >= sizeof f; |
| 1251 | length-= sizeof f, from+= sizeof f, to+= sizeof f) |
| 1252 | { |
| 1253 | memcpy(&f, from, sizeof f); |
| 1254 | if (f & (size_t) 0x8080808080808080ULL) |
| 1255 | goto nonascii; |
| 1256 | memcpy(to, from, sizeof f); |
| 1257 | } |
| 1258 | # if SIZEOF_SIZE_T > 4 |
| 1259 | if (length >= 4) |
| 1260 | { |
| 1261 | uint32 f; |
| 1262 | memcpy(&f, from, 4); |
| 1263 | if (f & 0x80808080U) |
| 1264 | goto nonascii; |
| 1265 | memcpy(to, from, 4); |
| 1266 | length-= 4, to+= 4, from+= 4; |
| 1267 | } |
| 1268 | # endif |
| 1269 | nonascii: |
| 1270 | #endif |
| 1271 | |
| 1272 | for (; ; *to++= *from++, length--) |
| 1273 | { |
| 1274 | if (!length) |
| 1275 | { |
| 1276 | *errors= 0; |
| 1277 | return length2; |
| 1278 | } |
| 1279 | if (*((unsigned char*) from) > 0x7F) /* A non-ASCII character */ |
| 1280 | { |
| 1281 | uint32 copied_length= length2 - length; |
| 1282 | to_length-= copied_length; |
| 1283 | from_length-= copied_length; |
| 1284 | return copied_length + my_convert_using_func(to, to_length, to_cs, |
| 1285 | to_cs->cset->wc_mb, |
| 1286 | from, from_length, from_cs, |
| 1287 | from_cs->cset->mb_wc, |
no test coverage detected