LCOV - code coverage report
Current view: top level - py - vstr.c (source / functions) Hit Total Coverage
Test: unix_coverage_v1.24.0-7-g548babf8a.info Lines: 141 141 100.0 %
Date: 2024-10-30 09:06:48 Functions: 24 24 100.0 %
Branches: 29 34 85.3 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * This file is part of the MicroPython project, http://micropython.org/
       3                 :            :  *
       4                 :            :  * The MIT License (MIT)
       5                 :            :  *
       6                 :            :  * Copyright (c) 2013, 2014 Damien P. George
       7                 :            :  * Copyright (c) 2014 Paul Sokolovsky
       8                 :            :  *
       9                 :            :  * Permission is hereby granted, free of charge, to any person obtaining a copy
      10                 :            :  * of this software and associated documentation files (the "Software"), to deal
      11                 :            :  * in the Software without restriction, including without limitation the rights
      12                 :            :  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      13                 :            :  * copies of the Software, and to permit persons to whom the Software is
      14                 :            :  * furnished to do so, subject to the following conditions:
      15                 :            :  *
      16                 :            :  * The above copyright notice and this permission notice shall be included in
      17                 :            :  * all copies or substantial portions of the Software.
      18                 :            :  *
      19                 :            :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      20                 :            :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      21                 :            :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      22                 :            :  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      23                 :            :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      24                 :            :  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      25                 :            :  * THE SOFTWARE.
      26                 :            :  */
      27                 :            : 
      28                 :            : #include <stdio.h>
      29                 :            : #include <stdarg.h>
      30                 :            : #include <string.h>
      31                 :            : #include <assert.h>
      32                 :            : 
      33                 :            : #include "py/mpconfig.h"
      34                 :            : #include "py/runtime.h"
      35                 :            : #include "py/mpprint.h"
      36                 :            : 
      37                 :            : // returned value is always at least 1 greater than argument
      38                 :            : #define ROUND_ALLOC(a) (((a) & ((~0U) - 7)) + 8)
      39                 :            : 
      40                 :            : // Init the vstr so it allocs exactly given number of bytes.  Set length to zero.
      41                 :     336706 : void vstr_init(vstr_t *vstr, size_t alloc) {
      42         [ +  + ]:     336706 :     if (alloc < 1) {
      43                 :       7501 :         alloc = 1;
      44                 :            :     }
      45                 :     336706 :     vstr->alloc = alloc;
      46                 :     336706 :     vstr->len = 0;
      47                 :     336706 :     vstr->buf = m_new(char, vstr->alloc);
      48                 :     336706 :     vstr->fixed_buf = false;
      49                 :     336706 : }
      50                 :            : 
      51                 :            : // Init the vstr so it allocs exactly enough ram to hold a null-terminated
      52                 :            : // string of the given length, and set the length.
      53                 :      81949 : void vstr_init_len(vstr_t *vstr, size_t len) {
      54                 :      81949 :     vstr_init(vstr, len + 1);
      55                 :      81949 :     vstr->len = len;
      56                 :      81949 : }
      57                 :            : 
      58                 :      23724 : void vstr_init_fixed_buf(vstr_t *vstr, size_t alloc, char *buf) {
      59                 :      23724 :     vstr->alloc = alloc;
      60                 :      23724 :     vstr->len = 0;
      61                 :      23724 :     vstr->buf = buf;
      62                 :      23724 :     vstr->fixed_buf = true;
      63                 :      23724 : }
      64                 :            : 
      65                 :     242122 : void vstr_init_print(vstr_t *vstr, size_t alloc, mp_print_t *print) {
      66                 :     242122 :     vstr_init(vstr, alloc);
      67                 :     242122 :     print->data = vstr;
      68                 :     242122 :     print->print_strn = (mp_print_strn_t)vstr_add_strn;
      69                 :     242122 : }
      70                 :            : 
      71                 :      50066 : void vstr_clear(vstr_t *vstr) {
      72         [ +  - ]:      50066 :     if (!vstr->fixed_buf) {
      73                 :      50066 :         m_del(char, vstr->buf, vstr->alloc);
      74                 :            :     }
      75                 :      50066 :     vstr->buf = NULL;
      76                 :      50066 : }
      77                 :            : 
      78                 :        236 : vstr_t *vstr_new(size_t alloc) {
      79                 :        236 :     vstr_t *vstr = m_new_obj(vstr_t);
      80                 :        236 :     vstr_init(vstr, alloc);
      81                 :        236 :     return vstr;
      82                 :            : }
      83                 :            : 
      84                 :         18 : void vstr_free(vstr_t *vstr) {
      85         [ +  - ]:         18 :     if (vstr != NULL) {
      86         [ +  + ]:         18 :         if (!vstr->fixed_buf) {
      87                 :         16 :             m_del(char, vstr->buf, vstr->alloc);
      88                 :            :         }
      89                 :         18 :         m_del_obj(vstr_t, vstr);
      90                 :            :     }
      91                 :         18 : }
      92                 :            : 
      93                 :            : // Extend vstr strictly by requested size, return pointer to newly added chunk.
      94                 :        186 : char *vstr_extend(vstr_t *vstr, size_t size) {
      95         [ +  + ]:        186 :     if (vstr->fixed_buf) {
      96                 :            :         // We can't reallocate, and the caller is expecting the space to
      97                 :            :         // be there, so the only safe option is to raise an exception.
      98                 :          2 :         mp_raise_msg(&mp_type_RuntimeError, NULL);
      99                 :            :     }
     100                 :        184 :     char *new_buf = m_renew(char, vstr->buf, vstr->alloc, vstr->alloc + size);
     101                 :        184 :     char *p = new_buf + vstr->alloc;
     102                 :        184 :     vstr->alloc += size;
     103                 :        184 :     vstr->buf = new_buf;
     104                 :        184 :     return p;
     105                 :            : }
     106                 :            : 
     107                 :    1666097 : static void vstr_ensure_extra(vstr_t *vstr, size_t size) {
     108         [ +  + ]:    1666097 :     if (vstr->len + size > vstr->alloc) {
     109         [ +  + ]:      35073 :         if (vstr->fixed_buf) {
     110                 :            :             // We can't reallocate, and the caller is expecting the space to
     111                 :            :             // be there, so the only safe option is to raise an exception.
     112                 :          2 :             mp_raise_msg(&mp_type_RuntimeError, NULL);
     113                 :            :         }
     114                 :      35071 :         size_t new_alloc = ROUND_ALLOC((vstr->len + size) + 16);
     115                 :      35071 :         char *new_buf = m_renew(char, vstr->buf, vstr->alloc, new_alloc);
     116                 :      35070 :         vstr->alloc = new_alloc;
     117                 :      35070 :         vstr->buf = new_buf;
     118                 :            :     }
     119                 :    1666094 : }
     120                 :            : 
     121                 :          2 : void vstr_hint_size(vstr_t *vstr, size_t size) {
     122                 :          2 :     vstr_ensure_extra(vstr, size);
     123                 :          2 : }
     124                 :            : 
     125                 :    1331984 : char *vstr_add_len(vstr_t *vstr, size_t len) {
     126                 :    1331984 :     vstr_ensure_extra(vstr, len);
     127                 :    1331987 :     char *buf = vstr->buf + vstr->len;
     128                 :    1331987 :     vstr->len += len;
     129                 :    1331987 :     return buf;
     130                 :            : }
     131                 :            : 
     132                 :            : // Doesn't increase len, just makes sure there is a null byte at the end
     133                 :     226228 : char *vstr_null_terminated_str(vstr_t *vstr) {
     134                 :            :     // If there's no more room, add single byte
     135         [ +  + ]:     226228 :     if (vstr->alloc == vstr->len) {
     136                 :          8 :         vstr_extend(vstr, 1);
     137                 :            :     }
     138                 :     226226 :     vstr->buf[vstr->len] = '\0';
     139                 :     226226 :     return vstr->buf;
     140                 :            : }
     141                 :            : 
     142                 :    1208187 : void vstr_add_byte(vstr_t *vstr, byte b) {
     143                 :    1208187 :     byte *buf = (byte *)vstr_add_len(vstr, 1);
     144                 :    1208188 :     buf[0] = b;
     145                 :    1208188 : }
     146                 :            : 
     147                 :     121526 : void vstr_add_char(vstr_t *vstr, unichar c) {
     148                 :            :     #if MICROPY_PY_BUILTINS_STR_UNICODE
     149                 :            :     // TODO: Can this be simplified and deduplicated?
     150                 :            :     // Is it worth just calling vstr_add_len(vstr, 4)?
     151         [ +  + ]:     121526 :     if (c < 0x80) {
     152                 :     121496 :         byte *buf = (byte *)vstr_add_len(vstr, 1);
     153                 :     121496 :         *buf = (byte)c;
     154         [ +  + ]:         30 :     } else if (c < 0x800) {
     155                 :         12 :         byte *buf = (byte *)vstr_add_len(vstr, 2);
     156                 :         12 :         buf[0] = (c >> 6) | 0xC0;
     157                 :         12 :         buf[1] = (c & 0x3F) | 0x80;
     158         [ +  + ]:         18 :     } else if (c < 0x10000) {
     159                 :         12 :         byte *buf = (byte *)vstr_add_len(vstr, 3);
     160                 :         12 :         buf[0] = (c >> 12) | 0xE0;
     161                 :         12 :         buf[1] = ((c >> 6) & 0x3F) | 0x80;
     162                 :         12 :         buf[2] = (c & 0x3F) | 0x80;
     163                 :            :     } else {
     164         [ -  + ]:          6 :         assert(c < 0x110000);
     165                 :          6 :         byte *buf = (byte *)vstr_add_len(vstr, 4);
     166                 :          6 :         buf[0] = (c >> 18) | 0xF0;
     167                 :          6 :         buf[1] = ((c >> 12) & 0x3F) | 0x80;
     168                 :          6 :         buf[2] = ((c >> 6) & 0x3F) | 0x80;
     169                 :          6 :         buf[3] = (c & 0x3F) | 0x80;
     170                 :            :     }
     171                 :            :     #else
     172                 :            :     vstr_add_byte(vstr, c);
     173                 :            :     #endif
     174                 :     121526 : }
     175                 :            : 
     176                 :       9587 : void vstr_add_str(vstr_t *vstr, const char *str) {
     177                 :       9587 :     vstr_add_strn(vstr, str, strlen(str));
     178                 :       9585 : }
     179                 :            : 
     180                 :     326080 : void vstr_add_strn(vstr_t *vstr, const char *str, size_t len) {
     181                 :     326080 :     vstr_ensure_extra(vstr, len);
     182                 :     326078 :     memmove(vstr->buf + vstr->len, str, len);
     183                 :     326078 :     vstr->len += len;
     184                 :     326078 : }
     185                 :            : 
     186                 :       8032 : static char *vstr_ins_blank_bytes(vstr_t *vstr, size_t byte_pos, size_t byte_len) {
     187                 :       8032 :     size_t l = vstr->len;
     188         [ +  + ]:       8032 :     if (byte_pos > l) {
     189                 :          2 :         byte_pos = l;
     190                 :            :     }
     191         [ +  - ]:       8032 :     if (byte_len > 0) {
     192                 :            :         // ensure room for the new bytes
     193                 :       8032 :         vstr_ensure_extra(vstr, byte_len);
     194                 :            :         // copy up the string to make room for the new bytes
     195                 :       8032 :         memmove(vstr->buf + byte_pos + byte_len, vstr->buf + byte_pos, l - byte_pos);
     196                 :            :         // increase the length
     197                 :       8032 :         vstr->len += byte_len;
     198                 :            :     }
     199                 :       8032 :     return vstr->buf + byte_pos;
     200                 :            : }
     201                 :            : 
     202                 :       4071 : void vstr_ins_byte(vstr_t *vstr, size_t byte_pos, byte b) {
     203                 :       4071 :     char *s = vstr_ins_blank_bytes(vstr, byte_pos, 1);
     204                 :       4071 :     *s = b;
     205                 :       4071 : }
     206                 :            : 
     207                 :       3961 : void vstr_ins_char(vstr_t *vstr, size_t char_pos, unichar chr) {
     208                 :            :     // TODO UNICODE
     209                 :       3961 :     char *s = vstr_ins_blank_bytes(vstr, char_pos, 1);
     210                 :       3961 :     *s = chr;
     211                 :       3961 : }
     212                 :            : 
     213                 :          2 : void vstr_cut_head_bytes(vstr_t *vstr, size_t bytes_to_cut) {
     214                 :          2 :     vstr_cut_out_bytes(vstr, 0, bytes_to_cut);
     215                 :          2 : }
     216                 :            : 
     217                 :      19277 : void vstr_cut_tail_bytes(vstr_t *vstr, size_t len) {
     218         [ +  + ]:      19277 :     if (len > vstr->len) {
     219                 :          2 :         vstr->len = 0;
     220                 :            :     } else {
     221                 :      19275 :         vstr->len -= len;
     222                 :            :     }
     223                 :      19277 : }
     224                 :            : 
     225                 :        115 : void vstr_cut_out_bytes(vstr_t *vstr, size_t byte_pos, size_t bytes_to_cut) {
     226         [ +  - ]:        115 :     if (byte_pos >= vstr->len) {
     227                 :            :         return;
     228         [ +  + ]:        115 :     } else if (byte_pos + bytes_to_cut >= vstr->len) {
     229                 :         81 :         vstr->len = byte_pos;
     230                 :            :     } else {
     231                 :         34 :         memmove(vstr->buf + byte_pos, vstr->buf + byte_pos + bytes_to_cut, vstr->len - byte_pos - bytes_to_cut);
     232                 :         34 :         vstr->len -= bytes_to_cut;
     233                 :            :     }
     234                 :            : }
     235                 :            : 
     236                 :         58 : void vstr_printf(vstr_t *vstr, const char *fmt, ...) {
     237                 :         58 :     va_list ap;
     238                 :         58 :     va_start(ap, fmt);
     239                 :         58 :     vstr_vprintf(vstr, fmt, ap);
     240                 :         58 :     va_end(ap);
     241                 :         58 : }
     242                 :            : 
     243                 :         58 : void vstr_vprintf(vstr_t *vstr, const char *fmt, va_list ap) {
     244                 :         58 :     mp_print_t print = {vstr, (mp_print_strn_t)vstr_add_strn};
     245                 :         58 :     mp_vprintf(&print, fmt, ap);
     246                 :         58 : }

Generated by: LCOV version 1.15-5-g462f71d