⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftlru.c

📁 下载来的一个看图软件的源代码
💻 C
字号:
/***************************************************************************//*                                                                         *//*  ftlru.c                                                                *//*                                                                         *//*    Simple LRU list-cache (body).                                        *//*                                                                         *//*  Copyright 2000-2001, 2002, 2003 by                                     *//*  David Turner, Robert Wilhelm, and Werner Lemberg.                      *//*                                                                         *//*  This file is part of the FreeType project, and may only be used,       *//*  modified, and distributed under the terms of the FreeType project      *//*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     *//*  this file you indicate that you have read the license and              *//*  understand and accept it fully.                                        *//*                                                                         *//***************************************************************************/#include <ft2build.h>#include FT_CACHE_H#include FT_CACHE_INTERNAL_LRU_H#include FT_LIST_H#include FT_INTERNAL_OBJECTS_H#include FT_INTERNAL_DEBUG_H#include "ftcerror.h"  FT_EXPORT_DEF( FT_Error )  FT_LruList_New( FT_LruList_Class  clazz,                  FT_UInt           max_nodes,                  FT_Pointer        user_data,                  FT_Memory         memory,                  FT_LruList       *alist )  {    FT_Error    error;    FT_LruList  list;    if ( !alist || !clazz )      return FTC_Err_Invalid_Argument;    *alist = NULL;    if ( !FT_ALLOC( list, clazz->list_size ) )    {      /* initialize common fields */      list->clazz      = clazz;      list->memory     = memory;      list->max_nodes  = max_nodes;      list->data       = user_data;      if ( clazz->list_init )      {        error = clazz->list_init( list );        if ( error )        {          if ( clazz->list_done )            clazz->list_done( list );          FT_FREE( list );        }      }      *alist = list;    }    return error;  }  FT_EXPORT_DEF( void )  FT_LruList_Destroy( FT_LruList  list )  {    FT_Memory         memory;    FT_LruList_Class  clazz;    if ( !list )      return;    memory = list->memory;    clazz  = list->clazz;    FT_LruList_Reset( list );    if ( clazz->list_done )      clazz->list_done( list );    FT_FREE( list );  }  FT_EXPORT_DEF( void )  FT_LruList_Reset( FT_LruList  list )  {    FT_LruNode        node;    FT_LruList_Class  clazz;    FT_Memory         memory;    if ( !list )      return;    node   = list->nodes;    clazz  = list->clazz;    memory = list->memory;    while ( node )    {      FT_LruNode  next = node->next;      if ( clazz->node_done )        clazz->node_done( node, list->data );      FT_FREE( node );      node = next;    }    list->nodes     = NULL;    list->num_nodes = 0;  }  FT_EXPORT_DEF( FT_Error )  FT_LruList_Lookup( FT_LruList   list,                     FT_LruKey    key,                     FT_LruNode  *anode )  {    FT_Error          error = 0;    FT_LruNode        node, *pnode;    FT_LruList_Class  clazz;    FT_LruNode        result = NULL;    FT_Memory         memory;    if ( !list || !key || !anode )      return FTC_Err_Invalid_Argument;    pnode  = &list->nodes;    node   = NULL;    clazz  = list->clazz;    memory = list->memory;    if ( clazz->node_compare )    {      for (;;)      {        node = *pnode;        if ( node == NULL )          break;        if ( clazz->node_compare( node, key, list->data ) )          break;        pnode = &(*pnode)->next;      }    }    else    {      for (;;)      {        node = *pnode;        if ( node == NULL )          break;        if ( node->key == key )          break;        pnode = &(*pnode)->next;      }    }    if ( node )    {      /* move element to top of list */      if ( list->nodes != node )      {        *pnode      = node->next;        node->next  = list->nodes;        list->nodes = node;      }      result = node;      goto Exit;    }   /* Since we haven't found the relevant element in our LRU list,    * we're going to "create" a new one.    *    * The following code is a bit special, because it tries to handle    * out-of-memory conditions (OOM) in an intelligent way.    *    * More precisely, if not enough memory is available to create a    * new node or "flush" an old one, we need to remove the oldest    * elements from our list, and try again.  Since several tries may    * be necessary, a loop is needed.    *    * This loop will only exit when:    *    *   - a new node was successfully created, or an old node flushed    *   - an error other than FTC_Err_Out_Of_Memory is detected    *   - the list of nodes is empty, and it isn't possible to create    *     new nodes    *    * On each unsuccessful attempt, one node will be removed from the list.    *    */        {      FT_Int  drop_last = ( list->max_nodes > 0 &&                             list->num_nodes >= list->max_nodes );      for (;;)      {        node = NULL;        /* If "drop_last" is true, we should free the last node in         * the list to make room for a new one.  Note that we reuse         * its memory block to save allocation calls.         */        if ( drop_last )        {         /* find the last node in the list          */          pnode = &list->nodes;          node  = *pnode;            if ( node == NULL )          {            FT_ASSERT( list->num_nodes == 0 );            error = FTC_Err_Out_Of_Memory;            goto Exit;          }          FT_ASSERT( list->num_nodes > 0 );          while ( node->next )          {            pnode = &node->next;            node  = *pnode;          }            /* Remove it from the list, and try to "flush" it.  Doing this will           * save a significant number of dynamic allocations compared to           * a classic destroy/create cycle.           */          *pnode = NULL;          list->num_nodes--;            if ( clazz->node_flush )          {            error = clazz->node_flush( node, key, list->data );            if ( !error )              goto Success;           /* Note that if an error occured during the flush, we need to            * finalize it since it is potentially in incomplete state.            */          }          /* We finalize, but do not destroy the last node, we           * simply reuse its memory block!           */          if ( clazz->node_done )            clazz->node_done( node, list->data );                      FT_MEM_ZERO( node, clazz->node_size );        }        else        {         /* Try to allocate a new node when "drop_last" is not TRUE.          * This usually happens on the first pass, when the LRU list          * is not already full.          */          if ( FT_ALLOC( node, clazz->node_size ) )            goto Fail;        }          FT_ASSERT( node != NULL );        node->key = key;        error = clazz->node_init( node, key, list->data );        if ( error )        {          if ( clazz->node_done )            clazz->node_done( node, list->data );          FT_FREE( node );          goto Fail;        }      Success:        result = node;        node->next  = list->nodes;        list->nodes = node;        list->num_nodes++;        goto Exit;        Fail:        if ( error != FTC_Err_Out_Of_Memory )          goto Exit;                drop_last = 1;        continue;      }    }  Exit:    *anode = result;    return error;  }  FT_EXPORT_DEF( void )  FT_LruList_Remove( FT_LruList  list,                     FT_LruNode  node )  {    FT_LruNode  *pnode;    if ( !list || !node )      return;    pnode = &list->nodes;    for (;;)    {      if ( *pnode == node )      {        FT_Memory         memory = list->memory;        FT_LruList_Class  clazz  = list->clazz;        *pnode     = node->next;        node->next = NULL;        if ( clazz->node_done )          clazz->node_done( node, list->data );        FT_FREE( node );        list->num_nodes--;        break;      }      pnode = &(*pnode)->next;    }  }  FT_EXPORT_DEF( void )  FT_LruList_Remove_Selection( FT_LruList             list,                               FT_LruNode_SelectFunc  select_func,                               FT_Pointer             select_data )  {    FT_LruNode       *pnode, node;    FT_LruList_Class  clazz;    FT_Memory         memory;    if ( !list || !select_func )      return;    memory = list->memory;    clazz  = list->clazz;    pnode  = &list->nodes;    for (;;)    {      node = *pnode;      if ( node == NULL )        break;      if ( select_func( node, select_data, list->data ) )      {        *pnode     = node->next;        node->next = NULL;        if ( clazz->node_done )          clazz->node_done( node, list );        FT_FREE( node );        list->num_nodes--;      }      else        pnode = &(*pnode)->next;    }  }/* END */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -