The little things give you away... A collection of various small helper stuff
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

115 lines
3.3 KiB

  1. /*
  2. This program is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program. If not, see <https://www.gnu.org/licenses/>.
  12. */
  13. // OrIdow6, late November 2021
  14. // stdin - a urlencoded string
  15. // stdout - the decoded string
  16. #define _GNU_SOURCE
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <stdint.h>
  20. #define BUFFER_SIZE 1024 * 300
  21. int main() {
  22. uint8_t* inbuf = malloc(sizeof(uint8_t) * BUFFER_SIZE);
  23. uint8_t* outbuf = malloc(sizeof(uint8_t) * BUFFER_SIZE + 2);
  24. size_t outp = 0;
  25. int state = -1;
  26. int8_t digita = 0x0;
  27. int8_t digitb = 0x0;
  28. uint8_t digita_real;
  29. uint8_t digitb_real;
  30. // https://stackoverflow.com/questions/10324/convert-a-hexadecimal-string-to-an-integer-efficiently-in-c
  31. // Because I can't be bothered to generate this manually
  32. // Could be faster if you had a table for 16-bit integers, depending on caching
  33. static const int8_t hextable[] = {
  34. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  35. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  36. -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,
  37. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  38. -1,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  39. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  40. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  41. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  42. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  43. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  44. -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
  45. };
  46. while (1) {
  47. size_t readS = fread(inbuf, sizeof(char), BUFFER_SIZE, stdin);
  48. if (readS == 0) {
  49. break;
  50. }
  51. for (size_t p = 0; p < readS; p++) {
  52. if (state == -1) {
  53. if (inbuf[p] != '%') {
  54. outbuf[outp++] = inbuf[p];
  55. } else {
  56. state = 0;
  57. }
  58. } else if (state == 0) {
  59. digita = hextable[inbuf[p]];
  60. if (digita == (int8_t)-1 ) {
  61. outbuf[outp++] = '%';
  62. if (inbuf[p] != '%') {
  63. outbuf[outp++] = inbuf[p];
  64. state = -1;
  65. } // else state remains 0
  66. continue;
  67. }
  68. digita_real = inbuf[p];
  69. state = 1;
  70. } else {
  71. digitb = hextable[inbuf[p]];
  72. if (digitb == (int8_t)-1 ) {
  73. digitb_real = inbuf[p];
  74. outbuf[outp++] = '%';
  75. outbuf[outp++] = digita_real;
  76. if (inbuf[p] != '%') {
  77. outbuf[outp++] = digitb_real;
  78. state = -1;
  79. } else {
  80. state = 0;
  81. }
  82. continue;
  83. }
  84. outbuf[outp++] = digita << 4 | digitb;
  85. state = -1;
  86. }
  87. }
  88. fwrite(outbuf, outp, 1, stdout);
  89. outp = 0;
  90. if (readS < BUFFER_SIZE) {
  91. break;
  92. }
  93. }
  94. if (state == 0 || state == 1) {
  95. fwrite("%", 1, 1, stdout);
  96. }
  97. if (state == 1) {
  98. fwrite(&digita_real, 1, 1, stdout);
  99. }
  100. }