/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "map_no_stl.h"
#include "critical_section_wrapper.h"
#include "trace.h"
namespace webrtc {
MapNoStlItem::MapNoStlItem(int id, void* item)
: next_(0),
prev_(0),
item_id_(id),
item_ptr_(item)
{
}
MapNoStlItem::~MapNoStlItem()
{
}
void* MapNoStlItem::GetItem()
{
return item_ptr_;
}
int MapNoStlItem::GetId()
{
return item_id_;
}
unsigned int MapNoStlItem::GetUnsignedId()
{
return static_cast<unsigned int>(item_id_);
}
void MapNoStlItem::SetItem(void* ptr)
{
item_ptr_ = ptr;
}
MapNoStl::MapNoStl()
: critical_section_(CriticalSectionWrapper::CreateCriticalSection()),
first_(0),
last_(0),
size_(0)
{
}
MapNoStl::~MapNoStl()
{
if (First())
{
WEBRTC_TRACE(kTraceMemory, kTraceUtility, -1,
"Potential memory leak in MapNoStl");
while (Erase(First()) == 0)
{}
}
delete critical_section_;
}
int MapNoStl::Size() const
{
return size_;
}
int MapNoStl::Insert(int id, void* ptr)
{
MapNoStlItem* new_item = new MapNoStlItem(id, ptr);
CriticalSectionScoped lock(*critical_section_);
MapNoStlItem* item = first_;
size_++;
if (!item)
{
first_ = new_item;
last_ = new_item;
return 0;
}
while(item->next_)
{
// Three scenarios
// 1. Item should be inserted first.
// 2. Item should be inserted between two items
// 3. Item should be inserted last
if (item->GetId() > id)
{
new_item->next_ = item;
item->prev_ = new_item;
if (item == first_)
{
first_ = new_item;
}
else
{
new_item->prev_ = item->prev_;
new_item->prev_->next_ = new_item;
}
return 0;
}
item = item->next_;
}
// 3
item->next_ = new_item;
new_item->prev_ = item;
last_ = new_item;
return 0;
}
MapNoStlItem* MapNoStl::First() const
{
return first_;
}
MapNoStlItem* MapNoStl::Last() const
{
return last_;
}
MapNoStlItem* MapNoStl::Next(MapNoStlItem* item) const
{
if (!item)
{
return 0;
}
return item->next_;
}
MapNoStlItem* MapNoStl::Previous(MapNoStlItem* item) const
{
if (!item)
{
return 0;
}
return item->prev_;
}
MapNoStlItem* MapNoStl::Find(int id) const
{
CriticalSectionScoped lock(*critical_section_);
MapNoStlItem* item = Locate(id);
return item;
}
int MapNoStl::Erase(MapNoStlItem* item)
{
if(!item)
{
return -1;
}
CriticalSectionScoped lock(*critical_section_);
return Remove(item);
}
int MapNoStl::Erase(const int id)
{
CriticalSectionScoped lock(*critical_section_);
MapNoStlItem* item = Locate(id);
if(!item)
{
return -1;
}
return Remove(item);
}
MapNoStlItem* MapNoStl::Locate(int id) const
{
MapNoStlItem* item = first_;
while(item)
{
if (item->GetId() == id)
{
return item;
}
item = item->next_;
}
return 0;
}
int MapNoStl::Remove(MapNoStlItem* item)
{
if (!item)
{
return -1;
}
size_--;
MapNoStlItem* previous_item = item->prev_;
MapNoStlItem* next_item = item->next_;
if (!previous_item)
{
next_item->prev_ = 0;
first_ = next_item;
}
else
{
previous_item->next_ = next_item;
}
if (!next_item)
{
previous_item->next_ = 0;
last_ = previous_item;
}
else
{
next_item->prev_ = previous_item;
}
delete item;
return 0;
}
} // namespace webrtc