blob: f3e5fc243a8ff6a4ea2df1a90fe529409e33c98c [file] [log] [blame]
// Copyright 2006 Google Inc.
// All Rights Reserved.
// Author: <renn@google.com> (Marius Renn)
//
// This file declares the Map class, and its base class MapBase. Map is used
// in Helium for holding any type of two-dimensional data, such as bitmasks or
// images. Maps are reference counted, so they may be copied and used in Arrays.
//
#ifndef HELIUM_MAP_H__
#define HELIUM_MAP_H__
// Local includes
#include "debugging.h"
#include "point.h"
#include "refcount.h"
#include "types.h"
// C includes
#include <stddef.h>
#include <string.h>
namespace helium {
// The MapBase class provides access to the dimensions of the map. It is meant
// to provide a common interface to all methods that are not data dependant.
class MapBase : public ReferenceCounted {
public:
// Constructor. Initializes width and height to 0.
MapBase() : width_(0), height_(0) {
}
// Constructor to initialize map with the specified dimenions.
MapBase(unsigned width, unsigned height) : width_(width), height_(height) {
}
// Accessor to the width of the map.
inline unsigned width() const {
return width_;
}
// Accessor to the height of the map.
inline unsigned height() const {
return height_;
}
// Valid() returns true, if the width and height of the map are greater
// than 0.
inline bool Valid() const {
return (width_ > 0) && (height_ > 0);
}
protected:
unsigned width_, height_;
};
// The template class Map provides methods to create and modify two dimensional
// data of any size and element type. The idea is to provide simple pointer
// access to any portion of the data, so that algorithms can work with the
// data pointers directly.
// TODO: Provide methods for faster sequential access (on a word basis).
template<typename T>
class Map : public MapBase {
public:
// Constructor to create an empty map with no data.
Map();
// Constructor to allocate a map of the given width and height.
Map(unsigned width, unsigned height);
// Constructor to wrap existing data in a Map object.
Map(unsigned width, unsigned height, T* data);
// Deconstructor. Deletes when data is no longer referenced by any object.
virtual ~Map();
// Accessor to data.
inline T* data() const {
return data_;
}
// Accessor to set the data, and release the old data.
inline void set_data(T* data) {
Release();
data_ = data;
}
// Reallocate the map size.
void Reset(unsigned width, unsigned height);
// Obtain a pointer to the specified coordinates. This method does bounds
// checking in only in debug mode!
inline T* Access(const Point& p) const {
ASSERT_IN_DEBUG_MODE(p.x >= 0 && p.x < width_
&& p.y >= 0 && p.y < height_);
return data_ + width_ * p.y + p.x;
}
// Obtain a pointer to the specified coordinates. This method does bounds
// checking in only in debug mode!
inline T* Access(int x, int y) const {
ASSERT_IN_DEBUG_MODE(p.x >= 0 && p.x < width_
&& p.y >= 0 && p.y < height_);
return data_ + width_ * y + x;
}
// Returns the value at the specified coordinates. This method does bounds
// checking in only in debug mode!
inline T ValueAt(const Point& p) const {
return *Access(p.x, p.y);
}
// Returns the value at the specified coordinates. This method does bounds
// checking in only in debug mode!
inline T ValueAt(int x, int y) const {
return *Access(x, y);
}
// Returns a pointer to the last value. This is useful as the upper limit,
// when looping over the entire set of values.
inline T* DataEnd() const {
return Access(width_ - 1, height_ - 1);
}
// Returns true if the dimensions of the map are valid, and the data
// pointer is not NULL.
inline bool Valid() const {
return (data_ != NULL) && MapBase::Valid();
}
// Sets all the values in the map to 0.
void Clear();
// Releases the current data, and makes a copy of the specified Map. Use
// this method sparingly, as it may require a large memcpy (Helium uses
// this method only for debugging / reporting purposes).
void Copy(const Map& other);
protected:
// Deletes the data. This is called when all objects referencing the data
// have been released.
void DeleteData();
// The pointer to the data.
T* data_;
};
// Template implementations ----------------------------------------------------
template<typename T>
Map<T>::Map()
: MapBase(), data_(NULL) {
}
template<typename T>
Map<T>::Map(unsigned width, unsigned height)
: MapBase(width, height), data_(NULL) {
if (width * height > 0) data_ = new T[width * height];
}
template<typename T>
Map<T>::Map(unsigned width, unsigned height, T* data)
: MapBase(width, height), data_(data) {
}
template<typename T>
void Map<T>::Clear() {
memset(data_, 0, width_ * height_ * sizeof(T));
}
template<typename T>
void Map<T>::Reset(unsigned width, unsigned height) {
Release();
width_ = width;
height_ = height;
data_ = new T[width_ * height_];
Realloc(); // reset reference counter
}
template<typename T>
void Map<T>::Copy(const Map<T>& other) {
Reset(other.width_, other.height_);
memcpy(data_, other.data_, width_ * height_ * sizeof(T));
}
template<typename T>
Map<T>::~Map() {
if (ShouldDelete()) DeleteData();
}
template<typename T>
void Map<T>::DeleteData() {
delete[] data_;
data_ = NULL;
ReferenceCounted::DeleteData(); // Call Super
}
} // namespace
#endif // HELIUM_MAP_H__