gfx/harfbuzz/src/hb-common.cc

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /*
     2  * Copyright © 2009,2010  Red Hat, Inc.
     3  * Copyright © 2011,2012  Google, Inc.
     4  *
     5  *  This is part of HarfBuzz, a text shaping library.
     6  *
     7  * Permission is hereby granted, without written agreement and without
     8  * license or royalty fees, to use, copy, modify, and distribute this
     9  * software and its documentation for any purpose, provided that the
    10  * above copyright notice and the following two paragraphs appear in
    11  * all copies of this software.
    12  *
    13  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
    14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
    15  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
    16  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
    17  * DAMAGE.
    18  *
    19  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
    20  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
    21  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
    22  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
    23  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
    24  *
    25  * Red Hat Author(s): Behdad Esfahbod
    26  * Google Author(s): Behdad Esfahbod
    27  */
    29 #include "hb-private.hh"
    31 #include "hb-mutex-private.hh"
    32 #include "hb-object-private.hh"
    34 #include <locale.h>
    37 /* hb_options_t */
    39 hb_options_union_t _hb_options;
    41 void
    42 _hb_options_init (void)
    43 {
    44   hb_options_union_t u;
    45   u.i = 0;
    46   u.opts.initialized = 1;
    48   char *c = getenv ("HB_OPTIONS");
    49   u.opts.uniscribe_bug_compatible = c && strstr (c, "uniscribe-bug-compatible");
    51   /* This is idempotent and threadsafe. */
    52   _hb_options = u;
    53 }
    56 /* hb_tag_t */
    58 /**
    59  * hb_tag_from_string:
    60  * @str: (array length=len): 
    61  * @len: 
    62  *
    63  * 
    64  *
    65  * Return value: 
    66  *
    67  * Since: 1.0
    68  **/
    69 hb_tag_t
    70 hb_tag_from_string (const char *str, int len)
    71 {
    72   char tag[4];
    73   unsigned int i;
    75   if (!str || !len || !*str)
    76     return HB_TAG_NONE;
    78   if (len < 0 || len > 4)
    79     len = 4;
    80   for (i = 0; i < (unsigned) len && str[i]; i++)
    81     tag[i] = str[i];
    82   for (; i < 4; i++)
    83     tag[i] = ' ';
    85   return HB_TAG_CHAR4 (tag);
    86 }
    88 /**
    89  * hb_tag_to_string:
    90  * @tag: 
    91  * @buf: (array fixed-size=4): 
    92  *
    93  * 
    94  *
    95  * Since: 1.0
    96  **/
    97 void
    98 hb_tag_to_string (hb_tag_t tag, char *buf)
    99 {
   100   buf[0] = (char) (uint8_t) (tag >> 24);
   101   buf[1] = (char) (uint8_t) (tag >> 16);
   102   buf[2] = (char) (uint8_t) (tag >>  8);
   103   buf[3] = (char) (uint8_t) (tag >>  0);
   104 }
   107 /* hb_direction_t */
   109 const char direction_strings[][4] = {
   110   "ltr",
   111   "rtl",
   112   "ttb",
   113   "btt"
   114 };
   116 /**
   117  * hb_direction_from_string:
   118  * @str: (array length=len): 
   119  * @len: 
   120  *
   121  * 
   122  *
   123  * Return value: 
   124  *
   125  * Since: 1.0
   126  **/
   127 hb_direction_t
   128 hb_direction_from_string (const char *str, int len)
   129 {
   130   if (unlikely (!str || !len || !*str))
   131     return HB_DIRECTION_INVALID;
   133   /* Lets match loosely: just match the first letter, such that
   134    * all of "ltr", "left-to-right", etc work!
   135    */
   136   char c = TOLOWER (str[0]);
   137   for (unsigned int i = 0; i < ARRAY_LENGTH (direction_strings); i++)
   138     if (c == direction_strings[i][0])
   139       return (hb_direction_t) (HB_DIRECTION_LTR + i);
   141   return HB_DIRECTION_INVALID;
   142 }
   144 /**
   145  * hb_direction_to_string:
   146  * @direction: 
   147  *
   148  * 
   149  *
   150  * Return value: (transfer none): 
   151  *
   152  * Since: 1.0
   153  **/
   154 const char *
   155 hb_direction_to_string (hb_direction_t direction)
   156 {
   157   if (likely ((unsigned int) (direction - HB_DIRECTION_LTR)
   158 	      < ARRAY_LENGTH (direction_strings)))
   159     return direction_strings[direction - HB_DIRECTION_LTR];
   161   return "invalid";
   162 }
   165 /* hb_language_t */
   167 struct hb_language_impl_t {
   168   const char s[1];
   169 };
   171 static const char canon_map[256] = {
   172    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
   173    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
   174    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,  '-',  0,   0,
   175   '0', '1', '2', '3', '4', '5', '6', '7',  '8', '9',  0,   0,   0,   0,   0,   0,
   176   '-', 'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
   177   'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  'x', 'y', 'z',  0,   0,   0,   0,  '-',
   178    0,  'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
   179   'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  'x', 'y', 'z',  0,   0,   0,   0,   0
   180 };
   182 static hb_bool_t
   183 lang_equal (hb_language_t  v1,
   184 	    const void    *v2)
   185 {
   186   const unsigned char *p1 = (const unsigned char *) v1;
   187   const unsigned char *p2 = (const unsigned char *) v2;
   189   while (*p1 && *p1 == canon_map[*p2])
   190     p1++, p2++;
   192   return *p1 == canon_map[*p2];
   193 }
   195 #if 0
   196 static unsigned int
   197 lang_hash (const void *key)
   198 {
   199   const unsigned char *p = key;
   200   unsigned int h = 0;
   201   while (canon_map[*p])
   202     {
   203       h = (h << 5) - h + canon_map[*p];
   204       p++;
   205     }
   207   return h;
   208 }
   209 #endif
   212 struct hb_language_item_t {
   214   struct hb_language_item_t *next;
   215   hb_language_t lang;
   217   inline bool operator == (const char *s) const {
   218     return lang_equal (lang, s);
   219   }
   221   inline hb_language_item_t & operator = (const char *s) {
   222     lang = (hb_language_t) strdup (s);
   223     for (unsigned char *p = (unsigned char *) lang; *p; p++)
   224       *p = canon_map[*p];
   226     return *this;
   227   }
   229   void finish (void) { free ((void *) lang); }
   230 };
   233 /* Thread-safe lock-free language list */
   235 static hb_language_item_t *langs;
   237 static inline
   238 void free_langs (void)
   239 {
   240   while (langs) {
   241     hb_language_item_t *next = langs->next;
   242     langs->finish ();
   243     free (langs);
   244     langs = next;
   245   }
   246 }
   248 static hb_language_item_t *
   249 lang_find_or_insert (const char *key)
   250 {
   251 retry:
   252   hb_language_item_t *first_lang = (hb_language_item_t *) hb_atomic_ptr_get (&langs);
   254   for (hb_language_item_t *lang = first_lang; lang; lang = lang->next)
   255     if (*lang == key)
   256       return lang;
   258   /* Not found; allocate one. */
   259   hb_language_item_t *lang = (hb_language_item_t *) calloc (1, sizeof (hb_language_item_t));
   260   if (unlikely (!lang))
   261     return NULL;
   262   lang->next = first_lang;
   263   *lang = key;
   265   if (!hb_atomic_ptr_cmpexch (&langs, first_lang, lang)) {
   266     free (lang);
   267     goto retry;
   268   }
   270 #ifdef HAVE_ATEXIT
   271   if (!first_lang)
   272     atexit (free_langs); /* First person registers atexit() callback. */
   273 #endif
   275   return lang;
   276 }
   279 /**
   280  * hb_language_from_string:
   281  * @str: (array length=len): 
   282  * @len: 
   283  *
   284  * 
   285  *
   286  * Return value: 
   287  *
   288  * Since: 1.0
   289  **/
   290 hb_language_t
   291 hb_language_from_string (const char *str, int len)
   292 {
   293   char strbuf[64];
   295   if (!str || !len || !*str)
   296     return HB_LANGUAGE_INVALID;
   298   if (len >= 0)
   299   {
   300     len = MIN (len, (int) sizeof (strbuf) - 1);
   301     str = (char *) memcpy (strbuf, str, len);
   302     strbuf[len] = '\0';
   303   }
   305   hb_language_item_t *item = lang_find_or_insert (str);
   307   return likely (item) ? item->lang : HB_LANGUAGE_INVALID;
   308 }
   310 /**
   311  * hb_language_to_string:
   312  * @language: 
   313  *
   314  * 
   315  *
   316  * Return value: (transfer none): 
   317  *
   318  * Since: 1.0
   319  **/
   320 const char *
   321 hb_language_to_string (hb_language_t language)
   322 {
   323   /* This is actually NULL-safe! */
   324   return language->s;
   325 }
   327 /**
   328  * hb_language_get_default:
   329  *
   330  * 
   331  *
   332  * Return value: 
   333  *
   334  * Since: 1.0
   335  **/
   336 hb_language_t
   337 hb_language_get_default (void)
   338 {
   339   static hb_language_t default_language = HB_LANGUAGE_INVALID;
   341   hb_language_t language = (hb_language_t) hb_atomic_ptr_get (&default_language);
   342   if (unlikely (language == HB_LANGUAGE_INVALID)) {
   343     language = hb_language_from_string (setlocale (LC_CTYPE, NULL), -1);
   344     hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language);
   345   }
   347   return default_language;
   348 }
   351 /* hb_script_t */
   353 /**
   354  * hb_script_from_iso15924_tag:
   355  * @tag: 
   356  *
   357  * 
   358  *
   359  * Return value: 
   360  *
   361  * Since: 1.0
   362  **/
   363 hb_script_t
   364 hb_script_from_iso15924_tag (hb_tag_t tag)
   365 {
   366   if (unlikely (tag == HB_TAG_NONE))
   367     return HB_SCRIPT_INVALID;
   369   /* Be lenient, adjust case (one capital letter followed by three small letters) */
   370   tag = (tag & 0xDFDFDFDF) | 0x00202020;
   372   switch (tag) {
   374     /* These graduated from the 'Q' private-area codes, but
   375      * the old code is still aliased by Unicode, and the Qaai
   376      * one in use by ICU. */
   377     case HB_TAG('Q','a','a','i'): return HB_SCRIPT_INHERITED;
   378     case HB_TAG('Q','a','a','c'): return HB_SCRIPT_COPTIC;
   380     /* Script variants from http://unicode.org/iso15924/ */
   381     case HB_TAG('C','y','r','s'): return HB_SCRIPT_CYRILLIC;
   382     case HB_TAG('L','a','t','f'): return HB_SCRIPT_LATIN;
   383     case HB_TAG('L','a','t','g'): return HB_SCRIPT_LATIN;
   384     case HB_TAG('S','y','r','e'): return HB_SCRIPT_SYRIAC;
   385     case HB_TAG('S','y','r','j'): return HB_SCRIPT_SYRIAC;
   386     case HB_TAG('S','y','r','n'): return HB_SCRIPT_SYRIAC;
   387   }
   389   /* If it looks right, just use the tag as a script */
   390   if (((uint32_t) tag & 0xE0E0E0E0) == 0x40606060)
   391     return (hb_script_t) tag;
   393   /* Otherwise, return unknown */
   394   return HB_SCRIPT_UNKNOWN;
   395 }
   397 /**
   398  * hb_script_from_string:
   399  * @s: (array length=len): 
   400  * @len: 
   401  *
   402  * 
   403  *
   404  * Return value: 
   405  *
   406  * Since: 1.0
   407  **/
   408 hb_script_t
   409 hb_script_from_string (const char *s, int len)
   410 {
   411   return hb_script_from_iso15924_tag (hb_tag_from_string (s, len));
   412 }
   414 /**
   415  * hb_script_to_iso15924_tag:
   416  * @script: 
   417  *
   418  * 
   419  *
   420  * Return value: 
   421  *
   422  * Since: 1.0
   423  **/
   424 hb_tag_t
   425 hb_script_to_iso15924_tag (hb_script_t script)
   426 {
   427   return (hb_tag_t) script;
   428 }
   430 /**
   431  * hb_script_get_horizontal_direction:
   432  * @script: 
   433  *
   434  * 
   435  *
   436  * Return value: 
   437  *
   438  * Since: 1.0
   439  **/
   440 hb_direction_t
   441 hb_script_get_horizontal_direction (hb_script_t script)
   442 {
   443   /* http://goo.gl/x9ilM */
   444   switch ((hb_tag_t) script)
   445   {
   446     /* Unicode-1.1 additions */
   447     case HB_SCRIPT_ARABIC:
   448     case HB_SCRIPT_HEBREW:
   450     /* Unicode-3.0 additions */
   451     case HB_SCRIPT_SYRIAC:
   452     case HB_SCRIPT_THAANA:
   454     /* Unicode-4.0 additions */
   455     case HB_SCRIPT_CYPRIOT:
   457     /* Unicode-4.1 additions */
   458     case HB_SCRIPT_KHAROSHTHI:
   460     /* Unicode-5.0 additions */
   461     case HB_SCRIPT_PHOENICIAN:
   462     case HB_SCRIPT_NKO:
   464     /* Unicode-5.1 additions */
   465     case HB_SCRIPT_LYDIAN:
   467     /* Unicode-5.2 additions */
   468     case HB_SCRIPT_AVESTAN:
   469     case HB_SCRIPT_IMPERIAL_ARAMAIC:
   470     case HB_SCRIPT_INSCRIPTIONAL_PAHLAVI:
   471     case HB_SCRIPT_INSCRIPTIONAL_PARTHIAN:
   472     case HB_SCRIPT_OLD_SOUTH_ARABIAN:
   473     case HB_SCRIPT_OLD_TURKIC:
   474     case HB_SCRIPT_SAMARITAN:
   476     /* Unicode-6.0 additions */
   477     case HB_SCRIPT_MANDAIC:
   479     /* Unicode-6.1 additions */
   480     case HB_SCRIPT_MEROITIC_CURSIVE:
   481     case HB_SCRIPT_MEROITIC_HIEROGLYPHS:
   483       return HB_DIRECTION_RTL;
   484   }
   486   return HB_DIRECTION_LTR;
   487 }
   490 /* hb_user_data_array_t */
   492 bool
   493 hb_user_data_array_t::set (hb_user_data_key_t *key,
   494 			   void *              data,
   495 			   hb_destroy_func_t   destroy,
   496 			   hb_bool_t           replace)
   497 {
   498   if (!key)
   499     return false;
   501   if (replace) {
   502     if (!data && !destroy) {
   503       items.remove (key, lock);
   504       return true;
   505     }
   506   }
   507   hb_user_data_item_t item = {key, data, destroy};
   508   bool ret = !!items.replace_or_insert (item, lock, replace);
   510   return ret;
   511 }
   513 void *
   514 hb_user_data_array_t::get (hb_user_data_key_t *key)
   515 {
   516   hb_user_data_item_t item = {NULL };
   518   return items.find (key, &item, lock) ? item.data : NULL;
   519 }
   522 /* hb_version */
   524 /**
   525  * hb_version:
   526  * @major: (out): Library major version component.
   527  * @minor: (out): Library minor version component.
   528  * @micro: (out): Library micro version component.
   529  *
   530  * Returns library version as three integer components.
   531  *
   532  * Since: 1.0
   533  **/
   534 void
   535 hb_version (unsigned int *major,
   536 	    unsigned int *minor,
   537 	    unsigned int *micro)
   538 {
   539   *major = HB_VERSION_MAJOR;
   540   *minor = HB_VERSION_MINOR;
   541   *micro = HB_VERSION_MICRO;
   542 }
   544 /**
   545  * hb_version_string:
   546  *
   547  * Returns library version as a string with three components.
   548  *
   549  * Return value: library version string.
   550  *
   551  * Since: 1.0
   552  **/
   553 const char *
   554 hb_version_string (void)
   555 {
   556   return HB_VERSION_STRING;
   557 }
   559 /**
   560  * hb_version_check:
   561  * @major: 
   562  * @minor: 
   563  * @micro: 
   564  *
   565  * 
   566  *
   567  * Return value: 
   568  *
   569  * Since: 1.0
   570  **/
   571 hb_bool_t
   572 hb_version_check (unsigned int major,
   573 		  unsigned int minor,
   574 		  unsigned int micro)
   575 {
   576   return HB_VERSION_CHECK (major, minor, micro);
   577 }

mercurial