コード例 #1
0
ファイル: i18n.c プロジェクト: bzed/pkg-open-vm-tools
static const void *
MsgGetString(const char *domain,
             const char *msgid,
             StringEncoding encoding)
{
   const char *idp;
   const char *strp;
   char idBuf[MSG_MAX_ID];
   size_t len;
   HashTable *source = NULL;
   MsgCatalog *catalog;
   MsgState *state = MsgGetState();

   /* All message strings must be prefixed by the message ID. */
   ASSERT(domain != NULL);
   ASSERT(msgid != NULL);
   ASSERT(MsgHasMsgID(msgid));
#if defined(_WIN32)
   ASSERT(encoding == STRING_ENCODING_UTF8 ||
          encoding == STRING_ENCODING_UTF16_LE);
#else
   ASSERT(encoding == STRING_ENCODING_UTF8);
#endif

   /*
    * Find the beginning of the ID (idp) and the string (strp).
    * The string should have the correct MSG_MAGIC(...)... form.
    */

   idp = msgid + MSG_MAGIC_LEN + 1;
   strp = strchr(idp, ')') + 1;

   len = strp - idp - 1;
   ASSERT_NOT_IMPLEMENTED(len <= MSG_MAX_ID - 1);
   memcpy(idBuf, idp, len);
   idBuf[len] = '\0';

   /*
    * This lock is pretty coarse-grained, but a lot of the code below just runs
    * in exceptional situations, so it should be OK.
    */
   g_static_mutex_lock(&state->lock);

   catalog = MsgGetCatalog(domain);
   if (catalog != NULL) {
      switch (encoding) {
      case STRING_ENCODING_UTF8:
         source = catalog->utf8;
         break;

#if defined(_WIN32)
      case STRING_ENCODING_UTF16_LE:
         source = catalog->utf16;
         break;
#endif

      default:
         NOT_IMPLEMENTED();
      }
   }

#if defined(_WIN32)
   /*
    * Lazily create the local and UTF-16 dictionaries. This may require also
    * registering an empty message catalog for the desired domain.
    */
   if (source == NULL && encoding == STRING_ENCODING_UTF16_LE) {
      catalog = MsgGetCatalog(domain);
      if (catalog == NULL) {
         if (domain == NULL) {
            g_error("Application did not set up a default text domain.");
         }
         catalog = g_new0(MsgCatalog, 1);
         MsgSetCatalog(domain, catalog);
      }

      catalog->utf16 = HashTable_Alloc(8, HASH_STRING_KEY, g_free);
      ASSERT_MEM_ALLOC(catalog->utf16);
      source = catalog->utf16;
   }
#endif

   /*
    * Look up the localized string, converting to requested encoding as needed.
    */

   if (source != NULL) {
      const void *retval = NULL;

      if (HashTable_Lookup(source, idBuf, (void **) &retval)) {
         strp = retval;
#if defined(_WIN32)
      } else if (encoding == STRING_ENCODING_UTF16_LE) {
         gchar *converted;
         Bool success;

         /*
          * Look up the string in UTF-8, convert it and cache it.
          */
         retval = MsgGetString(domain, msgid, STRING_ENCODING_UTF8);
         ASSERT(retval);

         converted = (gchar *) g_utf8_to_utf16(retval, -1, NULL, NULL, NULL);
         ASSERT(converted != NULL);

         success = HashTable_Insert(source, idBuf, converted);
         ASSERT(success);
         strp = converted;
#endif
      }
   }

   g_static_mutex_unlock(&state->lock);

   return strp;
}
コード例 #2
0
static GuestInfoCollector *
GuestInfoConstructCollector(GuestInfoQuery *queries,  // IN:
                            uint32 numQueries)        // IN:
{
   uint32 i;
   uint32 regExp = 0;
   GuestInfoCollector *collector = calloc(1, sizeof *collector);

   if (collector == NULL) {
      return NULL;
   }

   collector->reportMap = HashTable_Alloc(256, HASH_INT_KEY, NULL);

   collector->exactMatches = HashTable_Alloc(256,
                                           HASH_STRING_KEY | HASH_FLAG_COPYKEY,
                                             NULL);

   collector->numRegExps = 0;
   for (i = 0; i < numQueries; i++) {
      if (queries[i].isRegExp && queries[i].collect) {
         collector->numRegExps++;
      }
   }

   collector->numStats = numQueries;
   collector->stats = calloc(numQueries, sizeof *collector->stats);
   collector->regExps = calloc(collector->numRegExps, sizeof(GuestInfoStat *));

   if ((collector->exactMatches == NULL) ||
       (collector->reportMap == NULL) ||
       ((collector->numRegExps != 0) && (collector->regExps == NULL)) ||
       ((collector->numStats != 0) && (collector->stats == NULL))) {
      GuestInfoDestroyCollector(collector);
      return NULL;
   }

   regExp = 0;

   for (i = 0; i < numQueries; i++) {
      GuestInfoQuery *query = &queries[i];
      GuestInfoStat *stat = &collector->stats[i];

      ASSERT(query->reportID);

      stat->query = query;

      if (!query->collect) {
         continue;
      }

      if (query->isRegExp) {
         ASSERT(query->locatorString);

         collector->regExps[regExp++] = stat;
      } else {
         if (query->locatorString != NULL) {
            HashTable_Insert(collector->exactMatches, query->locatorString,
                              stat);
         }
      }

      /* The report lookup */
      HashTable_Insert(collector->reportMap, INT_AS_HASHKEY(query->reportID),
                       stat);
   }

   return collector;
}
コード例 #3
0
static void
VThreadBaseSimpleNoID(void)
{
   VThreadID newID;
   Bool reused = FALSE;
   Bool result;
   void *newNative = VThreadBaseGetNative();
   HashTable *ht = VThreadBaseGetNativeHash();
   VThreadBaseData *base;

   /* Require key allocation before TLS read */
   VThreadBaseGetKey();

   /* Before allocating a new ID, try to reclaim any old IDs. */
   for (newID = 0;
        newID < Atomic_Read(&vthreadBaseGlobals.dynamicID);
        newID++) {
      void *newKey = (void *)(uintptr_t)newID;

      /*
       * Windows: any entry that is found and not (alive or NULL)
       *    is reclaimable.  The check is slightly racy, but the race
       *    would only cause missing a reclaim which isn't a problem.
       * Posix: thread exit is hooked (via TLS destructor) and sets
       *    entries to NULL, so any entry that is NULL is reclaimable.
       */
#ifdef _WIN32
      void *oldNative;
      reused = HashTable_Lookup(ht, newKey, &oldNative) &&
               (oldNative == NULL ||
                !VThreadBaseNativeIsAlive(oldNative)) &&
               HashTable_ReplaceIfEqual(ht, newKey, oldNative, newNative);
#else
      reused = HashTable_ReplaceIfEqual(ht, newKey, NULL, newNative);
#endif
      if (reused) {
         break;
      }
   }

   if (!reused) {
      void *newKey;

      newID = Atomic_FetchAndInc(&vthreadBaseGlobals.dynamicID);
      /*
       * Detect VThreadID overflow (~0 is used as a sentinel).
       * Leave a space of ~10 IDs, since the increment and bounds-check
       * are not atomic.
       */
      ASSERT_NOT_IMPLEMENTED(newID < VTHREAD_INVALID_ID - 10);

      newKey = (void *)(uintptr_t)newID;
      result = HashTable_Insert(ht, newKey, newNative);
      ASSERT_NOT_IMPLEMENTED(result);
   }

   /* ID picked.  Now do the important stuff. */
   base = Util_SafeCalloc(1, sizeof *base);
   base->id = newID;
   Str_Sprintf(base->name, sizeof base->name, "vthread-%u", newID);

   result = VThreadBase_InitWithTLS(base);
   ASSERT(result);

   if (vmx86_debug && reused) {
      Log("VThreadBase reused VThreadID %d.\n", newID);
   }

   if (Atomic_Read(&vthreadBaseGlobals.numThreads) > 1) {
      LOG_ONCE(("VThreadBase detected multiple threads.\n"));
   }
}