// Charlemagne Package Manager // // Douglas Thrift // // $Id$ /* Menes - C++ High-Level Utility Library * Copyright (C) 2003-2005 Jay Freeman (saurik) */ /* * Redistribution and use in source and binary * forms, with or without modification, are permitted * provided that the following conditions are met: * * 1. Redistributions of source code must retain the * above copyright notice, this list of conditions * and the following disclaimer. * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions * and the following disclaimer in the documentation * and/or other materials provided with the * distribution. * 3. The name of the author may not be used to endorse * or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include "regex.hpp" #undef _assert #define _assert(b) assert(b) namespace Pcre { Error::Error(int code) { std::ostringstream message; message << "Pcre[#" << code << "] "; switch (code) { case PCRE_ERROR_NOMATCH: message << "PCRE_ERROR_NOMATCH"; break; case PCRE_ERROR_NULL: message << "PCRE_ERROR_NULL"; break; case PCRE_ERROR_BADOPTION: message << "PCRE_ERROR_BADOPTION"; break; case PCRE_ERROR_BADMAGIC: message << "PCRE_ERROR_BADMAGIC"; break; case PCRE_ERROR_UNKNOWN_NODE: message << "PCRE_ERROR_UNKNOWN_NODE"; break; case PCRE_ERROR_NOMEMORY: message << "PCRE_ERROR_NOMEMORY"; break; case PCRE_ERROR_NOSUBSTRING: message << "PCRE_ERROR_NOSUBSTRING"; break; case PCRE_ERROR_MATCHLIMIT: message << "PCRE_ERROR_MATCHLIMIT"; break; case PCRE_ERROR_CALLOUT: message << "PCRE_ERROR_CALLOUT"; break; case PCRE_ERROR_BADUTF8: message << "PCRE_ERROR_BADUTF8"; break; case PCRE_ERROR_BADUTF8_OFFSET: message << "PCRE_ERROR_BADUTF8_OFFSET"; break; default: message << "Unknown Error"; } this->message = message.str(); } RegEx::Match::Match(const std::string &data, std::vector &substrings) : data(data) { std::swap(this->substrings, substrings); } RegEx::Match::Match() {} RegEx::Match::operator bool() const { return !substrings.empty(); } std::string RegEx::Match::operator [](size_t substring) const { size_t index(substring * 2); if (index >= substrings.size()) return std::string(); return std::string(data.begin() + substrings[index], data.begin() + substrings[index + 1]); } RegEx::RegEx(const std::string &pattern) : code(NULL), study(NULL), capture(-1) { const char *error; int offset; code = ::pcre_compile(pattern.c_str(), PCRE_DOTALL | PCRE_DOLLAR_ENDONLY, &error, &offset, NULL); int err(::pcre_fullinfo(code, study, PCRE_INFO_CAPTURECOUNT, &capture)); if (err != 0) { _assert(err < 0); throw Error(err); } _assert(capture >= 0); } RegEx::~RegEx() { ::pcre_free(code); } RegEx::Match RegEx::operator ()(const std::string &data) const { std::vector substrings((capture + 1) * 3); int err(::pcre_exec(code, study, data.c_str(), data.size(), 0, 0, &substrings.front(), substrings.size())); _assert(err != 0); if (err == PCRE_ERROR_NOMATCH) err = 0; if (err < 0) throw Error(err); substrings.resize(err * 2); return Match(data, substrings); } }