309 lines
7.6 KiB
C++
309 lines
7.6 KiB
C++
/*
|
|
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
|
*
|
|
* openGauss is licensed under Mulan PSL v2.
|
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
* You may obtain a copy of Mulan PSL v2 at:
|
|
*
|
|
* http://license.coscl.org.cn/MulanPSL2
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
* See the Mulan PSL v2 for more details.
|
|
* ---------------------------------------------------------------------------------------
|
|
*
|
|
* dfs_vector.h
|
|
*
|
|
*
|
|
*
|
|
* IDENTIFICATION
|
|
* src/include/utils/dfs_vector.h
|
|
*
|
|
* ---------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
#ifndef VECTOR_H_
|
|
#define VECTOR_H_
|
|
|
|
#include "postgres.h"
|
|
#include "securec.h"
|
|
#include "securec_check.h"
|
|
|
|
#include <algorithm>
|
|
|
|
/* stands for non-int type */
|
|
struct __type_true {};
|
|
|
|
/* stands for int type */
|
|
struct __type_false {};
|
|
|
|
template <typename T>
|
|
struct _type_traits {
|
|
typedef __type_false is_POD_type;
|
|
};
|
|
|
|
template <>
|
|
struct _type_traits<int> {
|
|
typedef __type_true is_POD_type;
|
|
};
|
|
|
|
/*
|
|
* Afford the dynamic array function.
|
|
*/
|
|
template <typename T>
|
|
class Vector {
|
|
public:
|
|
typedef T value_type;
|
|
typedef value_type* iterator;
|
|
typedef typename _type_traits<T>::is_POD_type is_POD;
|
|
|
|
/* Return the start iterator. */
|
|
iterator begin()
|
|
{
|
|
if (currentSize == 0) {
|
|
return 0;
|
|
}
|
|
|
|
return iterator(vectorHead);
|
|
}
|
|
|
|
/* Return the last iterator. */
|
|
iterator end()
|
|
{
|
|
return iterator(vectorHead + currentSize);
|
|
}
|
|
|
|
/* constructor */
|
|
Vector(int n = 0) : currentSize(n), currentCapacity(n > VECTOR_INIT_SIZE ? n : VECTOR_INIT_SIZE)
|
|
{
|
|
vectorHead = allocateMemory(is_POD());
|
|
}
|
|
|
|
/* constructor */
|
|
Vector(int n, T val) : currentSize(n), currentCapacity(n > VECTOR_INIT_SIZE ? n : VECTOR_INIT_SIZE)
|
|
{
|
|
vectorHead = allocateMemory(is_POD());
|
|
for (int i = 0; i < n; i++)
|
|
vectorHead[i] = val;
|
|
}
|
|
|
|
/* constructor */
|
|
Vector(const Vector& b) : currentSize(b.currentSize), currentCapacity(b.currentCapacity)
|
|
{
|
|
errno_t rc = EOK;
|
|
|
|
vectorHead = allocateMemory(is_POD());
|
|
if (NULL == vectorHead) {
|
|
elog(ERROR, "memory alloc failed!\n");
|
|
}
|
|
|
|
rc = memcpy_s(vectorHead, currentCapacity * sizeof(T), b.vectorHead, currentSize * sizeof(T));
|
|
securec_check(rc, "\0", "\0");
|
|
}
|
|
|
|
~Vector()
|
|
{
|
|
freeVectorHead(is_POD());
|
|
}
|
|
|
|
/* Add a element into the vector. */
|
|
void push_back(T val)
|
|
{
|
|
/* Current capacity is enough. */
|
|
if (currentSize < currentCapacity) {
|
|
vectorHead[currentSize++] = val;
|
|
}
|
|
/* Enlarge the capacity of vector. */
|
|
else {
|
|
currentCapacity = currentCapacity + CAPICITY_INCREASE_STEP;
|
|
T* newAllocated = allocateMemory(is_POD());
|
|
errno_t rc = EOK;
|
|
rc = memcpy_s(newAllocated, currentCapacity * sizeof(T), vectorHead, currentSize * sizeof(T));
|
|
securec_check(rc, "\0", "\0");
|
|
newAllocated[currentSize++] = val;
|
|
freeVectorHead(is_POD());
|
|
vectorHead = newAllocated;
|
|
}
|
|
}
|
|
|
|
/* Pop off a element from the tail. */
|
|
void pop_back()
|
|
{
|
|
if (currentSize)
|
|
currentSize--;
|
|
}
|
|
|
|
/* Return the first one. */
|
|
const T& front() const
|
|
{
|
|
return vectorHead[0];
|
|
}
|
|
|
|
/* Return the last one. */
|
|
const T& back() const
|
|
{
|
|
return vectorHead[currentSize - 1];
|
|
}
|
|
|
|
/* Implement the array visit operator. */
|
|
const T& operator[](int i) const
|
|
{
|
|
return vectorHead[i];
|
|
}
|
|
|
|
/* Implement the array visit operator. */
|
|
T& operator[](int i)
|
|
{
|
|
return vectorHead[i];
|
|
}
|
|
|
|
/* Return the size of the current vector. */
|
|
int size()
|
|
{
|
|
return currentSize;
|
|
}
|
|
|
|
/* Return the size of the current vector. */
|
|
int size() const
|
|
{
|
|
return currentSize;
|
|
}
|
|
|
|
/* Resize the current vector and fill it with the special value. */
|
|
void resize(uint32 new_size, T x)
|
|
{
|
|
/* Current capacity is enough. */
|
|
if (new_size < currentCapacity) {
|
|
if (currentSize < new_size) {
|
|
for (uint32 i = currentSize; i < new_size; i++) {
|
|
vectorHead[i] = x;
|
|
}
|
|
}
|
|
currentSize = new_size;
|
|
}
|
|
/* Need to enlarge the capacity. */
|
|
else {
|
|
currentCapacity = new_size;
|
|
T* newAllocated = allocateMemory(is_POD());
|
|
|
|
if (NULL == newAllocated) {
|
|
elog(ERROR, "memory alloc failed!\n");
|
|
}
|
|
|
|
errno_t rc = EOK;
|
|
|
|
rc = memcpy_s(newAllocated, currentCapacity * sizeof(T), vectorHead, currentSize * sizeof(T));
|
|
securec_check(rc, "\0", "\0");
|
|
|
|
for (uint32 i = currentSize; i < currentCapacity; i++) {
|
|
newAllocated[i] = x;
|
|
}
|
|
freeVectorHead(is_POD());
|
|
vectorHead = newAllocated;
|
|
currentSize = new_size;
|
|
}
|
|
}
|
|
|
|
/* Resize the current vector and fill it with NULL. */
|
|
void resize(int new_size)
|
|
{
|
|
resize(new_size, (T)0);
|
|
}
|
|
|
|
/* Return the capacity of the current vector. */
|
|
int capacity()
|
|
{
|
|
return currentCapacity;
|
|
}
|
|
|
|
/* Implement the equal check operator. */
|
|
bool operator==(const Vector& b) const
|
|
{
|
|
for (int i = 0; i < std::min(currentSize, b.currentSize); i++) {
|
|
if (!(vectorHead[i] == b.vectorHead[i]))
|
|
return false;
|
|
}
|
|
|
|
return currentSize == b.currentSize;
|
|
}
|
|
|
|
/* Implement the non-equal check operator. */
|
|
bool operator!=(const Vector& b) const
|
|
{
|
|
return !(*this == b);
|
|
}
|
|
|
|
/* Clear the dynamic arrays. */
|
|
void clear()
|
|
{
|
|
errno_t errNo = EOK;
|
|
errNo = ::memset_s(vectorHead, sizeof(T) * currentCapacity, 0, sizeof(T) * currentCapacity);
|
|
if (EOK != errNo) {
|
|
elog(ERROR, "Initialize memory failed.");
|
|
}
|
|
currentSize = 0;
|
|
}
|
|
|
|
/* Erase the element on the special position. */
|
|
iterator erase(iterator postion)
|
|
{
|
|
if (postion < iterator(vectorHead)) {
|
|
return vectorHead;
|
|
}
|
|
|
|
if (postion >= iterator(vectorHead + currentSize)) {
|
|
return vectorHead + currentSize;
|
|
}
|
|
|
|
T* succeedor = postion + 1;
|
|
errno_t errNo = EOK;
|
|
errNo = ::memmove_s(postion, end() - succeedor, succeedor, end() - succeedor);
|
|
if (EOK != errNo) {
|
|
elog(ERROR, "Initialize memory failed.");
|
|
}
|
|
currentSize--;
|
|
|
|
return succeedor;
|
|
}
|
|
|
|
private:
|
|
T* allocateMemory(__type_false)
|
|
{
|
|
if (currentCapacity == 0) {
|
|
return 0;
|
|
}
|
|
T* newAllocated = new T[currentCapacity];
|
|
return newAllocated;
|
|
}
|
|
|
|
T* allocateMemory(__type_true)
|
|
{
|
|
if (currentCapacity == 0) {
|
|
return 0;
|
|
}
|
|
T* newAllocated = (T*)palloc(currentCapacity * sizeof(T));
|
|
return newAllocated;
|
|
}
|
|
|
|
void freeVectorHead(__type_false)
|
|
{
|
|
delete[] vectorHead;
|
|
vectorHead = NULL;
|
|
}
|
|
void freeVectorHead(__type_true)
|
|
{
|
|
pfree(vectorHead);
|
|
}
|
|
|
|
private:
|
|
enum { VECTOR_INIT_SIZE = 25 };
|
|
enum { CAPICITY_INCREASE_STEP = 15 };
|
|
|
|
uint32 currentSize; // size
|
|
uint32 currentCapacity; // capacity
|
|
T* vectorHead; // value array
|
|
};
|
|
|
|
#endif /* VECTOR_H_ */
|