/**
* Copyright (c) 2015 by Contributors
*/
#ifndef PS_SARRAY_H_
#define PS_SARRAY_H_
#include <string.h>
#include <string>
#include <vector>
#include <memory>
#include <sstream>
#include "ps/internal/utils.h"
#include "ps/range.h"
namespace ps {
/**
*共享數(shù)組凸舵,保留了共享所有關(guān)系钓简,提供了與std::vector相似功能,包含
*data(), size(), operator[], resize(), clear(). 具有較多構(gòu)造函數(shù)持际。
*/
/**
* \brief Shared array
*
* A smart array that retains shared ownership. It provides similar
* functionalities comparing to std::vector, including data(), size(),
* operator[], resize(), clear(). SArray can be easily constructed from
* std::vector, such as
*
* \code
* std::vector<int> a(10); SArray<int> b(a); // copying
* std::shared_ptr<std::vector<int>> c(new std::vector<int>(10));
* SArray<int> d(c); // only pointer copying
* \endcode
*
* SArray is also like a C pointer when copying and assigning, namely
* both copy are assign are passing by pointers. The memory will be release only
* if there is no copy exists. It is also can be cast without memory copy, such as
*
* \code
* SArray<int> a(10);
* SArray<char> b(a); // now b.size() = 10 * sizeof(int);
* \endcode
*
* \tparam V the value type
*/
template<typename V>
class SArray {
public:
/** \brief empty constructor */
SArray() { }
/** \brief empty deconstrcutor */
~SArray() { }
/**
* \brief Create an array with length n with initialized value
* \param size the length
* \param val the initial length (0 in default)
*/
explicit SArray(size_t size, V val = 0) { resize(size, val); }
/**
* \brief construct from another SArray.
*
* Zero-copy constructor, namely just copy the pointer
*
* \tparam W the value type of the source array
* \param arr the source array
*/
template <typename W>
explicit SArray(const SArray<W>& arr) { *this = arr; }
/**
* \brief construct from another SArray.
*
* Zero-copy constructor, namely just copy the pointer
*
* \tparam W the value type of the source array
* \param arr the source array
*/
template <typename W> void operator=(const SArray<W>& arr) {
size_ = arr.size() * sizeof(W) / sizeof(V);
CHECK_EQ(size_ * sizeof(V), arr.size() * sizeof(W)) << "cannot be divided";
capacity_ = arr.capacity() * sizeof(W) / sizeof(V);
ptr_ = std::shared_ptr<V>(arr.ptr(), reinterpret_cast<V*>(arr.data()));
}
/**
* \brief construct from a c-array
*
* Zero-copy constructor, namely just copy the pointer
*
* \param data the source data
* \param size the length
* \param deletable whether or not can call `delete [] data` when the reference
* count goes 0
*/
SArray(V* data, size_t size, bool deletable = false) {
if (deletable) {
reset(data, size, [](V* data){ delete [] data; });
} else {
reset(data, size, [](V* data) { });
}
}
/**
* \brief copy from a c-array
*
* \param data the source data
* \param size the length
*/
void CopyFrom(const V* data, size_t size) {
resize(size);
memcpy(this->data(), data, size*sizeof(V));
}
/**
* \brief copy from another SArray
*
* \param other the source data
*/
void CopyFrom(const SArray<V>& other) {
if (this == &other) return;
CopyFrom(other.data(), other.size());
}
/**
* \brief copy from an iterator
*/
template <typename ForwardIt>
void CopyFrom(const ForwardIt& first, const ForwardIt& last) {
int size = static_cast<int>(std::distance(first, last));
V* data = new V[size];
reset(data, size, [](V* data){ delete [] data; });
auto it = first;
while (size-- > 0) { *data = *it; ++data; ++it; }
}
/**
* \brief construct from a std::vector, copy the data
*/
explicit SArray(const std::vector<V>& vec) { CopyFrom(vec.data(), vec.size()); }
/**
* \brief construct from a shared std::vector pinter, no data copy
*/
explicit SArray(const std::shared_ptr<std::vector<V>>& vec) {
ptr_ = std::shared_ptr<V>(vec, vec->data());
size_ = vec->size();
capacity_ = size_;
}
/** @brief Copy from a initializer_list */
template <typename W> SArray(const std::initializer_list<W>& list) {
CopyFrom(list.begin(), list.end());
}
/** @brief Copy from a initializer_list */
template <typename W> void operator=(const std::initializer_list<W>& list) {
CopyFrom(list.begin(), list.end());
}
/**
* @brief Reset the current data pointer with a deleter
*/
template <typename Deleter>
void reset(V* data, size_t size, Deleter del) {
size_ = size; capacity_ = size; ptr_.reset(data, del);
}
/**
* @brief Resizes the array to size elements
*
* If size <= capacity_, then only change the size. otherwise, append size -
* current_size entries, and then set new value to val
*/
void resize(size_t size, V val = 0) {
size_t cur_n = size_;
if (capacity_ >= size) {
size_ = size;
} else {
V* new_data = new V[size+5];
memcpy(new_data, data(), size_*sizeof(V));
reset(new_data, size, [](V* data){ delete [] data; });
}
if (size <= cur_n) return;
V* p = data() + cur_n;
if (val == 0) {
memset(p, 0, (size - cur_n)*sizeof(V));
} else {
for (size_t i = 0; i < size - cur_n; ++i) { *p = val; ++p; }
}
}
/**
* @brief Requests that the capacity be at least enough to contain n elements.
*/
void reserve(size_t size) {
if (capacity_ >= size) { return; }
size_t old_size = size_;
resize(size);
size_ = old_size;
}
/** @brief release the memory */
void clear() { reset(nullptr, 0, [](V* data) {}); }
inline bool empty() const { return size() == 0; }
inline size_t size() const { return size_; }
inline size_t capacity() const { return capacity_; }
inline V* begin() { return data(); }
inline const V* begin() const { return data(); }
inline V* end() { return data() + size(); }
inline const V* end() const { return data() + size(); }
inline V* data() const { return ptr_.get(); }
/** \brief get the shared pointer */
inline std::shared_ptr<V>& ptr() { return ptr_; }
/** \brief get the const shared pointer */
inline const std::shared_ptr<V>& ptr() const { return ptr_; }
inline V back() const { CHECK(!empty()); return data()[size_-1]; }
inline V front() const { CHECK(!empty()); return data()[0]; }
inline V& operator[] (int i) { return data()[i]; }
inline const V& operator[] (int i) const { return data()[i]; }
inline void push_back(const V& val) {
if (size_ == capacity_) reserve(size_*2+5);
data()[size_++] = val;
}
void pop_back() { if (size_) --size_; }
void append(const SArray<V>& arr) {
if (arr.empty()) return;
auto orig_size = size_;
resize(size_ + arr.size());
memcpy(data()+orig_size, arr.data(), arr.size()*sizeof(V));
}
/**
* @brief Slice a segment, zero-copy
*
* @param begin the start index segment
* @param end the end index segment
* @return the segment [begin, end)
*/
SArray<V> segment(size_t begin, size_t end) const {
CHECK_GE(end, begin); CHECK_LE(end, size());
SArray<V> ret;
ret.ptr_ = std::shared_ptr<V>(ptr_, data() + begin);
ret.size_ = end - begin;
ret.capacity_ = end - begin;
return ret;
}
private:
size_t size_ = 0;
size_t capacity_ = 0;
std::shared_ptr<V> ptr_;
};
/**
* \brief Find the index range of a segment of a sorted array such that the
* entries in this segment is within [lower, upper). Assume
* array values are ordered.
*
* An example
* \code{cpp}
* SArray<int> a{1 3 5 7 9};
* CHECK_EQ(Range(1,3), FindRange(a, 2, 7);
* \endcode
*
* \param arr the source array
* \param lower the lower bound
* \param upper the upper bound
*
* \return the index range
*/
template<typename V>
Range FindRange(const SArray<V>& arr, V lower, V upper) {
if (upper <= lower) return Range(0, 0);
auto lb = std::lower_bound(arr.begin(), arr.end(), lower);
auto ub = std::lower_bound(arr.begin(), arr.end(), upper);
return Range(lb - arr.begin(), ub - arr.begin());
}
/*! \brief returns a short debug string */
template <typename V>
inline std::string DebugStr(const V* data, int n, int m = 5) {
std::stringstream ss;
ss << "[" << n << "]: ";
if (n < 2 * m) {
for (int i = 0; i < n; ++i) ss << data[i] << " ";
} else {
for (int i = 0; i < m; ++i) ss << data[i] << " ";
ss << "... ";
for (int i = n-m; i < n; ++i) ss << data[i] << " ";
}
return ss.str();
}
/**
* \brief print a debug string
*/
template <typename V>
std::ostream& operator<<(std::ostream& os, const SArray<V>& obj) {
os << DebugStr(obj.data(), obj.size());
return os;
}
} // namespace ps
#endif // PS_SARRAY_H_
ps-lite源碼分析: include/ps/sarray.h
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
- 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)腔彰,“玉大人叫编,你說(shuō)我怎么就攤上這事∨祝” “怎么了宵溅?”我有些...
- 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)上炎。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么藕施? 我笑而不...
- 正文 為了忘掉前任寇损,我火速辦了婚禮,結(jié)果婚禮上裳食,老公的妹妹穿的比我還像新娘矛市。我一直安慰自己,他們只是感情好诲祸,可當(dāng)我...
- 文/花漫 我一把揭開(kāi)白布浊吏。 她就那樣靜靜地躺著,像睡著了一般救氯。 火紅的嫁衣襯著肌膚如雪找田。 梳的紋絲不亂的頭發(fā)上,一...
- 那天着憨,我揣著相機(jī)與錄音墩衙,去河邊找鬼。 笑死甲抖,一個(gè)胖子當(dāng)著我的面吹牛漆改,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播准谚,決...
- 文/蒼蘭香墨 我猛地睜開(kāi)眼挫剑,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了柱衔?” 一聲冷哼從身側(cè)響起樊破,我...
- 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎秀存,沒(méi)想到半個(gè)月后捶码,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
- 正文 獨(dú)居荒郊野嶺守林人離奇死亡或链,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
- 正文 我和宋清朗相戀三年惫恼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片澳盐。...
- 正文 年R本政府宣布筛婉,位于F島的核電站簇爆,受9級(jí)特大地震影響癞松,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜入蛆,卻給世界環(huán)境...
- 文/蒙蒙 一响蓉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧哨毁,春花似錦枫甲、人聲如沸。這莊子的主人今日做“春日...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至话浇,卻和暖如春脏毯,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背凳枝。 一陣腳步聲響...
- 正文 我出身青樓叛买,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親蹋订。 傳聞我的和親對(duì)象是個(gè)殘疾皇子率挣,可洞房花燭夜當(dāng)晚...
推薦閱讀更多精彩內(nèi)容
- /*** Copyright (c) 2015 by Contributors*/#ifndef PS_INTE...
- /*** Copyright (c) 2015 by Contributors*/#ifndef PS_BASE...