📄 safe_array.h
字号:
/* Copyright (C) 2004-2005 Timothy C.A. Molteno This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#ifndef __safe_array__#define __safe_array__#include <iostream>#include <string>#include <sstream>#ifdef NEC_ERROR_CHECK#include "nec_exception.h"class BoundsViol : public nec_exception{public: BoundsViol(const char* message, long index, long bound) : nec_exception(message) { m_message << "array index: " << index << " exceeds " << bound << std::endl; }};#endif/*! \brief A Safe Array class for nec2++ that performs bounds checking if the macro NEC_ERROR_CHECK is defined at compile time. This class also includes some utility functions for handling common vector operations. \todo Modify the resize() operator so that we resize in units of _resize_chunk. This will increase efficiency.*/template<typename T>class safe_array{public: safe_array() : len_(0), rows_(0), cols_(0), resize_chunk_(2), data_(NULL), data_size_(0), own_data_(true) { } safe_array(long in_size) : len_(0), rows_(0), cols_(0), resize_chunk_(2), data_(NULL), data_size_(0), own_data_(true) { resize(in_size); } safe_array(long n_rows, long n_cols) : len_(0), rows_(0), cols_(0), resize_chunk_(2), data_(NULL), data_size_(0), own_data_(true) { resize(n_rows, n_cols); } safe_array(const safe_array<T>& in_array) : len_(0), rows_(0), cols_(0), resize_chunk_(2), data_(NULL), data_size_(0), own_data_(true) { copy(in_array); } ~safe_array() { if (own_data_) delete[] data_; } long size() const { return len_; } void resize(long n_rows, long n_cols) { rows_ = n_rows; cols_ = n_cols; resize(rows_ * cols_); } // Copy the contents of in_array to our array // resizing as appropriate. void copy(const safe_array<T>& in_array) { if (in_array.rows_ == 0) resize(in_array.len_); else resize(in_array.rows_,in_array.cols_); for (long i=0; i<len_; i++) data_[i] = in_array[i]; } void resize(long new_length) {#ifdef NEC_ERROR_CHECK if (! own_data_) throw new nec_exception("attempt to resize data we do not own");#endif if (new_length > data_size_) { // We allocate resize_chunk_ more bytes than we need to avoid // resizing too often. T* new_data_ = new T[new_length + resize_chunk_]; data_size_ = new_length + resize_chunk_; if (0 != len_) memcpy(new_data_, data_, len_ * sizeof(T)); delete[] data_; data_ = new_data_; len_ = new_length; } else { len_ = new_length; } } // return the largest element of the array T max() { T ret = data_[check(0)]; for (long i = 1; i < len_; i++ ) { if ( data_[check(i)] > ret) ret = data_[check(i)]; } return ret; } // return the sum of all elements in the array T sum(long start_index, long stop_index) { T ret = data_[check(start_index)]; for (long i = start_index+1; i < stop_index; i++ ) { ret += data_[check(i)]; } return ret; } // return the sum of all elements in the array T sum() { return sum(0,len_); } // fill all elements of the array with x void fill(long start, long N, const T& x) { long stop = start + N; for (long i = start; i < stop; i++ ) { data_[check(i)] = x; } } // fill all elements of the array with x void fill(const T& x) { fill(0,len_,x); } /*! Set an element assuming that the data is stored in column major form. */ void set_col_major(int col_dim, int col, int row, const T& val) { data_[check(row*col_dim + col)] = val; } /*! Get an element assuming that the data is stored in column major form. */ T& get_col_major(int col_dim, int col, int row) { return data_[check(row*col_dim + col)]; } T& get(long row, long col) { return data_[check(row,col)]; } T get(long row, long col) const { return data_[check(row,col)]; } void set(long row, long col, const T& x) { data_[check(row,col)] = x; } const T& operator[](long i) const { return data_[check(i)]; } T& operator[](long i) { return data_[check(i)]; } // if end_index is -1, then finish at the end of the array safe_array<T> sub_array(long start_index, long end_index = -1) { if (-1 == end_index) end_index = len_; return safe_array<T>(*this, start_index, end_index, false); } T* get_ptr() const { return data_; } safe_array<T>& operator=(const safe_array<T>& in_array) { copy(in_array); return *this; }private: long len_; long rows_; long cols_; long resize_chunk_; T* data_; long data_size_; bool own_data_; // Used to constructing sub_array's safe_array(safe_array<T>& in_array, long start_index, long end_index, bool in_copy_data) { resize_chunk_ = in_array.resize_chunk_; len_ = (end_index - start_index); rows_ = 0; cols_ = 0; if (in_copy_data) { data_ = new T[len_]; data_size_ = len_; for (long i=0; i<len_; i++) data_[check(i)] = in_array[start_index + i]; own_data_ = true; } else { data_ = in_array.get_ptr() + start_index; data_size_ = 0; own_data_ = false; } } inline long check(long i) const {#ifdef NEC_ERROR_CHECK if (i < 0 || i >= len_) throw new BoundsViol("safe_array: ", i, len_);#endif return i; } inline long check(long row, long col) const {#ifdef NEC_ERROR_CHECK if (row < 0 || row >= rows_) throw new BoundsViol("safe_array: ", row, rows_); if (col < 0 || col >= cols_) throw new BoundsViol("safe_array: ", col, cols_);#endif return check(row*cols_ + col); }}; #endif /* __safe_array__ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -