logo

xcd-rgb

colorful hex dump (RGB edition) git clone https://anongit.hacktivis.me/git/xcd-rgb.git

xcd.c (3605B)


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