Esempio n. 1
0
static orxSTATUS orxFASTCALL ParseTextFile(const orxSTRING _zFileName)
{
  orxFILE  *pstFile;
  orxSTATUS eResult;

  // Opens file
  pstFile = orxFile_Open(_zFileName, orxFILE_KU32_FLAG_OPEN_READ | orxFILE_KU32_FLAG_OPEN_BINARY);

  // Success?
  if(pstFile)
  {
    orxCHAR acBuffer[orxFONTGEN_KU32_BUFFER_SIZE];
    orxU32  u32Size, u32Offset, u32Counter;
    orxBOOL bFirst;

    // While file isn't empty
    for(u32Size = (orxU32)orxFile_Read(acBuffer, sizeof(orxCHAR), orxFONTGEN_KU32_BUFFER_SIZE, pstFile), u32Offset = 0, u32Counter = 0, bFirst = orxTRUE;
        u32Size > 0;
        u32Size = (orxU32)orxFile_Read(acBuffer + u32Offset, sizeof(orxCHAR), orxFONTGEN_KU32_BUFFER_SIZE - u32Offset, pstFile) + u32Offset, bFirst = orxFALSE)
    {
      orxCHAR *pc, *pcNext;

      // Has UTF-8 BOM?
      if((bFirst != orxFALSE) && (orxString_NCompare(acBuffer, orxFONTGEN_KZ_UTF8_BOM, orxFONTGEN_KU32_UTF8_BOM_LENGTH) == 0))
      {
        // Skips it
        pc = acBuffer + orxFONTGEN_KU32_UTF8_BOM_LENGTH;
      }
      else
      {
        // Starts at the beginning of the buffer
        pc = acBuffer;
      }

      // For all characters
      for(pcNext = orxNULL; pc < acBuffer + u32Size; pc = pcNext)
      {
        orxU32 u32CharacterCodePoint;

        // Reads it
        u32CharacterCodePoint = orxString_GetFirstCharacterCodePoint(pc, (const orxSTRING *)&pcNext);

        // Non EOL?
        if((u32CharacterCodePoint != orxCHAR_CR)
        && (u32CharacterCodePoint != orxCHAR_LF))
        {
          // Valid?
          if(u32CharacterCodePoint != orxU32_UNDEFINED)
          {
            // Not already in table?
            if(orxHashTable_Get(sstFontGen.pstCharacterTable, u32CharacterCodePoint) == orxNULL)
            {
              orxU32 u32GlyphIndex;

              // Gets character's glyph index
              u32GlyphIndex = (orxU32)FT_Get_Char_Index(sstFontGen.pstFontFace, (FT_ULong)u32CharacterCodePoint);

              // Valid?
              if(u32GlyphIndex)
              {
                orxFONTGEN_GLYPH *pstGlyph;

                // Allocates glyph
                pstGlyph = (orxFONTGEN_GLYPH *)orxBank_Allocate(sstFontGen.pstGlyphBank);

                // Checks
                orxASSERT(pstGlyph);

                // Inits it
                pstGlyph->u32Index      = u32GlyphIndex;
                pstGlyph->u32CodePoint  = u32CharacterCodePoint;

                // Adds it
                if(orxHashTable_Add(sstFontGen.pstCharacterTable, u32CharacterCodePoint, (void *)pstGlyph) != orxSTATUS_FAILURE)
                {
                  orxFONTGEN_GLYPH *pstSearchGlyph;

                  // Finds position
                  for(pstSearchGlyph = (orxFONTGEN_GLYPH *)orxLinkList_GetFirst(&sstFontGen.stGlyphList);
                      pstSearchGlyph && (u32CharacterCodePoint > pstSearchGlyph->u32CodePoint);
                      pstSearchGlyph = (orxFONTGEN_GLYPH *)orxLinkList_GetNext(&pstSearchGlyph->stNode));

                  // Valid?
                  if(pstSearchGlyph)
                  {
                    // Adds it before
                    orxLinkList_AddBefore(&pstSearchGlyph->stNode, &pstGlyph->stNode);
                  }
                  else
                  {
                    // Adds it at the end
                    orxLinkList_AddEnd(&sstFontGen.stGlyphList, &pstGlyph->stNode);
                  }

                  // Updates counter
                  u32Counter++;
                }
                else
                {
                  // Logs message
                  orxFONTGEN_LOG(LOAD, "Character '0x%X': couldn't add to table, skipping.", u32CharacterCodePoint);
                }
              }
              else
              {
                // Adds it
                orxHashTable_Add(sstFontGen.pstCharacterTable, u32CharacterCodePoint, (void *)sstFontGen.pstCharacterTable);

                // Logs message
                orxFONTGEN_LOG(LOAD, "Character '0x%X': glyph not found in font, skipping.", u32CharacterCodePoint);
              }
            }
          }
          else
          {
            // End of buffer?
            if(pcNext >= acBuffer + u32Size)
            {
              // Stops
              break;
            }
            else
            {
              // Logs message
              orxFONTGEN_LOG(LOAD, "Invalid character code point '0x%X', skipping.", u32CharacterCodePoint);
            }
          }
        }
      }

      // Has remaining buffer?
      if((pc != acBuffer) && (pcNext > pc))
      {
        // Updates offset
        u32Offset = (orxU32)(orxMIN(pcNext, acBuffer + u32Size) - pc);

        // Copies it at the beginning of the buffer
        orxMemory_Copy(acBuffer, pc, u32Offset);
      }
      else
      {
        // Clears offset
        u32Offset = 0;
      }
    }

    // Logs message
    orxFONTGEN_LOG(LOAD, "'%s': added %d characters.", _zFileName, u32Counter);

    // Updates result
    eResult = orxSTATUS_SUCCESS;
  }
  else
  {
    // Updates result
    eResult = orxSTATUS_FAILURE;
  }

  // Done!
  return eResult;
}
Esempio n. 2
0
/** Optimizes a hashtable for read accesses (minimizes number of cache misses upon collisions)
 * @param[in] _pstHashTable HashTable to optimize
 * @return orxSTATUS_SUCESS / orxSTATUS_FAILURE
 */
