Kaynağa Gözat

Fix Telegram markup parser.

Nikita Kalanakov 2 yıl önce
ebeveyn
işleme
ff8368d57e
1 değiştirilmiş dosya ile 68 ekleme ve 119 silme
  1. 68 119
      makeshot/makeshot.c

+ 68 - 119
makeshot/makeshot.c

@@ -67,18 +67,6 @@ typedef struct {
   size_t size, allocated;
 } buffer_t;
 
-#define FLAG_BOLD    (1 << 0)
-#define FLAG_STRIKE  (1 << 1)
-#define FLAG_ITALIC  (1 << 2)
-#define FLAG_TT      (1 << 3)
-
-typedef struct _node_t {
-  uint_t flags;
-  buffer_t *buffer;
-
-  struct _node_t *next;
-} node_t;
-
 void *malloc_protected(size_t z) {
   void *p;
 
@@ -139,128 +127,89 @@ void buffer_append_data(buffer_t *buffer, unsigned char *data, size_t data_lengt
 }
 
 #define BUFFER_APPEND(b, s) buffer_append_data(b, s, strlen(s))
-#define BUFFER_CONCAT(b1, b2) buffer_append_data(b1, (b2)->data, (b2)->size);
-
-node_t *new_node() {
-  node_t *node;
-
-  node = malloc_protected(sizeof(node_t));
-
-  node->flags = 0;
-  node->buffer = new_buffer();
-  node->next = NULL;
-
-  return node;
+#define BUFFER_CONCAT(b1, b2) {\
+  buffer_append_data(b2, "\0", 1);\
+  preprocess_text(b1, b2->data);\
 }
 
-void free_node(node_t *node) {
-  if (node->next)
-    free_node(node->next);
-
-  free_buffer(node->buffer);
-  free(node);
-}
-
-#define SET(flag) {\
-  if (tail->flags & FLAG_##flag) {\
-    tail = tail->next = new_node();\
-    continue;\
-  }\
-  uint_t flags = tail->flags;\
-  tail = tail->next = new_node();\
-  tail->flags = flags | FLAG_##flag;\
-}
-
-void preprocess_text(buffer_t *buffer, char *text) {
-  uint_t state;
-  node_t *head;
-  node_t *tail;
-
-  head = tail = new_node();
-
-  for (size_t i = 0; i < strlen(text); i++) {
-    unsigned char c, nc;
-
-    c = text[i];
-    nc = text[i+1];
-
-    if (c == '`') {
-      SET(TT);
-    } else if (c == '*' && nc == '*') {
-      i++;
+void buffer_append_escaped(buffer_t *buffer, char c) {
+  switch (c) {
+    case '<':
+      BUFFER_APPEND(buffer, "&lt;");
 
-      SET(BOLD);
-    } else if (c == '~' && nc == '~') {
-      i++;
+      return;
 
-      SET(STRIKE);
-    } else if (c == '_' && nc == '_') {
-      i++;
+    case '>':
+      BUFFER_APPEND(buffer, "&gt;");
 
-      SET(ITALIC);
-    } else {
-      switch (c) {
-        case '<':
-          BUFFER_APPEND(tail->buffer, "&lt;");
+      return;
 
-          continue;
+    case '&':
+      BUFFER_APPEND(buffer, "&amp;");
 
-        case '>':
-          BUFFER_APPEND(tail->buffer, "&gt;");
+      return;
 
-          continue;
+    case '"':
+      BUFFER_APPEND(buffer, "&quot;");
 
-        case '&':
-          BUFFER_APPEND(tail->buffer, "&amp;");
+      return;
 
-          continue;
+    case '\'':
+      BUFFER_APPEND(buffer, "&#39;");
 
-        case '"':
-          BUFFER_APPEND(tail->buffer, "&quot;");
-
-          continue;
+      return;
+    }
 
-        case '\'':
-          BUFFER_APPEND(tail->buffer, "&#39;");
+    buffer_append_data(buffer, &c, 1);
+}
 
-          continue;
-      }
+#define SET(s,tag) do {\
+  buffer_t *temp_buffer;\
+  uint_t k;\
+  temp_buffer = new_buffer();\
+  k = strlen(s);\
+  i += k;\
+  while (text[i]) {\
+    if (strncmp(&text[i], s, k) == 0) {\
+      i += k-1;\
+      buffer_append_data(buffer, "<", 1);\
+      BUFFER_APPEND(buffer, tag);\
+      buffer_append_data(buffer, ">", 1);\
+      BUFFER_CONCAT(buffer, temp_buffer);\
+      buffer_append_data(buffer, "</", 2);\
+      BUFFER_APPEND(buffer, tag);\
+      buffer_append_data(buffer, ">", 1);\
+      free_buffer(temp_buffer);\
+      goto escape;\
+    }\
+    buffer_append_escaped(temp_buffer, text[i]);\
+    i++;\
+  }\
+  i--;\
+  BUFFER_APPEND(buffer, s);\
+  BUFFER_CONCAT(buffer, temp_buffer);\
+  free_buffer(temp_buffer);\
+} while(0)
 
-      buffer_append_data(tail->buffer, &c, 1);
-    }
-  }
+void preprocess_text(buffer_t *buffer, char *text) {
+  for (size_t i = 0; text[i]; i++) {
+    unsigned char c, nc;
 
-  if (tail->flags) {
-    tail->flags = 0;
-  }
+    c = text[i];
+    nc = text[i+1];
 
-  node_t *start = head;
-
-  while (head) {
-    if (head->flags & FLAG_BOLD)
-      BUFFER_APPEND(buffer, "<b>");
-    if (head->flags & FLAG_STRIKE)
-      BUFFER_APPEND(buffer, "<s>");
-    if (head->flags & FLAG_ITALIC)
-      BUFFER_APPEND(buffer, "<i>");
-    if (head->flags & FLAG_TT)
-      BUFFER_APPEND(buffer, "<tt>");
-
-    BUFFER_CONCAT(buffer, head->buffer);
-
-    if (head->flags & FLAG_TT)
-      BUFFER_APPEND(buffer, "</tt>");
-    if (head->flags & FLAG_ITALIC)
-      BUFFER_APPEND(buffer, "</i>");
-    if (head->flags & FLAG_STRIKE)
-      BUFFER_APPEND(buffer, "</s>");
-    if (head->flags & FLAG_BOLD)
-      BUFFER_APPEND(buffer, "</b>");
-
-    head = head->next;
+    if (c == '`')
+      SET("`", "tt");
+    else if (c == '*' && nc == '*')
+      SET("**", "b");
+    else if (c == '_' && nc == '_')
+      SET("__", "i");
+    else if (c == '~' && nc == '~')
+      SET("~~", "s");
+    else
+      buffer_append_escaped(buffer, c);
+escape:;
   }
-
-  free_node(start);
 }
 
 text_t *new_text(cairo_t *cr, char *s, int size, int weight, int preprocess) {
@@ -384,7 +333,7 @@ void paste_image(cairo_t *cr, uint_t x, uint_t y, char *path) {
   cairo_surface_destroy(surface);
 }
 
-void fit(cairo_surface_t **surface, uint_t width, uint_t height) {
+void contain(cairo_surface_t **surface, uint_t width, uint_t height) {
   uint_t image_width, image_height;
   uint_t new_width, new_height;
   double image_ratio, new_ratio;
@@ -528,7 +477,7 @@ main() {
 
   cairo_destroy(cr);
 
-  fit(&surface, 512, 512);
+  contain(&surface, 512, 512);
   cairo_surface_write_to_png(surface, output_path->data);
 
   free_buffer(output_path);