logo

utils-extra

Collection of extra tools for Unixes git clone https://anongit.hacktivis.me/git/utils-extra.git/

xcd.c (3523B)


  1. // utils-extra: Collection of extra tools for Unixes
  2. // SPDX-FileCopyrightText: 2017-2022 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
  3. // SPDX-License-Identifier: MPL-2.0
  4. #define _POSIX_C_SOURCE 200809L
  5. #define _XOPEN_SOURCE 700
  6. #include <ctype.h> /* isprint() */
  7. #include <errno.h> /* errno */
  8. #include <math.h> /* sin() */
  9. #include <stdint.h> /* uint8_t */
  10. #include <stdio.h> /* printf(), fread(), fopen(), fclose() */
  11. #include <string.h> /* memset(), strerror() */
  12. #ifndef M_PI
  13. #define 3.14159265358979323846
  14. #endif
  15. struct rgb
  16. {
  17. int r, g, b;
  18. };
  19. static struct rgb
  20. rgb_char(uint8_t i)
  21. {
  22. double freq = 0.018;
  23. if(i == 0) return (struct rgb){64, 64, 64};
  24. struct rgb color;
  25. color.r = sin(freq * i + 0 * M_PI / 3) * 127 + 128;
  26. color.g = sin(freq * i + 2 * M_PI / 3) * 127 + 128;
  27. color.b = sin(freq * i + 4 * M_PI / 3) * 127 + 128;
  28. return color;
  29. }
  30. static int
  31. print_hex_rgb(uint8_t c)
  32. {
  33. struct rgb color = rgb_char(c);
  34. if(printf("\033[38;2;%d;%d;%dm%02hhx ", color.r, color.g, color.b, c) <= 0) return 1;
  35. return 0;
  36. }
  37. static int
  38. print_xcd_reset()
  39. {
  40. if(printf("\033[0m\033[48;2;0;0;0m") <= 0) return 1;
  41. return 0;
  42. }
  43. static int
  44. print_plain_rgb(char *line, size_t len)
  45. {
  46. if(print_xcd_reset() != 0) return 1;
  47. if(printf(" >") <= 0) return 1;
  48. for(size_t i = 0; i < len; i++)
  49. {
  50. struct rgb color = rgb_char(line[i]);
  51. if(printf(
  52. "\033[38;2;%d;%d;%dm%c", color.r, color.g, color.b, isprint(line[i]) ? line[i] : '.') <=
  53. 0)
  54. return 1;
  55. }
  56. if(print_xcd_reset() != 0) return 1;
  57. if(printf("<") <= 0) return 1;
  58. return 0;
  59. }
  60. #define WIDTH 16
  61. static int
  62. concat(FILE *stream)
  63. {
  64. long unsigned int bytes = 0;
  65. errno = 0;
  66. if(print_xcd_reset() != 0) goto werr;
  67. struct rgb pos_rgb = rgb_char(bytes);
  68. if(printf("\033[38;2;%d;%d;%dm0x%06lx ", pos_rgb.r, pos_rgb.g, pos_rgb.b, bytes) < 0) goto werr;
  69. size_t cols = 0;
  70. char line[WIDTH] = "";
  71. char c;
  72. while(fread(&c, 1, 1, stream) > 0)
  73. {
  74. if(cols >= WIDTH)
  75. {
  76. print_plain_rgb(line, cols);
  77. memset(&line, 0, WIDTH);
  78. pos_rgb = rgb_char(bytes);
  79. if(printf("\n\033[38;2;%d;%d;%dm0x%06lx ", pos_rgb.r, pos_rgb.g, pos_rgb.b, bytes) < 0)
  80. goto werr;
  81. cols = 0;
  82. }
  83. if(print_hex_rgb(c) != 0) goto werr;
  84. line[cols] = c;
  85. cols++;
  86. bytes++;
  87. }
  88. // Fill the rest of the hex space with spaces
  89. for(; cols < WIDTH; cols++)
  90. if(printf(" ") <= 0) goto werr;
  91. if(print_plain_rgb(line, cols) != 0) goto werr;
  92. pos_rgb = rgb_char(bytes);
  93. if(printf("\n\033[38;2;%d;%d;%dm0x%06lx\n", pos_rgb.r, pos_rgb.g, pos_rgb.b, bytes) <= 0)
  94. goto werr;
  95. if(print_xcd_reset() != 0) goto werr;
  96. return 0;
  97. werr:
  98. fprintf(stderr, "\n\033[0mxcd: error: Failed writing to stdout: %s\n", strerror(errno));
  99. return 1;
  100. }
  101. int
  102. main(int argc, char *argv[])
  103. {
  104. int err = 0;
  105. if(argc <= 1)
  106. {
  107. err = concat(stdin);
  108. printf("\033[0m");
  109. return err;
  110. }
  111. for(int argi = 1; (err == 0) && (argi < argc); argi++)
  112. {
  113. if(strncmp(argv[argi], "-", 2) == 0)
  114. {
  115. if(concat(stdin) != 0)
  116. {
  117. err = 1;
  118. break;
  119. }
  120. continue;
  121. }
  122. FILE *file = fopen(argv[argi], "rb");
  123. if(!file)
  124. {
  125. fprintf(stderr,
  126. "\n\033[0mxcd: error: Failed opening file ‘%s’: %s\n",
  127. argv[argi],
  128. strerror(errno));
  129. err = 1;
  130. break;
  131. }
  132. err += concat(file);
  133. if(fclose(file) != 0)
  134. {
  135. fprintf(stderr,
  136. "\n\033[0mxcd: error: Failed closing file ‘%s’: %s\n",
  137. argv[argi],
  138. strerror(errno));
  139. err = 1;
  140. break;
  141. }
  142. }
  143. printf("\033[0m");
  144. return err;
  145. }