|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- /*
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-
- // OrIdow6, late November 2021
-
-
- // stdin - a urlencoded string
- // stdout - the decoded string
-
- #define _GNU_SOURCE
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdint.h>
-
- #define BUFFER_SIZE 1024 * 300
-
-
- int main() {
- uint8_t* inbuf = malloc(sizeof(uint8_t) * BUFFER_SIZE);
- uint8_t* outbuf = malloc(sizeof(uint8_t) * BUFFER_SIZE + 2);
- size_t outp = 0;
- int state = -1;
- int8_t digita = 0x0;
- int8_t digitb = 0x0;
- uint8_t digita_real;
- uint8_t digitb_real;
-
- // https://stackoverflow.com/questions/10324/convert-a-hexadecimal-string-to-an-integer-efficiently-in-c
- // Because I can't be bothered to generate this manually
- // Could be faster if you had a table for 16-bit integers, depending on caching
- static const int8_t hextable[] = {
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1, 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,-1,10,11,12,13,14,15,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
- };
-
- while (1) {
- size_t readS = fread(inbuf, sizeof(char), BUFFER_SIZE, stdin);
- if (readS == 0) {
- break;
- }
- for (size_t p = 0; p < readS; p++) {
- if (state == -1) {
- if (inbuf[p] != '%') {
- outbuf[outp++] = inbuf[p];
- } else {
- state = 0;
- }
- } else if (state == 0) {
- digita = hextable[inbuf[p]];
- if (digita == (int8_t)-1 ) {
- outbuf[outp++] = '%';
- if (inbuf[p] != '%') {
- outbuf[outp++] = inbuf[p];
- state = -1;
- } // else state remains 0
- continue;
- }
- digita_real = inbuf[p];
- state = 1;
- } else {
- digitb = hextable[inbuf[p]];
- if (digitb == (int8_t)-1 ) {
- digitb_real = inbuf[p];
- outbuf[outp++] = '%';
- outbuf[outp++] = digita_real;
- if (inbuf[p] != '%') {
- outbuf[outp++] = digitb_real;
- state = -1;
- } else {
- state = 0;
- }
- continue;
- }
- outbuf[outp++] = digita << 4 | digitb;
- state = -1;
- }
- }
-
- fwrite(outbuf, outp, 1, stdout);
- outp = 0;
-
- if (readS < BUFFER_SIZE) {
- break;
- }
- }
-
- if (state == 0 || state == 1) {
- fwrite("%", 1, 1, stdout);
- }
- if (state == 1) {
- fwrite(&digita_real, 1, 1, stdout);
- }
- }
|