Repository: trafficserver Updated Branches: refs/heads/master f5c2b2c94 -> d3e4614bf
Fix issues releasing MLocHandles in headers Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/d3e4614b Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/d3e4614b Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/d3e4614b Branch: refs/heads/master Commit: d3e4614bf3e945c07c367cc488dc13ee832ce131 Parents: f5c2b2c Author: Brian Geffon <[email protected]> Authored: Tue Feb 18 14:48:36 2014 -0800 Committer: Brian Geffon <[email protected]> Committed: Tue Feb 18 14:48:36 2014 -0800 ---------------------------------------------------------------------- lib/atscppapi/src/Headers.cc | 171 +++++++++++---------- lib/atscppapi/src/include/atscppapi/Headers.h | 157 +++++++++---------- 2 files changed, 159 insertions(+), 169 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/d3e4614b/lib/atscppapi/src/Headers.cc ---------------------------------------------------------------------- diff --git a/lib/atscppapi/src/Headers.cc b/lib/atscppapi/src/Headers.cc index 8eb0ce5..871fecc 100644 --- a/lib/atscppapi/src/Headers.cc +++ b/lib/atscppapi/src/Headers.cc @@ -20,6 +20,7 @@ * @file Headers.cc */ #include "atscppapi/Headers.h" +#include "atscppapi/shared_ptr.h" #include "InitializableValue.h" #include "logging_internal.h" #include <string> @@ -147,45 +148,46 @@ bool header_field_value_iterator::operator!=(const header_field_value_iterator& /** * @private */ -struct HeaderFieldState: noncopyable { +struct MLocContainer { TSMBuffer hdr_buf_; TSMLoc hdr_loc_; TSMLoc field_loc_; - HeaderFieldState() : hdr_buf_(NULL), hdr_loc_(NULL), field_loc_(NULL) { } - void reset(TSMBuffer bufp, TSMLoc hdr_loc, TSMLoc field_loc) { - hdr_buf_ = bufp; - hdr_loc_ = hdr_loc; - field_loc_ = field_loc; + MLocContainer(TSMBuffer bufp, TSMLoc hdr_loc, TSMLoc field_loc) : + hdr_buf_(bufp), hdr_loc_(hdr_loc), field_loc_(field_loc) { } + ~MLocContainer() { + if (field_loc_ != TS_NULL_MLOC) { + TSHandleMLocRelease(hdr_buf_, hdr_loc_, field_loc_); + } } }; -HeaderField::HeaderField(void *bufp, void *hdr_loc, void *field_loc) -{ - state_ = new HeaderFieldState(); - state_->hdr_buf_ = static_cast<TSMBuffer>(bufp); - state_->hdr_loc_ = static_cast<TSMLoc>(hdr_loc); - state_->field_loc_ = static_cast<TSMLoc>(field_loc); -} +/** + * @private + */ +struct HeaderFieldIteratorState { + shared_ptr<MLocContainer> mloc_container_; + HeaderFieldIteratorState(TSMBuffer bufp, TSMLoc hdr_loc, TSMLoc field_loc) + : mloc_container_(new MLocContainer(bufp, hdr_loc, field_loc)) { } +}; HeaderField::~HeaderField() { - delete state_; } HeaderField::size_type HeaderField::size() const { - return TSMimeHdrFieldValuesCount(state_->hdr_buf_, state_->hdr_loc_, state_->field_loc_); + return TSMimeHdrFieldValuesCount(iter_.state_->mloc_container_->hdr_buf_, iter_.state_->mloc_container_->hdr_loc_, iter_.state_->mloc_container_->field_loc_); } header_field_value_iterator HeaderField::begin() { - return header_field_value_iterator(state_->hdr_buf_, state_->hdr_loc_, state_->field_loc_, 0); + return header_field_value_iterator(iter_.state_->mloc_container_->hdr_buf_, iter_.state_->mloc_container_->hdr_loc_, iter_.state_->mloc_container_->field_loc_, 0); } header_field_value_iterator HeaderField::end() { - return header_field_value_iterator(state_->hdr_buf_, state_->hdr_loc_, state_->field_loc_, size()); + return header_field_value_iterator(iter_.state_->mloc_container_->hdr_buf_, iter_.state_->mloc_container_->hdr_loc_, iter_.state_->mloc_container_->field_loc_, size()); } HeaderFieldName HeaderField::name() const { int length = 0; - const char *str = TSMimeHdrFieldNameGet(state_->hdr_buf_, state_->hdr_loc_, state_->field_loc_, &length); + const char *str = TSMimeHdrFieldNameGet(iter_.state_->mloc_container_->hdr_buf_, iter_.state_->mloc_container_->hdr_loc_, iter_.state_->mloc_container_->field_loc_, &length); if (str && length) { return std::string(str, length); } @@ -211,12 +213,29 @@ std::string HeaderField::values(const char join) { return values(std::string().append(1,join)); } +std::string Headers::value(const std::string key, size_type index /* = 0 */) { + header_field_iterator iter = find(key); + if (iter == end()) { + return string(); + } + if (index == 0) { // skip for loop + return *((*iter).begin()); + } + for (; iter != end(); iter.nextDup()) { + if (index < (*iter).size()) { + return (*iter)[index]; + } + index -= (*iter).size(); + } + return string(); +} + bool HeaderField::empty() { return (begin() == end()); } bool HeaderField::clear() { - return (TSMimeHdrFieldValuesClear(state_->hdr_buf_, state_->hdr_loc_, state_->field_loc_) == TS_SUCCESS); + return (TSMimeHdrFieldValuesClear(iter_.state_->mloc_container_->hdr_buf_, iter_.state_->mloc_container_->hdr_loc_, iter_.state_->mloc_container_->field_loc_) == TS_SUCCESS); } bool HeaderField::erase(header_field_value_iterator it) { @@ -228,11 +247,11 @@ bool HeaderField::append(const std::string &value) { } bool HeaderField::append(const char *value, int length) { - return (TSMimeHdrFieldValueStringInsert(state_->hdr_buf_, state_->hdr_loc_, state_->field_loc_, -1, value, -1) == TS_SUCCESS); + return (TSMimeHdrFieldValueStringInsert(iter_.state_->mloc_container_->hdr_buf_, iter_.state_->mloc_container_->hdr_loc_, iter_.state_->mloc_container_->field_loc_, -1, value, -1) == TS_SUCCESS); } bool HeaderField::setName(const std::string &str) { - return (TSMimeHdrFieldNameSet(state_->hdr_buf_, state_->hdr_loc_, state_->field_loc_, str.c_str(), str.length()) == TS_SUCCESS); + return (TSMimeHdrFieldNameSet(iter_.state_->mloc_container_->hdr_buf_, iter_.state_->mloc_container_->hdr_loc_, iter_.state_->mloc_container_->field_loc_, str.c_str(), str.length()) == TS_SUCCESS); } bool HeaderField::operator==(const char *field_name) const { @@ -266,7 +285,7 @@ bool HeaderField::operator=(const char *field_value) { } std::string HeaderField::operator[](const int index) { - return *header_field_value_iterator(state_->hdr_buf_, state_->hdr_loc_, state_->field_loc_, index); + return *header_field_value_iterator(iter_.state_->mloc_container_->hdr_buf_, iter_.state_->mloc_container_->hdr_loc_, iter_.state_->mloc_container_->field_loc_, index); } std::string HeaderField::str() { @@ -286,50 +305,40 @@ std::ostream& operator<<(std::ostream& os, HeaderField& obj) { return os; } -/** - * @private - */ -struct HeaderFieldIteratorState: noncopyable { - TSMBuffer hdr_buf_; - TSMLoc hdr_loc_; - TSMLoc field_loc_; - HeaderFieldIteratorState() : hdr_buf_(NULL), hdr_loc_(NULL), field_loc_(NULL) { } - void reset(TSMBuffer bufp, TSMLoc hdr_loc, TSMLoc field_loc) { - hdr_buf_ = bufp; - hdr_loc_ = hdr_loc; - field_loc_ = field_loc; - } -}; +header_field_iterator::header_field_iterator(void *hdr_buf, void *hdr_loc, void *field_loc) : + state_(new HeaderFieldIteratorState(static_cast<TSMBuffer>(hdr_buf), static_cast<TSMLoc>(hdr_loc), + static_cast<TSMLoc>(field_loc))) { } -header_field_iterator::header_field_iterator() { - state_ = new HeaderFieldIteratorState(); -} +header_field_iterator::header_field_iterator(const header_field_iterator& it) : + state_(new HeaderFieldIteratorState(*it.state_)) { } -header_field_iterator::header_field_iterator(void *bufp, void *hdr_loc, void *field_loc) { - state_ = new HeaderFieldIteratorState(); - state_->reset(static_cast<TSMBuffer>(bufp), static_cast<TSMLoc>(hdr_loc), static_cast<TSMLoc>(field_loc)); -} - -header_field_iterator::header_field_iterator(HeaderField &hf) { - state_ = new HeaderFieldIteratorState(); - state_->reset(hf.state_->hdr_buf_, hf.state_->hdr_loc_, hf.state_->field_loc_); -} - -header_field_iterator::header_field_iterator(const header_field_iterator& it) { - state_ = new HeaderFieldIteratorState(); - state_->reset(it.state_->hdr_buf_, it.state_->hdr_loc_, it.state_->field_loc_); +header_field_iterator &header_field_iterator::operator=(const header_field_iterator &rhs) { + if (this != &rhs) { + delete state_; + state_ = new HeaderFieldIteratorState(*rhs.state_); + } + return *this; } header_field_iterator::~header_field_iterator() { delete state_; } -header_field_iterator& header_field_iterator::operator++() { - if (state_->field_loc_ == TS_NULL_MLOC) { - return *this; +// utility function to use to advance iterators using different functions +HeaderFieldIteratorState *advanceIterator(HeaderFieldIteratorState *state, + TSMLoc (*getNextField)(TSMBuffer, TSMLoc, TSMLoc)) { + if (state->mloc_container_->field_loc_ != TS_NULL_MLOC) { + TSMBuffer hdr_buf = state->mloc_container_->hdr_buf_; + TSMLoc hdr_loc = state->mloc_container_->hdr_loc_; + TSMLoc next_field_loc = getNextField(hdr_buf, hdr_loc, state->mloc_container_->field_loc_); + delete state; + state = new HeaderFieldIteratorState(hdr_buf, hdr_loc, next_field_loc); } + return state; +} - state_->field_loc_ = TSMimeHdrFieldNext(state_->hdr_buf_, state_->hdr_loc_, state_->field_loc_); +header_field_iterator& header_field_iterator::operator++() { + state_ = advanceIterator(state_, TSMimeHdrFieldNext); return *this; } @@ -339,9 +348,14 @@ header_field_iterator header_field_iterator::operator++(int) { return tmp; } +header_field_iterator& header_field_iterator::nextDup() { + state_ = advanceIterator(state_, TSMimeHdrFieldNextDup); + return *this; +} + bool header_field_iterator::operator==(const header_field_iterator& rhs) const { - return (state_->hdr_buf_ == rhs.state_->hdr_buf_) && (state_->hdr_loc_ == rhs.state_->hdr_loc_) && - (state_->field_loc_ == rhs.state_->field_loc_); + return (state_->mloc_container_->hdr_buf_ == rhs.state_->mloc_container_->hdr_buf_) && (state_->mloc_container_->hdr_loc_ == rhs.state_->mloc_container_->hdr_loc_) && + (state_->mloc_container_->field_loc_ == rhs.state_->mloc_container_->field_loc_); } bool header_field_iterator::operator!=(const header_field_iterator& rhs) const { @@ -349,11 +363,7 @@ bool header_field_iterator::operator!=(const header_field_iterator& rhs) const { } HeaderField header_field_iterator::operator*() { - return HeaderField(state_->hdr_buf_, state_->hdr_loc_, state_->field_loc_); -} - -HeaderField header_field_iterator::operator()() { - return operator*(); + return HeaderField(*this); } /** @@ -415,7 +425,7 @@ bool Headers::clear() { } bool Headers::erase(header_field_iterator it) { - return (TSMimeHdrFieldDestroy(it.state_->hdr_buf_, it.state_->hdr_loc_, it.state_->field_loc_) == TS_SUCCESS); + return (TSMimeHdrFieldDestroy(it.state_->mloc_container_->hdr_buf_, it.state_->mloc_container_->hdr_loc_, it.state_->mloc_container_->field_loc_) == TS_SUCCESS); } Headers::size_type Headers::erase(const std::string &key) { @@ -423,20 +433,15 @@ Headers::size_type Headers::erase(const std::string &key) { } Headers::size_type Headers::erase(const char *key, int length) { - header_field_iterator it; - header_field_iterator prev_iter; - size_type count = 0; - while((it = find(key, length)) != end() && - it != prev_iter) { - - if(erase(it) != true) - return count; - - // If find continues to return the same element because erase fails then we will stop. - prev_iter = it; - count++; + header_field_iterator iter = find(key, length); + size_type erased_count = 0; + while (iter != end()) { + header_field_iterator iter_to_delete = iter; + iter.nextDup(); + erase(iter_to_delete); + ++erased_count; } - return count; + return erased_count; } Headers::size_type Headers::count(const char *key, int length) { @@ -458,12 +463,10 @@ std::string Headers::values(const std::string &key, const char *join) { Headers::size_type num_header_fields = count(key); ret.reserve(128 * num_header_fields); - for (header_field_iterator it = begin(); it != end(); ++it) { - if (*it == key) { - ret.append((*it).values(join)); - if (--num_header_fields > 0) { - ret.append(join); - } + for (header_field_iterator it = find(key); it != end(); it.nextDup()) { + ret.append((*it).values(join)); + if (--num_header_fields > 0) { + ret.append(join); } } @@ -502,7 +505,7 @@ Headers::iterator Headers::append(const std::string &key, const std::string &val return end(); } -Headers::iterator Headers::eraseAndSet(const std::string &key, const std::string &value) { +Headers::iterator Headers::set(const std::string &key, const std::string &value) { erase(key); return append(key, value); } http://git-wip-us.apache.org/repos/asf/trafficserver/blob/d3e4614b/lib/atscppapi/src/include/atscppapi/Headers.h ---------------------------------------------------------------------- diff --git a/lib/atscppapi/src/include/atscppapi/Headers.h b/lib/atscppapi/src/include/atscppapi/Headers.h index 2a41907..19d46f8 100644 --- a/lib/atscppapi/src/include/atscppapi/Headers.h +++ b/lib/atscppapi/src/include/atscppapi/Headers.h @@ -31,7 +31,6 @@ namespace atscppapi { struct HeadersState; struct HeaderFieldIteratorState; -struct HeaderFieldState; struct HeaderFieldValueIteratorState; class Request; class ClientRequest; @@ -165,7 +164,66 @@ class header_field_value_iterator : public std::iterator<std::forward_iterator_t friend class HeaderField; }; -class header_field_iterator; + +/** + * @brief A header field iterator is an iterator that dereferences to a HeaderField. + */ +class header_field_iterator : public std::iterator<std::forward_iterator_tag, int> +{ + private: + HeaderFieldIteratorState *state_; + header_field_iterator(void *hdr_buf, void *hdr_loc, void *field_loc); + public: + ~header_field_iterator(); + + /** + * Copy Constructor for header_field_iterator, this shouldn't need to be used directly. + * @param header_field_iterator: for constructing the iterator. + * @warning This shouldn't need to be used directly! + */ + header_field_iterator(const header_field_iterator& it); + + header_field_iterator &operator=(const header_field_iterator &rhs); + + /** + * Advance the iterator to the next header field + * @return a reference to a the next iterator + */ + header_field_iterator& operator++(); + + /** + * Advance the current iterator to the next header field + * @return a new iterator which points to the next element + */ + header_field_iterator operator++(int); + + /** + * Advance the iterator to the next header field with the same name + * @return a reference to a the next iterator + */ + header_field_iterator& nextDup(); + + /** + * Comparison operator, compare two iterators + * @return true if the two iterators point to the same HeaderField + */ + bool operator==(const header_field_iterator& rhs) const; + + /** + * Inequality Operator, compare two iterators + * @return false if the two iterators are the same. + */ + bool operator!=(const header_field_iterator& rhs) const; + + /** + * Dereference an iterator + * @return a HeaderField pointed to by this iterator + */ + HeaderField operator*(); + + friend class HeaderField; + friend class Headers; +}; /** * @brief A HeaderField is a class that contains the header field name and all of the values. @@ -173,19 +231,13 @@ class header_field_iterator; */ class HeaderField { private: - HeaderFieldState *state_; + header_field_iterator iter_; + HeaderField(header_field_iterator iter) : iter_(iter) { } + public: typedef unsigned int size_type; typedef header_field_value_iterator iterator; - /** - * Constructor for HeaderField, this shouldn't be used directly unless you're trying to mix the C++ and C apis. - * @param bufp the TSMBuffer associated with the header field - * @param mloc the TSMLoc associated with the headers - * @param field_loc the TSMLoc associated with the header field - * @warning This should only be used if you're mixing the C++ and C apis, it will be constructed automatically if using only the C++ api. - */ - HeaderField(void *bufp, void *hdr_loc, void *field_loc); ~HeaderField(); /** @@ -339,79 +391,6 @@ public: }; /** - * @brief A header field iterator is an iterator that dereferences to a HeaderField. - */ -class header_field_iterator : public std::iterator<std::forward_iterator_tag, int> -{ - private: - HeaderFieldIteratorState *state_; - public: - header_field_iterator(); - ~header_field_iterator(); - - /** - * Constructor for header_field_iterator, this shouldn't need to be used directly. - * @param bufp the TSMBuffer associated with the headers - * @param mloc the TSMLoc associated with the headers. - * @param field_loc the TSMLoc assocated with the field. - * @warning This shouldn't need to be used directly! - */ - header_field_iterator(void *bufp, void *hdr_loc, void *field_loc); - - /** - * Constructor for header_field_iterator, this shouldn't need to be used directly. - * @param HeaderField the header field to use for constructing the iterator. - * @warning This shouldn't need to be used directly! - */ - header_field_iterator(HeaderField &hf); - - /** - * Copy Constructor for header_field_iterator, this shouldn't need to be used directly. - * @param header_field_iterator: for constructing the iterator. - * @warning This shouldn't need to be used directly! - */ - header_field_iterator(const header_field_iterator& it); - - /** - * Advance the iterator to the next header field - * @return a reference to a the next iterator - */ - header_field_iterator& operator++(); - - /** - * Advance the current iterator to the next header field - * @return a new iterator which points to the next element - */ - header_field_iterator operator++(int); - - /** - * Comparison operator, compare two iterators - * @return true if the two iterators point to the same HeaderField - */ - bool operator==(const header_field_iterator& rhs) const; - - /** - * Inequality Operator, compare two iterators - * @return false if the two iterators are the same. - */ - bool operator!=(const header_field_iterator& rhs) const; - - /** - * Dereference an iterator - * @return a HeaderField pointed to by this iterator - */ - HeaderField operator*(); - - /** - * Dereference an iterator - * @return a HeaderField pointed to by this iterator - */ - HeaderField operator()(); - - friend class Headers; -}; - -/** * @brief Encapsulates the headers portion of a request or response. */ class Headers: noncopyable { @@ -547,6 +526,14 @@ public: std::string values(const std::string &key, const char join); /** + * Returns the value at given position of header with given name + * @param name of header + * @param position of value + * @return value + */ + std::string value(const std::string key, size_type index = 0); + + /** * Returns an iterator to the first HeaderField with the name key. * @param key the name of first header field ot find. * @return an iterator that points to the first matching header field with name key. @@ -575,7 +562,7 @@ public: * @param value the value of the header field to set. * @return an iterator to the new header field or the end() iterator if append fails. */ - iterator eraseAndSet(const std::string &key, const std::string &value); + iterator set(const std::string &key, const std::string &value); /** * Set the header field values to the value given, the header field will be created
