<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010 Francois Beaune
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "statusbar.h"

// appleseed.foundation headers.
#include "foundation/utility/string.h"

using namespace foundation;
using namespace std;

namespace appleseed {
namespace studio {

//
// StatusBar class implementation.
//

StatusBar::StatusBar()
  : m_timer(0)
  , m_timer_id(-1)
{
}

void StatusBar::set_text(const string& text)
{
    setText(QString::fromStdString(text));
}

void StatusBar::start_rendering_time_display(RenderingTimer* timer)
{
    assert(m_timer_id == -1);
    assert(timer);

    m_timer = timer;
    m_timer_id = startTimer(1000 / 4);
}

void StatusBar::stop_rendering_time_display()
{
    assert(m_timer_id != -1);

    killTimer(m_timer_id);
    m_timer_id = -1;
    m_timer = 0;
}

void StatusBar::timerEvent(QTimerEvent* event)
{
    assert(m_timer);

    m_timer->measure();

    const double rendering_time = m_timer->get_seconds();
    const string rendering_time_string = pretty_time(rendering_time, 0);

    set_text("Rendering time: " + rendering_time_string);
}

}   // namespace studio
}   // namespace appleseed
<commit_msg>fixed a random crash:  when the status bar is asked to stop displaying rendering time, we shouldn't reset our pointer to the rendering timer, because we might actually be inside a timer event at this point.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010 Francois Beaune
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "statusbar.h"

// appleseed.foundation headers.
#include "foundation/utility/string.h"

using namespace foundation;
using namespace std;

namespace appleseed {
namespace studio {

//
// StatusBar class implementation.
//

StatusBar::StatusBar()
  : m_timer(0)
  , m_timer_id(-1)
{
}

void StatusBar::set_text(const string& text)
{
    setText(QString::fromStdString(text));
}

void StatusBar::start_rendering_time_display(RenderingTimer* timer)
{
    assert(m_timer_id == -1);
    assert(timer);

    m_timer = timer;
    m_timer_id = startTimer(1000 / 4);
}

void StatusBar::stop_rendering_time_display()
{
    assert(m_timer_id != -1);

    killTimer(m_timer_id);
    m_timer_id = -1;
}

void StatusBar::timerEvent(QTimerEvent* event)
{
    assert(m_timer);

    m_timer->measure();

    const double rendering_time = m_timer->get_seconds();
    const string rendering_time_string = pretty_time(rendering_time, 0);

    set_text("Rendering time: " + rendering_time_string);
}

}   // namespace studio
}   // namespace appleseed
<|endoftext|>


<commit_before>//---------------------------------------------------------- -*- Mode: C++ -*-
// $Id$
//
// Created 2008/11/01
// Author: Mike Ovsiannikov
//
// Copyright 2008-2011 Quantcast Corp.
//
// This file is part of Kosmos File System (KFS).
//
// Licensed under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
//
// IO buffer pool implementation.
//
//----------------------------------------------------------------------------

#include "QCIoBufferPool.h"
#include "QCUtils.h"
#include "qcdebug.h"
#include "qcstutils.h"
#include "QCDLList.h"

#include <sys/mman.h>
#include <errno.h>
#include <unistd.h>

class QCIoBufferPool::Partition
{
public:
    Partition()
        : mAllocPtr(0),
          mAllocSize(0),
          mStartPtr(0),
          mFreeListPtr(0),
          mTotalCnt(0),
          mFreeCnt(0),
          mBufSizeShift(0)
        { List::Init(*this); }

    ~Partition()
        { Partition::Destroy(); }

    int Create(
        int  inNumBuffers,
        int  inBufferSize,
        bool inLockMemoryFlag)
    {
        int theBufSizeShift = -1;
        for (int i = inBufferSize; i > 0; i >>= 1, theBufSizeShift++)
        {}
        if (theBufSizeShift < 0 || inBufferSize != (1 << theBufSizeShift)) {
            return EINVAL;
        }
        Destroy();
        mBufSizeShift = theBufSizeShift;
        if (inNumBuffers <= 0) {
            return 0;
        }
        mFreeListPtr = new BufferIndex[inNumBuffers + 1];
        size_t const kPageSize = sysconf(_SC_PAGESIZE);
        size_t const kAlign    = kPageSize > size_t(inBufferSize) ?
            kPageSize : size_t(inBufferSize);
        mAllocSize = size_t(inNumBuffers) * inBufferSize + kAlign;
        mAllocSize = (mAllocSize + kPageSize - 1) / kPageSize * kPageSize;
        mAllocPtr = mmap(0, mAllocSize,
            PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
        if (mAllocPtr == MAP_FAILED) {
            const int theRet = errno;
            mAllocPtr = 0;
            return (theRet == 0 ? -1 : theRet);
        }
        if (inLockMemoryFlag && mlock(mAllocPtr, mAllocSize) != 0) {
            const int theRet = errno;
            Destroy();
            return (theRet == 0 ? -1 : theRet);
        }
        mStartPtr = 0;
        mStartPtr += (((char*)mAllocPtr - (char*)0) + kAlign - 1) /
            kAlign * kAlign;
        mTotalCnt     = inNumBuffers;
        mFreeCnt      = 0;
        *mFreeListPtr = 0;
        while (mFreeCnt < mTotalCnt) {
            mFreeListPtr[mFreeCnt] = mFreeCnt + 1;
            mFreeCnt++;
        }
        mFreeListPtr[mFreeCnt] = 0;
        return 0;
    }

    void Destroy()
    {
        delete [] mFreeListPtr;
        mFreeListPtr = 0;
        if (mAllocPtr && munmap(mAllocPtr, mAllocSize) != 0) {
            QCUtils::FatalError("munmap", errno);
        }
        mAllocPtr     = 0;
        mAllocSize    = 0;
        mStartPtr     = 0;
        mTotalCnt     = 0;
        mFreeCnt      = 0;
        mBufSizeShift = 0;
    }

    char* Get()
    {
        if (mFreeCnt <= 0) {
            QCASSERT(*mFreeListPtr == 0 && mFreeCnt == 0);
            return 0;
        }
        const BufferIndex theIdx = *mFreeListPtr;
        QCASSERT(theIdx > 0);
        mFreeCnt--;
        *mFreeListPtr = mFreeListPtr[theIdx];
        return (mStartPtr + ((theIdx - 1) << mBufSizeShift));
    }

    bool Put(char* inPtr)
    {
        if (inPtr < mStartPtr) {
            return false;
        }
        const size_t theOffset = inPtr - mStartPtr;
        const size_t theIdx    = (theOffset >> mBufSizeShift) + 1;
        if (theIdx > size_t(mTotalCnt)) {
            return false;
        }
        QCRTASSERT(mTotalCnt > mFreeCnt &&
            (theOffset & ((size_t(1) << mBufSizeShift) - 1)) == 0);
        mFreeListPtr[theIdx] = *mFreeListPtr;
        *mFreeListPtr = BufferIndex(theIdx);
        mFreeCnt++;
        return true;
    }

    int GetFreeCount() const
        { return mFreeCnt; }

    int GetTotalCount() const
        { return mTotalCnt; }

    bool IsEmpty() const
        { return (mFreeCnt <= 0); }

    bool IsFull() const
        { return (mFreeCnt >= mTotalCnt); }

    typedef QCDLList<Partition, 0> List;

private:
    friend class QCDLListOp<Partition, 0>;
    friend class QCDLListOp<const Partition, 0>;
    typedef unsigned int BufferIndex;

    void*        mAllocPtr;
    size_t       mAllocSize;
    char*        mStartPtr;
    BufferIndex* mFreeListPtr;
    int          mTotalCnt;
    int          mFreeCnt;
    int          mBufSizeShift;
    Partition*   mPrevPtr[1];
    Partition*   mNextPtr[1];
};

typedef QCDLList<QCIoBufferPool::Client, 0> QCIoBufferPoolClientList;

QCIoBufferPool::Client::Client()
    : mPoolPtr(0)
{
    QCIoBufferPoolClientList::Init(*this);
}

bool
QCIoBufferPool::Client::Unregister()
{
    return (mPoolPtr && mPoolPtr->UnRegister(*this));
}

QCIoBufferPool::QCIoBufferPool()
    : mMutex(),
      mBufferSize(0),
      mFreeCnt(0),
      mTotalCnt(0)
{
    QCIoBufferPoolClientList::Init(mClientListPtr);
    Partition::List::Init(mPartitionListPtr);
}

QCIoBufferPool::~QCIoBufferPool()
{
    QCStMutexLocker theLock(mMutex);
    QCIoBufferPool::Destroy();
    while (! QCIoBufferPoolClientList::IsEmpty(mClientListPtr)) {
        Client& theClient = *QCIoBufferPoolClientList::PopBack(mClientListPtr);
        QCASSERT(theClient.mPoolPtr == this);
        theClient.mPoolPtr = 0;
    }
}

int
QCIoBufferPool::Create(
    int          inPartitionCount,
    int          inPartitionBufferCount,
    int          inBufferSize,
    bool         inLockMemoryFlag)
{
    QCStMutexLocker theLock(mMutex);
    Destroy();
    mBufferSize = inBufferSize;
    int theErr = 0;
    for (int i = 0; i < inPartitionCount; i++) {
        Partition& thePart = *(new Partition());
        Partition::List::PushBack(mPartitionListPtr, thePart);
        theErr = thePart.Create(
            inPartitionBufferCount, inBufferSize, inLockMemoryFlag);
        if (theErr) {
            Destroy();
            break;
        }
        mFreeCnt  += thePart.GetFreeCount();
        mTotalCnt += thePart.GetTotalCount();
    }
    return theErr;
}

void
QCIoBufferPool::Destroy()
{
    QCStMutexLocker theLock(mMutex);
    while (! Partition::List::IsEmpty(mPartitionListPtr)) {
        delete Partition::List::PopBack(mPartitionListPtr);
    }
    mBufferSize = 0;
    mFreeCnt    = 0;
}

char*
QCIoBufferPool::Get(
    QCIoBufferPool::RefillReqId inRefillReqId /* = kRefillReqIdUndefined */)
{
    QCStMutexLocker theLock(mMutex);
    if (mFreeCnt <= 0 && ! TryToRefill(inRefillReqId, 1)) {
        return 0;
    }
    QCASSERT(mFreeCnt >= 1);
    // Always start from the first partition, to try to keep next
    // partitions full, and be able to reclaim these if needed.
    Partition::List::Iterator theItr(mPartitionListPtr);
    Partition* thePtr;
    while ((thePtr = theItr.Next()) && thePtr->IsEmpty())
        {}
    char* const theBufPtr = thePtr ? thePtr->Get() : 0;
    QCASSERT(theBufPtr && mFreeCnt > 0);
    mFreeCnt--;
    return theBufPtr;
}

bool
QCIoBufferPool::Get(
    QCIoBufferPool::OutputIterator& inIt,
    int                             inBufCnt,
    QCIoBufferPool::RefillReqId     inRefillReqId /* = kRefillReqIdUndefined */)
{
    if (inBufCnt <= 0) {
        return true;
    }
    QCStMutexLocker theLock(mMutex);
    if (mFreeCnt < inBufCnt && ! TryToRefill(inRefillReqId, inBufCnt)) {
        return false;
    }
    QCASSERT(mFreeCnt >= inBufCnt);
    Partition::List::Iterator theItr(mPartitionListPtr);
    for (int i = 0; i < inBufCnt; ) {
        Partition* thePPtr;
        while ((thePPtr = theItr.Next()) && thePPtr->IsEmpty())
            {}
        QCASSERT(thePPtr);
        for (char* theBPtr; i < inBufCnt && (theBPtr = thePPtr->Get()); i++) {
            mFreeCnt--;
            inIt.Put(theBPtr);
        }
    }
    return true;
}

void
QCIoBufferPool::Put(
    char* inBufPtr)
{
    if (! inBufPtr) {
        return;
    }
    QCStMutexLocker theLock(mMutex);
    PutSelf(inBufPtr);
}

void
QCIoBufferPool::Put(
    QCIoBufferPool::InputIterator& inIt,
    int                            inBufCnt)
{
    if (inBufCnt < 0) {
        return;
    }
    QCStMutexLocker theLock(mMutex);
    for (int i = 0; i < inBufCnt; i++) {
        char* const theBufPtr = inIt.Get();
        if (! theBufPtr) {
            break;
        }
        PutSelf(theBufPtr);
    }
}

bool
QCIoBufferPool::Register(
    QCIoBufferPool::Client& inClient)
{
    QCStMutexLocker theLock(mMutex);
    if (inClient.mPoolPtr) {
        return (inClient.mPoolPtr == this);
    }
    QCIoBufferPoolClientList::PushBack(mClientListPtr, inClient);
    inClient.mPoolPtr = this;
    return true;
}

bool
QCIoBufferPool::UnRegister(
    QCIoBufferPool::Client& inClient)
{
    QCStMutexLocker theLock(mMutex);
    if (inClient.mPoolPtr != this) {
        return false;
    }
    QCIoBufferPoolClientList::Remove(mClientListPtr, inClient);
    inClient.mPoolPtr = 0;
    return true;
}

void
QCIoBufferPool::PutSelf(
    char* inBufPtr)
{
    QCASSERT(mMutex.IsOwned());
    if (! inBufPtr) {
        return;
    }
    Partition::List::Iterator theItr(mPartitionListPtr);
    Partition* thePtr;
    while ((thePtr = theItr.Next()) && ! thePtr->Put(inBufPtr))
        {}
    QCRTASSERT(thePtr);
    mFreeCnt++;
}

bool
QCIoBufferPool::TryToRefill(
    QCIoBufferPool::RefillReqId inReqId,
    int                         inBufCnt)
{
    QCASSERT(mMutex.IsOwned());
    if (inReqId == kRefillReqIdUndefined) {
        return false;
    }
    QCIoBufferPoolClientList::Iterator theItr(mClientListPtr);
    Client* thePtr;
    while ((thePtr = theItr.Next()) && mFreeCnt < inBufCnt) {
        QCASSERT(thePtr->mPoolPtr == this);
        {
            // QCStMutexUnlocker theUnlock(mMutex);
            thePtr->Release(inReqId, inBufCnt - mFreeCnt);
        }
    }
    return (mFreeCnt >= inBufCnt);
}

int
QCIoBufferPool::GetFreeBufferCount()
{
    QCStMutexLocker theLock(mMutex);
    return mFreeCnt;
}

int
QCIoBufferPool::GetTotalBufferCount()
{
    QCStMutexLocker theLock(mMutex);
    return mTotalCnt;
}

int
QCIoBufferPool::GetUsedBufferCount()
{
    QCStMutexLocker theLock(mMutex);
    return (mTotalCnt - mFreeCnt);
}
<commit_msg>Qcdio library: eliminate lint warning.<commit_after>//---------------------------------------------------------- -*- Mode: C++ -*-
// $Id$
//
// Created 2008/11/01
// Author: Mike Ovsiannikov
//
// Copyright 2008-2011 Quantcast Corp.
//
// This file is part of Kosmos File System (KFS).
//
// Licensed under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
//
// IO buffer pool implementation.
//
//----------------------------------------------------------------------------

#include "QCIoBufferPool.h"
#include "QCUtils.h"
#include "qcdebug.h"
#include "qcstutils.h"
#include "QCDLList.h"

#include <sys/mman.h>
#include <errno.h>
#include <unistd.h>

class QCIoBufferPool::Partition
{
public:
    Partition()
        : mAllocPtr(0),
          mAllocSize(0),
          mStartPtr(0),
          mFreeListPtr(0),
          mTotalCnt(0),
          mFreeCnt(0),
          mBufSizeShift(0)
        { List::Init(*this); }

