- if (!reverse_init) {
- for (i = 0; i < 32; i++) {
- c = cb32[i];
- rev32[(int) c] = i;
- }
- reverse_init = 1;
- }
-
- /* chars needed to decode slen */
- newsize = 5 * (slen / 8 + 1) + 1;
- /* encoded chars that fit in buf */
- maxsize = 8 * (*buflen / 5 + 1) + 1;
- /* if the buffer is too small, eat some of the data */
- if (*buflen < newsize) {
- slen = maxsize;
- }
+ base32_reverse_init ();
+
+ /* Note: Don't bother to optimize manually. GCC optimizes
+ better(!) when using simplistic array indexing. */
+
+ while (1) {
+ if (iout >= *buflen || iin + 1 >= slen ||
+ str[iin] == '\0' || str[iin + 1] == '\0')
+ break;
+ ubuf[iout] = ((REV32(str[iin]) & 0x1f) << 3) |
+ ((REV32(str[iin + 1]) & 0x1c) >> 2);
+ iin++; /* 0 used up, iin=1 */
+ iout++;
+
+ if (iout >= *buflen || iin + 2 >= slen ||
+ str[iin] == '\0' || str[iin + 1] == '\0' ||
+ str[iin + 2] == '\0')
+ break;
+ ubuf[iout] = ((REV32(str[iin]) & 0x03) << 6) |
+ ((REV32(str[iin + 1]) & 0x1f) << 1) |
+ ((REV32(str[iin + 2]) & 0x10) >> 4);
+ iin += 2; /* 1,2 used up, iin=3 */
+ iout++;
+
+ if (iout >= *buflen || iin + 1 >= slen ||
+ str[iin] == '\0' || str[iin + 1] == '\0')
+ break;
+ ubuf[iout] = ((REV32(str[iin]) & 0x0f) << 4) |
+ ((REV32(str[iin + 1]) & 0x1e) >> 1);
+ iin++; /* 3 used up, iin=4 */
+ iout++;