1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2010-2014 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 void lsmash_init_entry_list( lsmash_entry_list_t
*list
)
31 list
->last_accessed_entry
= NULL
;
32 list
->last_accessed_number
= 0;
33 list
->entry_count
= 0;
36 lsmash_entry_list_t
*lsmash_create_entry_list( void )
38 lsmash_entry_list_t
*list
= lsmash_malloc( sizeof(lsmash_entry_list_t
) );
41 lsmash_init_entry_list( list
);
45 int lsmash_add_entry( lsmash_entry_list_t
*list
, void *data
)
48 return LSMASH_ERR_FUNCTION_PARAM
;
49 lsmash_entry_t
*entry
= lsmash_malloc( sizeof(lsmash_entry_t
) );
51 return LSMASH_ERR_MEMORY_ALLOC
;
53 entry
->prev
= list
->tail
;
56 list
->tail
->next
= entry
;
60 list
->entry_count
+= 1;
64 int lsmash_remove_entry_direct_orig( lsmash_entry_list_t
*list
, lsmash_entry_t
*entry
, lsmash_entry_data_eliminator eliminator
)
67 return LSMASH_ERR_FUNCTION_PARAM
;
69 eliminator
= lsmash_free
;
70 lsmash_entry_t
*next
= entry
->next
;
71 lsmash_entry_t
*prev
= entry
->prev
;
72 if( entry
== list
->head
)
76 if( entry
== list
->tail
)
81 eliminator( entry
->data
);
82 if( entry
== list
->last_accessed_entry
)
85 list
->last_accessed_entry
= next
;
88 list
->last_accessed_entry
= prev
;
89 list
->last_accessed_number
-= 1;
93 list
->last_accessed_entry
= NULL
;
94 list
->last_accessed_number
= 0;
99 /* We can't know the current entry number immediately,
100 * so discard the last accessed entry info because time is wasted to know it. */
101 list
->last_accessed_entry
= NULL
;
102 list
->last_accessed_number
= 0;
104 lsmash_free( entry
);
105 list
->entry_count
-= 1;
109 int lsmash_remove_entry_orig( lsmash_entry_list_t
*list
, uint32_t entry_number
, lsmash_entry_data_eliminator eliminator
)
111 lsmash_entry_t
*entry
= lsmash_get_entry( list
, entry_number
);
112 return lsmash_remove_entry_direct( list
, entry
, eliminator
);
115 int lsmash_remove_entry_tail_orig( lsmash_entry_list_t
*list
, lsmash_entry_data_eliminator eliminator
)
117 return lsmash_remove_entry_direct( list
, list
->tail
, eliminator
);
120 void lsmash_remove_entries_orig( lsmash_entry_list_t
*list
, lsmash_entry_data_eliminator eliminator
)
125 eliminator
= lsmash_free
;
126 for( lsmash_entry_t
*entry
= list
->head
; entry
; )
128 lsmash_entry_t
*next
= entry
->next
;
130 eliminator( entry
->data
);
131 lsmash_free( entry
);
134 lsmash_init_entry_list( list
);
137 void lsmash_remove_list_orig( lsmash_entry_list_t
*list
, lsmash_entry_data_eliminator eliminator
)
141 lsmash_remove_entries( list
, eliminator
);
145 lsmash_entry_t
*lsmash_get_entry( lsmash_entry_list_t
*list
, uint32_t entry_number
)
147 if( !list
|| !entry_number
|| entry_number
> list
->entry_count
)
150 lsmash_entry_t
*entry
= NULL
;
151 if( list
->last_accessed_entry
)
153 if( entry_number
== list
->last_accessed_number
)
154 entry
= list
->last_accessed_entry
;
155 else if( entry_number
== list
->last_accessed_number
+ 1 )
156 entry
= list
->last_accessed_entry
->next
;
157 else if( entry_number
== list
->last_accessed_number
- 1 )
158 entry
= list
->last_accessed_entry
->prev
;
166 if( entry_number
<= (list
->entry_count
>> 1) )
168 /* Look for from the head. */
169 uint32_t distance_plus_one
= entry_number
;
170 for( entry
= list
->head
; entry
&& --distance_plus_one
; entry
= entry
->next
);
174 /* Look for from the tail. */
175 uint32_t distance
= list
->entry_count
- entry_number
;
176 for( entry
= list
->tail
; entry
&& distance
--; entry
= entry
->prev
);
181 list
->last_accessed_entry
= entry
;
182 list
->last_accessed_number
= entry_number
;
187 void *lsmash_get_entry_data( lsmash_entry_list_t
*list
, uint32_t entry_number
)
189 lsmash_entry_t
*entry
= lsmash_get_entry( list
, entry_number
);
190 return entry
? entry
->data
: NULL
;