    ~Partition()
        { Partition::Destroy(); }

    int Create(
        int  inNumBuffers,
        int  inBufferSize,
        bool inLockMemoryFlag)
    {
        int theBufSizeShift = -1;
        for (int i = inBufferSize; i > 0; i >>= 1, theBufSizeShift++)
        {}
        if (theBufSizeShift < 0 || inBufferSize != (1 << theBufSizeShift)) {
            return EINVAL;
        }
        Destroy();
        mBufSizeShift = theBufSizeShift;
        if (inNumBuffers <= 0) {
            return 0;
        }
        mFreeListPtr = new BufferIndex[inNumBuffers + 1];
        size_t const kPageSize = sysconf(_SC_PAGESIZE);
        size_t const kAlign    = kPageSize > size_t(inBufferSize) ?
            kPageSize : size_t(inBufferSize);
        mAllocSize = size_t(inNumBuffers) * inBufferSize + kAlign;
        mAllocSize = (mAllocSize + kPageSize - 1) / kPageSize * kPageSize;
        mAllocPtr = mmap(0, mAllocSize,
            PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
        if (mAllocPtr == MAP_FAILED) {
            const int theRet = errno;
            mAllocPtr = 0;
            return (theRet == 0 ? -1 : theRet);
        }
        if (inLockMemoryFlag && mlock(mAllocPtr, mAllocSize) != 0) {
            const int theRet = errno;
            Destroy();
            return (theRet == 0 ? -1 : theRet);
        }
        mStartPtr = 0;
        mStartPtr += (((char*)mAllocPtr - (char*)0) + kAlign - 1) /
            kAlign * kAlign;
        mTotalCnt     = inNumBuffers;
        mFreeCnt      = 0;
        *mFreeListPtr = 0;
        while (mFreeCnt < mTotalCnt) {
            mFreeListPtr[mFreeCnt] = mFreeCnt + 1;
            mFreeCnt++;
        }
        mFreeListPtr[mFreeCnt] = 0;
        return 0;
    }

    void Destroy()
    {
        delete [] mFreeListPtr;
        mFreeListPtr = 0;
        if (mAllocPtr && munmap(mAllocPtr, mAllocSize) != 0) {
            QCUtils::FatalError("munmap", errno);
        }
        mAllocPtr     = 0;
        mAllocSize    = 0;
        mStartPtr     = 0;
        mTotalCnt     = 0;
        mFreeCnt      = 0;
        mBufSizeShift = 0;
    }

    char* Get()
    {
        if (mFreeCnt <= 0) {
            QCASSERT(*mFreeListPtr == 0 && mFreeCnt == 0);
            return 0;
        }
        const BufferIndex theIdx = *mFreeListPtr;
        QCASSERT(theIdx > 0);
        mFreeCnt--;
        *mFreeListPtr = mFreeListPtr[theIdx];
        return (mStartPtr + ((theIdx - 1) << mBufSizeShift));
    }

    bool Put(char* inPtr)
    {
        if (inPtr < mStartPtr) {
            return false;
        }
        const size_t theOffset = inPtr - mStartPtr;
        const size_t theIdx    = (theOffset >> mBufSizeShift) + 1;
        if (theIdx > size_t(mTotalCnt)) {
            return false;
        }
        QCRTASSERT(mTotalCnt > mFreeCnt &&
            (theOffset & ((size_t(1) << mBufSizeShift) - 1)) == 0);
        mFreeListPtr[theIdx] = *mFreeListPtr;
        *mFreeListPtr = BufferIndex(theIdx);
        mFreeCnt++;
        return true;
    }

    int GetFreeCount() const
        { return mFreeCnt; }

    int GetTotalCount() const
        { return mTotalCnt; }

    bool IsEmpty() const
        { return (mFreeCnt <= 0); }

    bool IsFull() const
        { return (mFreeCnt >= mTotalCnt); }

    typedef QCDLList<Partition, 0> List;

private:
    friend class QCDLListOp<Partition, 0>;
    friend class QCDLListOp<const Partition, 0>;
    typedef unsigned int BufferIndex;

    void*        mAllocPtr;
    size_t       mAllocSize;
    char*        mStartPtr;
    BufferIndex* mFreeListPtr;
    int          mTotalCnt;
    int          mFreeCnt;
    int          mBufSizeShift;
    Partition*   mPrevPtr[1];
    Partition*   mNextPtr[1];
};

typedef QCDLList<QCIoBufferPool::Client, 0> QCIoBufferPoolClientList;

QCIoBufferPool::Client::Client()
    : mPoolPtr(0)
{
    QCIoBufferPoolClientList::Init(*this);
}

bool
QCIoBufferPool::Client::Unregister()
{
    return (mPoolPtr && mPoolPtr->UnRegister(*this));
}

QCIoBufferPool::QCIoBufferPool()
    : mMutex(),
      mBufferSize(0),
      mFreeCnt(0),
      mTotalCnt(0)
{
    QCIoBufferPoolClientList::Init(mClientListPtr);
    Partition::List::Init(mPartitionListPtr);
}

QCIoBufferPool::~QCIoBufferPool()
{
    QCStMutexLocker theLock(mMutex);
    QCIoBufferPool::Destroy();
    Client* thePtr;
    while ((thePtr = QCIoBufferPoolClientList::PopBack(mClientListPtr))) {
        Client& theClient = *thePtr;
        QCASSERT(theClient.mPoolPtr == this);
        theClient.mPoolPtr = 0;
    }
}

int
QCIoBufferPool::Create(
    int          inPartitionCount,
    int          inPartitionBufferCount,
    int          inBufferSize,
    bool         inLockMemoryFlag)
{
    QCStMutexLocker theLock(mMutex);
    Destroy();
    mBufferSize = inBufferSize;
    int theErr = 0;
    for (int i = 0; i < inPartitionCount; i++) {
        Partition& thePart = *(new Partition());
        Partition::List::PushBack(mPartitionListPtr, thePart);
        theErr = thePart.Create(
            inPartitionBufferCount, inBufferSize, inLockMemoryFlag);
        if (theErr) {
            Destroy();
            break;
        }
        mFreeCnt  += thePart.GetFreeCount();
        mTotalCnt += thePart.GetTotalCount();
    }
    return theErr;
}

void
QCIoBufferPool::Destroy()
{
    QCStMutexLocker theLock(mMutex);
    Partition* thePtr;
    while ((thePtr = Partition::List::PopBack(mPartitionListPtr))) {
        delete thePtr;
    }
    mBufferSize = 0;
    mFreeCnt    = 0;
}

char*
QCIoBufferPool::Get(
    QCIoBufferPool::RefillReqId inRefillReqId /* = kRefillReqIdUndefined */)
{
    QCStMutexLocker theLock(mMutex);
    if (mFreeCnt <= 0 && ! TryToRefill(inRefillReqId, 1)) {
        return 0;
    }
    QCASSERT(mFreeCnt >= 1);
    // Always start from the first partition, to try to keep next
    // partitions full, and be able to reclaim these if needed.
    Partition::List::Iterator theItr(mPartitionListPtr);
    Partition* thePtr;
    while ((thePtr = theItr.Next()) && thePtr->IsEmpty())
        {}
    char* const theBufPtr = thePtr ? thePtr->Get() : 0;
    QCASSERT(theBufPtr && mFreeCnt > 0);
    mFreeCnt--;
    return theBufPtr;
}

bool
QCIoBufferPool::Get(
    QCIoBufferPool::OutputIterator& inIt,
    int                             inBufCnt,
    QCIoBufferPool::RefillReqId     inRefillReqId /* = kRefillReqIdUndefined */)
{
    if (inBufCnt <= 0) {
        return true;
    }
    QCStMutexLocker theLock(mMutex);
    if (mFreeCnt < inBufCnt && ! TryToRefill(inRefillReqId, inBufCnt)) {
        return false;
    }
    QCASSERT(mFreeCnt >= inBufCnt);
    Partition::List::Iterator theItr(mPartitionListPtr);
    for (int i = 0; i < inBufCnt; ) {
        Partition* thePPtr;
        while ((thePPtr = theItr.Next()) && thePPtr->IsEmpty())
            {}
        QCASSERT(thePPtr);
        for (char* theBPtr; i < inBufCnt && (theBPtr = thePPtr->Get()); i++) {
            mFreeCnt--;
            inIt.Put(theBPtr);
        }
    }
    return true;
}

void
QCIoBufferPool::Put(
    char* inBufPtr)
{
    if (! inBufPtr) {
        return;
    }
    QCStMutexLocker theLock(mMutex);
    PutSelf(inBufPtr);
}

void
QCIoBufferPool::Put(
    QCIoBufferPool::InputIterator& inIt,
    int                            inBufCnt)
{
    if (inBufCnt < 0) {
        return;
    }
    QCStMutexLocker theLock(mMutex);
    for (int i = 0; i < inBufCnt; i++) {
        char* const theBufPtr = inIt.Get();
        if (! theBufPtr) {
            break;
        }
        PutSelf(theBufPtr);
    }
}

bool
QCIoBufferPool::Register(
    QCIoBufferPool::Client& inClient)
{
    QCStMutexLocker theLock(mMutex);
    if (inClient.mPoolPtr) {
        return (inClient.mPoolPtr == this);
    }
    QCIoBufferPoolClientList::PushBack(mClientListPtr, inClient);
    inClient.mPoolPtr = this;
    return true;
}

bool
QCIoBufferPool::UnRegister(
    QCIoBufferPool::Client& inClient)
{
    QCStMutexLocker theLock(mMutex);
    if (inClient.mPoolPtr != this) {
        return false;
    }
    QCIoBufferPoolClientList::Remove(mClientListPtr, inClient);
    inClient.mPoolPtr = 0;
    return true;
}

void
QCIoBufferPool::PutSelf(
    char* inBufPtr)
{
    QCASSERT(mMutex.IsOwned());
    if (! inBufPtr) {
        return;
    }
    Partition::List::Iterator theItr(mPartitionListPtr);
    Partition* thePtr;
    while ((thePtr = theItr.Next()) && ! thePtr->Put(inBufPtr))
        {}
    QCRTASSERT(thePtr);
    mFreeCnt++;
}

bool
QCIoBufferPool::TryToRefill(
    QCIoBufferPool::RefillReqId inReqId,
    int                         inBufCnt)
{
    QCASSERT(mMutex.IsOwned());
    if (inReqId == kRefillReqIdUndefined) {
        return false;
    }
    QCIoBufferPoolClientList::Iterator theItr(mClientListPtr);
    Client* thePtr;
    while ((thePtr = theItr.Next()) && mFreeCnt < inBufCnt) {
        QCASSERT(thePtr->mPoolPtr == this);
        {
            // QCStMutexUnlocker theUnlock(mMutex);
            thePtr->Release(inReqId, inBufCnt - mFreeCnt);
        }
    }
    return (mFreeCnt >= inBufCnt);
}

int
QCIoBufferPool::GetFreeBufferCount()
{
    QCStMutexLocker theLock(mMutex);
    return mFreeCnt;
}

int
QCIoBufferPool::GetTotalBufferCount()
{
    QCStMutexLocker theLock(mMutex);
    return mTotalCnt;
}

int
QCIoBufferPool::GetUsedBufferCount()
{
    QCStMutexLocker theLock(mMutex);
    return (mTotalCnt - mFreeCnt);
}
<|endoftext|>


<commit_before>//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//
#pragma once

#include <Half.hpp>

#include <aclCommon/ArmComputeTensorUtils.hpp>
#include <cl/OpenClTimer.hpp>
#include <backendsCommon/CpuTensorHandle.hpp>

#include <armnn/Utils.hpp>

#include <arm_compute/runtime/CL/CLTensor.h>
#include <arm_compute/runtime/IFunction.h>

#include <sstream>

#define ARMNN_SCOPED_PROFILING_EVENT_CL(name) \
    ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS(armnn::Compute::GpuAcc, \
                                                  name, \
                                                  armnn::OpenClTimer(), \
                                                  armnn::WallClockTimer())

namespace armnn
{

template <typename T>
void CopyArmComputeClTensorData(arm_compute::CLTensor& dstTensor, const T* srcData)
{
    {
        ARMNN_SCOPED_PROFILING_EVENT_CL("MapClTensorForWriting");
        dstTensor.map(true);
    }

    {
        ARMNN_SCOPED_PROFILING_EVENT_CL("CopyToClTensor");
        armcomputetensorutils::CopyArmComputeITensorData<T>(srcData, dstTensor);
    }

    dstTensor.unmap();
}

inline auto SetClStridedSliceData(const std::vector<int>& m_begin,
                                  const std::vector<int>& m_end,
                                  const std::vector<int>& m_stride)
{
    arm_compute::Coordinates starts;
    arm_compute::Coordinates ends;
    arm_compute::Coordinates strides;

    unsigned int num_dims = static_cast<unsigned int>(m_begin.size());

    for (unsigned int i = 0; i < num_dims; i++) {
        unsigned int revertedIndex = num_dims - i - 1;

        starts.set(i, static_cast<int>(m_begin[revertedIndex]));
        ends.set(i, static_cast<int>(m_end[revertedIndex]));
        strides.set(i, static_cast<int>(m_stride[revertedIndex]));
    }

    return std::make_tuple(starts, ends, strides);
}

inline auto SetClSliceData(const std::vector<unsigned int>& m_begin,
                           const std::vector<unsigned int>& m_size)
{
    // This function must translate the size vector given to an end vector
    // expected by the ACL NESlice workload
    arm_compute::Coordinates starts;
    arm_compute::Coordinates ends;

    unsigned int num_dims = static_cast<unsigned int>(m_begin.size());

    // For strided slices, we have the relationship size = (end - begin) / stride
    // For slice, we assume stride to be a vector of all ones, yielding the formula
    // size = (end - begin) therefore we know end = size + begin
    for (unsigned int i = 0; i < num_dims; i++)
    {
        unsigned int revertedIndex = num_dims - i - 1;

        starts.set(i, static_cast<int>(m_begin[revertedIndex]));
        ends.set(i, static_cast<int>(m_begin[revertedIndex] + m_size[revertedIndex]));
    }

    return std::make_tuple(starts, ends);
}

inline void InitializeArmComputeClTensorData(arm_compute::CLTensor& clTensor,
                                             const ConstCpuTensorHandle* handle)
{
    ARMNN_ASSERT(handle);

    armcomputetensorutils::InitialiseArmComputeTensorEmpty(clTensor);
    switch(handle->GetTensorInfo().GetDataType())
    {
        case DataType::Float16:
            CopyArmComputeClTensorData(clTensor, handle->GetConstTensor<armnn::Half>());
            break;
        case DataType::Float32:
            CopyArmComputeClTensorData(clTensor, handle->GetConstTensor<float>());
            break;
        case DataType::QAsymmS8:
        case DataType::QAsymmU8:
            CopyArmComputeClTensorData(clTensor, handle->GetConstTensor<uint8_t>());
            break;
        ARMNN_NO_DEPRECATE_WARN_BEGIN
        case DataType::QuantizedSymm8PerAxis:
            ARMNN_FALLTHROUGH;
        case DataType::QSymmS8:
            CopyArmComputeClTensorData(clTensor, handle->GetConstTensor<int8_t>());
            break;
        case DataType::QSymmS16:
            CopyArmComputeClTensorData(clTensor, handle->GetConstTensor<int16_t>());
            break;
        ARMNN_NO_DEPRECATE_WARN_END
        case DataType::Signed32:
            CopyArmComputeClTensorData(clTensor, handle->GetConstTensor<int32_t>());
            break;
        default:
            ARMNN_ASSERT_MSG(false, "Unexpected tensor type.");
    }
};

inline RuntimeException WrapClError(const cl::Error& clError, const CheckLocation& location)
{
    std::stringstream message;
    message << "CL error: " << clError.what() << ". Error code: " << clError.err();

    return RuntimeException(message.str(), location);
}

inline void RunClFunction(arm_compute::IFunction& function, const CheckLocation& location)
{
    try
    {
        function.run();
    }
    catch (cl::Error& error)
    {
        throw WrapClError(error, location);
    }
}

} //namespace armnn
<commit_msg>IVGCVSW-5189 Fix error running EfficientNet-Lite on GpuAcc<commit_after>//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//
#pragma once

#include <Half.hpp>

#include <aclCommon/ArmComputeTensorUtils.hpp>
#include <cl/OpenClTimer.hpp>
#include <backendsCommon/CpuTensorHandle.hpp>

#include <armnn/Utils.hpp>

#include <arm_compute/runtime/CL/CLTensor.h>
#include <arm_compute/runtime/IFunction.h>

#include <sstream>

#define ARMNN_SCOPED_PROFILING_EVENT_CL(name) \
    ARMNN_SCOPED_PROFILING_EVENT_WITH_INSTRUMENTS(armnn::Compute::GpuAcc, \
                                                  name, \
                                                  armnn::OpenClTimer(), \
                                                  armnn::WallClockTimer())

namespace armnn
{

template <typename T>
void CopyArmComputeClTensorData(arm_compute::CLTensor& dstTensor, const T* srcData)
{
    {
        ARMNN_SCOPED_PROFILING_EVENT_CL("MapClTensorForWriting");
        dstTensor.map(true);
    }

    {
        ARMNN_SCOPED_PROFILING_EVENT_CL("CopyToClTensor");
        armcomputetensorutils::CopyArmComputeITensorData<T>(srcData, dstTensor);
    }

    dstTensor.unmap();
}

inline auto SetClStridedSliceData(const std::vector<int>& m_begin,
                                  const std::vector<int>& m_end,
                                  const std::vector<int>& m_stride)
{
    arm_compute::Coordinates starts;
    arm_compute::Coordinates ends;
    arm_compute::Coordinates strides;

    unsigned int num_dims = static_cast<unsigned int>(m_begin.size());

    for (unsigned int i = 0; i < num_dims; i++) {
        unsigned int revertedIndex = num_dims - i - 1;

        starts.set(i, static_cast<int>(m_begin[revertedIndex]));
        ends.set(i, static_cast<int>(m_end[revertedIndex]));
        strides.set(i, static_cast<int>(m_stride[revertedIndex]));
    }

    return std::make_tuple(starts, ends, strides);
}

inline auto SetClSliceData(const std::vector<unsigned int>& m_begin,
                           const std::vector<unsigned int>& m_size)
{
    // This function must translate the size vector given to an end vector
    // expected by the ACL NESlice workload
    arm_compute::Coordinates starts;
    arm_compute::Coordinates ends;

    unsigned int num_dims = static_cast<unsigned int>(m_begin.size());

    // For strided slices, we have the relationship size = (end - begin) / stride
    // For slice, we assume stride to be a vector of all ones, yielding the formula
    // size = (end - begin) therefore we know end = size + begin
    for (unsigned int i = 0; i < num_dims; i++)
    {
        unsigned int revertedIndex = num_dims - i - 1;

        starts.set(i, static_cast<int>(m_begin[revertedIndex]));
        ends.set(i, static_cast<int>(m_begin[revertedIndex] + m_size[revertedIndex]));
    }

    return std::make_tuple(starts, ends);
}

inline void InitializeArmComputeClTensorData(arm_compute::CLTensor& clTensor,
                                             const ConstCpuTensorHandle* handle)
{
    ARMNN_ASSERT(handle);

    armcomputetensorutils::InitialiseArmComputeTensorEmpty(clTensor);
    switch(handle->GetTensorInfo().GetDataType())
    {
        case DataType::Float16:
            CopyArmComputeClTensorData(clTensor, handle->GetConstTensor<armnn::Half>());
            break;
        case DataType::Float32:
            CopyArmComputeClTensorData(clTensor, handle->GetConstTensor<float>());
            break;
        case DataType::QAsymmU8:
            CopyArmComputeClTensorData(clTensor, handle->GetConstTensor<uint8_t>());
            break;
        ARMNN_NO_DEPRECATE_WARN_BEGIN
        case DataType::QuantizedSymm8PerAxis:
            ARMNN_FALLTHROUGH;
        case DataType::QAsymmS8:
        case DataType::QSymmS8:
            CopyArmComputeClTensorData(clTensor, handle->GetConstTensor<int8_t>());
            break;
        case DataType::QSymmS16:
            CopyArmComputeClTensorData(clTensor, handle->GetConstTensor<int16_t>());
            break;
        ARMNN_NO_DEPRECATE_WARN_END
        case DataType::Signed32:
            CopyArmComputeClTensorData(clTensor, handle->GetConstTensor<int32_t>());
            break;
        default:
            ARMNN_ASSERT_MSG(false, "Unexpected tensor type.");
    }
};

inline RuntimeException WrapClError(const cl::Error& clError, const CheckLocation& location)
{
    std::stringstream message;
    message << "CL error: " << clError.what() << ". Error code: " << clError.err();

    return RuntimeException(message.str(), location);
}

inline void RunClFunction(arm_compute::IFunction& function, const CheckLocation& location)
{
    try
    {
        function.run();
    }
    catch (cl::Error& error)
    {
        throw WrapClError(error, location);
    }
}

} //namespace armnn
<|endoftext|>


<commit_before>/**
 *  Copyright (C) 2015 Topology LP
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#ifndef BONEFISH_RAWSOCKET_LISTENER_HPP
#define BONEFISH_RAWSOCKET_LISTENER_HPP

#include <bonefish/rawsocket/rawsocket_connection.hpp>

#include <boost/asio/io_service.hpp>
#include <functional>

namespace bonefish {

class rawsocket_listener
{
public:
    using accept_handler = std::function<void(const std::shared_ptr<rawsocket_connection>&)>;

public:
    rawsocket_listener();
    virtual ~rawsocket_listener();

    virtual void start_listening() = 0;
    virtual void stop_listening() = 0;
    virtual std::shared_ptr<rawsocket_connection> create_connection() = 0;

    bool is_listening() const;
    const accept_handler& get_accept_handler() const;

    void set_accept_handler(const accept_handler& handler);

    void handle_accept(const boost::system::error_code& error_code);

protected:
    virtual void async_accept() = 0;

    void set_listening(bool is_listening);

private:
    bool m_listening;
    accept_handler m_accept_handler;
};

inline rawsocket_listener::rawsocket_listener()
    : m_listening(false)
    , m_accept_handler()
{
}

inline rawsocket_listener::~rawsocket_listener()
{
}

inline bool rawsocket_listener::is_listening() const
{
    return m_listening;
}

inline const typename rawsocket_listener::accept_handler&
rawsocket_listener::get_accept_handler() const
{
    return m_accept_handler;
}

inline void rawsocket_listener::set_accept_handler(
        const rawsocket_listener::accept_handler& handler)
{
    m_accept_handler = handler;
}

inline void rawsocket_listener::handle_accept(
        const boost::system::error_code &error_code)
{
    if (error_code) {
        return;
    }

    assert(get_accept_handler());
    const auto& accept_handler = get_accept_handler();
    accept_handler(create_connection());

    async_accept();
}

inline void rawsocket_listener::set_listening(bool is_listening)
{
    m_listening = is_listening;
}

} // namespace bonefish

#endif // BONEFISH_RAWSOCKET_LISTENER_HPP
<commit_msg>Remove rawsocket connection include from rawsocket listener<commit_after>/**
 *  Copyright (C) 2015 Topology LP
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#ifndef BONEFISH_RAWSOCKET_LISTENER_HPP
#define BONEFISH_RAWSOCKET_LISTENER_HPP

#include <boost/asio/io_service.hpp>
#include <functional>

namespace bonefish {

class rawsocket_connection;

class rawsocket_listener
{
public:
    using accept_handler = std::function<void(const std::shared_ptr<rawsocket_connection>&)>;

public:
    rawsocket_listener();
    virtual ~rawsocket_listener();

    virtual void start_listening() = 0;
    virtual void stop_listening() = 0;
    virtual std::shared_ptr<rawsocket_connection> create_connection() = 0;

    bool is_listening() const;
    const accept_handler& get_accept_handler() const;

    void set_accept_handler(const accept_handler& handler);

    void handle_accept(const boost::system::error_code& error_code);

protected:
    virtual void async_accept() = 0;

    void set_listening(bool is_listening);

private:
    bool m_listening;
    accept_handler m_accept_handler;
};

inline rawsocket_listener::rawsocket_listener()
    : m_listening(false)
    , m_accept_handler()
{
}

inline rawsocket_listener::~rawsocket_listener()
{
}

inline bool rawsocket_listener::is_listening() const
{
    return m_listening;
}

inline const typename rawsocket_listener::accept_handler&
rawsocket_listener::get_accept_handler() const
{
    return m_accept_handler;
}

inline void rawsocket_listener::set_accept_handler(
        const rawsocket_listener::accept_handler& handler)
{
    m_accept_handler = handler;
}

inline void rawsocket_listener::handle_accept(
        const boost::system::error_code &error_code)
{
    if (error_code) {
        return;
    }

    assert(get_accept_handler());
    const auto& accept_handler = get_accept_handler();
    accept_handler(create_connection());

    async_accept();
}

inline void rawsocket_listener::set_listening(bool is_listening)
{
    m_listening = is_listening;
}

} // namespace bonefish

#endif // BONEFISH_RAWSOCKET_LISTENER_HPP
<|endoftext|>


<commit_before>// Copyright (c) 2015
// Author: Chrono Law
#ifndef _NGX_THREAD_HPP
#define _NGX_THREAD_HPP

#include "NgxPool.hpp"
#include "NgxEvent.hpp"

template<typename T>
class NgxThreadTask final : public NgxWrapper<ngx_thread_task_t>
{
public:
    typedef NgxWrapper<ngx_thread_task_t> super_type;
    typedef NgxThreadTask this_type;
    typedef T task_ctx_type;
public:
    NgxThreadTask(ngx_thread_task_t* t) : super_type(t)
    {}

    ~NgxThreadTask() = default;
public:
    T& ctx() const
    {
        return *reinterpret_cast<T*>(get()->ctx);
    }

    template<typename F>
    void handler(F f) const
    {
        if(!get()->handler)
        {
            get()->handler = f;
        }
    }
public:
    NgxEvent event() const
    {
        return &get()->event;
    }
public:
    static ngx_thread_task_t* create(const NgxPool& pool)
    {
        auto p = pool.thread_task<T>();

        return p;
    }
};

class NgxThreadPool final : public NgxWrapper<ngx_thread_pool_t>
{
public:
    typedef NgxWrapper<ngx_thread_pool_t> super_type;
    typedef NgxThreadPool this_type;
public:
    NgxThreadPool(ngx_thread_pool_t* p) : super_type(p)
    {}

    ~NgxThreadPool() = default;
public:
    void post(ngx_thread_task_t* task) const
    {
        auto rc = ngx_thread_task_post(get(), task);

        NgxException::require(rc);
    }
public:
    static ngx_thread_pool_t* acquire(ngx_str_t& name)
    {
        auto p = ngx_thread_pool_get((ngx_cycle_t *) ngx_cycle, &name);

        NgxException::require(p);

        return p;
    }
};

#endif  //_NGX_THREAD_HPP
<commit_msg>NgxThread.hpp<commit_after>// Copyright (c) 2017
// Author: Chrono Law
#ifndef _NGX_THREAD_HPP
#define _NGX_THREAD_HPP

#include "NgxPool.hpp"
#include "NgxEvent.hpp"

template<typename T>
class NgxThreadTask final : public NgxWrapper<ngx_thread_task_t>
{
public:
    typedef NgxWrapper<ngx_thread_task_t>   super_type;
    typedef NgxThreadTask                   this_type;
    typedef T                               task_ctx_type;
public:
    NgxThreadTask(ngx_thread_task_t* t) : super_type(t)
    {}

    ~NgxThreadTask() = default;
public:
    T* ctx() const
    {
        return reinterpret_cast<T*>(get()->ctx);
    }

    template<typename F>
    void handler(F f) const
    {
        if(!get()->handler)
        {
            get()->handler = f;
        }
    }
public:
    NgxEvent event() const
    {
        return &get()->event;
    }
public:
    static ngx_thread_task_t* create(const NgxPool& pool)
    {
        auto p = pool.thread_task<T>();

        return p;
    }
};

class NgxThreadPool final : public NgxWrapper<ngx_thread_pool_t>
{
public:
    typedef NgxWrapper<ngx_thread_pool_t>   super_type;
    typedef NgxThreadPool                   this_type;
public:
    NgxThreadPool(ngx_thread_pool_t* p) : super_type(p)
    {}

    NgxThreadPool(ngx_str_t name) : super_type(acquire(name))
    {}

    ~NgxThreadPool() = default;
public:
    void post(ngx_thread_task_t* task) const
    {
        auto rc = ngx_thread_task_post(get(), task);

        NgxException::require(rc);
    }
public:
    static ngx_thread_pool_t* acquire(ngx_str_t& name)
    {
        auto p = ngx_thread_pool_get((ngx_cycle_t *) ngx_cycle, &name);

        NgxException::require(p);

        return p;
    }
};

#endif  //_NGX_THREAD_HPP
<|endoftext|>


<commit_before>#include "contextpanewidgetrectangle.h"
#include "ui_contextpanewidgetrectangle.h"
#include "contextpanewidget.h"
#include <qmljs/qmljspropertyreader.h>
#include <QDebug>

namespace QmlDesigner {

ContextPaneWidgetRectangle::ContextPaneWidgetRectangle(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ContextPaneWidgetRectangle),
    m_gradientLineDoubleClicked(false),
    m_gradientTimer(-1)
{
    ui->setupUi(this);

    ui->colorColorButton->setShowArrow(false);
    ui->borderColorButton->setShowArrow(false);

    connect(ui->colorColorButton, SIGNAL(toggled(bool)), this, SLOT(onColorButtonToggled(bool)));
    connect(ui->borderColorButton, SIGNAL(toggled(bool)), this, SLOT(onBorderColorButtonToggled(bool)));

    connect(ui->colorSolid, SIGNAL(clicked()), this, SLOT(onColorSolidClicked()));
    connect(ui->borderSolid, SIGNAL(clicked()), this, SLOT(onBorderSolidClicked()));

    connect(ui->colorNone, SIGNAL(clicked()), this, SLOT(onColorNoneClicked()));
    connect(ui->borderNone, SIGNAL(clicked()), this, SLOT(onBorderNoneClicked()));

    connect(ui->colorGradient, SIGNAL(clicked()), this, SLOT(onGradientClicked()));

    ContextPaneWidget *parentContextWidget = qobject_cast<ContextPaneWidget*>(parentWidget());
    connect(parentContextWidget->colorDialog(), SIGNAL(accepted(QColor)), this, SLOT(onColorDialogApplied(QColor)));
    connect(parentContextWidget->colorDialog(), SIGNAL(rejected()), this, SLOT(onColorDialogCancled()));

    connect(ui->gradientLine, SIGNAL(openColorDialog(QPoint)), this, SLOT(onGradientLineDoubleClicked(QPoint)));
    connect(ui->gradientLine, SIGNAL(gradientChanged()), this, SLOT(onUpdateGradient()));
}

ContextPaneWidgetRectangle::~ContextPaneWidgetRectangle()
{
    delete ui;
}

void ContextPaneWidgetRectangle::setProperties(QmlJS::PropertyReader *propertyReader)
{
    m_hasGradient = propertyReader->hasProperty(QLatin1String("gradient"));
    m_none = false;
    m_hasBorder = false;

    if (propertyReader->hasProperty(QLatin1String("color"))) {
        QString str = propertyReader->readProperty("color").toString();
        if (QColor(str).alpha() == 0)
            m_none = true;
        ui->colorColorButton->setColor(str);

    } else {
        ui->colorColorButton->setColor(QLatin1String("black"));
    }

    if (propertyReader->hasProperty(QLatin1String("border.color"))) {
        ui->borderColorButton->setColor(propertyReader->readProperty("border.color").toString());
        m_hasBorder = true;
    } else {
        ui->borderColorButton->setColor(QLatin1String("transparent"));
    }

    if (propertyReader->hasProperty(QLatin1String("border.width")))
        m_hasBorder = true;

    ui->colorSolid->setChecked(true);
    ui->borderNone->setChecked(true);
    ui->borderSolid->setChecked(m_hasBorder);

    if (m_none)
        ui->colorNone->setChecked(true);

    ui->gradientLabel->setEnabled(true);
    ui->gradientLine->setEnabled(true);

    if (m_hasGradient) {
        bool isBound;
        ui->colorGradient->setChecked(true);
        ui->gradientLine->setGradient(propertyReader->parseGradient("gradient", &isBound));
        if (isBound) {
            ui->gradientLabel->setEnabled(false);
            ui->gradientLine->setEnabled(false);
            ui->colorColorButton->setColor("invalidColor");
        }
    } else {
        //ui->gradientLine->setEnabled(false);
        //ui->gradientLabel->setEnabled(false);
        setColor();
    }

    if (m_gradientTimer > 0) {
        killTimer(m_gradientTimer);
        m_gradientTimer = -1;
    }

}

void ContextPaneWidgetRectangle::onBorderColorButtonToggled(bool flag)
{
    if (flag) {
        ui->colorColorButton->setChecked(false);
        m_gradientLineDoubleClicked = false;
    }
    ContextPaneWidget *parentContextWidget = qobject_cast<ContextPaneWidget*>(parentWidget());
    QPoint p = mapToGlobal(ui->borderColorButton->pos());
    parentContextWidget->colorDialog()->setupColor(ui->borderColorButton->convertedColor());
    p = parentContextWidget->colorDialog()->parentWidget()->mapFromGlobal(p);
    parentContextWidget->onShowColorDialog(flag, p);
}

void ContextPaneWidgetRectangle::onColorButtonToggled(bool flag )
{
    if (flag) {
        ui->borderColorButton->setChecked(false);
        m_gradientLineDoubleClicked = false;
    }
    ContextPaneWidget *parentContextWidget = qobject_cast<ContextPaneWidget*>(parentWidget());
    QPoint p = mapToGlobal(ui->colorColorButton->pos());
    parentContextWidget->colorDialog()->setupColor(ui->colorColorButton->convertedColor());
    p = parentContextWidget->colorDialog()->parentWidget()->mapFromGlobal(p);
    parentContextWidget->onShowColorDialog(flag, p);
}

void ContextPaneWidgetRectangle::onColorDialogApplied(const QColor &)
{
    ContextPaneWidget *parentContextWidget = qobject_cast<ContextPaneWidget*>(parentWidget());
    parentContextWidget->onShowColorDialog(false, QPoint());
    if (ui->colorColorButton->isChecked())
        emit  propertyChanged(QLatin1String("color"),parentContextWidget->colorDialog()->color());; //write back color
    if (ui->borderColorButton->isChecked())
        emit  propertyChanged(QLatin1String("border.color"),parentContextWidget->colorDialog()->color());; //write back color
    if (m_gradientLineDoubleClicked)
        ui->gradientLine->setActiveColor(parentContextWidget->colorDialog()->color());
    ui->colorColorButton->setChecked(false);
    ui->borderColorButton->setChecked(false);
    m_gradientLineDoubleClicked = false;
}

void ContextPaneWidgetRectangle::onColorDialogCancled()
{
    ContextPaneWidget *parentContextWidget = qobject_cast<ContextPaneWidget*>(parentWidget());
    parentContextWidget->onShowColorDialog(false, QPoint());
    ui->colorColorButton->setChecked(false);
    ui->borderColorButton->setChecked(false);
    m_gradientLineDoubleClicked = false;
}

void ContextPaneWidgetRectangle::onGradientClicked()
{
    if (ui->colorGradient->isChecked()) {
        m_hasGradient = true;
        QLinearGradient gradient;
        QGradientStops stops;
        QColor color = ui->colorColorButton->convertedColor();
        stops.append(QGradientStop(0, ui->colorColorButton->convertedColor()));
        stops.append(QGradientStop(1, Qt::white));
        gradient.setStops(stops);
        ui->gradientLine->setGradient(gradient);
    }
}

void ContextPaneWidgetRectangle::onColorNoneClicked()
{
    if (ui->colorNone->isChecked()) {
        emit removeAndChangeProperty("gradient", "color", "transparent", true);
    }
}

void ContextPaneWidgetRectangle::onColorSolidClicked()
{
    if (ui->colorSolid->isChecked()) {
        emit removeAndChangeProperty("gradient", "color", "\"black\"", true);
    }
}

void ContextPaneWidgetRectangle::onBorderNoneClicked()
{
    if (ui->borderNone->isChecked()) {
        emit removeProperty("border.color");
        emit removeProperty("border.width");//###
    }
}

void ContextPaneWidgetRectangle::onBorderSolidClicked()
{
    if (ui->borderSolid->isChecked()) {
        emit propertyChanged("border.color", "\"black\"");
    }
}

void ContextPaneWidgetRectangle::onGradientLineDoubleClicked(const QPoint &p)
{
    m_gradientLineDoubleClicked = true;
    ContextPaneWidget *parentContextWidget = qobject_cast<ContextPaneWidget*>(parentWidget());
    QPoint pos = mapToGlobal(p);
    parentContextWidget->colorDialog()->setupColor(ui->gradientLine->activeColor());
    pos = parentContextWidget->colorDialog()->parentWidget()->mapFromGlobal(pos);
    parentContextWidget->onShowColorDialog(true, pos);
}

void ContextPaneWidgetRectangle::onUpdateGradient()
{
    if (m_gradientTimer > 0)
        killTimer(m_gradientTimer);
    m_gradientTimer = startTimer(100);
}

void ContextPaneWidgetRectangle::timerEvent(QTimerEvent *event)
{
    if (event->timerId() == m_gradientTimer) {
        killTimer(m_gradientTimer);
        m_gradientTimer = -1;

        QLinearGradient gradient = ui->gradientLine->gradient();
        QString str = "Gradient {\n";
        foreach (const QGradientStop &stop, gradient.stops()) {
            str += QLatin1String("GradientStop {\n");
            str += QLatin1String("position: ") + QString::number(stop.first, 'f', 2) + QLatin1String(";\n");
            str += QLatin1String("color: ") + QLatin1String("\"") + stop.second.name() + QLatin1String("\";\n");
            str += QLatin1String("}\n");
        }
        str += QLatin1String("}");
        emit propertyChanged("gradient", str);
    }
}

void ContextPaneWidgetRectangle::changeEvent(QEvent *e)
{
    QWidget::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void ContextPaneWidgetRectangle::setColor()
{
    QLinearGradient gradient;
    QGradientStops stops;
    QColor color = ui->colorColorButton->convertedColor();
    stops.append(QGradientStop(0, color));
    stops.append(QGradientStop(1, color));
    gradient.setStops(stops);
    ui->gradientLine->setGradient(gradient);
}

} //QmlDesigner
<commit_msg>QtQuickToolBar: default for Rectangle color is white not black<commit_after>#include "contextpanewidgetrectangle.h"
#include "ui_contextpanewidgetrectangle.h"
#include "contextpanewidget.h"
#include <qmljs/qmljspropertyreader.h>
#include <QDebug>

namespace QmlDesigner {

ContextPaneWidgetRectangle::ContextPaneWidgetRectangle(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ContextPaneWidgetRectangle),
    m_gradientLineDoubleClicked(false),
    m_gradientTimer(-1)
{
    ui->setupUi(this);

    ui->colorColorButton->setShowArrow(false);
    ui->borderColorButton->setShowArrow(false);

    connect(ui->colorColorButton, SIGNAL(toggled(bool)), this, SLOT(onColorButtonToggled(bool)));
    connect(ui->borderColorButton, SIGNAL(toggled(bool)), this, SLOT(onBorderColorButtonToggled(bool)));

    connect(ui->colorSolid, SIGNAL(clicked()), this, SLOT(onColorSolidClicked()));
    connect(ui->borderSolid, SIGNAL(clicked()), this, SLOT(onBorderSolidClicked()));

    connect(ui->colorNone, SIGNAL(clicked()), this, SLOT(onColorNoneClicked()));
    connect(ui->borderNone, SIGNAL(clicked()), this, SLOT(onBorderNoneClicked()));

    connect(ui->colorGradient, SIGNAL(clicked()), this, SLOT(onGradientClicked()));

    ContextPaneWidget *parentContextWidget = qobject_cast<ContextPaneWidget*>(parentWidget());
    connect(parentContextWidget->colorDialog(), SIGNAL(accepted(QColor)), this, SLOT(onColorDialogApplied(QColor)));
    connect(parentContextWidget->colorDialog(), SIGNAL(rejected()), this, SLOT(onColorDialogCancled()));

    connect(ui->gradientLine, SIGNAL(openColorDialog(QPoint)), this, SLOT(onGradientLineDoubleClicked(QPoint)));
    connect(ui->gradientLine, SIGNAL(gradientChanged()), this, SLOT(onUpdateGradient()));
}

ContextPaneWidgetRectangle::~ContextPaneWidgetRectangle()
{
    delete ui;
}

void ContextPaneWidgetRectangle::setProperties(QmlJS::PropertyReader *propertyReader)
{
    m_hasGradient = propertyReader->hasProperty(QLatin1String("gradient"));
    m_none = false;
    m_hasBorder = false;

    if (propertyReader->hasProperty(QLatin1String("color"))) {
        QString str = propertyReader->readProperty("color").toString();
        if (QColor(str).alpha() == 0)
            m_none = true;
        ui->colorColorButton->setColor(str);

    } else {
        ui->colorColorButton->setColor(QLatin1String("white"));
    }

    if (propertyReader->hasProperty(QLatin1String("border.color"))) {
        ui->borderColorButton->setColor(propertyReader->readProperty("border.color").toString());
        m_hasBorder = true;
    } else {
        ui->borderColorButton->setColor(QLatin1String("transparent"));
    }

    if (propertyReader->hasProperty(QLatin1String("border.width")))
        m_hasBorder = true;

    ui->colorSolid->setChecked(true);
    ui->borderNone->setChecked(true);
    ui->borderSolid->setChecked(m_hasBorder);

    if (m_none)
        ui->colorNone->setChecked(true);

    ui->gradientLabel->setEnabled(true);
    ui->gradientLine->setEnabled(true);

    if (m_hasGradient) {
        bool isBound;
        ui->colorGradient->setChecked(true);
        ui->gradientLine->setGradient(propertyReader->parseGradient("gradient", &isBound));
        if (isBound) {
            ui->gradientLabel->setEnabled(false);
            ui->gradientLine->setEnabled(false);
            ui->colorColorButton->setColor("invalidColor");
        }
    } else {
        //ui->gradientLine->setEnabled(false);
        //ui->gradientLabel->setEnabled(false);
        setColor();
    }

    if (m_gradientTimer > 0) {
        killTimer(m_gradientTimer);
        m_gradientTimer = -1;
    }

}

void ContextPaneWidgetRectangle::onBorderColorButtonToggled(bool flag)
{
    if (flag) {
        ui->colorColorButton->setChecked(false);
        m_gradientLineDoubleClicked = false;
    }
    ContextPaneWidget *parentContextWidget = qobject_cast<ContextPaneWidget*>(parentWidget());
    QPoint p = mapToGlobal(ui->borderColorButton->pos());
    parentContextWidget->colorDialog()->setupColor(ui->borderColorButton->convertedColor());
    p = parentContextWidget->colorDialog()->parentWidget()->mapFromGlobal(p);
    parentContextWidget->onShowColorDialog(flag, p);
}

void ContextPaneWidgetRectangle::onColorButtonToggled(bool flag )
{
    if (flag) {
        ui->borderColorButton->setChecked(false);
        m_gradientLineDoubleClicked = false;
    }
    ContextPaneWidget *parentContextWidget = qobject_cast<ContextPaneWidget*>(parentWidget());
    QPoint p = mapToGlobal(ui->colorColorButton->pos());
    parentContextWidget->colorDialog()->setupColor(ui->colorColorButton->convertedColor());
    p = parentContextWidget->colorDialog()->parentWidget()->mapFromGlobal(p);
    parentContextWidget->onShowColorDialog(flag, p);
}

void ContextPaneWidgetRectangle::onColorDialogApplied(const QColor &)
{
    ContextPaneWidget *parentContextWidget = qobject_cast<ContextPaneWidget*>(parentWidget());
    parentContextWidget->onShowColorDialog(false, QPoint());
    if (ui->colorColorButton->isChecked())
        emit  propertyChanged(QLatin1String("color"),parentContextWidget->colorDialog()->color());; //write back color
    if (ui->borderColorButton->isChecked())
        emit  propertyChanged(QLatin1String("border.color"),parentContextWidget->colorDialog()->color());; //write back color
    if (m_gradientLineDoubleClicked)
        ui->gradientLine->setActiveColor(parentContextWidget->colorDialog()->color());
    ui->colorColorButton->setChecked(false);
    ui->borderColorButton->setChecked(false);
    m_gradientLineDoubleClicked = false;
}

void ContextPaneWidgetRectangle::onColorDialogCancled()
{
    ContextPaneWidget *parentContextWidget = qobject_cast<ContextPaneWidget*>(parentWidget());
    parentContextWidget->onShowColorDialog(false, QPoint());
    ui->colorColorButton->setChecked(false);
    ui->borderColorButton->setChecked(false);
    m_gradientLineDoubleClicked = false;
}

void ContextPaneWidgetRectangle::onGradientClicked()
{
    if (ui->colorGradient->isChecked()) {
        m_hasGradient = true;
        QLinearGradient gradient;
        QGradientStops stops;
        QColor color = ui->colorColorButton->convertedColor();
        stops.append(QGradientStop(0, ui->colorColorButton->convertedColor()));
        stops.append(QGradientStop(1, Qt::white));
        gradient.setStops(stops);
        ui->gradientLine->setGradient(gradient);
    }
}

void ContextPaneWidgetRectangle::onColorNoneClicked()
{
    if (ui->colorNone->isChecked()) {
        emit removeAndChangeProperty("gradient", "color", "transparent", true);
    }
}

void ContextPaneWidgetRectangle::onColorSolidClicked()
{
    if (ui->colorSolid->isChecked()) {
        emit removeAndChangeProperty("gradient", "color", "\"black\"", true);
    }
}

void ContextPaneWidgetRectangle::onBorderNoneClicked()
{
    if (ui->borderNone->isChecked()) {
        emit removeProperty("border.color");
        emit removeProperty("border.width");//###
    }
}

void ContextPaneWidgetRectangle::onBorderSolidClicked()
{
    if (ui->borderSolid->isChecked()) {
        emit propertyChanged("border.color", "\"black\"");
    }
}

void ContextPaneWidgetRectangle::onGradientLineDoubleClicked(const QPoint &p)
{
    m_gradientLineDoubleClicked = true;
    ContextPaneWidget *parentContextWidget = qobject_cast<ContextPaneWidget*>(parentWidget());
    QPoint pos = mapToGlobal(p);
    parentContextWidget->colorDialog()->setupColor(ui->gradientLine->activeColor());
    pos = parentContextWidget->colorDialog()->parentWidget()->mapFromGlobal(pos);
    parentContextWidget->onShowColorDialog(true, pos);
}

void ContextPaneWidgetRectangle::onUpdateGradient()
{
    if (m_gradientTimer > 0)
        killTimer(m_gradientTimer);
    m_gradientTimer = startTimer(100);
}

void ContextPaneWidgetRectangle::timerEvent(QTimerEvent *event)
{
    if (event->timerId() == m_gradientTimer) {
        killTimer(m_gradientTimer);
        m_gradientTimer = -1;

        QLinearGradient gradient = ui->gradientLine->gradient();
        QString str = "Gradient {\n";
        foreach (const QGradientStop &stop, gradient.stops()) {
            str += QLatin1String("GradientStop {\n");
            str += QLatin1String("position: ") + QString::number(stop.first, 'f', 2) + QLatin1String(";\n");
            str += QLatin1String("color: ") + QLatin1String("\"") + stop.second.name() + QLatin1String("\";\n");
            str += QLatin1String("}\n");
        }
        str += QLatin1String("}");
        emit propertyChanged("gradient", str);
    }
}

void ContextPaneWidgetRectangle::changeEvent(QEvent *e)
{
    QWidget::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void ContextPaneWidgetRectangle::setColor()
{
    QLinearGradient gradient;
    QGradientStops stops;
    QColor color = ui->colorColorButton->convertedColor();
    stops.append(QGradientStop(0, color));
    stops.append(QGradientStop(1, color));
    gradient.setStops(stops);
    ui->gradientLine->setGradient(gradient);
}

} //QmlDesigner
<|endoftext|>


<commit_before>/*
 * opencog/persist/sql/SQLPersistSCM.cc
 *
 * Copyright (c) 2008 by OpenCog Foundation
 * Copyright (c) 2008, 2009, 2013, 2015 Linas Vepstas <linasvepstas@gmail.com>
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifdef HAVE_GUILE

#include <opencog/atomspace/AtomSpace.h>
#include <opencog/atomspace/BackingStore.h>
#include <opencog/guile/SchemePrimitive.h>
#include <opencog/persist/sql/SQLBackingStore.h>

#include "ODBCAtomStorage.h"
#include "SQLPersistSCM.h"

using namespace opencog;

// =================================================================

SQLPersistSCM::SQLPersistSCM(AtomSpace *as)
{
    _as = as;
    _store = NULL;
    _backing = new SQLBackingStore();

    // XXX FIXME Huge hack alert.
    // As of 2013, no one uses this thing, except for NLP processing.
    // Since I'm too lazy to find an elegant solution right now, I'm
    // just going to hack this in.  Fix this someday.
    //
    // Anyway, what the below does is to ignore these certain types,
    // when they are to be fetched from the backing store.  This can
    // speed up document processing, since we know that word instances
    // and documents and sentences will not be stored in the database.
    // Thus, we don't even try to fetch these.

#define NLP_HACK 0
#if NLP_HACK
    _backing->_ignored_types.insert(VARIABLE_NODE);
    _backing->_ignored_types.insert(TYPE_NODE);
    _backing->_ignored_types.insert(TYPED_VARIABLE_LINK);
    _backing->_ignored_types.insert(BIND_LINK);

    _backing->_ignored_types.insert(DOCUMENT_NODE);
    _backing->_ignored_types.insert(SENTENCE_NODE);
    _backing->_ignored_types.insert(PARSE_NODE);
    _backing->_ignored_types.insert(PARSE_LINK);
    _backing->_ignored_types.insert(WORD_INSTANCE_NODE);
    _backing->_ignored_types.insert(WORD_INSTANCE_LINK);
#endif // NLP_HACK

    static bool is_init = false;
    if (is_init) return;
    is_init = true;
    scm_with_guile(init_in_guile, this);
}

void* SQLPersistSCM::init_in_guile(void* self)
{
    scm_c_define_module("opencog persist-sql", init_in_module, self);
    scm_c_use_module("opencog persist-sql");
    return NULL;
}

void SQLPersistSCM::init_in_module(void* data)
{
   SQLPersistSCM* self = (SQLPersistSCM*) data;
   self->init();
}

void SQLPersistSCM::init(void)
{
    define_scheme_primitive("sql-open", &SQLPersistSCM::do_open, this, "persist-sql");
    define_scheme_primitive("sql-close", &SQLPersistSCM::do_close, this, "persist-sql");
    define_scheme_primitive("sql-load", &SQLPersistSCM::do_load, this, "persist-sql");
    define_scheme_primitive("sql-store", &SQLPersistSCM::do_store, this, "persist-sql");
#ifdef STORAGE_DEBUG
    define_scheme_primitive("sql-stats", &SQLPersistSCM::do_stats, this, "persist-sql");
#endif
}

SQLPersistSCM::~SQLPersistSCM()
{
    delete _backing;
}

void SQLPersistSCM::do_open(const std::string& dbname,
                         const std::string& username,
                         const std::string& auth)
{
    _store = new ODBCAtomStorage(dbname, username, auth);
    if (!_store)
        throw RuntimeException(TRACE_INFO,
            "sql-open: Error: Unable to open the database");

    if (!_store->connected())
    {
        delete _store;
        _store = NULL;
        throw RuntimeException(TRACE_INFO,
            "sql-open: Error: Unable to connect to the database");
    }

    _backing->set_store(_store);
    AtomSpace *as = _as;
    if (NULL == as)
        as = SchemeSmob::ss_get_env_as("sql-open");
    _backing->registerWith(as);
}

void SQLPersistSCM::do_close(void)
{
    if (_store == NULL)
        throw RuntimeException(TRACE_INFO,
             "sql-close: Error: Database not open");

    AtomSpace *as = _as;
    if (NULL == as)
        as = SchemeSmob::ss_get_env_as("sql-close");
    _backing->unregisterWith(as);
    _backing->set_store(NULL);
    delete _store;
    _store = NULL;
}

void SQLPersistSCM::do_load(void)
{
    if (_store == NULL)
        throw RuntimeException(TRACE_INFO,
            "sql-load: Error: Database not open");

    AtomSpace *as = _as;
    if (NULL == as)
        as = SchemeSmob::ss_get_env_as("sql-load");
    // XXX TODO: this should probably be done in a separate thread.
    _store->loadAtomSpace(as);
}

void SQLPersistSCM::do_store(void)
{
    if (_store == NULL)
        throw RuntimeException(TRACE_INFO,
            "sql-store: Error: Database not open");

    AtomSpace *as = _as;
    if (NULL == as)
        as = SchemeSmob::ss_get_env_as("sql-store");
    // XXX TODO This should really be started in a new thread ...
    _store->storeAtomSpace(as);
}

#ifdef STORAGE_DEBUG
void SQLPersistSCM::do_stats(void)
{
    if (_store == NULL)
        printf("sql-stats: Database not open\n");

    if (NULL == _as)
        printf("sql-stats: AtomSpace not set\n");

    printf("sql-stats: tlbuf size=%lu\n", _store->_tlbuf.size());

    size_t extra = 0;
    HandleSeq all;
    AtomSpace* as = SchemeSmob::ss_get_env_as("sql-stats");
    as->get_all_atoms(all);
    for (const Handle& h: all)
    {
        UUID uuid = _store->_tlbuf.getUUID(h);
        if (TLB::INVALID_UUID != uuid)
        {
            extra++;
            printf("TLB holds extra atoms %lu UUID=%lu %s\n",
                    extra, uuid, h->toString().c_str());
        }
    }

    printf("sql-stats: Examined %lu atoms in atomspace\n", all.size());
}
#endif

void opencog_persist_sql_init(void)
{
    static SQLPersistSCM patty(NULL);
}
#endif // HAVE_GUILE
<commit_msg>Move summary repor to the end<commit_after>/*
 * opencog/persist/sql/SQLPersistSCM.cc
 *
 * Copyright (c) 2008 by OpenCog Foundation
 * Copyright (c) 2008, 2009, 2013, 2015 Linas Vepstas <linasvepstas@gmail.com>
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifdef HAVE_GUILE

#include <opencog/atomspace/AtomSpace.h>
#include <opencog/atomspace/BackingStore.h>
#include <opencog/guile/SchemePrimitive.h>
#include <opencog/persist/sql/SQLBackingStore.h>

#include "ODBCAtomStorage.h"
#include "SQLPersistSCM.h"

using namespace opencog;

// =================================================================

SQLPersistSCM::SQLPersistSCM(AtomSpace *as)
{
    _as = as;
    _store = NULL;
    _backing = new SQLBackingStore();

    // XXX FIXME Huge hack alert.
    // As of 2013, no one uses this thing, except for NLP processing.
    // Since I'm too lazy to find an elegant solution right now, I'm
    // just going to hack this in.  Fix this someday.
    //
    // Anyway, what the below does is to ignore these certain types,
    // when they are to be fetched from the backing store.  This can
    // speed up document processing, since we know that word instances
    // and documents and sentences will not be stored in the database.
    // Thus, we don't even try to fetch these.

#define NLP_HACK 0
#if NLP_HACK
    _backing->_ignored_types.insert(VARIABLE_NODE);
    _backing->_ignored_types.insert(TYPE_NODE);
    _backing->_ignored_types.insert(TYPED_VARIABLE_LINK);
    _backing->_ignored_types.insert(BIND_LINK);

    _backing->_ignored_types.insert(DOCUMENT_NODE);
    _backing->_ignored_types.insert(SENTENCE_NODE);
    _backing->_ignored_types.insert(PARSE_NODE);
    _backing->_ignored_types.insert(PARSE_LINK);
    _backing->_ignored_types.insert(WORD_INSTANCE_NODE);
    _backing->_ignored_types.insert(WORD_INSTANCE_LINK);
#endif // NLP_HACK

    static bool is_init = false;
    if (is_init) return;
    is_init = true;
    scm_with_guile(init_in_guile, this);
}

void* SQLPersistSCM::init_in_guile(void* self)
{
    scm_c_define_module("opencog persist-sql", init_in_module, self);
    scm_c_use_module("opencog persist-sql");
    return NULL;
}

void SQLPersistSCM::init_in_module(void* data)
{
   SQLPersistSCM* self = (SQLPersistSCM*) data;
   self->init();
}

void SQLPersistSCM::init(void)
{
    define_scheme_primitive("sql-open", &SQLPersistSCM::do_open, this, "persist-sql");
    define_scheme_primitive("sql-close", &SQLPersistSCM::do_close, this, "persist-sql");
    define_scheme_primitive("sql-load", &SQLPersistSCM::do_load, this, "persist-sql");
    define_scheme_primitive("sql-store", &SQLPersistSCM::do_store, this, "persist-sql");
#ifdef STORAGE_DEBUG
    define_scheme_primitive("sql-stats", &SQLPersistSCM::do_stats, this, "persist-sql");
#endif
}

SQLPersistSCM::~SQLPersistSCM()
{
    delete _backing;
}

void SQLPersistSCM::do_open(const std::string& dbname,
                         const std::string& username,
                         const std::string& auth)
{
    _store = new ODBCAtomStorage(dbname, username, auth);
    if (!_store)
        throw RuntimeException(TRACE_INFO,
            "sql-open: Error: Unable to open the database");

    if (!_store->connected())
    {
        delete _store;
        _store = NULL;
        throw RuntimeException(TRACE_INFO,
            "sql-open: Error: Unable to connect to the database");
    }

    _backing->set_store(_store);
    AtomSpace *as = _as;
    if (NULL == as)
        as = SchemeSmob::ss_get_env_as("sql-open");
    _backing->registerWith(as);
}

void SQLPersistSCM::do_close(void)
{
    if (_store == NULL)
        throw RuntimeException(TRACE_INFO,
             "sql-close: Error: Database not open");

    AtomSpace *as = _as;
    if (NULL == as)
        as = SchemeSmob::ss_get_env_as("sql-close");
    _backing->unregisterWith(as);
    _backing->set_store(NULL);
    delete _store;
    _store = NULL;
}

void SQLPersistSCM::do_load(void)
{
    if (_store == NULL)
        throw RuntimeException(TRACE_INFO,
            "sql-load: Error: Database not open");

    AtomSpace *as = _as;
    if (NULL == as)
        as = SchemeSmob::ss_get_env_as("sql-load");
    // XXX TODO: this should probably be done in a separate thread.
    _store->loadAtomSpace(as);
}

void SQLPersistSCM::do_store(void)
{
    if (_store == NULL)
        throw RuntimeException(TRACE_INFO,
            "sql-store: Error: Database not open");

    AtomSpace *as = _as;
    if (NULL == as)
        as = SchemeSmob::ss_get_env_as("sql-store");
    // XXX TODO This should really be started in a new thread ...
    _store->storeAtomSpace(as);
}

#ifdef STORAGE_DEBUG
void SQLPersistSCM::do_stats(void)
{
    if (_store == NULL)
        printf("sql-stats: Database not open\n");

    if (NULL == _as)
        printf("sql-stats: AtomSpace not set\n");

    size_t extra = 0;
    HandleSeq all;
    AtomSpace* as = SchemeSmob::ss_get_env_as("sql-stats");
    as->get_all_atoms(all);
    for (const Handle& h: all)
    {
        UUID uuid = _store->_tlbuf.getUUID(h);
        if (TLB::INVALID_UUID != uuid)
        {
            extra++;
            printf("TLB holds extra atoms %lu UUID=%lu %s\n",
                    extra, uuid, h->toString().c_str());
        }
    }

    printf("sql-stats: Examined %lu atoms in atomspace\n", all.size());
    printf("sql-stats: tlbuf size=%lu\n", _store->_tlbuf.size());
}
#endif

void opencog_persist_sql_init(void)
{
    static SQLPersistSCM patty(NULL);
}
#endif // HAVE_GUILE
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// values_runtime.cpp
//
// Identification: src/codegen/values_runtime.cpp
//
// Copyright (c) 2015-2017, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "codegen/values_runtime.h"

#include "type/type_util.h"
#include "type/value_factory.h"
#include "type/value_peeker.h"

namespace peloton {
namespace codegen {

void ValuesRuntime::OutputBoolean(char *values, uint32_t idx, bool val,
                                  bool is_null) {
  type::Value *vals = reinterpret_cast<type::Value *>(values);
  if (is_null) {
    vals[idx] = type::ValueFactory::GetNullValueByType(type::BOOLEAN);
  } else {
    vals[idx] = type::ValueFactory::GetBooleanValue(val);
  }
}

void ValuesRuntime::OutputTinyInt(char *values, uint32_t idx, int8_t val) {
  type::Value *vals = reinterpret_cast<type::Value *>(values);
  vals[idx] = type::ValueFactory::GetTinyIntValue(val);
}

void ValuesRuntime::OutputSmallInt(char *values, uint32_t idx, int16_t val) {
  type::Value *vals = reinterpret_cast<type::Value *>(values);
  vals[idx] = type::ValueFactory::GetSmallIntValue(val);
}

void ValuesRuntime::OutputInteger(char *values, uint32_t idx, int32_t val) {
  type::Value *vals = reinterpret_cast<type::Value *>(values);
  vals[idx] = type::ValueFactory::GetIntegerValue(val);
}

void ValuesRuntime::OutputBigInt(char *values, uint32_t idx, int64_t val) {
  type::Value *vals = reinterpret_cast<type::Value *>(values);
  vals[idx] = type::ValueFactory::GetBigIntValue(val);
}

void ValuesRuntime::OutputDate(char *values, uint32_t idx, int32_t val) {
  type::Value *vals = reinterpret_cast<type::Value *>(values);
  vals[idx] = type::ValueFactory::GetDateValue(val);
}

void ValuesRuntime::OutputTimestamp(char *values, uint32_t idx, int64_t val) {
  type::Value *vals = reinterpret_cast<type::Value *>(values);
  vals[idx] = type::ValueFactory::GetTimestampValue(val);
}

void ValuesRuntime::OutputDecimal(char *values, uint32_t idx, double val) {
  type::Value *vals = reinterpret_cast<type::Value *>(values);
  vals[idx] = type::ValueFactory::GetDecimalValue(val);
}

void ValuesRuntime::OutputVarchar(char *values, uint32_t idx, char *str,
                                  UNUSED_ATTRIBUTE uint32_t len) {
  type::Value *vals = reinterpret_cast<type::Value *>(values);
  // There are two types of VARCHAR: one is from storage and the other is from
  // the query, e.g. CASE. In the latter case, the variable 'len' does not
  // include a null terminator at the end of the array, while it does in the
  // former. This function is used for both of them, so computes based on 'str'.
  vals[idx] = type::ValueFactory::GetVarcharValue(str, false);
}

void ValuesRuntime::OutputVarbinary(char *values, uint32_t idx, char *ptr,
                                    uint32_t len) {
  type::Value *vals = reinterpret_cast<type::Value *>(values);
  const auto *bin_ptr = reinterpret_cast<unsigned char *>(ptr);
  vals[idx] = type::ValueFactory::GetVarbinaryValue(bin_ptr, len, false);
}

int32_t ValuesRuntime::CompareStrings(const char *str1, uint32_t len1,
                                      const char *str2, uint32_t len2) {
  return type::TypeUtil::CompareStrings(str1, len1, str2, len2);
}

}  // namespace codegen
}  // namespace peloton
<commit_msg>Adding some fixes<commit_after>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// values_runtime.cpp
//
// Identification: src/codegen/values_runtime.cpp
//
// Copyright (c) 2015-2017, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "codegen/values_runtime.h"

#include "type/type_util.h"
#include "type/value_factory.h"
#include "type/value_peeker.h"

namespace peloton {
namespace codegen {

void ValuesRuntime::OutputBoolean(char *values, uint32_t idx, bool val,
                                  bool is_null) {
  type::Value *vals = reinterpret_cast<type::Value *>(values);
  if (is_null) {
    vals[idx] = type::ValueFactory::GetNullValueByType(type::TypeId::BOOLEAN);
  } else {
    vals[idx] = type::ValueFactory::GetBooleanValue(val);
  }
}

void ValuesRuntime::OutputTinyInt(char *values, uint32_t idx, int8_t val) {
  type::Value *vals = reinterpret_cast<type::Value *>(values);
  vals[idx] = type::ValueFactory::GetTinyIntValue(val);
}

void ValuesRuntime::OutputSmallInt(char *values, uint32_t idx, int16_t val) {
  type::Value *vals = reinterpret_cast<type::Value *>(values);
  vals[idx] = type::ValueFactory::GetSmallIntValue(val);
}

void ValuesRuntime::OutputInteger(char *values, uint32_t idx, int32_t val) {
  type::Value *vals = reinterpret_cast<type::Value *>(values);
  vals[idx] = type::ValueFactory::GetIntegerValue(val);
}

void ValuesRuntime::OutputBigInt(char *values, uint32_t idx, int64_t val) {
  type::Value *vals = reinterpret_cast<type::Value *>(values);
  vals[idx] = type::ValueFactory::GetBigIntValue(val);
}

void ValuesRuntime::OutputDate(char *values, uint32_t idx, int32_t val) {
  type::Value *vals = reinterpret_cast<type::Value *>(values);
  vals[idx] = type::ValueFactory::GetDateValue(val);
}

void ValuesRuntime::OutputTimestamp(char *values, uint32_t idx, int64_t val) {
  type::Value *vals = reinterpret_cast<type::Value *>(values);
  vals[idx] = type::ValueFactory::GetTimestampValue(val);
}

void ValuesRuntime::OutputDecimal(char *values, uint32_t idx, double val) {
  type::Value *vals = reinterpret_cast<type::Value *>(values);
  vals[idx] = type::ValueFactory::GetDecimalValue(val);
}

void ValuesRuntime::OutputVarchar(char *values, uint32_t idx, char *str,
                                  UNUSED_ATTRIBUTE uint32_t len) {
  type::Value *vals = reinterpret_cast<type::Value *>(values);
  // There are two types of VARCHAR: one is from storage and the other is from
  // the query, e.g. CASE. In the latter case, the variable 'len' does not
  // include a null terminator at the end of the array, while it does in the
  // former. This function is used for both of them, so computes based on 'str'.
  vals[idx] = type::ValueFactory::GetVarcharValue(str, false);
}

void ValuesRuntime::OutputVarbinary(char *values, uint32_t idx, char *ptr,
                                    uint32_t len) {
  type::Value *vals = reinterpret_cast<type::Value *>(values);
  const auto *bin_ptr = reinterpret_cast<unsigned char *>(ptr);
  vals[idx] = type::ValueFactory::GetVarbinaryValue(bin_ptr, len, false);
}

int32_t ValuesRuntime::CompareStrings(const char *str1, uint32_t len1,
                                      const char *str2, uint32_t len2) {
  return type::TypeUtil::CompareStrings(str1, len1, str2, len2);
}

}  // namespace codegen
}  // namespace peloton
<|endoftext|>


<commit_before>// Copyright (c) 2017 offa
// Copyright 2011 Ciaran McHale.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions.
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include "danek/internal/UidIdentifierProcessor.h"
#include "danek/internal/Util.h"
#include "danek/internal/Compat.h"
#include "danek/ConfigurationException.h"
#include "danek/StringVector.h"
#include <algorithm>
#include <sstream>
#include <iomanip>
#include <cctype>
#include <string.h>
#include <ctype.h>
#include <stdio.h>

namespace danek
{

    UidIdentifierProcessor::UidIdentifierProcessor() : m_count(0), m_uidToken("uid-")
    {
    }

    //----------------------------------------------------------------------
    // Spelling must be in one of the following forms:
    //      - "foo"                 -->  "foo"
    //      - "uid-<foo>"           -->  "uid-<digits>-<foo>"
    //      - "uid-<digits>-<foo>"  -->  "uid-<new-digits>-<foo>"
    // where "<foo>" does NOT start with a digit or "-"
    //----------------------------------------------------------------------

    std::string UidIdentifierProcessor::expand(const std::string& spelling)
    {
        // Common case optimizations
        if( spelling.find('.') == std::string::npos )
        {
            return expandOne(spelling);
        }

        if( spelling.find(m_uidToken) == std::string::npos )
        {
            return spelling;
        }

        // Let's break apart the scoped name, expand each local part
        // and then recombine the parts into an expanded scoped name.
        std::ostringstream result;
        const auto vec = util::splitScopes(spelling);

        for( std::size_t i=0; i<vec.size(); ++i )
        {
            result << expandOne(vec[i]);

            if (i < vec.size() - 1)
            {
                result << '.';
            }
        }

        return result.str();
    }

    std::string UidIdentifierProcessor::expandOne(const std::string& spelling)
    {
        if( startsWithUidToken(spelling) == false )
        {
            return spelling;
        }

        checkCondition(hasValidPrefix(spelling), spelling);

        const auto startPayload = std::next(spelling.cbegin(), m_uidToken.size());
        auto digitsEnd = std::find_if_not(startPayload, spelling.cend(), [](auto v) { return std::isdigit(v); });

        if( digitsEnd == startPayload )
        {
            return formatExpanded(std::string(digitsEnd, spelling.cend()));
        }

        checkCondition(hasValidPayload(digitsEnd, spelling.cend()), spelling);

        return formatExpanded(std::string(std::next(digitsEnd), spelling.cend()));
    }

    std::string UidIdentifierProcessor::unexpand(const char* spelling, StringBuffer& buf) const
    {
        //--------
        // Common case optimizations
        //--------
        if (strchr(spelling, '.') == nullptr)
        {
            const auto result = unexpandOne(spelling);
            buf = result;
            return result;
        }
        if (strstr(spelling, "uid-") == nullptr)
        {
            return spelling;
        }

        //--------
        // Let's break apart the scoped name, unexpand each local part
        // and then recombine the parts into an unexpanded scoped name.
        //--------
        StringBuffer result;
        StringBuffer msg;

        StringVector vec{util::splitScopes(spelling)};
        const int len = vec.size();
        for (int i = 0; i < len; ++i)
        {
            std::string str;
            try
            {
                str = unexpandOne(vec[i]);
                buf = str;
            }
            catch (const ConfigurationException&)
            {
                msg << "'" << spelling << "' is not a legal identifier";
                throw ConfigurationException(msg.str());
            }
            result.append(str);
            if (i < len - 1)
            {
                result.append(".");
            }
        }
        buf = result.str();
        return buf.str().c_str();
    }

    std::string UidIdentifierProcessor::unexpandOne(const std::string& spelling) const
    {
        if( startsWithUidToken(spelling) == false )
        {
            return spelling;
        }

        const auto startPayload = std::next(spelling.cbegin(), m_uidToken.size());
        auto digitsEnd = std::find_if_not(startPayload, spelling.cend(), [](auto v) { return std::isdigit(v); });

        if( digitsEnd == startPayload )
        {
            return spelling;
        }

        return formatUnexpanded(std::string(std::next(digitsEnd), spelling.cend()));
    }

    bool UidIdentifierProcessor::startsWithUidToken(const std::string& str) const
    {
        return std::equal(m_uidToken.cbegin(), m_uidToken.cend(), str.cbegin());
    }

    bool UidIdentifierProcessor::hasValidPrefix(const std::string& str) const
    {
        return ( str != m_uidToken ) && ( str.at(m_uidToken.size()) != '-' );
    }

    std::string UidIdentifierProcessor::formatExpanded(const std::string& suffix)
    {
        compat::checkAssertion(m_count < 1000 * 1000 * 1000);
        constexpr std::size_t numDigits = 9;

        std::ostringstream ss;
        ss << m_uidToken << std::setw(numDigits) << std::setfill('0') << (m_count++) << "-" << suffix;

        return ss.str();
    }

    std::string UidIdentifierProcessor::formatUnexpanded(const std::string& suffix) const
    {
        return m_uidToken + suffix;
    }

    void UidIdentifierProcessor::checkCondition(bool result, const std::string& input) const
    {
        if( result == false )
        {
            throw ConfigurationException{"'" + input + "' is not a legal identifier"};
        }
    }

}
<commit_msg>Refactoring.<commit_after>// Copyright (c) 2017 offa
// Copyright 2011 Ciaran McHale.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions.
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include "danek/internal/UidIdentifierProcessor.h"
#include "danek/internal/Util.h"
#include "danek/internal/Compat.h"
#include "danek/ConfigurationException.h"
#include "danek/StringVector.h"
#include <algorithm>
#include <sstream>
#include <iomanip>
#include <cctype>
#include <string.h>
#include <ctype.h>
#include <stdio.h>

namespace danek
{

    UidIdentifierProcessor::UidIdentifierProcessor() : m_count(0), m_uidToken("uid-")
    {
    }

    //----------------------------------------------------------------------
    // Spelling must be in one of the following forms:
    //      - "foo"                 -->  "foo"
    //      - "uid-<foo>"           -->  "uid-<digits>-<foo>"
    //      - "uid-<digits>-<foo>"  -->  "uid-<new-digits>-<foo>"
    // where "<foo>" does NOT start with a digit or "-"
    //----------------------------------------------------------------------

    std::string UidIdentifierProcessor::expand(const std::string& spelling)
    {
        // Common case optimizations
        if( spelling.find('.') == std::string::npos )
        {
            return expandOne(spelling);
        }

        if( spelling.find(m_uidToken) == std::string::npos )
        {
            return spelling;
        }

        // Let's break apart the scoped name, expand each local part
        // and then recombine the parts into an expanded scoped name.
        std::ostringstream result;
        const auto scopes = util::splitScopes(spelling);

        for( std::size_t i=0; i<scopes.size(); ++i )
        {
            result << expandOne(scopes[i]);

            if( i < scopes.size() - 1 )
            {
                result << '.';
            }
        }

        return result.str();
    }

    std::string UidIdentifierProcessor::expandOne(const std::string& spelling)
    {
        if( startsWithUidToken(spelling) == false )
        {
            return spelling;
        }

        checkCondition(hasValidPrefix(spelling), spelling);

        const auto startPayload = std::next(spelling.cbegin(), m_uidToken.size());
        auto digitsEnd = std::find_if_not(startPayload, spelling.cend(), [](auto v) { return std::isdigit(v); });

        if( digitsEnd == startPayload )
        {
            return formatExpanded(std::string(digitsEnd, spelling.cend()));
        }

        checkCondition(hasValidPayload(digitsEnd, spelling.cend()), spelling);

        return formatExpanded(std::string(std::next(digitsEnd), spelling.cend()));
    }

    std::string UidIdentifierProcessor::unexpand(const char* spelling, StringBuffer& buf) const
    {
        //--------
        // Common case optimizations
        //--------
        if (strchr(spelling, '.') == nullptr)
        {
            const auto result = unexpandOne(spelling);
            buf = result;
            return result;
        }
        if (strstr(spelling, "uid-") == nullptr)
        {
            return spelling;
        }

        //--------
        // Let's break apart the scoped name, unexpand each local part
        // and then recombine the parts into an unexpanded scoped name.
        //--------
        StringBuffer result;
        StringBuffer msg;

        StringVector vec{util::splitScopes(spelling)};
        const int len = vec.size();
        for (int i = 0; i < len; ++i)
        {
            std::string str;
            try
            {
                str = unexpandOne(vec[i]);
                buf = str;
            }
            catch (const ConfigurationException&)
            {
                msg << "'" << spelling << "' is not a legal identifier";
                throw ConfigurationException(msg.str());
            }
            result.append(str);
            if (i < len - 1)
            {
                result.append(".");
            }
        }
        buf = result.str();
        return buf.str().c_str();
    }

    std::string UidIdentifierProcessor::unexpandOne(const std::string& spelling) const
    {
        if( startsWithUidToken(spelling) == false )
        {
            return spelling;
        }

        const auto startPayload = std::next(spelling.cbegin(), m_uidToken.size());
        auto digitsEnd = std::find_if_not(startPayload, spelling.cend(), [](auto v) { return std::isdigit(v); });

        if( digitsEnd == startPayload )
        {
            return spelling;
        }

        return formatUnexpanded(std::string(std::next(digitsEnd), spelling.cend()));
    }

    bool UidIdentifierProcessor::startsWithUidToken(const std::string& str) const
    {
        return std::equal(m_uidToken.cbegin(), m_uidToken.cend(), str.cbegin());
    }

    bool UidIdentifierProcessor::hasValidPrefix(const std::string& str) const
    {
        return ( str != m_uidToken ) && ( str.at(m_uidToken.size()) != '-' );
    }

    std::string UidIdentifierProcessor::formatExpanded(const std::string& suffix)
    {
        compat::checkAssertion(m_count < 1000 * 1000 * 1000);
        constexpr std::size_t numDigits = 9;

        std::ostringstream ss;
        ss << m_uidToken << std::setw(numDigits) << std::setfill('0') << (m_count++) << "-" << suffix;

        return ss.str();
    }

    std::string UidIdentifierProcessor::formatUnexpanded(const std::string& suffix) const
    {
        return m_uidToken + suffix;
    }

    void UidIdentifierProcessor::checkCondition(bool result, const std::string& input) const
    {
        if( result == false )
        {
            throw ConfigurationException{"'" + input + "' is not a legal identifier"};
        }
    }

}
<|endoftext|>