1/*
2 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "list_wrapper.h"
12
13#include "trace.h"
14
15namespace webrtc {
16ListItem::ListItem(const void* item)
17    : this_iter_(),
18      item_ptr_(item),
19      item_(0)
20{
21}
22
23ListItem::ListItem(const unsigned int item)
24    : this_iter_(),
25      item_ptr_(0),
26      item_(item)
27{
28}
29
30ListItem::~ListItem()
31{
32}
33
34void* ListItem::GetItem() const
35{
36    return const_cast<void*>(item_ptr_);
37}
38
39unsigned int ListItem::GetUnsignedItem() const
40{
41    return item_;
42}
43
44ListWrapper::ListWrapper() : list_()
45{
46}
47
48ListWrapper::~ListWrapper()
49{
50    if (!Empty())
51    {
52        // TODO (hellner) I'm not sure this loggin is useful.
53        WEBRTC_TRACE(kTraceMemory, kTraceUtility, -1,
54                   "Potential memory leak in ListWrapper");
55        // Remove all remaining list items.
56        while (Erase(First()) == 0)
57        {}
58    }
59}
60
61bool ListWrapper::Empty() const
62{
63    return list_.empty();
64}
65
66unsigned int ListWrapper::GetSize() const
67{
68    return list_.size();
69}
70
71int ListWrapper::PushBack(const void* ptr)
72{
73    ListItem* item = new ListItem(ptr);
74    list_.push_back(item);
75    return 0;
76}
77
78int ListWrapper::PushBack(const unsigned int item_id)
79{
80    ListItem* item = new ListItem(item_id);
81    list_.push_back(item);
82    return 0;
83}
84
85int ListWrapper::PushFront(const unsigned int item_id)
86{
87    ListItem* item = new ListItem(item_id);
88    list_.push_front(item);
89    return 0;
90}
91
92int ListWrapper::PushFront(const void* ptr)
93{
94    ListItem* item = new ListItem(ptr);
95    list_.push_front(item);
96    return 0;
97}
98
99int ListWrapper::PopFront()
100{
101    if(list_.empty())
102    {
103        return -1;
104    }
105    list_.pop_front();
106    return 0;
107}
108
109int ListWrapper::PopBack()
110{
111    if(list_.empty())
112    {
113        return -1;
114    }
115    list_.pop_back();
116    return 0;
117}
118
119ListItem* ListWrapper::First() const
120{
121    if(list_.empty())
122    {
123        return NULL;
124    }
125    std::list<ListItem*>::iterator item_iter = list_.begin();
126    ListItem* return_item = (*item_iter);
127    return_item->this_iter_ = item_iter;
128    return return_item;
129}
130
131ListItem* ListWrapper::Last() const
132{
133    if(list_.empty())
134    {
135        return NULL;
136    }
137    // std::list::end() addresses the last item + 1. Decrement so that the
138    // actual last is accessed.
139    std::list<ListItem*>::iterator item_iter = list_.end();
140    --item_iter;
141    ListItem* return_item = (*item_iter);
142    return_item->this_iter_ = item_iter;
143    return return_item;
144}
145
146ListItem* ListWrapper::Next(ListItem* item) const
147{
148    if(item == NULL)
149    {
150        return NULL;
151    }
152    std::list<ListItem*>::iterator item_iter = item->this_iter_;
153    ++item_iter;
154    if (item_iter == list_.end())
155    {
156        return NULL;
157    }
158    ListItem* return_item = (*item_iter);
159    return_item->this_iter_ = item_iter;
160    return return_item;
161}
162
163ListItem* ListWrapper::Previous(ListItem* item) const
164{
165    if(item == NULL)
166    {
167        return NULL;
168    }
169    std::list<ListItem*>::iterator item_iter = item->this_iter_;
170    if (item_iter == list_.begin())
171    {
172      return NULL;
173    }
174    --item_iter;
175    ListItem* return_item = (*item_iter);
176    return_item->this_iter_ = item_iter;
177    return return_item;
178}
179
180int ListWrapper::Insert(ListItem* existing_previous_item,
181                        ListItem* new_item)
182{
183    // Allow existingPreviousItem to be NULL if the list is empty.
184    // TODO (hellner) why allow this? Keep it as is for now to avoid
185    // breaking API contract.
186    if (!existing_previous_item && !Empty())
187    {
188        return -1;
189    }
190
191    if (!new_item)
192    {
193        return -1;
194    }
195
196    std::list<ListItem*>::iterator insert_location = list_.begin();
197    if (!Empty())
198    {
199        insert_location = existing_previous_item->this_iter_;
200        if(insert_location != list_.end())
201        {
202            ++insert_location;
203        }
204    }
205
206    list_.insert(insert_location,new_item);
207    return 0;
208}
209
210int ListWrapper::InsertBefore(ListItem* existing_next_item,
211                           ListItem* new_item)
212{
213    // Allow existing_next_item to be NULL if the list is empty.
214    // Todo: why allow this? Keep it as is for now to avoid breaking API
215    // contract.
216    if (!existing_next_item && !Empty())
217    {
218        return -1;
219    }
220    if (!new_item)
221    {
222        return -1;
223    }
224
225    std::list<ListItem*>::iterator insert_location = list_.begin();
226    if (!Empty())
227    {
228        insert_location = existing_next_item->this_iter_;
229    }
230
231    list_.insert(insert_location,new_item);
232    return 0;
233}
234
235int ListWrapper::Erase(ListItem* item)
236{
237    if(item == NULL)
238    {
239        return -1;
240    }
241    list_.erase(item->this_iter_);
242    return 0;
243}
244} // namespace webrtc
245