orxSTATUS orxFASTCALL orxHashTable_Optimize(orxHASHTABLE *_pstHashTable)
{
  orxSTATUS eResult = orxSTATUS_SUCCESS;

  /* Checks */
  orxASSERT(_pstHashTable != orxNULL);

  /* Has elements? */
  if(_pstHashTable->u32Counter > 0)
  {
    orxHASHTABLE_CELL *astWorkBuffer;

    /* Allocates work buffer */
    astWorkBuffer = (orxHASHTABLE_CELL *)orxMemory_Allocate(_pstHashTable->u32Counter * sizeof(orxHASHTABLE_CELL), orxMEMORY_TYPE_TEMP);

    /* Valid? */
    if(astWorkBuffer != orxNULL)
    {
      orxU64              u64KeyIndex;
      orxU32              u32BufferIndex, i;
      orxHASHTABLE_CELL  *pstCell;

      /* For all cells */
      for(i = 0, u64KeyIndex = 0, u32BufferIndex = 0, pstCell = orxNULL; i < _pstHashTable->u32Counter; i++, u32BufferIndex++)
      {
        /* Linked cell? */
        if((pstCell != orxNULL) && (pstCell->pstNext != orxNULL))
        {
          /* Gets next in line */
          pstCell = pstCell->pstNext;
        }
        else
        {
          /* Finds next head cell */
          do{pstCell = _pstHashTable->apstCell[u64KeyIndex++];} while(pstCell == orxNULL);
        }

        /* Stores it */
        orxMemory_Copy(&astWorkBuffer[u32BufferIndex], pstCell, sizeof(orxHASHTABLE_CELL));
      }

      /* Clears bank */
      orxBank_Clear(_pstHashTable->pstBank);

      /* For all ordered cells */
      for(i = 0, pstCell = orxNULL; i < _pstHashTable->u32Counter; i++)
      {
        orxHASHTABLE_CELL *pstPreviousCell;

        /* Allocates new cell */
        pstPreviousCell = pstCell;
        pstCell         = (orxHASHTABLE_CELL *)orxBank_Allocate(_pstHashTable->pstBank);

        /* Checks */
        orxASSERT(pstCell != orxNULL);

        /* Stores its data */
        orxMemory_Copy(pstCell, &astWorkBuffer[i], sizeof(orxHASHTABLE_CELL));

        /* Chained? */
        if((pstPreviousCell != orxNULL) && (pstPreviousCell->pstNext != orxNULL))
        {
          /* Updates chaining */
          pstPreviousCell->pstNext = pstCell;
        }
        else
        {
          /* Updates head pointer */
          _pstHashTable->apstCell[orxHashTable_FindIndex(_pstHashTable, pstCell->u64Key)] = pstCell;
        }
      }

      /* Clears work buffer */
      orxMemory_Free(astWorkBuffer);
    }
    else
    {
      /* Updates result */
      eResult = orxSTATUS_FAILURE;
    }
  }

  /* Done! */
  return eResult;
}