1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/
2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  ftutil.c                                                               */
4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*    FreeType utility file for memory and list management (body).         */
6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  Copyright 2002, 2004-2007, 2013 by                                     */
8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  This file is part of the FreeType project, and may only be used,       */
11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  modified, and distributed under the terms of the FreeType project      */
12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  this file you indicate that you have read the license and              */
14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  understand and accept it fully.                                        */
15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/
17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
19e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include <ft2build.h>
20e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_INTERNAL_DEBUG_H
21e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_INTERNAL_MEMORY_H
22e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_INTERNAL_OBJECTS_H
23e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_LIST_H
24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                       */
28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* messages during execution.                                            */
31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                       */
32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef  FT_COMPONENT
33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_COMPONENT  trace_memory
34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*****                                                               *****/
40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*****                                                               *****/
41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*****               M E M O R Y   M A N A G E M E N T               *****/
42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*****                                                               *****/
43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*****                                                               *****/
44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_BASE_DEF( FT_Pointer )
50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ft_mem_alloc( FT_Memory  memory,
51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FT_Long    size,
52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FT_Error  *p_error )
53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error    error;
55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Pointer  block = ft_mem_qalloc( memory, size, &error );
56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( !error && size > 0 )
58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_MEM_ZERO( block, size );
59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *p_error = error;
61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return block;
62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_BASE_DEF( FT_Pointer )
66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ft_mem_qalloc( FT_Memory  memory,
67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                 FT_Long    size,
68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                 FT_Error  *p_error )
69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error    error = FT_Err_Ok;
71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Pointer  block = NULL;
72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( size > 0 )
75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      block = memory->alloc( memory, size );
77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( block == NULL )
78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        error = FT_THROW( Out_Of_Memory );
79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else if ( size < 0 )
81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* may help catch/prevent security issues */
83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = FT_THROW( Invalid_Argument );
84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *p_error = error;
87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return block;
88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_BASE_DEF( FT_Pointer )
92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ft_mem_realloc( FT_Memory  memory,
93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  FT_Long    item_size,
94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  FT_Long    cur_count,
95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  FT_Long    new_count,
96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  void*      block,
97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  FT_Error  *p_error )
98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error  error = FT_Err_Ok;
100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    block = ft_mem_qrealloc( memory, item_size,
103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                             cur_count, new_count, block, &error );
104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( !error && new_count > cur_count )
105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_MEM_ZERO( (char*)block + cur_count * item_size,
106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   ( new_count - cur_count ) * item_size );
107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *p_error = error;
109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return block;
110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_BASE_DEF( FT_Pointer )
114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ft_mem_qrealloc( FT_Memory  memory,
115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   FT_Long    item_size,
116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   FT_Long    cur_count,
117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   FT_Long    new_count,
118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   void*      block,
119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   FT_Error  *p_error )
120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error  error = FT_Err_Ok;
122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* Note that we now accept `item_size == 0' as a valid parameter, in
125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     * order to cover very weird cases where an ALLOC_MULT macro would be
126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     * called.
127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     */
128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( cur_count < 0 || new_count < 0 || item_size < 0 )
129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* may help catch/prevent nasty security issues */
131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = FT_THROW( Invalid_Argument );
132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else if ( new_count == 0 || item_size == 0 )
134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      ft_mem_free( memory, block );
136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      block = NULL;
137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else if ( new_count > FT_INT_MAX/item_size )
139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = FT_THROW( Array_Too_Large );
141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else if ( cur_count == 0 )
143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_ASSERT( block == NULL );
145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      block = ft_mem_alloc( memory, new_count*item_size, &error );
147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Pointer  block2;
151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Long     cur_size = cur_count*item_size;
152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Long     new_size = new_count*item_size;
153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      block2 = memory->realloc( memory, cur_size, new_size, block );
156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( block2 == NULL )
157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        error = FT_THROW( Out_Of_Memory );
158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        block = block2;
160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *p_error = error;
163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return block;
164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_BASE_DEF( void )
168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ft_mem_free( FT_Memory   memory,
169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               const void *P )
170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( P )
172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      memory->free( memory, (void*)P );
173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_BASE_DEF( FT_Pointer )
177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ft_mem_dup( FT_Memory    memory,
178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              const void*  address,
179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              FT_ULong     size,
180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              FT_Error    *p_error )
181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error    error;
183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Pointer  p = ft_mem_qalloc( memory, size, &error );
184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( !error && address )
187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      ft_memcpy( p, address, size );
188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *p_error = error;
190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return p;
191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_BASE_DEF( FT_Pointer )
195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ft_mem_strdup( FT_Memory    memory,
196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                 const char*  str,
197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                 FT_Error    *p_error )
198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_ULong  len = str ? (FT_ULong)ft_strlen( str ) + 1
200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        : 0;
201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ft_mem_dup( memory, str, len, p_error );
204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_BASE_DEF( FT_Int )
208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ft_mem_strcpyn( char*        dst,
209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  const char*  src,
210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  FT_ULong     size )
211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while ( size > 1 && *src != 0 )
213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      *dst++ = *src++;
215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      size--;
216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *dst = 0;  /* always zero-terminate */
219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return *src != 0;
221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*****                                                               *****/
228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*****                                                               *****/
229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*****            D O U B L Y   L I N K E D   L I S T S              *****/
230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*****                                                               *****/
231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*****                                                               *****/
232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef  FT_COMPONENT
237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_COMPONENT  trace_list
238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in ftlist.h */
240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( FT_ListNode )
242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_List_Find( FT_List  list,
243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                void*    data )
244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_ListNode  cur;
246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
248e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if ( !list )
249e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov      return NULL;
250e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cur = list->head;
252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while ( cur )
253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( cur->data == data )
255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return cur;
256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      cur = cur->next;
258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
260e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return NULL;
261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in ftlist.h */
265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( void )
267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_List_Add( FT_List      list,
268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               FT_ListNode  node )
269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
270e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FT_ListNode  before;
271e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
272e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
273e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if ( !list || !node )
274e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov      return;
275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
276e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    before = list->tail;
277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    node->next = 0;
279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    node->prev = before;
280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( before )
282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      before->next = node;
283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      list->head = node;
285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    list->tail = node;
287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in ftlist.h */
291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( void )
293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_List_Insert( FT_List      list,
294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  FT_ListNode  node )
295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
296e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FT_ListNode  after;
297e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
298e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
299e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if ( !list || !node )
300e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov      return;
301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
302e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    after = list->head;
303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    node->next = after;
305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    node->prev = 0;
306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( !after )
308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      list->tail = node;
309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      after->prev = node;
311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    list->head = node;
313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in ftlist.h */
317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( void )
319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_List_Remove( FT_List      list,
320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  FT_ListNode  node )
321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_ListNode  before, after;
323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
325e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if ( !list || !node )
326e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov      return;
327e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    before = node->prev;
329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    after  = node->next;
330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( before )
332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      before->next = after;
333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      list->head = after;
335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( after )
337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      after->prev = before;
338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      list->tail = before;
340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in ftlist.h */
344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( void )
346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_List_Up( FT_List      list,
347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              FT_ListNode  node )
348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_ListNode  before, after;
350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
352e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if ( !list || !node )
353e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov      return;
354e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    before = node->prev;
356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    after  = node->next;
357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* check whether we are already on top of the list */
359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( !before )
360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return;
361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    before->next = after;
363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( after )
365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      after->prev = before;
366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      list->tail = before;
368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    node->prev       = 0;
370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    node->next       = list->head;
371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    list->head->prev = node;
372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    list->head       = node;
373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in ftlist.h */
377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( FT_Error )
379e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov  FT_List_Iterate( FT_List           list,
380e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                   FT_List_Iterator  iterator,
381e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                   void*             user )
382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
383e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FT_ListNode  cur;
384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error     error = FT_Err_Ok;
385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
387e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if ( !list || !iterator )
388e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov      return FT_THROW( Invalid_Argument );
389e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
390e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    cur = list->head;
391e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while ( cur )
393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_ListNode  next = cur->next;
395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = iterator( cur, user );
398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( error )
399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        break;
400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      cur = next;
402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in ftlist.h */
409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( void )
411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_List_Finalize( FT_List             list,
412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    FT_List_Destructor  destroy,
413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    FT_Memory           memory,
414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    void*               user )
415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_ListNode  cur;
417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
419e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if ( !list || !memory )
420e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov      return;
421e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cur = list->head;
423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while ( cur )
424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_ListNode  next = cur->next;
426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      void*        data = cur->data;
427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( destroy )
430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        destroy( memory, data, user );
431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_FREE( cur );
433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      cur = next;
434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    list->head = 0;
437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    list->tail = 0;
438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* END */
442