Allow level-array to have different size from line length - libgrapheme - unicode string library
 (HTM) git clone git://git.suckless.org/libgrapheme
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit f320b0ad8b7b2bc7ab5b63e91379012adbd19d12
 (DIR) parent c0cab63c5300fa12284194fbef57aa2ed62a94c0
 (HTM) Author: Laslo Hunhold <dev@frign.de>
       Date:   Thu, 11 May 2023 18:16:09 +0200
       
       Allow level-array to have different size from line length
       
       This may not be apparent at first, but it allows you to only extract
       as many levels of a line as you need, e.g. only the first 10. Truncation
       is indicated by the return value being larger than levlen.
       
       Signed-off-by: Laslo Hunhold <dev@frign.de>
       
       Diffstat:
         M grapheme.h                          |       5 +++--
         M src/bidirectional.c                 |      24 ++++++++++++++++--------
         M test/bidirectional.c                |      12 +++++++++---
       
       3 files changed, 28 insertions(+), 13 deletions(-)
       ---
 (DIR) diff --git a/grapheme.h b/grapheme.h
       @@ -15,8 +15,9 @@ enum grapheme_bidirectional_override {
                GRAPHEME_BIDIRECTIONAL_OVERRIDE_RTL,
        };
        
       -void grapheme_bidirectional_get_line_embedding_levels(const uint_least32_t *,
       -                                                      size_t, int_least8_t *);
       +size_t grapheme_bidirectional_get_line_embedding_levels(const uint_least32_t *,
       +                                                        size_t, int_least8_t *,
       +                                                        size_t);
        
        size_t grapheme_bidirectional_preprocess(const uint_least32_t *, size_t,
                                                 enum grapheme_bidirectional_override,
 (DIR) diff --git a/src/bidirectional.c b/src/bidirectional.c
       @@ -1435,23 +1435,29 @@ grapheme_bidirectional_preprocess_utf8(
                return preprocess(&r, override, dest, destlen);
        }
        
       -void
       +size_t
        grapheme_bidirectional_get_line_embedding_levels(const uint_least32_t *linedata,
                                                         size_t linelen,
       -                                                 int_least8_t *linelevel)
       +                                                 int_least8_t *lev,
       +                                                 size_t levlen)
        {
                enum bidi_property prop;
                size_t i, runsince;
       +        int_least8_t level;
        
                /* rule L1.4 */
                runsince = SIZE_MAX;
                for (i = 0; i < linelen; i++) {
       +                level = (int_least8_t)get_state(STATE_LEVEL, linedata[i]);
                        prop = (uint_least8_t)get_state(STATE_PRESERVED_PROP,
                                                        linedata[i]);
        
       -                /* write level into level array */
       -                if ((linelevel[i] = (int_least8_t)get_state(
       -                             STATE_LEVEL, linedata[i])) == -1) {
       +                /* write level into level array if we still have space */
       +                if (i < levlen) {
       +                        lev[i] = level;
       +                }
       +
       +                if (level == -1) {
                                /* ignored character */
                                continue;
                        }
       @@ -1473,11 +1479,13 @@ grapheme_bidirectional_get_line_embedding_levels(const uint_least32_t *linedata,
                         * we hit the end of the line but were in a run;
                         * reset the line levels to the paragraph level
                         */
       -                for (i = runsince; i < linelen; i++) {
       -                        if (linelevel[i] != -1) {
       -                                linelevel[i] = (int_least8_t)get_state(
       +                for (i = runsince; i < MIN(linelen, levlen); i++) {
       +                        if (lev[i] != -1) {
       +                                lev[i] = (int_least8_t)get_state(
                                                STATE_PARAGRAPH_LEVEL, linedata[i]);
                                }
                        }
                }
       +
       +        return linelen;
        }
 (DIR) diff --git a/test/bidirectional.c b/test/bidirectional.c
       @@ -14,9 +14,10 @@ main(int argc, char *argv[])
        {
                uint_least32_t data[512]; /* TODO iterate and get max, allocate */
                int_least8_t lev[512];
       -        size_t i, num_tests, failed, datalen, ret, j, m;
       +        size_t i, num_tests, failed, datalen, levlen, ret, j, m;
        
                datalen = LEN(data);
       +        levlen = LEN(lev);
        
                (void)argc;
        
       @@ -30,14 +31,19 @@ main(int argc, char *argv[])
                                        bidirectional_test[i].cp,
                                        bidirectional_test[i].cplen,
                                        bidirectional_test[i].mode[m], data, datalen);
       -                        grapheme_bidirectional_get_line_embedding_levels(
       -                                data, ret, lev);
        
                                if (ret != bidirectional_test[i].cplen ||
                                    ret > datalen) {
                                        goto err;
                                }
        
       +                        ret = grapheme_bidirectional_get_line_embedding_levels(
       +                                data, ret, lev, levlen);
       +
       +                        if (ret > levlen) {
       +                                goto err;
       +                        }
       +
                                for (j = 0; j < ret; j++) {
                                        if (lev[j] != bidirectional_test[i].level[j]) {
                                                goto err;