]> git.neil.brown.name Git - edlib.git/commitdiff
base64: use do_char_byte
authorNeilBrown <neil@brown.name>
Wed, 19 Jul 2023 10:01:17 +0000 (20:01 +1000)
committerNeilBrown <neil@brown.name>
Fri, 21 Jul 2023 01:02:08 +0000 (11:02 +1000)
I duplicated the code.. I wonder if I should have done.

Signed-off-by: NeilBrown <neil@brown.name>
core.h
lib-base64.c

diff --git a/core.h b/core.h
index 5c899dbe0a5204002fe9611b75ccc6dfdec94ae5..acc5b9a01ddd9307c062f6f0e1d6f27555f0b13b 100644 (file)
--- a/core.h
+++ b/core.h
@@ -554,11 +554,11 @@ static inline wint_t doc_pending(struct pane *p safe, struct mark *m, int n)
 
 #if defined(DOC_NEXT)
 #ifdef DOC_NEXT_DECL
-static inline wint_t DOC_NEXT_DECL(struct pane *p safe, struct mark *m, struct doc_ref *r safe, bool byte);
-static inline wint_t DOC_PREV_DECL(struct pane *p safe, struct mark *m, struct doc_ref *r safe, bool byte);
+static inline wint_t DOC_NEXT_DECL(struct pane *p safe, struct mark *m safe, struct doc_ref *r safe, bool byte);
+static inline wint_t DOC_PREV_DECL(struct pane *p safe, struct mark *m safe, struct doc_ref *r safe, bool byte);
 #else
-static inline wint_t DOC_NEXT(struct pane *p safe, struct mark *m, struct doc_ref *r safe, bool byte);
-static inline wint_t DOC_PREV(struct pane *p safe, struct mark *m, struct doc_ref *r safe, bool byte);
+static inline wint_t DOC_NEXT(struct pane *p safe, struct mark *m safe, struct doc_ref *r safe, bool byte);
+static inline wint_t DOC_PREV(struct pane *p safe, struct mark *m safe, struct doc_ref *r safe, bool byte);
 #endif
 static inline int do_char_byte(const struct cmd_info *ci safe)
 {
index 9594d82f5bea73e5bdc63e4679277387640fa4ae..faccce4625f84da8a4e65bb9cd70d2f96b99bceb 100644 (file)
@@ -22,6 +22,9 @@
 #include <stdlib.h>
 #include <wctype.h>
 
+#define DOC_NEXT base64_next
+#define DOC_PREV base64_prev
+
 #include "core.h"
 
 static struct map *b64_map safe;
@@ -102,16 +105,15 @@ static int get_pos(struct mark *m safe)
        return -1;
 }
 
