LCOV - differential code coverage report
Current view: top level - src/backend/access/gin - ginpostinglist.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 87.3 % 142 124 18 124
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 9 9 9
Baseline: 16@8cea358b128 Branches: 59.8 % 82 49 33 49
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed (240..) days: 87.3 % 142 124 18 124
Function coverage date bins:
(240..) days: 100.0 % 9 9 9
Branch coverage date bins:
(240..) days: 59.8 % 82 49 33 49

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * ginpostinglist.c
                                  4                 :                :  *    routines for dealing with posting lists.
                                  5                 :                :  *
                                  6                 :                :  *
                                  7                 :                :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
                                  8                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  9                 :                :  *
                                 10                 :                :  * IDENTIFICATION
                                 11                 :                :  *          src/backend/access/gin/ginpostinglist.c
                                 12                 :                :  *-------------------------------------------------------------------------
                                 13                 :                :  */
                                 14                 :                : 
                                 15                 :                : #include "postgres.h"
                                 16                 :                : 
                                 17                 :                : #include "access/gin_private.h"
                                 18                 :                : 
                                 19                 :                : #ifdef USE_ASSERT_CHECKING
                                 20                 :                : #define CHECK_ENCODING_ROUNDTRIP
                                 21                 :                : #endif
                                 22                 :                : 
                                 23                 :                : /*
                                 24                 :                :  * For encoding purposes, item pointers are represented as 64-bit unsigned
                                 25                 :                :  * integers. The lowest 11 bits represent the offset number, and the next
                                 26                 :                :  * lowest 32 bits are the block number. That leaves 21 bits unused, i.e.
                                 27                 :                :  * only 43 low bits are used.
                                 28                 :                :  *
                                 29                 :                :  * 11 bits is enough for the offset number, because MaxHeapTuplesPerPage <
                                 30                 :                :  * 2^11 on all supported block sizes. We are frugal with the bits, because
                                 31                 :                :  * smaller integers use fewer bytes in the varbyte encoding, saving disk
                                 32                 :                :  * space. (If we get a new table AM in the future that wants to use the full
                                 33                 :                :  * range of possible offset numbers, we'll need to change this.)
                                 34                 :                :  *
                                 35                 :                :  * These 43-bit integers are encoded using varbyte encoding. In each byte,
                                 36                 :                :  * the 7 low bits contain data, while the highest bit is a continuation bit.
                                 37                 :                :  * When the continuation bit is set, the next byte is part of the same
                                 38                 :                :  * integer, otherwise this is the last byte of this integer. 43 bits need
                                 39                 :                :  * at most 7 bytes in this encoding:
                                 40                 :                :  *
                                 41                 :                :  * 0XXXXXXX
                                 42                 :                :  * 1XXXXXXX 0XXXXYYY
                                 43                 :                :  * 1XXXXXXX 1XXXXYYY 0YYYYYYY
                                 44                 :                :  * 1XXXXXXX 1XXXXYYY 1YYYYYYY 0YYYYYYY
                                 45                 :                :  * 1XXXXXXX 1XXXXYYY 1YYYYYYY 1YYYYYYY 0YYYYYYY
                                 46                 :                :  * 1XXXXXXX 1XXXXYYY 1YYYYYYY 1YYYYYYY 1YYYYYYY 0YYYYYYY
                                 47                 :                :  * 1XXXXXXX 1XXXXYYY 1YYYYYYY 1YYYYYYY 1YYYYYYY 1YYYYYYY 0uuuuuuY
                                 48                 :                :  *
                                 49                 :                :  * X = bits used for offset number
                                 50                 :                :  * Y = bits used for block number
                                 51                 :                :  * u = unused bit
                                 52                 :                :  *
                                 53                 :                :  * The bytes are in stored in little-endian order.
                                 54                 :                :  *
                                 55                 :                :  * An important property of this encoding is that removing an item from list
                                 56                 :                :  * never increases the size of the resulting compressed posting list. Proof:
                                 57                 :                :  *
                                 58                 :                :  * Removing number is actually replacement of two numbers with their sum. We
                                 59                 :                :  * have to prove that varbyte encoding of a sum can't be longer than varbyte
                                 60                 :                :  * encoding of its summands. Sum of two numbers is at most one bit wider than
                                 61                 :                :  * the larger of the summands. Widening a number by one bit enlarges its length
                                 62                 :                :  * in varbyte encoding by at most one byte. Therefore, varbyte encoding of sum
                                 63                 :                :  * is at most one byte longer than varbyte encoding of larger summand. Lesser
                                 64                 :                :  * summand is at least one byte, so the sum cannot take more space than the
                                 65                 :                :  * summands, Q.E.D.
                                 66                 :                :  *
                                 67                 :                :  * This property greatly simplifies VACUUM, which can assume that posting
                                 68                 :                :  * lists always fit on the same page after vacuuming. Note that even though
                                 69                 :                :  * that holds for removing items from a posting list, you must also be
                                 70                 :                :  * careful to not cause expansion e.g. when merging uncompressed items on the
                                 71                 :                :  * page into the compressed lists, when vacuuming.
                                 72                 :                :  */
                                 73                 :                : 
                                 74                 :                : /*
                                 75                 :                :  * How many bits do you need to encode offset number? OffsetNumber is a 16-bit
                                 76                 :                :  * integer, but you can't fit that many items on a page. 11 ought to be more
                                 77                 :                :  * than enough. It's tempting to derive this from MaxHeapTuplesPerPage, and
                                 78                 :                :  * use the minimum number of bits, but that would require changing the on-disk
                                 79                 :                :  * format if MaxHeapTuplesPerPage changes. Better to leave some slack.
                                 80                 :                :  */
                                 81                 :                : #define MaxHeapTuplesPerPageBits        11
                                 82                 :                : 
                                 83                 :                : /* Max. number of bytes needed to encode the largest supported integer. */
                                 84                 :                : #define MaxBytesPerInteger              7
                                 85                 :                : 
                                 86                 :                : static inline uint64
 3735 heikki.linnakangas@i       87                 :CBC    17497941 : itemptr_to_uint64(const ItemPointer iptr)
                                 88                 :                : {
                                 89                 :                :     uint64      val;
                                 90                 :                : 
                                 91         [ -  + ]:       17497941 :     Assert(ItemPointerIsValid(iptr));
 2574 alvherre@alvh.no-ip.       92         [ -  + ]:       17497941 :     Assert(GinItemPointerGetOffsetNumber(iptr) < (1 << MaxHeapTuplesPerPageBits));
                                 93                 :                : 
                                 94                 :       17497941 :     val = GinItemPointerGetBlockNumber(iptr);
 3735 heikki.linnakangas@i       95                 :       17497941 :     val <<= MaxHeapTuplesPerPageBits;
 2574 alvherre@alvh.no-ip.       96                 :       17497941 :     val |= GinItemPointerGetOffsetNumber(iptr);
                                 97                 :                : 
 3735 heikki.linnakangas@i       98                 :       17497941 :     return val;
                                 99                 :                : }
                                100                 :                : 
                                101                 :                : static inline void
                                102                 :       33594769 : uint64_to_itemptr(uint64 val, ItemPointer iptr)
                                103                 :                : {
 2574 alvherre@alvh.no-ip.      104                 :       33594769 :     GinItemPointerSetOffsetNumber(iptr, val & ((1 << MaxHeapTuplesPerPageBits) - 1));
 3735 heikki.linnakangas@i      105                 :       33594769 :     val = val >> MaxHeapTuplesPerPageBits;
 2574 alvherre@alvh.no-ip.      106                 :       33594769 :     GinItemPointerSetBlockNumber(iptr, val);
                                107                 :                : 
 3735 heikki.linnakangas@i      108         [ -  + ]:       33594769 :     Assert(ItemPointerIsValid(iptr));
                                109                 :       33594769 : }
                                110                 :                : 
                                111                 :                : /*
                                112                 :                :  * Varbyte-encode 'val' into *ptr. *ptr is incremented to next integer.
                                113                 :                :  */
                                114                 :                : static void
                                115                 :       16402982 : encode_varbyte(uint64 val, unsigned char **ptr)
                                116                 :                : {
                                117                 :       16402982 :     unsigned char *p = *ptr;
                                118                 :                : 
                                119         [ +  + ]:       16700544 :     while (val > 0x7F)
                                120                 :                :     {
                                121                 :         297562 :         *(p++) = 0x80 | (val & 0x7F);
                                122                 :         297562 :         val >>= 7;
                                123                 :                :     }
                                124                 :       16402982 :     *(p++) = (unsigned char) val;
                                125                 :                : 
                                126                 :       16402982 :     *ptr = p;
                                127                 :       16402982 : }
                                128                 :                : 
                                129                 :                : /*
                                130                 :                :  * Decode varbyte-encoded integer at *ptr. *ptr is incremented to next integer.
                                131                 :                :  */
                                132                 :                : static uint64
                                133                 :       33594769 : decode_varbyte(unsigned char **ptr)
                                134                 :                : {
                                135                 :                :     uint64      val;
                                136                 :       33594769 :     unsigned char *p = *ptr;
                                137                 :                :     uint64      c;
                                138                 :                : 
                                139                 :                :     /* 1st byte */
                                140                 :       33594769 :     c = *(p++);
                                141                 :       33594769 :     val = c & 0x7F;
                                142         [ +  + ]:       33594769 :     if (c & 0x80)
                                143                 :                :     {
                                144                 :                :         /* 2nd byte */
                                145                 :         873206 :         c = *(p++);
                                146                 :         873206 :         val |= (c & 0x7F) << 7;
                                147         [ +  + ]:         873206 :         if (c & 0x80)
                                148                 :                :         {
                                149                 :                :             /* 3rd byte */
                                150                 :          90625 :             c = *(p++);
                                151                 :          90625 :             val |= (c & 0x7F) << 14;
                                152         [ +  + ]:          90625 :             if (c & 0x80)
                                153                 :                :             {
                                154                 :                :                 /* 4th byte */
                                155                 :              2 :                 c = *(p++);
                                156                 :              2 :                 val |= (c & 0x7F) << 21;
                                157         [ +  - ]:              2 :                 if (c & 0x80)
                                158                 :                :                 {
                                159                 :                :                     /* 5th byte */
                                160                 :              2 :                     c = *(p++);
                                161                 :              2 :                     val |= (c & 0x7F) << 28;
                                162         [ +  - ]:              2 :                     if (c & 0x80)
                                163                 :                :                     {
                                164                 :                :                         /* 6th byte */
                                165                 :              2 :                         c = *(p++);
                                166                 :              2 :                         val |= (c & 0x7F) << 35;
                                167         [ +  - ]:              2 :                         if (c & 0x80)
                                168                 :                :                         {
                                169                 :                :                             /* 7th byte, should not have continuation bit */
                                170                 :              2 :                             c = *(p++);
                                171                 :              2 :                             val |= c << 42;
 1691                           172         [ -  + ]:              2 :                             Assert((c & 0x80) == 0);
                                173                 :                :                         }
                                174                 :                :                     }
                                175                 :                :                 }
                                176                 :                :             }
                                177                 :                :         }
                                178                 :                :     }
                                179                 :                : 
 3735                           180                 :       33594769 :     *ptr = p;
                                181                 :                : 
                                182                 :       33594769 :     return val;
                                183                 :                : }
                                184                 :                : 
                                185                 :                : /*
                                186                 :                :  * Encode a posting list.
                                187                 :                :  *
                                188                 :                :  * The encoded list is returned in a palloc'd struct, which will be at most
                                189                 :                :  * 'maxsize' bytes in size.  The number items in the returned segment is
                                190                 :                :  * returned in *nwritten. If it's not equal to nipd, not all the items fit
                                191                 :                :  * in 'maxsize', and only the first *nwritten were encoded.
                                192                 :                :  *
                                193                 :                :  * The allocated size of the returned struct is short-aligned, and the padding
                                194                 :                :  * byte at the end, if any, is zero.
                                195                 :                :  */
                                196                 :                : GinPostingList *
                                197                 :         391279 : ginCompressPostingList(const ItemPointer ipd, int nipd, int maxsize,
                                198                 :                :                        int *nwritten)
                                199                 :                : {
                                200                 :                :     uint64      prev;
                                201                 :         391279 :     int         totalpacked = 0;
                                202                 :                :     int         maxbytes;
                                203                 :                :     GinPostingList *result;
                                204                 :                :     unsigned char *ptr;
                                205                 :                :     unsigned char *endptr;
                                206                 :                : 
 3660                           207                 :         391279 :     maxsize = SHORTALIGN_DOWN(maxsize);
                                208                 :                : 
 3735                           209                 :         391279 :     result = palloc(maxsize);
                                210                 :                : 
                                211                 :         391279 :     maxbytes = maxsize - offsetof(GinPostingList, bytes);
 3660                           212         [ -  + ]:         391279 :     Assert(maxbytes > 0);
                                213                 :                : 
                                214                 :                :     /* Store the first special item */
 3735                           215                 :         391279 :     result->first = ipd[0];
                                216                 :                : 
                                217                 :         391279 :     prev = itemptr_to_uint64(&result->first);
                                218                 :                : 
                                219                 :         391279 :     ptr = result->bytes;
                                220                 :         391279 :     endptr = result->bytes + maxbytes;
                                221         [ +  + ]:       16792129 :     for (totalpacked = 1; totalpacked < nipd; totalpacked++)
                                222                 :                :     {
                                223                 :       16402982 :         uint64      val = itemptr_to_uint64(&ipd[totalpacked]);
                                224                 :       16402982 :         uint64      delta = val - prev;
                                225                 :                : 
 3631 bruce@momjian.us          226         [ -  + ]:       16402982 :         Assert(val > prev);
                                227                 :                : 
 1691 heikki.linnakangas@i      228         [ +  + ]:       16402982 :         if (endptr - ptr >= MaxBytesPerInteger)
 3735                           229                 :       16388340 :             encode_varbyte(delta, &ptr);
                                230                 :                :         else
                                231                 :                :         {
                                232                 :                :             /*
                                233                 :                :              * There are less than 7 bytes left. Have to check if the next
                                234                 :                :              * item fits in that space before writing it out.
                                235                 :                :              */
                                236                 :                :             unsigned char buf[MaxBytesPerInteger];
                                237                 :          14642 :             unsigned char *p = buf;
                                238                 :                : 
                                239                 :          14642 :             encode_varbyte(delta, &p);
                                240         [ +  + ]:          14642 :             if (p - buf > (endptr - ptr))
 3631 bruce@momjian.us          241                 :           2132 :                 break;          /* output is full */
                                242                 :                : 
 3735 heikki.linnakangas@i      243                 :          12510 :             memcpy(ptr, buf, p - buf);
                                244                 :          12510 :             ptr += (p - buf);
                                245                 :                :         }
                                246                 :       16400850 :         prev = val;
                                247                 :                :     }
                                248                 :         391279 :     result->nbytes = ptr - result->bytes;
                                249                 :                : 
                                250                 :                :     /*
                                251                 :                :      * If we wrote an odd number of bytes, zero out the padding byte at the
                                252                 :                :      * end.
                                253                 :                :      */
 3660                           254         [ +  + ]:         391279 :     if (result->nbytes != SHORTALIGN(result->nbytes))
                                255                 :          30381 :         result->bytes[result->nbytes] = 0;
                                256                 :                : 
 3735                           257         [ +  + ]:         391279 :     if (nwritten)
                                258                 :          30211 :         *nwritten = totalpacked;
                                259                 :                : 
                                260         [ -  + ]:         391279 :     Assert(SizeOfGinPostingList(result) <= maxsize);
                                261                 :                : 
                                262                 :                :     /*
                                263                 :                :      * Check that the encoded segment decodes back to the original items.
                                264                 :                :      */
                                265                 :                : #if defined (CHECK_ENCODING_ROUNDTRIP)
                                266                 :                :     {
                                267                 :                :         int         ndecoded;
                                268                 :         391279 :         ItemPointer tmp = ginPostingListDecode(result, &ndecoded);
                                269                 :                : 
                                270         [ -  + ]:         391279 :         Assert(ndecoded == totalpacked);
 1499 tgl@sss.pgh.pa.us         271         [ -  + ]:         391279 :         Assert(memcmp(tmp, ipd, ndecoded * sizeof(ItemPointerData)) == 0);
 3735 heikki.linnakangas@i      272                 :         391279 :         pfree(tmp);
                                273                 :                :     }
                                274                 :                : #endif
                                275                 :                : 
                                276                 :         391279 :     return result;
                                277                 :                : }
                                278                 :                : 
                                279                 :                : /*
                                280                 :                :  * Decode a compressed posting list into an array of item pointers.
                                281                 :                :  * The number of items is returned in *ndecoded.
                                282                 :                :  */
                                283                 :                : ItemPointer
  573 pg@bowt.ie                284                 :         702004 : ginPostingListDecode(GinPostingList *plist, int *ndecoded_out)
                                285                 :                : {
 3735 heikki.linnakangas@i      286                 :        1404008 :     return ginPostingListDecodeAllSegments(plist,
                                287                 :         702004 :                                            SizeOfGinPostingList(plist),
                                288                 :                :                                            ndecoded_out);
                                289                 :                : }
                                290                 :                : 
                                291                 :                : /*
                                292                 :                :  * Decode multiple posting list segments into an array of item pointers.
                                293                 :                :  * The number of items is returned in *ndecoded_out. The segments are stored
                                294                 :                :  * one after each other, with total size 'len' bytes.
                                295                 :                :  */
                                296                 :                : ItemPointer
                                297                 :         702095 : ginPostingListDecodeAllSegments(GinPostingList *segment, int len, int *ndecoded_out)
                                298                 :                : {
                                299                 :                :     ItemPointer result;
                                300                 :                :     int         nallocated;
                                301                 :                :     uint64      val;
                                302                 :         702095 :     char       *endseg = ((char *) segment) + len;
                                303                 :                :     int         ndecoded;
                                304                 :                :     unsigned char *ptr;
                                305                 :                :     unsigned char *endptr;
                                306                 :                : 
                                307                 :                :     /*
                                308                 :                :      * Guess an initial size of the array.
                                309                 :                :      */
                                310                 :         702095 :     nallocated = segment->nbytes * 2 + 1;
                                311                 :         702095 :     result = palloc(nallocated * sizeof(ItemPointerData));
                                312                 :                : 
                                313                 :         702095 :     ndecoded = 0;
                                314         [ +  + ]:        1405775 :     while ((char *) segment < endseg)
                                315                 :                :     {
                                316                 :                :         /* enlarge output array if needed */
                                317         [ -  + ]:         703680 :         if (ndecoded >= nallocated)
                                318                 :                :         {
 3735 heikki.linnakangas@i      319                 :UBC           0 :             nallocated *= 2;
                                320                 :              0 :             result = repalloc(result, nallocated * sizeof(ItemPointerData));
                                321                 :                :         }
                                322                 :                : 
                                323                 :                :         /* copy the first item */
 3667 heikki.linnakangas@i      324   [ +  -  +  -  :CBC      703680 :         Assert(OffsetNumberIsValid(ItemPointerGetOffsetNumber(&segment->first)));
                                              -  + ]
                                325   [ +  +  -  + ]:         703680 :         Assert(ndecoded == 0 || ginCompareItemPointers(&segment->first, &result[ndecoded - 1]) > 0);
 3735                           326                 :         703680 :         result[ndecoded] = segment->first;
                                327                 :         703680 :         ndecoded++;
                                328                 :                : 
                                329                 :         703680 :         val = itemptr_to_uint64(&segment->first);
                                330                 :         703680 :         ptr = segment->bytes;
                                331                 :         703680 :         endptr = segment->bytes + segment->nbytes;
                                332         [ +  + ]:       34298449 :         while (ptr < endptr)
                                333                 :                :         {
                                334                 :                :             /* enlarge output array if needed */
                                335         [ +  + ]:       33594769 :             if (ndecoded >= nallocated)
                                336                 :                :             {
                                337                 :            290 :                 nallocated *= 2;
                                338                 :            290 :                 result = repalloc(result, nallocated * sizeof(ItemPointerData));
                                339                 :                :             }
                                340                 :                : 
                                341                 :       33594769 :             val += decode_varbyte(&ptr);
                                342                 :                : 
                                343                 :       33594769 :             uint64_to_itemptr(val, &result[ndecoded]);
                                344                 :       33594769 :             ndecoded++;
                                345                 :                :         }
                                346                 :         703680 :         segment = GinNextPostingListSegment(segment);
                                347                 :                :     }
                                348                 :                : 
                                349         [ +  - ]:         702095 :     if (ndecoded_out)
                                350                 :         702095 :         *ndecoded_out = ndecoded;
                                351                 :         702095 :     return result;
                                352                 :                : }
                                353                 :                : 
                                354                 :                : /*
                                355                 :                :  * Add all item pointers from a bunch of posting lists to a TIDBitmap.
                                356                 :                :  */
                                357                 :                : int
                                358                 :             15 : ginPostingListDecodeAllSegmentsToTbm(GinPostingList *ptr, int len,
                                359                 :                :                                      TIDBitmap *tbm)
                                360                 :                : {
                                361                 :                :     int         ndecoded;
                                362                 :                :     ItemPointer items;
                                363                 :                : 
                                364                 :             15 :     items = ginPostingListDecodeAllSegments(ptr, len, &ndecoded);
                                365                 :             15 :     tbm_add_tuples(tbm, items, ndecoded, false);
                                366                 :             15 :     pfree(items);
                                367                 :                : 
                                368                 :             15 :     return ndecoded;
                                369                 :                : }
                                370                 :                : 
                                371                 :                : /*
                                372                 :                :  * Merge two ordered arrays of itempointers, eliminating any duplicates.
                                373                 :                :  *
                                374                 :                :  * Returns a palloc'd array, and *nmerged is set to the number of items in
                                375                 :                :  * the result, after eliminating duplicates.
                                376                 :                :  */
                                377                 :                : ItemPointer
 3674                           378                 :          44256 : ginMergeItemPointers(ItemPointerData *a, uint32 na,
                                379                 :                :                      ItemPointerData *b, uint32 nb,
                                380                 :                :                      int *nmerged)
                                381                 :                : {
                                382                 :                :     ItemPointerData *dst;
                                383                 :                : 
                                384                 :          44256 :     dst = (ItemPointer) palloc((na + nb) * sizeof(ItemPointerData));
                                385                 :                : 
                                386                 :                :     /*
                                387                 :                :      * If the argument arrays don't overlap, we can just append them to each
                                388                 :                :      * other.
                                389                 :                :      */
 3735                           390   [ +  -  +  -  :          44256 :     if (na == 0 || nb == 0 || ginCompareItemPointers(&a[na - 1], &b[0]) < 0)
                                              +  + ]
                                391                 :                :     {
 3674                           392                 :          24594 :         memcpy(dst, a, na * sizeof(ItemPointerData));
                                393                 :          24594 :         memcpy(&dst[na], b, nb * sizeof(ItemPointerData));
                                394                 :          24594 :         *nmerged = na + nb;
                                395                 :                :     }
 3735                           396         [ +  - ]:          19662 :     else if (ginCompareItemPointers(&b[nb - 1], &a[0]) < 0)
                                397                 :                :     {
 3674                           398                 :          19662 :         memcpy(dst, b, nb * sizeof(ItemPointerData));
                                399                 :          19662 :         memcpy(&dst[nb], a, na * sizeof(ItemPointerData));
                                400                 :          19662 :         *nmerged = na + nb;
                                401                 :                :     }
                                402                 :                :     else
                                403                 :                :     {
 3674 heikki.linnakangas@i      404                 :UBC           0 :         ItemPointerData *dptr = dst;
                                405                 :              0 :         ItemPointerData *aptr = a;
                                406                 :              0 :         ItemPointerData *bptr = b;
                                407                 :                : 
 3735                           408   [ #  #  #  # ]:              0 :         while (aptr - a < na && bptr - b < nb)
                                409                 :                :         {
                                410                 :              0 :             int         cmp = ginCompareItemPointers(aptr, bptr);
                                411                 :                : 
                                412         [ #  # ]:              0 :             if (cmp > 0)
                                413                 :              0 :                 *dptr++ = *bptr++;
                                414         [ #  # ]:              0 :             else if (cmp == 0)
                                415                 :                :             {
                                416                 :                :                 /* only keep one copy of the identical items */
                                417                 :              0 :                 *dptr++ = *bptr++;
                                418                 :              0 :                 aptr++;
                                419                 :                :             }
                                420                 :                :             else
                                421                 :              0 :                 *dptr++ = *aptr++;
                                422                 :                :         }
                                423                 :                : 
                                424         [ #  # ]:              0 :         while (aptr - a < na)
 3812                           425                 :              0 :             *dptr++ = *aptr++;
                                426                 :                : 
 3735                           427         [ #  # ]:              0 :         while (bptr - b < nb)
                                428                 :              0 :             *dptr++ = *bptr++;
                                429                 :                : 
 3674                           430                 :              0 :         *nmerged = dptr - dst;
                                431                 :                :     }
                                432                 :                : 
 3674 heikki.linnakangas@i      433                 :CBC       44256 :     return dst;
                                434                 :                : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622