LCOV - code coverage report
Current view: directory - gfx/harfbuzz/src - hb-blob.cc (source / functions) Found Hit Coverage
Test: app.info Lines: 93 2 2.2 %
Date: 2012-06-02 Functions: 19 2 10.5 %

       1                 : /*
       2                 :  * Copyright © 2009  Red Hat, Inc.
       3                 :  *
       4                 :  *  This is part of HarfBuzz, a text shaping library.
       5                 :  *
       6                 :  * Permission is hereby granted, without written agreement and without
       7                 :  * license or royalty fees, to use, copy, modify, and distribute this
       8                 :  * software and its documentation for any purpose, provided that the
       9                 :  * above copyright notice and the following two paragraphs appear in
      10                 :  * all copies of this software.
      11                 :  *
      12                 :  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
      13                 :  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
      14                 :  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
      15                 :  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
      16                 :  * DAMAGE.
      17                 :  *
      18                 :  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
      19                 :  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
      20                 :  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
      21                 :  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
      22                 :  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
      23                 :  *
      24                 :  * Red Hat Author(s): Behdad Esfahbod
      25                 :  */
      26                 : 
      27                 : #include "hb-private.hh"
      28                 : 
      29                 : #include "hb-blob.h"
      30                 : #include "hb-object-private.hh"
      31                 : 
      32                 : #ifdef HAVE_SYS_MMAN_H
      33                 : #ifdef HAVE_UNISTD_H
      34                 : #include <unistd.h>
      35                 : #endif /* HAVE_UNISTD_H */
      36                 : #include <sys/mman.h>
      37                 : #endif /* HAVE_SYS_MMAN_H */
      38                 : 
      39                 : #include <stdio.h>
      40                 : #include <errno.h>
      41                 : 
      42                 : 
      43                 : 
      44                 : #ifndef HB_DEBUG_BLOB
      45                 : #define HB_DEBUG_BLOB (HB_DEBUG+0)
      46                 : #endif
      47                 : 
      48                 : 
      49                 : struct _hb_blob_t {
      50                 :   hb_object_header_t header;
      51                 : 
      52                 :   bool immutable;
      53                 : 
      54                 :   const char *data;
      55                 :   unsigned int length;
      56                 :   hb_memory_mode_t mode;
      57                 : 
      58                 :   void *user_data;
      59                 :   hb_destroy_func_t destroy;
      60                 : };
      61                 : 
      62                 : static hb_blob_t _hb_blob_nil = {
      63                 :   HB_OBJECT_HEADER_STATIC,
      64                 : 
      65                 :   TRUE, /* immutable */
      66                 : 
      67                 :   NULL, /* data */
      68                 :   0, /* length */
      69                 :   HB_MEMORY_MODE_READONLY, /* mode */
      70                 : 
      71                 :   NULL, /* user_data */
      72                 :   NULL  /* destroy */
      73            1464 : };
      74                 : 
      75                 : 
      76                 : static bool _try_writable (hb_blob_t *blob);
      77                 : 
      78                 : static void
      79               0 : _hb_blob_destroy_user_data (hb_blob_t *blob)
      80                 : {
      81               0 :   if (blob->destroy) {
      82               0 :     blob->destroy (blob->user_data);
      83               0 :     blob->user_data = NULL;
      84               0 :     blob->destroy = NULL;
      85                 :   }
      86               0 : }
      87                 : 
      88                 : hb_blob_t *
      89               0 : hb_blob_create (const char        *data,
      90                 :                 unsigned int       length,
      91                 :                 hb_memory_mode_t   mode,
      92                 :                 void              *user_data,
      93                 :                 hb_destroy_func_t  destroy)
      94                 : {
      95                 :   hb_blob_t *blob;
      96                 : 
      97               0 :   if (!length || !(blob = hb_object_create<hb_blob_t> ())) {
      98               0 :     if (destroy)
      99               0 :       destroy (user_data);
     100               0 :     return &_hb_blob_nil;
     101                 :   }
     102                 : 
     103               0 :   blob->data = data;
     104               0 :   blob->length = length;
     105               0 :   blob->mode = mode;
     106                 : 
     107               0 :   blob->user_data = user_data;
     108               0 :   blob->destroy = destroy;
     109                 : 
     110               0 :   if (blob->mode == HB_MEMORY_MODE_DUPLICATE) {
     111               0 :     blob->mode = HB_MEMORY_MODE_READONLY;
     112               0 :     if (!_try_writable (blob)) {
     113               0 :       hb_blob_destroy (blob);
     114               0 :       return &_hb_blob_nil;
     115                 :     }
     116                 :   }
     117                 : 
     118               0 :   return blob;
     119                 : }
     120                 : 
     121                 : hb_blob_t *
     122               0 : hb_blob_create_sub_blob (hb_blob_t    *parent,
     123                 :                          unsigned int  offset,
     124                 :                          unsigned int  length)
     125                 : {
     126                 :   hb_blob_t *blob;
     127                 : 
     128               0 :   if (!length || offset >= parent->length)
     129               0 :     return &_hb_blob_nil;
     130                 : 
     131               0 :   hb_blob_make_immutable (parent);
     132                 : 
     133                 :   blob = hb_blob_create (parent->data + offset,
     134                 :                          MIN (length, parent->length - offset),
     135                 :                          parent->mode,
     136               0 :                          hb_blob_reference (parent),
     137               0 :                          (hb_destroy_func_t) hb_blob_destroy);
     138                 : 
     139               0 :   return blob;
     140                 : }
     141                 : 
     142                 : hb_blob_t *
     143               0 : hb_blob_get_empty (void)
     144                 : {
     145               0 :   return &_hb_blob_nil;
     146                 : }
     147                 : 
     148                 : hb_blob_t *
     149               0 : hb_blob_reference (hb_blob_t *blob)
     150                 : {
     151               0 :   return hb_object_reference (blob);
     152                 : }
     153                 : 
     154                 : void
     155               0 : hb_blob_destroy (hb_blob_t *blob)
     156                 : {
     157               0 :   if (!hb_object_destroy (blob)) return;
     158                 : 
     159               0 :   _hb_blob_destroy_user_data (blob);
     160                 : 
     161               0 :   free (blob);
     162                 : }
     163                 : 
     164                 : hb_bool_t
     165               0 : hb_blob_set_user_data (hb_blob_t          *blob,
     166                 :                        hb_user_data_key_t *key,
     167                 :                        void *              data,
     168                 :                        hb_destroy_func_t   destroy,
     169                 :                        hb_bool_t           replace)
     170                 : {
     171               0 :   return hb_object_set_user_data (blob, key, data, destroy, replace);
     172                 : }
     173                 : 
     174                 : void *
     175               0 : hb_blob_get_user_data (hb_blob_t          *blob,
     176                 :                        hb_user_data_key_t *key)
     177                 : {
     178               0 :   return hb_object_get_user_data (blob, key);
     179                 : }
     180                 : 
     181                 : 
     182                 : void
     183               0 : hb_blob_make_immutable (hb_blob_t *blob)
     184                 : {
     185               0 :   if (hb_object_is_inert (blob))
     186               0 :     return;
     187                 : 
     188               0 :   blob->immutable = TRUE;
     189                 : }
     190                 : 
     191                 : hb_bool_t
     192               0 : hb_blob_is_immutable (hb_blob_t *blob)
     193                 : {
     194               0 :   return blob->immutable;
     195                 : }
     196                 : 
     197                 : 
     198                 : unsigned int
     199               0 : hb_blob_get_length (hb_blob_t *blob)
     200                 : {
     201               0 :   return blob->length;
     202                 : }
     203                 : 
     204                 : const char *
     205               0 : hb_blob_get_data (hb_blob_t *blob, unsigned int *length)
     206                 : {
     207               0 :   if (length)
     208               0 :     *length = blob->length;
     209                 : 
     210               0 :   return blob->data;
     211                 : }
     212                 : 
     213                 : char *
     214               0 : hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length)
     215                 : {
     216               0 :   if (!_try_writable (blob)) {
     217               0 :     if (length)
     218               0 :       *length = 0;
     219                 : 
     220               0 :     return NULL;
     221                 :   }
     222                 : 
     223               0 :   if (length)
     224               0 :     *length = blob->length;
     225                 : 
     226               0 :   return const_cast<char *> (blob->data);
     227                 : }
     228                 : 
     229                 : 
     230                 : static hb_bool_t
     231               0 : _try_make_writable_inplace_unix (hb_blob_t *blob)
     232                 : {
     233                 : #if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MPROTECT)
     234                 :   uintptr_t pagesize = -1, mask, length;
     235                 :   const char *addr;
     236                 : 
     237                 : #if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
     238                 :   pagesize = (uintptr_t) sysconf (_SC_PAGE_SIZE);
     239                 : #elif defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
     240                 :   pagesize = (uintptr_t) sysconf (_SC_PAGESIZE);
     241                 : #elif defined(HAVE_GETPAGESIZE)
     242                 :   pagesize = (uintptr_t) getpagesize ();
     243                 : #endif
     244                 : 
     245                 :   if ((uintptr_t) -1L == pagesize) {
     246                 :     DEBUG_MSG_FUNC (BLOB, blob, "failed to get pagesize: %s", strerror (errno));
     247                 :     return FALSE;
     248                 :   }
     249                 :   DEBUG_MSG_FUNC (BLOB, blob, "pagesize is %lu", (unsigned long) pagesize);
     250                 : 
     251                 :   mask = ~(pagesize-1);
     252                 :   addr = (const char *) (((uintptr_t) blob->data) & mask);
     253                 :   length = (const char *) (((uintptr_t) blob->data + blob->length + pagesize-1) & mask)  - addr;
     254                 :   DEBUG_MSG_FUNC (BLOB, blob,
     255                 :                   "calling mprotect on [%p..%p] (%lu bytes)",
     256                 :                   addr, addr+length, (unsigned long) length);
     257                 :   if (-1 == mprotect ((void *) addr, length, PROT_READ | PROT_WRITE)) {
     258                 :     DEBUG_MSG_FUNC (BLOB, blob, "mprotect failed: %s", strerror (errno));
     259                 :     return FALSE;
     260                 :   }
     261                 : 
     262                 :   blob->mode = HB_MEMORY_MODE_WRITABLE;
     263                 : 
     264                 :   DEBUG_MSG_FUNC (BLOB, blob,
     265                 :                   "successfully made [%p..%p] (%lu bytes) writable\n",
     266                 :                   addr, addr+length, (unsigned long) length);
     267                 :   return TRUE;
     268                 : #else
     269               0 :   return FALSE;
     270                 : #endif
     271                 : }
     272                 : 
     273                 : static bool
     274               0 : _try_writable_inplace (hb_blob_t *blob)
     275                 : {
     276               0 :   DEBUG_MSG_FUNC (BLOB, blob, "making writable inplace\n");
     277                 : 
     278               0 :   if (_try_make_writable_inplace_unix (blob))
     279               0 :     return TRUE;
     280                 : 
     281               0 :   DEBUG_MSG_FUNC (BLOB, blob, "making writable -> FAILED\n");
     282                 : 
     283                 :   /* Failed to make writable inplace, mark that */
     284               0 :   blob->mode = HB_MEMORY_MODE_READONLY;
     285               0 :   return FALSE;
     286                 : }
     287                 : 
     288                 : static bool
     289               0 : _try_writable (hb_blob_t *blob)
     290                 : {
     291               0 :   if (blob->immutable)
     292               0 :     return FALSE;
     293                 : 
     294               0 :   if (blob->mode == HB_MEMORY_MODE_WRITABLE)
     295               0 :     return TRUE;
     296                 : 
     297               0 :   if (blob->mode == HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE && _try_writable_inplace (blob))
     298               0 :     return TRUE;
     299                 : 
     300               0 :   if (blob->mode == HB_MEMORY_MODE_WRITABLE)
     301               0 :     return TRUE;
     302                 : 
     303                 : 
     304               0 :   DEBUG_MSG_FUNC (BLOB, blob, "currect data is -> %p\n", blob->data);
     305                 : 
     306                 :   char *new_data;
     307                 : 
     308               0 :   new_data = (char *) malloc (blob->length);
     309               0 :   if (unlikely (!new_data))
     310               0 :     return FALSE;
     311                 : 
     312               0 :   DEBUG_MSG_FUNC (BLOB, blob, "dupped successfully -> %p\n", blob->data);
     313                 : 
     314               0 :   memcpy (new_data, blob->data, blob->length);
     315               0 :   _hb_blob_destroy_user_data (blob);
     316               0 :   blob->mode = HB_MEMORY_MODE_WRITABLE;
     317               0 :   blob->data = new_data;
     318               0 :   blob->user_data = new_data;
     319               0 :   blob->destroy = free;
     320                 : 
     321               0 :   return TRUE;
     322            4392 : }
     323                 : 
     324                 : 

Generated by: LCOV version 1.7