-static int base64_step(struct pane *home safe, struct mark *mark,
-                      int forward, int move)
+static inline wint_t base64_next(struct pane *home safe, struct mark *mark safe,
+                                struct doc_ref *r safe, bool bytes)
 {
        int pos = 0;
+       int move = r == &mark->ref;
        struct mark *m;
        struct pane *p = home->parent;
        wint_t c1, c2, b;
 
-       if (!mark)
-               return Enoarg;
        pos = get_pos(mark);
        if (pos < 0)
                /* bug? */
@@ -119,38 +121,83 @@ static int base64_step(struct pane *home safe, struct mark *mark,
 
        m = mark_dup(mark);
 retry:
-       if (forward) {
-               c1 = get_b64(p, m);
-               c2 = get_b64(p, m);
-               /* If we found '=', there is no more to find */
-               if (c1 == 64 || c2 == 64) {
-                       while (pos < 2 && c2 != WEOF) {
-                               c2 = get_b64(p, m);
-                               pos += 1;
-                       }
-                       pos = 0;
-                       if (c2 != WEOF)
-                               /* hopefully it was 64 aka '=' */
-                               goto retry;
+       c1 = get_b64(p, m);
+       c2 = get_b64(p, m);
+       /* If we found '=', there is no more to find */
+       if (c1 == 64 || c2 == 64) {
+               while (pos < 2 && c2 != WEOF) {
+                       c2 = get_b64(p, m);
+                       pos += 1;
                }
-       } else {
-               if (pos)
-                       if (get_b64(p, m) == WEOF)
-                               pos = 0;
-               c2 = get_b64_rev(p, m);
+               pos = 0;
+               if (c2 != WEOF)
+                       /* hopefully it was 64 aka '=' */
+                       goto retry;
+       }
+       if (c1 == WEOF || c2 == WEOF) {
+               mark_free(m);
+               return CHAR_RET(WEOF);
+       }
+
+       switch(pos) {
+       case 0:
+               b = (c1 << 2) | (c2 >> 4);
+               break;
+       case 1:
+               b = ((c1 << 4) & 0xF0) | (c2 >> 2);
+               break;
+       case 2:
+               b = ((c1 << 6) & 0xC0) | c2;
+               break;
+       default:
+               b = 0;
+       }
+       if (move) {
+               if (pos < 2)
+                       /* Step back to look at the last char read */
+                       doc_prev(p, m);
+               else
+                       pos += 1;
+               mark_to_mark(mark, m);
+               set_pos(mark, pos+1);
+       }
+
+       mark_free(m);
+       return b;
+}
+
+static inline wint_t base64_prev(struct pane *home safe, struct mark *mark safe,
+                                struct doc_ref *r safe, bool bytes)
+{
+       int pos = 0;
+       int move = r == &mark->ref;
+       struct mark *m;
+       struct pane *p = home->parent;
+       wint_t c1, c2, b;
+
+       pos = get_pos(mark);
+       if (pos < 0)
+               /* bug? */
+               pos = 0;
+
+       m = mark_dup(mark);
+
+       if (pos)
+               if (get_b64(p, m) == WEOF)
+                       pos = 0;
+       c2 = get_b64_rev(p, m);
+       c1 = get_b64_rev(p, m);
+       if (pos <= 0)
+               pos = 2;
+       else
+               pos -= 1;
+       while (c2 == 64) {
+               c2 = c1;
                c1 = get_b64_rev(p, m);
                if (pos <= 0)
                        pos = 2;
                else
                        pos -= 1;
-               while (c2 == 64) {
-                       c2 = c1;
-                       c1 = get_b64_rev(p, m);
-                       if (pos <= 0)
-                               pos = 2;
-                       else
-                               pos -= 1;
-               }
        }
 
        if (c1 == WEOF || c2 == WEOF) {
@@ -172,51 +219,17 @@ retry:
                b = 0;
        }
        if (move) {
-               if (forward) {
-                       if (pos < 2)
-                               /* Step back to look at the last char read */
-                               doc_prev(p, m);
-                       else
-                               pos += 1;
-               }
                mark_to_mark(mark, m);
-               if (forward)
-                       set_pos(mark, pos+1);
-               else
-                       set_pos(mark, pos);
+               set_pos(mark, pos);
        }
 
        mark_free(m);
-       return CHAR_RET(b);
+       return b;
 }
 
 DEF_CMD(base64_char)
 {
-       struct mark *m = ci->mark;
-       struct mark *end = ci->mark2;
-       int steps = ci->num;
-       int forward = steps > 0;
-       int ret = Einval;
-
-       if (!m)
-               return Enoarg;
-       if (end && mark_same(m, end))
-               return 1;
-       if (end && (end->seq < m->seq) != (steps < 0))
-               /* Can never cross 'end' */
-               return Einval;
-       while (steps && ret != CHAR_RET(WEOF) && (!end || !mark_same(m, end))) {
-               ret = base64_step(ci->home, m, forward, 1);
-               steps -= forward*2 - 1;
-       }
-       if (end)
-               return 1 + (forward ? ci->num - steps : steps - ci->num);
-       if (ret == CHAR_RET(WEOF) || ci->num2 == 0)
-               return ret;
-       if (ci->num && (ci->num2 < 0) == forward)
-               return ret;
-       /* Want the 'next' char */
-       return base64_step(ci->home, m, ci->num2 > 0, 0);
+       return do_char_byte(ci);
 }
 
 DEF_CMD(base64_setref)