1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2010-2017 L-SMASH project
6 * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *****************************************************************************/
21 /* This file is available under an ISC license. */
23 #include "internal.h" /* must be placed first */
27 static void lsmash_list_clear
29 lsmash_entry_list_t
*list
34 list
->last_accessed_entry
= NULL
;
35 list
->last_accessed_number
= 0;
36 list
->entry_count
= 0;
37 list
->eliminator
= NULL
;
40 void lsmash_list_init_orig
42 lsmash_entry_list_t
*list
,
43 lsmash_entry_data_eliminator eliminator
46 assert( eliminator
!= NULL
);
49 list
->last_accessed_entry
= NULL
;
50 list
->last_accessed_number
= 0;
51 list
->entry_count
= 0;
52 list
->eliminator
= eliminator
;
55 lsmash_entry_list_t
*lsmash_list_create_orig
57 lsmash_entry_data_eliminator eliminator
60 lsmash_entry_list_t
*list
= lsmash_malloc( sizeof(lsmash_entry_list_t
) );
63 lsmash_list_init( list
, eliminator
);
67 void lsmash_list_destroy
69 lsmash_entry_list_t
*list
72 lsmash_list_remove_entries( list
);
76 int lsmash_list_add_entry
78 lsmash_entry_list_t
*list
,
83 return LSMASH_ERR_FUNCTION_PARAM
;
84 lsmash_entry_t
*entry
= lsmash_malloc( sizeof(lsmash_entry_t
) );
86 return LSMASH_ERR_MEMORY_ALLOC
;
88 entry
->prev
= list
->tail
;
91 list
->tail
->next
= entry
;
95 list
->entry_count
+= 1;
99 int lsmash_list_remove_entry_direct
101 lsmash_entry_list_t
*list
,
102 lsmash_entry_t
*entry
105 if( !list
|| !entry
)
106 return LSMASH_ERR_FUNCTION_PARAM
;
107 assert( !entry
->data
|| list
->eliminator
);
108 lsmash_entry_t
*next
= entry
->next
;
109 lsmash_entry_t
*prev
= entry
->prev
;
110 if( entry
== list
->head
)
114 if( entry
== list
->tail
)
119 list
->eliminator( entry
->data
);
120 if( entry
== list
->last_accessed_entry
)
123 list
->last_accessed_entry
= next
;
126 list
->last_accessed_entry
= prev
;
127 list
->last_accessed_number
-= 1;
131 list
->last_accessed_entry
= NULL
;
132 list
->last_accessed_number
= 0;
137 /* We can't know the current entry number immediately,
138 * so discard the last accessed entry info because time is wasted to know it. */
139 list
->last_accessed_entry
= NULL
;
140 list
->last_accessed_number
= 0;
142 lsmash_free( entry
);
143 list
->entry_count
-= 1;
147 int lsmash_list_remove_entry
149 lsmash_entry_list_t
*list
,
150 uint32_t entry_number
153 lsmash_entry_t
*entry
= lsmash_list_get_entry( list
, entry_number
);
154 return lsmash_list_remove_entry_direct( list
, entry
);
157 int lsmash_list_remove_entry_tail
159 lsmash_entry_list_t
*list
162 return lsmash_list_remove_entry_direct( list
, list
->tail
);
165 void lsmash_list_remove_entries
167 lsmash_entry_list_t
*list
172 /* Note that it's valid that list contain no entries or no data to be eliminated. */
173 for( lsmash_entry_t
*entry
= list
->head
; entry
; )
175 lsmash_entry_t
*next
= entry
->next
;
177 list
->eliminator( entry
->data
);
178 lsmash_free( entry
);
181 lsmash_entry_data_eliminator eliminator
= list
->eliminator
;
182 lsmash_list_clear( list
);
183 list
->eliminator
= eliminator
;
186 void lsmash_list_move_entries
188 lsmash_entry_list_t
*dst
,
189 lsmash_entry_list_t
*src
193 lsmash_entry_data_eliminator eliminator
= src
->eliminator
;
194 lsmash_list_clear( src
);
195 src
->eliminator
= eliminator
;
198 lsmash_entry_t
*lsmash_list_get_entry
200 lsmash_entry_list_t
*list
,
201 uint32_t entry_number
204 if( !list
|| !entry_number
|| entry_number
> list
->entry_count
)
207 lsmash_entry_t
*entry
= NULL
;
208 if( list
->last_accessed_entry
)
210 if( entry_number
== list
->last_accessed_number
)
211 entry
= list
->last_accessed_entry
;
212 else if( entry_number
== list
->last_accessed_number
+ 1 )
213 entry
= list
->last_accessed_entry
->next
;
214 else if( entry_number
== list
->last_accessed_number
- 1 )
215 entry
= list
->last_accessed_entry
->prev
;
223 if( entry_number
<= (list
->entry_count
>> 1) )
225 /* Look for from the head. */
226 uint32_t distance_plus_one
= entry_number
;
227 for( entry
= list
->head
; entry
&& --distance_plus_one
; entry
= entry
->next
);
231 /* Look for from the tail. */
232 uint32_t distance
= list
->entry_count
- entry_number
;
233 for( entry
= list
->tail
; entry
&& distance
--; entry
= entry
->prev
);
238 list
->last_accessed_entry
= entry
;
239 list
->last_accessed_number
= entry_number
;
244 void *lsmash_list_get_entry_data
246 lsmash_entry_list_t
*list
,
247 uint32_t entry_number
250 lsmash_entry_t
*entry
= lsmash_list_get_entry( list
, entry_number
);
251 return entry
? entry
->data
: NULL
;