// ------------------------------------------------------------------- bool PosixRegEx::execute(MatchArray &sub, const String &str, size_t index, size_t count, int eflags) { if( !compiled) { BLOCXX_THROW(RegExCompileException, "Regular expression is not compiled"); } if( index > str.length()) { BLOCXX_THROW(OutOfBoundsException, Format("String index out of bounds (" "length = %1, index = %2).", str.length(), index ).c_str()); } if( count == 0) { count = m_regex.re_nsub + 1; } AutoPtrVec<regmatch_t> rsub(new regmatch_t[count]); rsub[0].rm_so = -1; rsub[0].rm_eo = -1; sub.clear(); m_ecode = ::regexec(&m_regex, str.c_str() + index, count, rsub.get(), eflags); if( m_ecode == REG_NOERROR) { m_error.erase(); if( m_flags & REG_NOSUB) { return true; } sub.resize(count); for(size_t n = 0; n < count; n++) { if( rsub[n].rm_so < 0 || rsub[n].rm_eo < 0) { sub[n] = rsub[n]; } else { rsub[n].rm_so += index; rsub[n].rm_eo += index; sub[n] = rsub[n]; } } return true; } else { m_error = getError(&m_regex, m_ecode); return false; } }
// ------------------------------------------------------------------- StringArray PosixRegEx::split(const String &str, bool empty, int eflags) { if( !compiled) { BLOCXX_THROW(RegExCompileException, "Regular expression is not compiled"); } MatchArray rsub; StringArray ssub; bool match; size_t off = 0; size_t len = str.length(); do { match = execute(rsub, str, off, 1, eflags); if( match) { if( rsub.empty() || rsub[0].rm_so < 0 || rsub[0].rm_eo < 0) { BLOCXX_THROW(RegExCompileException, "Non-capturing regular expression"); } if( empty || ((size_t)rsub[0].rm_so > off)) { ssub.push_back(str.substring(off, rsub[0].rm_so - off)); } off = rsub[0].rm_eo; } else if(m_ecode == REG_NOMATCH) { String tmp = str.substring(off); if( empty || !tmp.empty()) { ssub.push_back(tmp); } m_ecode = REG_NOERROR; m_error.erase(); } else { BLOCXX_THROW_ERR(RegExExecuteException, errorString().c_str(), m_ecode); } } while(match && len > off); return ssub; }
// ------------------------------------------------------------------- blocxx::String PosixRegEx::replace(const String &str, const String &rep, bool global, int eflags) { if( !compiled) { BLOCXX_THROW(RegExCompileException, "Regular expression is not compiled"); } MatchArray rsub; bool match; size_t off = 0; String out = str; do { match = execute(rsub, out, off, 0, eflags); if( match) { if( rsub.empty() || rsub[0].rm_so < 0 || rsub[0].rm_eo < 0) { // only if empty (missused as guard). BLOCXX_THROW(RegExCompileException, "Non-capturing regular expression"); } String res = substitute_caps(rsub, out, rep); out = out.substring(0, rsub[0].rm_so) + res + out.substring(rsub[0].rm_eo); off = rsub[0].rm_so + res.length(); } else if(m_ecode == REG_NOMATCH) { m_ecode = REG_NOERROR; m_error.erase(); } else { BLOCXX_THROW_ERR(RegExExecuteException, errorString().c_str(), m_ecode); } } while(global && match && out.length() > off); return out; }
void GenericRWLockImpl<IdT, CompareT>::acquireReadLock(const IdT id, const Timeout& timeout) { TimeoutTimer timer(timeout); NonRecursiveMutexLock l(m_guard); typename IdMap::iterator info = m_lockerInfo.find(id); if (info != m_lockerInfo.end()) { LockerInfo& ti(info->second); // id already have a read or write lock, so just increment. BLOCXX_ASSERT(ti.isReader() || ti.isWriter()); ++ti.readCount; return; } // id is a new reader while (!m_canRead || m_numWriters > 0) { if (!m_waiting_readers.timedWait(l, timer.asAbsoluteTimeout())) { BLOCXX_THROW(TimeoutException, "Timeout while waiting for read lock."); } } // Increase the reader count LockerInfo lockerInfo; lockerInfo.readCount = 1; lockerInfo.writeCount = 0; m_lockerInfo.insert(typename IdMap::value_type(id, lockerInfo)); ++m_numReaders; }
void throwNULLException() { #ifdef BLOCXX_DEBUG abort(); // segfault so we can get a core #endif BLOCXX_THROW(NULLReferenceException, "NULL Reference dereferenced"); }
void GenericRWLockImpl<IdT, CompareT>::releaseReadLock(const IdT id) { NonRecursiveMutexLock l(m_guard); typename IdMap::iterator pInfo = m_lockerInfo.find(id); if (pInfo == m_lockerInfo.end() || !pInfo->second.isReader()) { BLOCXX_THROW(GenericRWLockImplException, "Cannot release a read lock when no read lock is held"); } LockerInfo& info(pInfo->second); --info.readCount; if (!info.isWriter() && !info.isReader()) { --m_numReaders; if (m_numReaders == 0) { // This needs to wake them all up. In the case where one thread is waiting to upgrade a read to a write lock // and others are waiting to get a write lock, we have to wake up the thread trying to upgrade. m_waiting_writers.notifyAll(); } m_lockerInfo.erase(pInfo); } }
// ------------------------------------------------------------------- StringArray PosixRegEx::capture(const String &str, size_t index, size_t count, int eflags) { if( !compiled) { BLOCXX_THROW(RegExCompileException, "Regular expression is not compiled"); } MatchArray rsub; StringArray ssub; bool match = execute(rsub, str, index, count, eflags); if( match) { if( rsub.empty()) { BLOCXX_THROW(RegExCompileException, "Non-capturing regular expression"); } MatchArray::const_iterator i=rsub.begin(); for( ; i != rsub.end(); ++i) { if( i->rm_so >= 0 && i->rm_eo >= 0) { ssub.push_back(str.substring(i->rm_so, i->rm_eo - i->rm_so)); } else { ssub.push_back(String("")); } } } else if(m_ecode != REG_NOMATCH) { BLOCXX_THROW_ERR(RegExExecuteException, errorString().c_str(), m_ecode); } return ssub; }
AutoDescriptor receiveDescriptor(Descriptor streamPipe) { size_t const BUFSZ = 512; char errbuf[BUFSZ]; AutoDescriptor d = receiveDescriptor(streamPipe, errbuf, BUFSZ); if (d.get() < 0) { BLOCXX_THROW(IOException, errbuf); } return d; }
////////////////////////////////////////////////////////////////////////////// // STATIC void verifySignature(std::streambuf & istrm, UInt8 validSig) { UInt8 val; read(istrm, val); if (val != validSig) { BLOCXX_THROW(BadSignatureException, Format("Received invalid signature. Got: %1 Expected: %2", Int32(val), Int32(validSig)).c_str()); } }
// ------------------------------------------------------------------- bool PosixRegEx::match(const String &str, size_t index, int eflags) const { if( !compiled) { BLOCXX_THROW(RegExCompileException, "Regular expression is not compiled"); } if( index > str.length()) { BLOCXX_THROW(OutOfBoundsException, Format("String index out of bounds (" "length = %1, index = %2).", str.length(), index ).c_str()); } m_ecode = ::regexec(&m_regex, str.c_str() + index, 0, NULL, eflags); if( m_ecode == REG_NOERROR) { m_error.erase(); return true; } else if(m_ecode == REG_NOMATCH) { m_error = getError(&m_regex, m_ecode); return false; } else { m_error = getError(&m_regex, m_ecode); BLOCXX_THROW_ERR(RegExExecuteException, errorString().c_str(), m_ecode); } }
////////////////////////////////////////////////////////////////////////////// // STATIC void read(std::streambuf & istrm, void * dataIn, size_t dataInLen) { std::streamsize cnt = dataInLen; #ifdef BLOCXX_WIN32 // VC10 warns that sgetn is unsafe. #pragma warning(push) #pragma warning(disable:4996) #endif if (istrm.sgetn(static_cast<char *>(dataIn), cnt) != cnt) #ifdef BLOCXX_WIN32 #pragma warning(pop) #endif { BLOCXX_THROW(IOException, "Failed reading data"); } }
IPCMutex::IPCMutex(int semKey) { m_sbuf.sem_num = 0; m_sbuf.sem_flg = 0; m_semid = semget((key_t)semKey, 1, 0666); if (m_semid == -1) { m_semid = semget((key_t)semKey, 1, IPC_CREAT | 0666); if (m_semid == -1) { BLOCXX_THROW(IPCMutexException, "Unable to create semaphore"); return; } m_arg.val = 1; if (semctl(m_semid, 0, SETVAL, m_arg) != 0) { BLOCXX_THROW_ERRNO_MSG(IPCMutexException, "semctl() failed"); } } }
void GenericRWLockImpl<IdT, CompareT>::releaseWriteLock(const IdT id) { NonRecursiveMutexLock l(m_guard); typename IdMap::iterator pInfo = m_lockerInfo.find(id); if (pInfo == m_lockerInfo.end() || !pInfo->second.isWriter()) { BLOCXX_THROW(GenericRWLockImplException, "Cannot release a write lock when no write lock is held"); } LockerInfo& ti(pInfo->second); BLOCXX_ASSERT(ti.isWriter()); --ti.writeCount; if (!ti.isWriter()) { --m_numWriters; BLOCXX_ASSERT(m_numWriters == 0); m_canRead = true; if (ti.isReader()) { // restore reader status ++m_numReaders; } else { // This id no longer holds locks. m_waiting_writers.notifyOne(); m_lockerInfo.erase(pInfo); } m_waiting_readers.notifyAll(); } }
// ------------------------------------------------------------------- StringArray PosixRegEx::grep(const StringArray &src, int eflags) { if( !compiled) { BLOCXX_THROW(RegExCompileException, "Regular expression is not compiled"); } m_ecode = REG_NOERROR; m_error.erase(); StringArray out; if( !src.empty()) { StringArray::const_iterator i=src.begin(); for( ; i != src.end(); ++i) { int ret = ::regexec(&m_regex, i->c_str(), 0, NULL, eflags); if( ret == REG_NOERROR) { out.push_back(*i); } else if(ret != REG_NOMATCH) { m_ecode = ret; m_error = getError(&m_regex, m_ecode); BLOCXX_THROW_ERR(RegExExecuteException, errorString().c_str(), m_ecode); } } } return out; }
size_t Format::process(String& str, size_t minArg, size_t maxArg, FormatFlags& flags, FormatErrorHandling errortype) { size_t len(str.length()); size_t c = static_cast<size_t>(-1); bool err = false; size_t i = 0; size_t percentStart = 0; for (; (i < len) && (c == size_t(-1)) && !err; ++i) { if( str[i] == '%' ) { percentStart = i; if (i + 1 < len) { ++i; if( str[i] == '%' ) { oss.append('%'); } else if( str[i] == BRACE_OPEN ) { if( !processFormatSpecifier(str, i, c, flags) ) { // No close brace or some other error. err = true; } else { // Incremented next loop. --i; } } else if( isdigit(str[i]) ) { c = str[i] - '0'; } else { // Random junk after '%' err = true; } } else { err = true; } } else // anything other than a '%' { oss.append(str[i]); } } // for if ( (i <= len) && (c != size_t(-1))) { if( c > maxArg ) { String error = String("Parameter specifier ") + c + " is too large (>" + maxArg + ")"; if( errortype == E_FORMAT_EXCEPTION ) { BLOCXX_THROW(FormatException, error.c_str()); } oss.append("\n*** " + error); err = true; } else if( c < minArg ) { String error = String("Parameter specifier ") + c + " must be >= " + minArg; if( errortype == E_FORMAT_EXCEPTION ) { BLOCXX_THROW(FormatException, error.c_str()); } oss.append("\n*** " + error); err = true; } } if (err) { // Print the percent and all of the text causing the error. size_t textlength = std::max(i, percentStart + 1) - percentStart; String error = "Error in format string at \"" + str.substring(percentStart, textlength) + "\""; if( errortype == E_FORMAT_EXCEPTION ) { BLOCXX_THROW(FormatException, error.c_str()); } oss.append("\n*** " + error + "\n"); str.erase(); return '0'; } str.erase(0, i); return c; } // process
static inline void throwStringConversion(const char* str, const char* type) { BLOCXX_THROW(StringConversionException, Format("Unable to convert \"%1\" into %2", str, type).c_str()); }
static inline void throwStringConversion(const String::buf_t& m_buf, const char* type) { BLOCXX_THROW(StringConversionException, Format("Unable to convert \"%1\" into %2", m_buf->data(), type).c_str()); }
void GenericRWLockImpl<IdT, CompareT>::acquireWriteLock(const IdT id, const Timeout& timeout) { // 7 cases: // 1. No id has the lock // Get the lock // 2. This id has the write lock // Increment the lock count // 3. Another id has the write lock & other ids may be waiting for read and/or write locks. // Block until the lock is acquired. // 4. Only this id has a read lock // Increment the write lock count . // 5. >0 other ids have the read lock & other ids may be waiting for write locks. // Block until the write lock is acquired. // 6. This id and other ids have the read lock // Block new readers and writers and wait until existing readers finish. // 7. This id and other ids have the read lock and one of the other ids has requested a write lock. // Throw an exception. TimeoutTimer timer(timeout); NonRecursiveMutexLock l(m_guard); typename IdMap::iterator pInfo = m_lockerInfo.find(id); if (pInfo != m_lockerInfo.end()) { // This id already has some sort of lock LockerInfo& ti(pInfo->second); BLOCXX_ASSERT(ti.isReader() || ti.isWriter()); if (!ti.isWriter()) { // The id is upgrading BLOCXX_ASSERT(m_numWriters == 0 || m_numWriters == 1); if (m_numWriters == 1) { // another id beat us to upgrading the write lock. Throw an exception. BLOCXX_THROW(DeadlockException, "Upgrading read lock to a write lock failed, another upgrade is already in progress."); } // switch from being a reader to a writer --m_numReaders; // mark us as a writer, this will prevent other ids from becoming a writer ++m_numWriters; // This thread isn't the only reader. Wait for others to finish. while (m_numReaders != 0) { // stop new readers - inside while loop, because it may get reset by other ids releasing locks. m_canRead = false; if (!m_waiting_writers.timedWait(l, timer.asAbsoluteTimeout())) { // undo changes ++m_numReaders; --m_numWriters; m_canRead = true; if (m_numWriters == 0) { m_waiting_readers.notifyAll(); } BLOCXX_THROW(TimeoutException, "Timeout while waiting for write lock."); } } } ++ti.writeCount; } else { // This id doesn't have any lock while (m_numReaders != 0 || m_numWriters != 0) { // stop new readers m_canRead = false; if (!m_waiting_writers.timedWait(l, timer.asAbsoluteTimeout())) { m_canRead = true; if (m_numWriters == 0) { m_waiting_readers.notifyAll(); } BLOCXX_THROW(TimeoutException, "Timeout while waiting for write lock."); } } LockerInfo ti; ti.readCount = 0; ti.writeCount = 1; m_lockerInfo.insert(typename IdMap::value_type(id, ti)); ++m_numWriters; m_canRead = false; } }