<commit_before>//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
//
// ExceptionWithCallStack.cpp : Defines the CNTK exception and stack utilities
//

//#define _CRT_SECURE_NO_WARNINGS // "secure" CRT not available on all platforms  --add this at the top of all CPP files that give "function or variable may be unsafe" warnings
#ifdef _WIN32
#pragma comment(lib, "Dbghelp.lib")
#pragma warning(push)
#pragma warning(disable: 4091) // 'typedef ': ignored on left of '' when no variable is declared
#define NOMINMAX
#include <Windows.h>
#include "DbgHelp.h"
#pragma warning(pop)
#else
#include <execinfo.h>
#include <cxxabi.h>
#endif

#include "ExceptionWithCallStack.h"

#include <algorithm>
#include <iostream>
#include <functional>
#include <stdexcept>

namespace Microsoft { namespace MSR { namespace CNTK {

using namespace std;

static string MakeFunctionNameStandOut(string name);
static void CollectCallStack(size_t skipLevels, bool makeFunctionNamesStandOut, const function<void(string)>& write);

namespace DebugUtil
{
    /// This function retrieves the call stack as a string
    string GetCallStack(size_t skipLevels /*= 0*/, bool makeFunctionNamesStandOut /*= false*/)
    {
        try
        {
            string output;
            CollectCallStack(skipLevels + 1/*skip this function*/, makeFunctionNamesStandOut, [&output](string stack)
            {
                output += stack;
            });
            return output;
        }
        catch (...) // since we run as part of error reporting, don't get hung up on our own error
        {
            return string();
        }
    }

    /// This function outputs the call stack to the std err
    void PrintCallStack(size_t skipLevels /*= 0*/, bool makeFunctionNamesStandOut /*= false*/)
    {
        CollectCallStack(skipLevels + 1/*skip this function*/, makeFunctionNamesStandOut, [](string stack)
        {
            cerr << stack;
        });
    }
}

// make the unmangled name a bit more readable
// Insert spaces around the main function name for better visual parsability; and double-spaces between function arguments.
// This uses some heuristics for C++ names that may be fragile, but that's OK since this only adds/removes spaces.
static string MakeFunctionNameStandOut(string origName)
{
    try // guard against exception, since this is used for exception reporting
    {
        auto name = origName;
        // strip off modifiers for parsing (will be put back at the end)
        string modifiers;
        auto pos = name.find_last_not_of(" abcdefghijklmnopqrstuvwxyz");
        if (pos != string::npos)
        {
            modifiers = name.substr(pos + 1);
            name = name.substr(0, pos + 1);
        }
        bool hasArgList = !name.empty() && name.back() == ')';
        size_t angleDepth = 0;
        size_t parenDepth = 0;
        bool hitEnd = !hasArgList; // hit end of function name already?
        bool hitStart = false;
        // we parse the function name from the end; escape nested <> and ()
        // We look for the end and start of the function name itself (without namespace qualifiers),
        // and for commas separating function arguments.
        for (size_t i = name.size(); i--> 0;)
        {
            // account for nested <> and ()
            if (name[i] == '>')
                angleDepth++;
            else if (name[i] == '<')
                angleDepth--;
            else if (name[i] == ')')
                parenDepth++;
            else if (name[i] == '(')
                parenDepth--;
            // space before '>'
            if (name[i] == ' ' && i + 1 < name.size() && name[i + 1] == '>')
                name.erase(i, 1); // remove
            // commas
            if (name[i] == ',')
            {
                if (i + 1 < name.size() && name[i + 1] == ' ')
                    name.erase(i + 1, 1);  // remove spaces after comma
                if (!hitEnd && angleDepth == 0 && parenDepth == 1)
                    name.insert(i + 1, "  "); // except for top-level arguments, we separate them by 2 spaces for better readability
            }
            // function name
            if ((name[i] == '(' || name[i] == '<') &&
                parenDepth == 0 && angleDepth == 0 &&
                (i == 0 || name[i - 1] != '>') &&
                !hitEnd && !hitStart) // we hit the start of the argument list
            {
                hitEnd = true;
                name.insert(i, "  ");
            }
            else if ((name[i] == ' ' || name[i] == ':' || name[i] == '>') && hitEnd && !hitStart && i > 0) // we hit the start of the function name
            {
                if (name[i] != ' ')
                    name.insert(i + 1, " ");
                name.insert(i + 1, " "); // in total insert 2 spaces
                hitStart = true;
            }
        }
        return name + modifiers;
    }
    catch (...)
    {
        return origName;
    }
}

/// This function collects the stack tracke and writes it through the provided write function
/// <param name="write">Function for writing the text associated to a the callstack</param>
/// <param name="newline">Function for writing and "end-of-line" / "newline"</param>
///
static void CollectCallStack(size_t skipLevels, bool makeFunctionNamesStandOut, const function<void(string)>& write)
{
    static const int MAX_CALLERS = 62;
    static const unsigned short MAX_CALL_STACK_DEPTH = 20;

    write("\n[CALL STACK]\n");

#ifdef _WIN32

    // RtlCaptureStackBackTrace() is a kernel API without default binding, we must manually determine its function pointer.
    typedef USHORT(WINAPI * CaptureStackBackTraceType)(__in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG);
    CaptureStackBackTraceType RtlCaptureStackBackTrace = (CaptureStackBackTraceType)(GetProcAddress(LoadLibrary(L"kernel32.dll"), "RtlCaptureStackBackTrace"));
    if (RtlCaptureStackBackTrace == nullptr) // failed somehow
        return write("Failed to generate CALL STACK. GetProcAddress(\"RtlCaptureStackBackTrace\") failed\n");

    HANDLE process = GetCurrentProcess();
    if (!SymInitialize(process, nullptr, TRUE))
        return write("Failed to generate CALL STACK. SymInitialize() failed\n");

    // get the call stack
    void* callStack[MAX_CALLERS];
    unsigned short frames;
    frames = RtlCaptureStackBackTrace(0, MAX_CALLERS, callStack, nullptr);

    SYMBOL_INFO* symbolInfo = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); // this is a variable-length structure, can't use vector easily
    symbolInfo->MaxNameLen = 255;
    symbolInfo->SizeOfStruct = sizeof(SYMBOL_INFO);
    frames = min(frames, MAX_CALL_STACK_DEPTH);

    // format and emit
    size_t firstFrame = skipLevels + 1; // skip CollectCallStack()
    for (size_t i = firstFrame; i < frames; i++)
    {
        if (i == firstFrame)
            write("    > ");
        else
            write("    - ");

        if (SymFromAddr(process, (DWORD64)(callStack[i]), 0, symbolInfo))
        {
            write(makeFunctionNamesStandOut ? MakeFunctionNameStandOut(symbolInfo->Name) : symbolInfo->Name);
            write("\n");
        }
        else
        {
            char buf[17];
            sprintf_s(buf, "%p", callStack[i]);
            write(buf);
            write(" (SymFromAddr() error)\n");
        }
    }

    write("\n");

    free(symbolInfo);

    SymCleanup(process);

#else // Linux

    unsigned int MAX_NUM_FRAMES = 1024;
    void* backtraceAddresses[MAX_NUM_FRAMES];
    unsigned int numFrames = backtrace(backtraceAddresses, MAX_NUM_FRAMES);
    char** symbolList = backtrace_symbols(backtraceAddresses, numFrames);

    for (size_t i = skipLevels; i < numFrames; i++)
    {
        char* beginName    = NULL;
        char* beginOffset  = NULL;
        char* beginAddress = NULL;

        // Find parentheses and +address offset surrounding the mangled name
        for (char* p = symbolList[i]; *p; ++p)
        {
            if (*p == '(')      // function name begins here
                beginName = p;
            else if (*p == '+') // relative address ofset
                beginOffset = p;
            else if ((*p == ')') && (beginOffset || beginName)) // absolute address
                beginAddress = p;
        }
        const int buf_size = 1024;
        char buffer[buf_size];

        if (beginName && beginAddress && (beginName < beginAddress))
        {
            *beginName++ = '\0';
            *beginAddress++ = '\0';
            if (beginOffset) // has relative address
                *beginOffset++ = '\0';

            // Mangled name is now in [beginName, beginOffset) and caller offset in [beginOffset, beginAddress).
            int status = 0;
            unsigned int MAX_FUNCNAME_SIZE = 4096;
            size_t funcNameSize = MAX_FUNCNAME_SIZE;
            char funcName[MAX_FUNCNAME_SIZE]; // working buffer
            const char* ret = abi::__cxa_demangle(beginName, funcName, &funcNameSize, &status);
            string fName;
            if (status == 0)
                fName = makeFunctionNamesStandOut ? MakeFunctionNameStandOut(ret) : ret; // make it a bit more readable
            else
                fName = beginName; // failed: fall back

            // name of source file--not printing since it is not super-useful
            //string sourceFile = symbolList[i];
            //static const size_t sourceFileWidth = 20;
            //if (sourceFile.size() > sourceFileWidth)
            //    sourceFile = "..." + sourceFile.substr(sourceFile.size() - (sourceFileWidth-3));
            while (*beginAddress == ' ') // eat unnecessary space
                beginAddress++;
            string pcOffset = beginOffset ? string(" + ") + beginOffset : string();
            snprintf(buffer, buf_size, "%-20s%-50s%s\n", beginAddress, fName.c_str(), pcOffset.c_str());
        }
        else // Couldn't parse the line. Print the whole line as it came.
            snprintf(buffer, buf_size, "%s\n", symbolList[i]);

        write(buffer);
    }

    free(symbolList);

#endif
}

template class ExceptionWithCallStack<std::runtime_error>;
template class ExceptionWithCallStack<std::logic_error>;
template class ExceptionWithCallStack<std::invalid_argument>;

}}}
<commit_msg>another warning fixed<commit_after>//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
//
// ExceptionWithCallStack.cpp : Defines the CNTK exception and stack utilities
//

//#define _CRT_SECURE_NO_WARNINGS // "secure" CRT not available on all platforms  --add this at the top of all CPP files that give "function or variable may be unsafe" warnings
#ifdef _WIN32
#pragma comment(lib, "Dbghelp.lib")
#pragma warning(push)
#pragma warning(disable: 4091) // 'typedef ': ignored on left of '' when no variable is declared
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <Windows.h>
#include "DbgHelp.h"
#pragma warning(pop)
#else
#include <execinfo.h>
#include <cxxabi.h>
#endif

#include "ExceptionWithCallStack.h"

#include <algorithm>
#include <iostream>
#include <functional>
#include <stdexcept>

namespace Microsoft { namespace MSR { namespace CNTK {

using namespace std;

static string MakeFunctionNameStandOut(string name);
static void CollectCallStack(size_t skipLevels, bool makeFunctionNamesStandOut, const function<void(string)>& write);

namespace DebugUtil
{
    /// This function retrieves the call stack as a string
    string GetCallStack(size_t skipLevels /*= 0*/, bool makeFunctionNamesStandOut /*= false*/)
    {
        try
        {
            string output;
            CollectCallStack(skipLevels + 1/*skip this function*/, makeFunctionNamesStandOut, [&output](string stack)
            {
                output += stack;
            });
            return output;
        }
        catch (...) // since we run as part of error reporting, don't get hung up on our own error
        {
            return string();
        }
    }

    /// This function outputs the call stack to the std err
    void PrintCallStack(size_t skipLevels /*= 0*/, bool makeFunctionNamesStandOut /*= false*/)
    {
        CollectCallStack(skipLevels + 1/*skip this function*/, makeFunctionNamesStandOut, [](string stack)
        {
            cerr << stack;
        });
    }
}

// make the unmangled name a bit more readable
// Insert spaces around the main function name for better visual parsability; and double-spaces between function arguments.
// This uses some heuristics for C++ names that may be fragile, but that's OK since this only adds/removes spaces.
static string MakeFunctionNameStandOut(string origName)
{
    try // guard against exception, since this is used for exception reporting
    {
        auto name = origName;
        // strip off modifiers for parsing (will be put back at the end)
        string modifiers;
        auto pos = name.find_last_not_of(" abcdefghijklmnopqrstuvwxyz");
        if (pos != string::npos)
        {
            modifiers = name.substr(pos + 1);
            name = name.substr(0, pos + 1);
        }
        bool hasArgList = !name.empty() && name.back() == ')';
        size_t angleDepth = 0;
        size_t parenDepth = 0;
        bool hitEnd = !hasArgList; // hit end of function name already?
        bool hitStart = false;
        // we parse the function name from the end; escape nested <> and ()
        // We look for the end and start of the function name itself (without namespace qualifiers),
        // and for commas separating function arguments.
        for (size_t i = name.size(); i--> 0;)
        {
            // account for nested <> and ()
            if (name[i] == '>')
                angleDepth++;
            else if (name[i] == '<')
                angleDepth--;
            else if (name[i] == ')')
                parenDepth++;
            else if (name[i] == '(')
                parenDepth--;
            // space before '>'
            if (name[i] == ' ' && i + 1 < name.size() && name[i + 1] == '>')
                name.erase(i, 1); // remove
            // commas
            if (name[i] == ',')
            {
                if (i + 1 < name.size() && name[i + 1] == ' ')
                    name.erase(i + 1, 1);  // remove spaces after comma
                if (!hitEnd && angleDepth == 0 && parenDepth == 1)
                    name.insert(i + 1, "  "); // except for top-level arguments, we separate them by 2 spaces for better readability
            }
            // function name
            if ((name[i] == '(' || name[i] == '<') &&
                parenDepth == 0 && angleDepth == 0 &&
                (i == 0 || name[i - 1] != '>') &&
                !hitEnd && !hitStart) // we hit the start of the argument list
            {
                hitEnd = true;
                name.insert(i, "  ");
            }
            else if ((name[i] == ' ' || name[i] == ':' || name[i] == '>') && hitEnd && !hitStart && i > 0) // we hit the start of the function name
            {
                if (name[i] != ' ')
                    name.insert(i + 1, " ");
                name.insert(i + 1, " "); // in total insert 2 spaces
                hitStart = true;
            }
        }
        return name + modifiers;
    }
    catch (...)
    {
        return origName;
    }
}

/// This function collects the stack tracke and writes it through the provided write function
/// <param name="write">Function for writing the text associated to a the callstack</param>
/// <param name="newline">Function for writing and "end-of-line" / "newline"</param>
///
static void CollectCallStack(size_t skipLevels, bool makeFunctionNamesStandOut, const function<void(string)>& write)
{
    static const int MAX_CALLERS = 62;
    static const unsigned short MAX_CALL_STACK_DEPTH = 20;

    write("\n[CALL STACK]\n");

#ifdef _WIN32

    // RtlCaptureStackBackTrace() is a kernel API without default binding, we must manually determine its function pointer.
    typedef USHORT(WINAPI * CaptureStackBackTraceType)(__in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG);
    CaptureStackBackTraceType RtlCaptureStackBackTrace = (CaptureStackBackTraceType)(GetProcAddress(LoadLibrary(L"kernel32.dll"), "RtlCaptureStackBackTrace"));
    if (RtlCaptureStackBackTrace == nullptr) // failed somehow
        return write("Failed to generate CALL STACK. GetProcAddress(\"RtlCaptureStackBackTrace\") failed\n");

    HANDLE process = GetCurrentProcess();
    if (!SymInitialize(process, nullptr, TRUE))
        return write("Failed to generate CALL STACK. SymInitialize() failed\n");

    // get the call stack
    void* callStack[MAX_CALLERS];
    unsigned short frames;
    frames = RtlCaptureStackBackTrace(0, MAX_CALLERS, callStack, nullptr);

    SYMBOL_INFO* symbolInfo = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); // this is a variable-length structure, can't use vector easily
    symbolInfo->MaxNameLen = 255;
    symbolInfo->SizeOfStruct = sizeof(SYMBOL_INFO);
    frames = min(frames, MAX_CALL_STACK_DEPTH);

    // format and emit
    size_t firstFrame = skipLevels + 1; // skip CollectCallStack()
    for (size_t i = firstFrame; i < frames; i++)
    {
        if (i == firstFrame)
            write("    > ");
        else
            write("    - ");

        if (SymFromAddr(process, (DWORD64)(callStack[i]), 0, symbolInfo))
        {
            write(makeFunctionNamesStandOut ? MakeFunctionNameStandOut(symbolInfo->Name) : symbolInfo->Name);
            write("\n");
        }
        else
        {
            char buf[17];
            sprintf_s(buf, "%p", callStack[i]);
            write(buf);
            write(" (SymFromAddr() error)\n");
        }
    }

    write("\n");

    free(symbolInfo);

    SymCleanup(process);

#else // Linux

    unsigned int MAX_NUM_FRAMES = 1024;
    void* backtraceAddresses[MAX_NUM_FRAMES];
    unsigned int numFrames = backtrace(backtraceAddresses, MAX_NUM_FRAMES);
    char** symbolList = backtrace_symbols(backtraceAddresses, numFrames);

    for (size_t i = skipLevels; i < numFrames; i++)
    {
        char* beginName    = NULL;
        char* beginOffset  = NULL;
        char* beginAddress = NULL;

        // Find parentheses and +address offset surrounding the mangled name
        for (char* p = symbolList[i]; *p; ++p)
        {
            if (*p == '(')      // function name begins here
                beginName = p;
            else if (*p == '+') // relative address ofset
                beginOffset = p;
            else if ((*p == ')') && (beginOffset || beginName)) // absolute address
                beginAddress = p;
        }
        const int buf_size = 1024;
        char buffer[buf_size];

        if (beginName && beginAddress && (beginName < beginAddress))
        {
            *beginName++ = '\0';
            *beginAddress++ = '\0';
            if (beginOffset) // has relative address
                *beginOffset++ = '\0';

            // Mangled name is now in [beginName, beginOffset) and caller offset in [beginOffset, beginAddress).
            int status = 0;
            unsigned int MAX_FUNCNAME_SIZE = 4096;
            size_t funcNameSize = MAX_FUNCNAME_SIZE;
            char funcName[MAX_FUNCNAME_SIZE]; // working buffer
            const char* ret = abi::__cxa_demangle(beginName, funcName, &funcNameSize, &status);
            string fName;
            if (status == 0)
                fName = makeFunctionNamesStandOut ? MakeFunctionNameStandOut(ret) : ret; // make it a bit more readable
            else
                fName = beginName; // failed: fall back

            // name of source file--not printing since it is not super-useful
            //string sourceFile = symbolList[i];
            //static const size_t sourceFileWidth = 20;
            //if (sourceFile.size() > sourceFileWidth)
            //    sourceFile = "..." + sourceFile.substr(sourceFile.size() - (sourceFileWidth-3));
            while (*beginAddress == ' ') // eat unnecessary space
                beginAddress++;
            string pcOffset = beginOffset ? string(" + ") + beginOffset : string();
            snprintf(buffer, buf_size, "%-20s%-50s%s\n", beginAddress, fName.c_str(), pcOffset.c_str());
        }
        else // Couldn't parse the line. Print the whole line as it came.
            snprintf(buffer, buf_size, "%s\n", symbolList[i]);

        write(buffer);
    }

    free(symbolList);

#endif
}

template class ExceptionWithCallStack<std::runtime_error>;
template class ExceptionWithCallStack<std::logic_error>;
template class ExceptionWithCallStack<std::invalid_argument>;

}}}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: notemark.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: obo $ $Date: 2004-06-04 12:02:31 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifdef PCH
#include "ui_pch.hxx"
#endif

#pragma hdrstop

// INCLUDE ---------------------------------------------------------------

#include <svx/svdoutl.hxx>
#include <svx/svdmodel.hxx>
#include <svx/svdobj.hxx>
#include <svx/xoutx.hxx>
#include <sfx2/printer.hxx>
#include <svtools/pathoptions.hxx>
#include <svtools/itempool.hxx>
#include <vcl/svapp.hxx>

#include "notemark.hxx"
#include "document.hxx"
#include "detfunc.hxx"

#define SC_NOTEMARK_TIME    800
#define SC_NOTEMARK_SHORT   70

// STATIC DATA -----------------------------------------------------------

// -----------------------------------------------------------------------

ScNoteMarker::ScNoteMarker( Window* pWin, Window* pRight, Window* pBottom, Window* pDiagonal,
                            ScDocument* pD, ScAddress aPos, const String& rUser,
                            const MapMode& rMap, BOOL bLeftEdge, BOOL bForce, BOOL bKeyboard ) :
    pWindow( pWin ),
    pRightWin( pRight ),
    pBottomWin( pBottom ),
    pDiagWin( pDiagonal ),
    pDoc( pD ),
    aDocPos( aPos ),
    aUserText( rUser ),
    aMapMode( rMap ),
    bLeft( bLeftEdge ),
    bByKeyboard( bKeyboard ),
    bVisible( FALSE ),
    pModel( NULL ),
    pObject( NULL )
{
    aTimer.SetTimeoutHdl( LINK( this, ScNoteMarker, TimeHdl ) );
    aTimer.SetTimeout( bForce ? SC_NOTEMARK_SHORT : SC_NOTEMARK_TIME );
    aTimer.Start();
}

ScNoteMarker::~ScNoteMarker()
{
    InvalidateWin();

    delete pModel;
}

IMPL_LINK( ScNoteMarker, TimeHdl, Timer*, pTimer )
{
    if (!bVisible)
    {
        SvtPathOptions aPathOpt;
        String aPath = aPathOpt.GetPalettePath();
        pModel = new SdrModel(aPath);
        pModel->SetScaleUnit(MAP_100TH_MM);
        SfxItemPool& rPool = pModel->GetItemPool();
        rPool.SetDefaultMetric(SFX_MAPUNIT_100TH_MM);
        rPool.FreezeIdRanges();

        Printer* pPrinter = pDoc->GetPrinter();
        if (pPrinter)
        {
            //  Am Outliner des Draw-Model ist auch der Drucker als RefDevice gesetzt,
            //  und es soll einheitlich aussehen.
            Outliner& rOutliner = pModel->GetDrawOutliner();
            rOutliner.SetRefDevice(pPrinter);
        }

        SdrPage* pPage = pModel->AllocPage(FALSE);

        Size aSizePixel = pWindow->GetOutputSizePixel();
        Rectangle aVisPixel( Point(0,0), aSizePixel );
        Rectangle aVisible = pWindow->PixelToLogic( aVisPixel, aMapMode );

        SCCOL nCol = aDocPos.Col();
        SCROW nRow = aDocPos.Row();
        SCTAB nTab = aDocPos.Tab();
        pObject = ScDetectiveFunc( pDoc,nTab ).
                    ShowCommentUser( nCol, nRow, aUserText, aVisible, bLeft, FALSE, pPage );

        if (pObject)
            aRect = pObject->GetCurrentBoundRect();

        // #39351# Page einfuegen damit das Model sie kennt und auch deleted
        pModel->InsertPage( pPage );

        bVisible = TRUE;
    }

    Draw();
    return 0;
}

void lcl_DrawWin( SdrObject* pObject, Window* pWindow, const MapMode& rMap )
{
    MapMode aOld = pWindow->GetMapMode();
    pWindow->SetMapMode( rMap );

    ULONG nOldDrawMode = pWindow->GetDrawMode();
    if ( Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
    {
        pWindow->SetDrawMode( nOldDrawMode | DRAWMODE_SETTINGSLINE | DRAWMODE_SETTINGSFILL |
                            DRAWMODE_SETTINGSTEXT | DRAWMODE_SETTINGSGRADIENT );
    }

    ExtOutputDevice* pXOut = new ExtOutputDevice( pWindow );
    pXOut->SetOutDev( pWindow );
    SdrPaintInfoRec aInfoRec;
    pObject->SingleObjectPainter( *pXOut, aInfoRec ); // #110094#-17
    delete pXOut;

    pWindow->SetDrawMode( nOldDrawMode );
    pWindow->SetMapMode( aOld );
}

MapMode lcl_MoveMapMode( const MapMode& rMap, const Size& rMove )
{
    MapMode aNew = rMap;
    Point aOrigin = aNew.GetOrigin();
    aOrigin.X() -= rMove.Width();
    aOrigin.Y() -= rMove.Height();
    aNew.SetOrigin(aOrigin);
    return aNew;
}

void ScNoteMarker::Draw()
{
    if ( pObject && bVisible )
    {
        lcl_DrawWin( pObject, pWindow, aMapMode );

        if ( pRightWin || pBottomWin )
        {
            Size aWinSize = pWindow->PixelToLogic( pWindow->GetOutputSizePixel(), aMapMode );
            if ( pRightWin )
                lcl_DrawWin( pObject, pRightWin,
                                lcl_MoveMapMode( aMapMode, Size( aWinSize.Width(), 0 ) ) );
            if ( pBottomWin )
                lcl_DrawWin( pObject, pBottomWin,
                                lcl_MoveMapMode( aMapMode, Size( 0, aWinSize.Height() ) ) );
            if ( pDiagWin )
                lcl_DrawWin( pObject, pDiagWin, lcl_MoveMapMode( aMapMode, aWinSize ) );
        }
    }
}

void ScNoteMarker::InvalidateWin()
{
    if (bVisible)
    {
        pWindow->Invalidate( pWindow->LogicToLogic(aRect, aMapMode, pWindow->GetMapMode()) );

        if ( pRightWin || pBottomWin )
        {
            Size aWinSize = pWindow->PixelToLogic( pWindow->GetOutputSizePixel(), aMapMode );
            if ( pRightWin )
                pRightWin->Invalidate( pRightWin->LogicToLogic(aRect,
                                        lcl_MoveMapMode( aMapMode, Size( aWinSize.Width(), 0 ) ),
                                        pRightWin->GetMapMode()) );
            if ( pBottomWin )
                pBottomWin->Invalidate( pBottomWin->LogicToLogic(aRect,
                                        lcl_MoveMapMode( aMapMode, Size( 0, aWinSize.Height() ) ),
                                        pBottomWin->GetMapMode()) );
            if ( pDiagWin )
                pDiagWin->Invalidate( pDiagWin->LogicToLogic(aRect,
                                        lcl_MoveMapMode( aMapMode, aWinSize ),
                                        pDiagWin->GetMapMode()) );
        }
    }
}

<commit_msg>INTEGRATION: CWS aw019 (1.6.156); FILE MERGED 2004/10/06 16:23:41 aw 1.6.156.1: #i34831#<commit_after>/*************************************************************************
 *
 *  $RCSfile: notemark.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: pjunck $ $Date: 2004-11-03 09:21:34 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifdef PCH
#include "ui_pch.hxx"
#endif

#pragma hdrstop

// INCLUDE ---------------------------------------------------------------

#include <svx/svdoutl.hxx>
#include <svx/svdmodel.hxx>
#include <svx/svdobj.hxx>
#include <svx/xoutx.hxx>
#include <sfx2/printer.hxx>
#include <svtools/pathoptions.hxx>
#include <svtools/itempool.hxx>
#include <vcl/svapp.hxx>

#include "notemark.hxx"
#include "document.hxx"
#include "detfunc.hxx"

#define SC_NOTEMARK_TIME    800
#define SC_NOTEMARK_SHORT   70

// STATIC DATA -----------------------------------------------------------

// -----------------------------------------------------------------------

ScNoteMarker::ScNoteMarker( Window* pWin, Window* pRight, Window* pBottom, Window* pDiagonal,
                            ScDocument* pD, ScAddress aPos, const String& rUser,
                            const MapMode& rMap, BOOL bLeftEdge, BOOL bForce, BOOL bKeyboard ) :
    pWindow( pWin ),
    pRightWin( pRight ),
    pBottomWin( pBottom ),
    pDiagWin( pDiagonal ),
    pDoc( pD ),
    aDocPos( aPos ),
    aUserText( rUser ),
    aMapMode( rMap ),
    bLeft( bLeftEdge ),
    bByKeyboard( bKeyboard ),
    bVisible( FALSE ),
    pModel( NULL ),
    pObject( NULL )
{
    aTimer.SetTimeoutHdl( LINK( this, ScNoteMarker, TimeHdl ) );
    aTimer.SetTimeout( bForce ? SC_NOTEMARK_SHORT : SC_NOTEMARK_TIME );
    aTimer.Start();
}

ScNoteMarker::~ScNoteMarker()
{
    InvalidateWin();

    delete pModel;
}

IMPL_LINK( ScNoteMarker, TimeHdl, Timer*, pTimer )
{
    if (!bVisible)
    {
        SvtPathOptions aPathOpt;
        String aPath = aPathOpt.GetPalettePath();
        pModel = new SdrModel(aPath);
        pModel->SetScaleUnit(MAP_100TH_MM);
        SfxItemPool& rPool = pModel->GetItemPool();
        rPool.SetDefaultMetric(SFX_MAPUNIT_100TH_MM);
        rPool.FreezeIdRanges();

        Printer* pPrinter = pDoc->GetPrinter();
        if (pPrinter)
        {
            //  Am Outliner des Draw-Model ist auch der Drucker als RefDevice gesetzt,
            //  und es soll einheitlich aussehen.
            Outliner& rOutliner = pModel->GetDrawOutliner();
            rOutliner.SetRefDevice(pPrinter);
        }

        SdrPage* pPage = pModel->AllocPage(FALSE);

        Size aSizePixel = pWindow->GetOutputSizePixel();
        Rectangle aVisPixel( Point(0,0), aSizePixel );
        Rectangle aVisible = pWindow->PixelToLogic( aVisPixel, aMapMode );

        SCCOL nCol = aDocPos.Col();
        SCROW nRow = aDocPos.Row();
        SCTAB nTab = aDocPos.Tab();
        pObject = ScDetectiveFunc( pDoc,nTab ).
                    ShowCommentUser( nCol, nRow, aUserText, aVisible, bLeft, FALSE, pPage );

        if (pObject)
            aRect = pObject->GetCurrentBoundRect();

        // #39351# Page einfuegen damit das Model sie kennt und auch deleted
        pModel->InsertPage( pPage );

        bVisible = TRUE;
    }

    Draw();
    return 0;
}

void lcl_DrawWin( SdrObject* pObject, Window* pWindow, const MapMode& rMap )
{
    MapMode aOld = pWindow->GetMapMode();
    pWindow->SetMapMode( rMap );

    ULONG nOldDrawMode = pWindow->GetDrawMode();
    if ( Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
    {
        pWindow->SetDrawMode( nOldDrawMode | DRAWMODE_SETTINGSLINE | DRAWMODE_SETTINGSFILL |
                            DRAWMODE_SETTINGSTEXT | DRAWMODE_SETTINGSGRADIENT );
    }

    XOutputDevice* pXOut = new XOutputDevice( pWindow );
    pXOut->SetOutDev( pWindow );
    SdrPaintInfoRec aInfoRec;
    pObject->SingleObjectPainter( *pXOut, aInfoRec ); // #110094#-17
    delete pXOut;

    pWindow->SetDrawMode( nOldDrawMode );
    pWindow->SetMapMode( aOld );
}

MapMode lcl_MoveMapMode( const MapMode& rMap, const Size& rMove )
{
    MapMode aNew = rMap;
    Point aOrigin = aNew.GetOrigin();
    aOrigin.X() -= rMove.Width();
    aOrigin.Y() -= rMove.Height();
    aNew.SetOrigin(aOrigin);
    return aNew;
}

void ScNoteMarker::Draw()
{
    if ( pObject && bVisible )
    {
        lcl_DrawWin( pObject, pWindow, aMapMode );

        if ( pRightWin || pBottomWin )
        {
            Size aWinSize = pWindow->PixelToLogic( pWindow->GetOutputSizePixel(), aMapMode );
            if ( pRightWin )
                lcl_DrawWin( pObject, pRightWin,
                                lcl_MoveMapMode( aMapMode, Size( aWinSize.Width(), 0 ) ) );
            if ( pBottomWin )
                lcl_DrawWin( pObject, pBottomWin,
                                lcl_MoveMapMode( aMapMode, Size( 0, aWinSize.Height() ) ) );
            if ( pDiagWin )
                lcl_DrawWin( pObject, pDiagWin, lcl_MoveMapMode( aMapMode, aWinSize ) );
        }
    }
}

void ScNoteMarker::InvalidateWin()
{
    if (bVisible)
    {
        pWindow->Invalidate( pWindow->LogicToLogic(aRect, aMapMode, pWindow->GetMapMode()) );

        if ( pRightWin || pBottomWin )
        {
            Size aWinSize = pWindow->PixelToLogic( pWindow->GetOutputSizePixel(), aMapMode );
            if ( pRightWin )
                pRightWin->Invalidate( pRightWin->LogicToLogic(aRect,
                                        lcl_MoveMapMode( aMapMode, Size( aWinSize.Width(), 0 ) ),
                                        pRightWin->GetMapMode()) );
            if ( pBottomWin )
                pBottomWin->Invalidate( pBottomWin->LogicToLogic(aRect,
                                        lcl_MoveMapMode( aMapMode, Size( 0, aWinSize.Height() ) ),
                                        pBottomWin->GetMapMode()) );
            if ( pDiagWin )
                pDiagWin->Invalidate( pDiagWin->LogicToLogic(aRect,
                                        lcl_MoveMapMode( aMapMode, aWinSize ),
                                        pDiagWin->GetMapMode()) );
        }
    }
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2013 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * 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 Affero 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, see <http://www.gnu.org/licenses/>.
 */
#ifndef LIBBITCOIN_SERIALIZER_IPP
#define LIBBITCOIN_SERIALIZER_IPP

#include <boost/asio/streambuf.hpp>
#include <bitcoin/bitcoin/utility/assert.hpp>
#include <bitcoin/bitcoin/utility/endian.hpp>

namespace libbitcoin {

template <typename Iterator>
serializer<Iterator>::serializer(const Iterator begin)
  : iter_(begin)
{
}

template <typename Iterator>
void serializer<Iterator>::write_byte(uint8_t value)
{
    *iter_ = value;
    ++iter_;
}
template <typename Iterator>
void serializer<Iterator>::write_2_bytes(uint16_t value)
{
    write_little_endian(value);
}
template <typename Iterator>
void serializer<Iterator>::write_4_bytes(uint32_t value)
{
    write_little_endian(value);
}
template <typename Iterator>
void serializer<Iterator>::write_8_bytes(uint64_t value)
{
    write_little_endian(value);
}

template <typename Iterator>
template <typename T>
void serializer<Iterator>::write_big_endian(T n)
{
    return write_data(to_big_endian(n));
}
template <typename Iterator>
template <typename T>
void serializer<Iterator>::write_little_endian(T n)
{
    return write_data(to_little_endian(n));
}

template <typename Iterator>
void serializer<Iterator>::write_variable_uint(uint64_t value)
{
    if (value < 0xfd)
    {
        write_byte((uint8_t)value);
    }
    else if (value <= 0xffff)
    {
        write_byte(0xfd);
        write_2_bytes((uint16_t)value);
    }
    else if (value <= 0xffffffff)
    {
        write_byte(0xfe);
        write_4_bytes((uint32_t)value);
    }
    else
    {
        write_byte(0xff);
        write_8_bytes(value);
    }
}

template <typename Iterator>
template <typename T>
void serializer<Iterator>::write_data(const T& data)
{
    iter_ = std::copy(data.begin(), data.end(), iter_);
}

template <typename Iterator>
void serializer<Iterator>::write_network_address(network_address_type addr)
{
    write_8_bytes(addr.services);
    write_data(addr.ip);
    write_big_endian<uint16_t>(addr.port);
}

template <typename Iterator>
void serializer<Iterator>::write_hash(const hash_digest& hash)
{
    write_data(hash);
}

template <typename Iterator>
void serializer<Iterator>::write_short_hash(const short_hash& hash)
{
    write_data(hash);
}

template <typename Iterator>
void serializer<Iterator>::write_fixed_string(
    const std::string& command, size_t string_size)
{
    BITCOIN_ASSERT(command.size() <= string_size);
    data_chunk raw_string(string_size, 0);
    std::copy(command.begin(), command.end(), raw_string.begin());
    write_data(raw_string);
}

template <typename Iterator>
void serializer<Iterator>::write_string(const std::string& str)
{
    write_variable_uint(str.size());
    write_data(str);
}

/**
 * Returns underlying iterator.
 */
template <typename Iterator>
Iterator serializer<Iterator>::iterator()
{
    return iter_;
}

/**
 * Useful if you want to serialize some data using another
 * routine and then continue with this serializer.
 */
template <typename Iterator>
void serializer<Iterator>::set_iterator(Iterator iter)
{
    iter_ = iter;
}

template <typename Iterator>
template <typename T>
void serializer<Iterator>::write_data_reverse(const T& data)
{
    iter_ = std::reverse_copy(data.begin(), data.end(), iter_);
}

template <typename Iterator>
serializer<Iterator> make_serializer(Iterator begin)
{
    return serializer<Iterator>(begin);
}

// Macro used so that compiler will optimise out function calls to
// check_distance() if SafeCheckLast is false.
#define SAFE_CHECK_DISTANCE(N) \
    if (SafeCheckLast) \
        check_distance(iter_, end_, N);

template <typename Iterator, bool SafeCheckLast>
deserializer<Iterator, SafeCheckLast>::deserializer(
    const Iterator begin, const Iterator end)
  : iter_(begin), end_(end)
{
}

template <typename Iterator, bool SafeCheckLast>
uint8_t deserializer<Iterator, SafeCheckLast>::read_byte()
{
    SAFE_CHECK_DISTANCE(1);
    return *(iter_++);
}
template <typename Iterator, bool SafeCheckLast>
uint16_t deserializer<Iterator, SafeCheckLast>::read_2_bytes()
{
    return read_little_endian<uint16_t>();
}
template <typename Iterator, bool SafeCheckLast>
uint32_t deserializer<Iterator, SafeCheckLast>::read_4_bytes()
{
    return read_little_endian<uint32_t>();
}
template <typename Iterator, bool SafeCheckLast>
uint64_t deserializer<Iterator, SafeCheckLast>::read_8_bytes()
{
    return read_little_endian<uint64_t>();
}

template <typename Iterator, bool SafeCheckLast>
template <typename T>
T deserializer<Iterator, SafeCheckLast>::read_big_endian()
{
    const auto begin = iter_;
    SAFE_CHECK_DISTANCE(sizeof(T));
    iter_ += sizeof(T);
    return from_big_endian_unsafe<T>(begin);
}
template <typename Iterator, bool SafeCheckLast>
template <typename T>
T deserializer<Iterator, SafeCheckLast>::read_little_endian()
{
    const auto begin = iter_;
    SAFE_CHECK_DISTANCE(sizeof(T));
    iter_ += sizeof(T);
    return from_little_endian_unsafe<T>(begin);
}

template <typename Iterator, bool SafeCheckLast>
uint64_t deserializer<Iterator, SafeCheckLast>::read_variable_uint()
{
    uint8_t length = read_byte();
    if (length < 0xfd)
        return length;
    else if (length == 0xfd)
        return read_2_bytes();
    else if (length == 0xfe)
        return read_4_bytes();
    // length should be 0xff
    return read_8_bytes();
}

// NOTE: n_bytes changed to uint32_t to prevent array overflow.
template <typename Iterator, bool SafeCheckLast>
data_chunk deserializer<
    Iterator, SafeCheckLast>::read_data(uint32_t n_bytes)
{
    SAFE_CHECK_DISTANCE(n_bytes);
    data_chunk raw_bytes(n_bytes);
    for (uint32_t i = 0; i < n_bytes; ++i)
        raw_bytes[i] = read_byte();
    return raw_bytes;
}

template <typename Iterator, bool SafeCheckLast>
network_address_type deserializer<
    Iterator, SafeCheckLast>::read_network_address()
{
    network_address_type addr;
    addr.services = read_8_bytes();
    // Read IP address
    addr.ip = read_bytes<16>();
    addr.port = read_big_endian<uint16_t>();
    return addr;
}

template <typename Iterator, bool SafeCheckLast>
hash_digest deserializer<Iterator, SafeCheckLast>::read_hash()
{
    return read_bytes<hash_size>();
}

template <typename Iterator, bool SafeCheckLast>
short_hash deserializer<Iterator, SafeCheckLast>::read_short_hash()
{
    return read_bytes<short_hash_size>();
}

template <typename Iterator, bool SafeCheckLast>
std::string deserializer<
    Iterator, SafeCheckLast>::read_fixed_string(size_t len)
{
    data_chunk string_bytes = read_data(len);
    std::string result(string_bytes.begin(), string_bytes.end());
    // Removes trailing 0s... Needed for string comparisons
    return result.c_str();
}

template <typename Iterator, bool SafeCheckLast>
std::string deserializer<Iterator, SafeCheckLast>::read_string()
{
    uint64_t string_size = read_variable_uint();
    // Warning: conversion from uint64_t to size_t, possible loss of data.
    return read_fixed_string((size_t)string_size);
}

template <typename Iterator, bool SafeCheckLast>
template<unsigned N>
byte_array<N> deserializer<Iterator, SafeCheckLast>::read_bytes()
{
    SAFE_CHECK_DISTANCE(N);
    byte_array<N> out;
    std::copy(iter_, iter_ + N, out.begin());
    iter_ += N;
    return out;
}

template <typename Iterator, bool SafeCheckLast>
template<unsigned N>
byte_array<N> deserializer<Iterator, SafeCheckLast>::read_bytes_reverse()
{
    SAFE_CHECK_DISTANCE(N);
    byte_array<N> out;
    std::reverse_copy(iter_, iter_ + N, out.begin());
    iter_ += N;
    return out;
}

/**
 * Returns underlying iterator.
 */
template <typename Iterator, bool SafeCheckLast>
Iterator deserializer<Iterator, SafeCheckLast>::iterator() const
{
    return iter_;
}

/**
 * Useful if you advance the iterator using other serialization
 * methods or objects.
 */
template <typename Iterator, bool SafeCheckLast>
void deserializer<Iterator, SafeCheckLast>::set_iterator(const Iterator iter)
{
    iter_ = iter;
}

// Try to advance iterator 'distance' increments forwards.
// Throw if we prematurely reach the end.
template <typename Iterator, bool SafeCheckLast>
void deserializer<Iterator, SafeCheckLast>::check_distance(
    Iterator it, const Iterator end, size_t distance)
{
    BITCOIN_ASSERT(SafeCheckLast);
    for (size_t i = 0; i < distance; ++i)
    {
        // Is this a valid byte?
        if (it == end)
            throw end_of_stream();
        // If so move to next value.
        ++it;
    }
}

#undef SAFE_CHECK_DISTANCE

template <typename Iterator>
deserializer<Iterator, true> make_deserializer(
    const Iterator begin, const Iterator end)
{
    return deserializer<Iterator, true>(begin, end);
}

template <typename Iterator>
deserializer<Iterator, false> make_deserializer_unsafe(
    const Iterator begin)
{
    // end argument isn't used so just reuse begin here.
    return deserializer<Iterator, false>(begin, begin);
}

} // libbitcoin

#endif

<commit_msg>Add missing include.<commit_after>/*
 * Copyright (c) 2011-2013 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * 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 Affero 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, see <http://www.gnu.org/licenses/>.
 */
#ifndef LIBBITCOIN_SERIALIZER_IPP
#define LIBBITCOIN_SERIALIZER_IPP

#include <algorithm>
#include <boost/asio/streambuf.hpp>
#include <bitcoin/bitcoin/utility/assert.hpp>
#include <bitcoin/bitcoin/utility/endian.hpp>

namespace libbitcoin {

template <typename Iterator>
serializer<Iterator>::serializer(const Iterator begin)
  : iter_(begin)
{
}

template <typename Iterator>
void serializer<Iterator>::write_byte(uint8_t value)
{
    *iter_ = value;
    ++iter_;
}
template <typename Iterator>
void serializer<Iterator>::write_2_bytes(uint16_t value)
{
    write_little_endian(value);
}
template <typename Iterator>
void serializer<Iterator>::write_4_bytes(uint32_t value)
{
    write_little_endian(value);
}
template <typename Iterator>
void serializer<Iterator>::write_8_bytes(uint64_t value)
{
    write_little_endian(value);
}

template <typename Iterator>
template <typename T>
void serializer<Iterator>::write_big_endian(T n)
{
    return write_data(to_big_endian(n));
}
template <typename Iterator>
template <typename T>
void serializer<Iterator>::write_little_endian(T n)
{
    return write_data(to_little_endian(n));
}

template <typename Iterator>
void serializer<Iterator>::write_variable_uint(uint64_t value)
{
    if (value < 0xfd)
    {
        write_byte((uint8_t)value);
    }
    else if (value <= 0xffff)
    {
        write_byte(0xfd);
        write_2_bytes((uint16_t)value);
    }
    else if (value <= 0xffffffff)
    {
        write_byte(0xfe);
        write_4_bytes((uint32_t)value);
    }
    else
    {
        write_byte(0xff);
        write_8_bytes(value);
    }
}

template <typename Iterator>
template <typename T>
void serializer<Iterator>::write_data(const T& data)
{
    iter_ = std::copy(data.begin(), data.end(), iter_);
}

template <typename Iterator>
void serializer<Iterator>::write_network_address(network_address_type addr)
{
    write_8_bytes(addr.services);
    write_data(addr.ip);
    write_big_endian<uint16_t>(addr.port);
}

template <typename Iterator>
void serializer<Iterator>::write_hash(const hash_digest& hash)
{
    write_data(hash);
}

template <typename Iterator>
void serializer<Iterator>::write_short_hash(const short_hash& hash)
{
    write_data(hash);
}

template <typename Iterator>
void serializer<Iterator>::write_fixed_string(
    const std::string& command, size_t string_size)
{
    BITCOIN_ASSERT(command.size() <= string_size);
    data_chunk raw_string(string_size, 0);
    std::copy(command.begin(), command.end(), raw_string.begin());
    write_data(raw_string);
}

template <typename Iterator>
void serializer<Iterator>::write_string(const std::string& str)
{
    write_variable_uint(str.size());
    write_data(str);
}

/**
 * Returns underlying iterator.
 */
template <typename Iterator>
Iterator serializer<Iterator>::iterator()
{
    return iter_;
}

/**
 * Useful if you want to serialize some data using another
 * routine and then continue with this serializer.
 */
template <typename Iterator>
void serializer<Iterator>::set_iterator(Iterator iter)
{
    iter_ = iter;
}

template <typename Iterator>
template <typename T>
void serializer<Iterator>::write_data_reverse(const T& data)
{
    iter_ = std::reverse_copy(data.begin(), data.end(), iter_);
}

template <typename Iterator>
serializer<Iterator> make_serializer(Iterator begin)
{
    return serializer<Iterator>(begin);
}

// Macro used so that compiler will optimise out function calls to
// check_distance() if SafeCheckLast is false.
#define SAFE_CHECK_DISTANCE(N) \
    if (SafeCheckLast) \
        check_distance(iter_, end_, N);

template <typename Iterator, bool SafeCheckLast>
deserializer<Iterator, SafeCheckLast>::deserializer(
    const Iterator begin, const Iterator end)
  : iter_(begin), end_(end)
{
}

template <typename Iterator, bool SafeCheckLast>
uint8_t deserializer<Iterator, SafeCheckLast>::read_byte()
{
    SAFE_CHECK_DISTANCE(1);
    return *(iter_++);
}
template <typename Iterator, bool SafeCheckLast>
uint16_t deserializer<Iterator, SafeCheckLast>::read_2_bytes()
{
    return read_little_endian<uint16_t>();
}
template <typename Iterator, bool SafeCheckLast>
uint32_t deserializer<Iterator, SafeCheckLast>::read_4_bytes()
{
    return read_little_endian<uint32_t>();
}
template <typename Iterator, bool SafeCheckLast>
uint64_t deserializer<Iterator, SafeCheckLast>::read_8_bytes()
{
    return read_little_endian<uint64_t>();
}

template <typename Iterator, bool SafeCheckLast>
template <typename T>
T deserializer<Iterator, SafeCheckLast>::read_big_endian()
{
    const auto begin = iter_;
    SAFE_CHECK_DISTANCE(sizeof(T));
    iter_ += sizeof(T);
    return from_big_endian_unsafe<T>(begin);
}
template <typename Iterator, bool SafeCheckLast>
template <typename T>
T deserializer<Iterator, SafeCheckLast>::read_little_endian()
{
    const auto begin = iter_;
    SAFE_CHECK_DISTANCE(sizeof(T));
    iter_ += sizeof(T);
    return from_little_endian_unsafe<T>(begin);
}

template <typename Iterator, bool SafeCheckLast>
uint64_t deserializer<Iterator, SafeCheckLast>::read_variable_uint()
{
    uint8_t length = read_byte();
    if (length < 0xfd)
        return length;
    else if (length == 0xfd)
        return read_2_bytes();
    else if (length == 0xfe)
        return read_4_bytes();
    // length should be 0xff
    return read_8_bytes();
}

// NOTE: n_bytes changed to uint32_t to prevent array overflow.
template <typename Iterator, bool SafeCheckLast>
data_chunk deserializer<
    Iterator, SafeCheckLast>::read_data(uint32_t n_bytes)
{
    SAFE_CHECK_DISTANCE(n_bytes);
    data_chunk raw_bytes(n_bytes);
    for (uint32_t i = 0; i < n_bytes; ++i)
        raw_bytes[i] = read_byte();
    return raw_bytes;
}

template <typename Iterator, bool SafeCheckLast>
network_address_type deserializer<
    Iterator, SafeCheckLast>::read_network_address()
{
    network_address_type addr;
    addr.services = read_8_bytes();
    // Read IP address
    addr.ip = read_bytes<16>();
    addr.port = read_big_endian<uint16_t>();
    return addr;
}

template <typename Iterator, bool SafeCheckLast>
hash_digest deserializer<Iterator, SafeCheckLast>::read_hash()
{
    return read_bytes<hash_size>();
}

template <typename Iterator, bool SafeCheckLast>
short_hash deserializer<Iterator, SafeCheckLast>::read_short_hash()
{
    return read_bytes<short_hash_size>();
}

template <typename Iterator, bool SafeCheckLast>
std::string deserializer<
    Iterator, SafeCheckLast>::read_fixed_string(size_t len)
{
    data_chunk string_bytes = read_data(len);
    std::string result(string_bytes.begin(), string_bytes.end());
    // Removes trailing 0s... Needed for string comparisons
    return result.c_str();
}

template <typename Iterator, bool SafeCheckLast>
std::string deserializer<Iterator, SafeCheckLast>::read_string()
{
    uint64_t string_size = read_variable_uint();
    // Warning: conversion from uint64_t to size_t, possible loss of data.
    return read_fixed_string((size_t)string_size);
}

template <typename Iterator, bool SafeCheckLast>
template<unsigned N>
byte_array<N> deserializer<Iterator, SafeCheckLast>::read_bytes()
{
    SAFE_CHECK_DISTANCE(N);
    byte_array<N> out;
    std::copy(iter_, iter_ + N, out.begin());
    iter_ += N;
    return out;
}

template <typename Iterator, bool SafeCheckLast>
template<unsigned N>
byte_array<N> deserializer<Iterator, SafeCheckLast>::read_bytes_reverse()
{
    SAFE_CHECK_DISTANCE(N);
    byte_array<N> out;
    std::reverse_copy(iter_, iter_ + N, out.begin());
    iter_ += N;
    return out;
}

/**
 * Returns underlying iterator.
 */
template <typename Iterator, bool SafeCheckLast>
Iterator deserializer<Iterator, SafeCheckLast>::iterator() const
{
    return iter_;
}

/**
 * Useful if you advance the iterator using other serialization
 * methods or objects.
 */
template <typename Iterator, bool SafeCheckLast>
void deserializer<Iterator, SafeCheckLast>::set_iterator(const Iterator iter)
{
    iter_ = iter;
}

// Try to advance iterator 'distance' increments forwards.
// Throw if we prematurely reach the end.
template <typename Iterator, bool SafeCheckLast>
void deserializer<Iterator, SafeCheckLast>::check_distance(
    Iterator it, const Iterator end, size_t distance)
{
    BITCOIN_ASSERT(SafeCheckLast);
    for (size_t i = 0; i < distance; ++i)
    {
        // Is this a valid byte?
        if (it == end)
            throw end_of_stream();
        // If so move to next value.
        ++it;
    }
}

#undef SAFE_CHECK_DISTANCE

template <typename Iterator>
deserializer<Iterator, true> make_deserializer(
    const Iterator begin, const Iterator end)
{
    return deserializer<Iterator, true>(begin, end);
}

template <typename Iterator>
deserializer<Iterator, false> make_deserializer_unsafe(
    const Iterator begin)
{
    // end argument isn't used so just reuse begin here.
    return deserializer<Iterator, false>(begin, begin);
}

} // libbitcoin

#endif

<|endoftext|>


<commit_before>/**
* @file lldonotdisturbnotificationstorage.cpp
* @brief Implementation of lldonotdisturbnotificationstorage
* @author Stinson@lindenlab.com
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
* $/LicenseInfo$
*/

#include "llviewerprecompiledheaders.h"

#include "lldonotdisturbnotificationstorage.h"

#include "llcommunicationchannel.h"
#include "lldir.h"
#include "llerror.h"
#include "llfloaterreg.h"
#include "llimview.h"
#include "llnotifications.h"
#include "llnotificationhandler.h"
#include "llnotificationstorage.h"
#include "llscriptfloater.h"
#include "llsd.h"
#include "llsingleton.h"
#include "lluuid.h"

static const F32 DND_TIMER = 3.0;
const char * LLDoNotDisturbNotificationStorage::toastName = "IMToast";
const char * LLDoNotDisturbNotificationStorage::offerName = "UserGiveItem";

LLDoNotDisturbNotificationStorageTimer::LLDoNotDisturbNotificationStorageTimer() : LLEventTimer(DND_TIMER)
{

}

LLDoNotDisturbNotificationStorageTimer::~LLDoNotDisturbNotificationStorageTimer()
{

}

BOOL LLDoNotDisturbNotificationStorageTimer::tick()
{
    LLDoNotDisturbNotificationStorage * doNotDisturbNotificationStorage =  LLDoNotDisturbNotificationStorage::getInstance();

    if(doNotDisturbNotificationStorage
        && doNotDisturbNotificationStorage->getDirty())
    {
        doNotDisturbNotificationStorage->saveNotifications();
    }
    return FALSE;
}

LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage()
	: LLSingleton<LLDoNotDisturbNotificationStorage>()
	, LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "dnd_notifications.xml"))
    , mDirty(false)
{
    nameToPayloadParameterMap[toastName] = "SESSION_ID";
    nameToPayloadParameterMap[offerName] = "object_id";
}

LLDoNotDisturbNotificationStorage::~LLDoNotDisturbNotificationStorage()
{
}

void LLDoNotDisturbNotificationStorage::initialize()
{
	getCommunicationChannel()->connectFailedFilter(boost::bind(&LLDoNotDisturbNotificationStorage::onChannelChanged, this, _1));
}

bool LLDoNotDisturbNotificationStorage::getDirty()
{
    return mDirty;
}

void LLDoNotDisturbNotificationStorage::resetDirty()
{
    mDirty = false;
}

static LLFastTimer::DeclareTimer FTM_SAVE_DND_NOTIFICATIONS("Save DND Notifications");

void LLDoNotDisturbNotificationStorage::saveNotifications()
{
	LLFastTimer _(FTM_SAVE_DND_NOTIFICATIONS);

	LLNotificationChannelPtr channelPtr = getCommunicationChannel();
	const LLCommunicationChannel *commChannel = dynamic_cast<LLCommunicationChannel*>(channelPtr.get());
	llassert(commChannel != NULL);

	LLSD output = LLSD::emptyMap();
	LLSD& data = output["data"];
	data = LLSD::emptyArray();

	for (LLCommunicationChannel::history_list_t::const_iterator historyIter = commChannel->beginHistory();
		historyIter != commChannel->endHistory(); ++historyIter)
	{
		LLNotificationPtr notificationPtr = historyIter->second;

		if (!notificationPtr->isRespondedTo() && !notificationPtr->isCancelled() && !notificationPtr->isExpired())
		{
			data.append(notificationPtr->asLLSD(true));
		}
	}

	writeNotifications(output);

    resetDirty();
}

static LLFastTimer::DeclareTimer FTM_LOAD_DND_NOTIFICATIONS("Load DND Notifications");

void LLDoNotDisturbNotificationStorage::loadNotifications()
{
	LLFastTimer _(FTM_LOAD_DND_NOTIFICATIONS);

	LL_INFOS("LLDoNotDisturbNotificationStorage") << "start loading notifications" << LL_ENDL;

	LLSD input;
	if (!readNotifications(input) ||input.isUndefined())
	{
		return;
	}

	LLSD& data = input["data"];
	if (data.isUndefined())
	{
		return;
	}

	LLNotifications& instance = LLNotifications::instance();
    bool imToastExists = false;
	bool group_ad_hoc_toast_exists = false;
	S32 toastSessionType;
    bool offerExists = false;

	for (LLSD::array_const_iterator notification_it = data.beginArray();
		 notification_it != data.endArray();
		 ++notification_it)
	{
		LLSD notification_params = *notification_it;
        const LLUUID& notificationID = notification_params["id"];
        std::string notificationName = notification_params["name"];
        LLNotificationPtr notification = instance.find(notificationID);

        if(notificationName == toastName)
        {
			toastSessionType = notification_params["payload"]["SESSION_TYPE"];
			if(toastSessionType == LLIMModel::LLIMSession::P2P_SESSION)
			{
				imToastExists = true;
			}
			//Don't add group/ad-hoc messages to the notification system because
			//this means the group/ad-hoc session has to be re-created
			else if(toastSessionType == LLIMModel::LLIMSession::GROUP_SESSION
					|| toastSessionType == LLIMModel::LLIMSession::ADHOC_SESSION)
			{
				//Just allows opening the conversation log for group/ad-hoc messages upon startup
				group_ad_hoc_toast_exists = true;
				continue;
			}
        }
        else if(notificationName == offerName)
        {
            offerExists = true;
        }

		//Notification already exists due to persistent storage adding it first into the notification system
		if(notification)
		{
			notification->setDND(true);
			instance.update(instance.find(notificationID));
		}
		//New notification needs to be added
		else
		{
			notification = (LLNotificationPtr) new LLNotification(notification_params.with("is_dnd", true));
			LLNotificationResponderInterface* responder = createResponder(notification_params["responder_sd"]["responder_type"], notification_params["responder_sd"]);
			if (responder == NULL)
			{
				LL_WARNS("LLDoNotDisturbNotificationStorage") << "cannot create responder for notification of type '"
					<< notification->getType() << "'" << LL_ENDL;
			}
			else
			{
				LLNotificationResponderPtr responderPtr(responder);
				notification->setResponseFunctor(responderPtr);
			}

			instance.add(notification);
		}

	}

    if(imToastExists)
    {
        LLFloaterReg::showInstance("im_container");
    }

	if(group_ad_hoc_toast_exists)
	{
		LLFloaterReg::showInstance("conversation");
	}

    if(imToastExists || group_ad_hoc_toast_exists || offerExists)
    {
		make_ui_sound_deferred("UISndNewIncomingIMSession");
    }

    //writes out empty .xml file (since LLCommunicationChannel::mHistory is empty)
	saveNotifications();

	LL_INFOS("LLDoNotDisturbNotificationStorage") << "finished loading notifications" << LL_ENDL;
}

void LLDoNotDisturbNotificationStorage::updateNotifications()
{

	LLNotificationChannelPtr channelPtr = getCommunicationChannel();
	LLCommunicationChannel *commChannel = dynamic_cast<LLCommunicationChannel*>(channelPtr.get());
	llassert(commChannel != NULL);

    LLNotifications& instance = LLNotifications::instance();
    bool imToastExists = false;
    bool offerExists = false;

    for (LLCommunicationChannel::history_list_t::const_iterator it = commChannel->beginHistory();
        it != commChannel->endHistory();
        ++it)
    {
        LLNotificationPtr notification = it->second;
        std::string notificationName = notification->getName();

        if(notificationName == toastName)
        {
            imToastExists = true;
        }
        else if(notificationName == offerName)
        {
            offerExists = true;
        }

        //Notification already exists in notification pipeline (same instance of app running)
        if (notification)
        {
            notification->setDND(true);
            instance.update(notification);
        }
    }

    if(imToastExists)
    {
        LLFloaterReg::showInstance("im_container");
    }

    if(imToastExists || offerExists)
    {
        make_ui_sound("UISndNewIncomingIMSession");
    }

    //When exit DND mode, write empty notifications file
    if(commChannel->getHistorySize())
    {
	    commChannel->clearHistory();
	    saveNotifications();
    }
}

LLNotificationChannelPtr LLDoNotDisturbNotificationStorage::getCommunicationChannel() const
{
	LLNotificationChannelPtr channelPtr = LLNotifications::getInstance()->getChannel("Communication");
	llassert(channelPtr);
	return channelPtr;
}

void LLDoNotDisturbNotificationStorage::removeNotification(const char * name, const LLUUID& id)
{
    LLNotifications& instance = LLNotifications::instance();
    LLNotificationChannelPtr channelPtr = getCommunicationChannel();
    LLCommunicationChannel *commChannel = dynamic_cast<LLCommunicationChannel*>(channelPtr.get());
    LLNotificationPtr notification;
    LLSD payload;
    LLUUID notificationObjectID;
    std::string notificationName;
    std::string payloadVariable = nameToPayloadParameterMap[name];
    LLCommunicationChannel::history_list_t::iterator it;
    std::vector<LLCommunicationChannel::history_list_t::iterator> itemsToRemove;

    //Find notification with the matching session id
    for (it = commChannel->beginHistory();
        it != commChannel->endHistory();
        ++it)
    {
        notification = it->second;
        payload = notification->getPayload();
        notificationObjectID = payload[payloadVariable].asUUID();
        notificationName = notification->getName();

        if((notificationName == name)
            && id == notificationObjectID)
        {
            itemsToRemove.push_back(it);
        }
    }

    //Remove the notifications
    if(itemsToRemove.size())
    {
        while(itemsToRemove.size())
        {
            it = itemsToRemove.back();
            notification = it->second;
            commChannel->removeItemFromHistory(notification);
            instance.cancel(notification);
            itemsToRemove.pop_back();
        }
        //Trigger saving of notifications to xml once all have been removed
        saveNotifications();
    }
}

bool LLDoNotDisturbNotificationStorage::onChannelChanged(const LLSD& pPayload)
{
	if (pPayload["sigtype"].asString() != "load")
	{
        mDirty = true;
	}

	return false;
}
<commit_msg>CHUI-936 FIXED Do not show Conversation log floater if logging is disabled.<commit_after>/**
* @file lldonotdisturbnotificationstorage.cpp
* @brief Implementation of lldonotdisturbnotificationstorage
* @author Stinson@lindenlab.com
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
* $/LicenseInfo$
*/

#include "llviewerprecompiledheaders.h"

#include "lldonotdisturbnotificationstorage.h"

#include "llcommunicationchannel.h"
#include "lldir.h"
#include "llerror.h"
#include "llfloaterreg.h"
#include "llimview.h"
#include "llnotifications.h"
#include "llnotificationhandler.h"
#include "llnotificationstorage.h"
#include "llscriptfloater.h"
#include "llsd.h"
#include "llsingleton.h"
#include "lluuid.h"

static const F32 DND_TIMER = 3.0;
const char * LLDoNotDisturbNotificationStorage::toastName = "IMToast";
const char * LLDoNotDisturbNotificationStorage::offerName = "UserGiveItem";

LLDoNotDisturbNotificationStorageTimer::LLDoNotDisturbNotificationStorageTimer() : LLEventTimer(DND_TIMER)
{

}

LLDoNotDisturbNotificationStorageTimer::~LLDoNotDisturbNotificationStorageTimer()
{

}

BOOL LLDoNotDisturbNotificationStorageTimer::tick()
{
    LLDoNotDisturbNotificationStorage * doNotDisturbNotificationStorage =  LLDoNotDisturbNotificationStorage::getInstance();

    if(doNotDisturbNotificationStorage
        && doNotDisturbNotificationStorage->getDirty())
    {
        doNotDisturbNotificationStorage->saveNotifications();
    }
    return FALSE;
}

LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage()
	: LLSingleton<LLDoNotDisturbNotificationStorage>()
	, LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "dnd_notifications.xml"))
    , mDirty(false)
{
    nameToPayloadParameterMap[toastName] = "SESSION_ID";
    nameToPayloadParameterMap[offerName] = "object_id";
}

LLDoNotDisturbNotificationStorage::~LLDoNotDisturbNotificationStorage()
{
}

void LLDoNotDisturbNotificationStorage::initialize()
{
	getCommunicationChannel()->connectFailedFilter(boost::bind(&LLDoNotDisturbNotificationStorage::onChannelChanged, this, _1));
}

bool LLDoNotDisturbNotificationStorage::getDirty()
{
    return mDirty;
}

void LLDoNotDisturbNotificationStorage::resetDirty()
{
    mDirty = false;
}

static LLFastTimer::DeclareTimer FTM_SAVE_DND_NOTIFICATIONS("Save DND Notifications");

void LLDoNotDisturbNotificationStorage::saveNotifications()
{
	LLFastTimer _(FTM_SAVE_DND_NOTIFICATIONS);

	LLNotificationChannelPtr channelPtr = getCommunicationChannel();
	const LLCommunicationChannel *commChannel = dynamic_cast<LLCommunicationChannel*>(channelPtr.get());
	llassert(commChannel != NULL);

	LLSD output = LLSD::emptyMap();
	LLSD& data = output["data"];
	data = LLSD::emptyArray();

	for (LLCommunicationChannel::history_list_t::const_iterator historyIter = commChannel->beginHistory();
		historyIter != commChannel->endHistory(); ++historyIter)
	{
		LLNotificationPtr notificationPtr = historyIter->second;

		if (!notificationPtr->isRespondedTo() && !notificationPtr->isCancelled() && !notificationPtr->isExpired())
		{
			data.append(notificationPtr->asLLSD(true));
		}
	}

	writeNotifications(output);

    resetDirty();
}

static LLFastTimer::DeclareTimer FTM_LOAD_DND_NOTIFICATIONS("Load DND Notifications");

void LLDoNotDisturbNotificationStorage::loadNotifications()
{
	LLFastTimer _(FTM_LOAD_DND_NOTIFICATIONS);

	LL_INFOS("LLDoNotDisturbNotificationStorage") << "start loading notifications" << LL_ENDL;

	LLSD input;
	if (!readNotifications(input) ||input.isUndefined())
	{
		return;
	}

	LLSD& data = input["data"];
	if (data.isUndefined())
	{
		return;
	}

	LLNotifications& instance = LLNotifications::instance();
    bool imToastExists = false;
	bool group_ad_hoc_toast_exists = false;
	S32 toastSessionType;
    bool offerExists = false;

	for (LLSD::array_const_iterator notification_it = data.beginArray();
		 notification_it != data.endArray();
		 ++notification_it)
	{
		LLSD notification_params = *notification_it;
        const LLUUID& notificationID = notification_params["id"];
        std::string notificationName = notification_params["name"];
        LLNotificationPtr notification = instance.find(notificationID);

        if(notificationName == toastName)
        {
			toastSessionType = notification_params["payload"]["SESSION_TYPE"];
			if(toastSessionType == LLIMModel::LLIMSession::P2P_SESSION)
			{
				imToastExists = true;
			}
			//Don't add group/ad-hoc messages to the notification system because
			//this means the group/ad-hoc session has to be re-created
			else if(toastSessionType == LLIMModel::LLIMSession::GROUP_SESSION
					|| toastSessionType == LLIMModel::LLIMSession::ADHOC_SESSION)
			{
				//Just allows opening the conversation log for group/ad-hoc messages upon startup
				group_ad_hoc_toast_exists = true;
				continue;
			}
        }
        else if(notificationName == offerName)
        {
            offerExists = true;
        }

		//Notification already exists due to persistent storage adding it first into the notification system
		if(notification)
		{
			notification->setDND(true);
			instance.update(instance.find(notificationID));
		}
		//New notification needs to be added
		else
		{
			notification = (LLNotificationPtr) new LLNotification(notification_params.with("is_dnd", true));
			LLNotificationResponderInterface* responder = createResponder(notification_params["responder_sd"]["responder_type"], notification_params["responder_sd"]);
			if (responder == NULL)
			{
				LL_WARNS("LLDoNotDisturbNotificationStorage") << "cannot create responder for notification of type '"
					<< notification->getType() << "'" << LL_ENDL;
			}
			else
			{
				LLNotificationResponderPtr responderPtr(responder);
				notification->setResponseFunctor(responderPtr);
			}

			instance.add(notification);
		}

	}

    if(imToastExists)
    {
        LLFloaterReg::showInstance("im_container");
    }

    bool isConversationLoggingAllowed = gSavedPerAccountSettings.getS32("KeepConversationLogTranscripts") > 0;
	if(group_ad_hoc_toast_exists && isConversationLoggingAllowed)
	{
		LLFloaterReg::showInstance("conversation");
	}

    if(imToastExists || group_ad_hoc_toast_exists || offerExists)
    {
		make_ui_sound_deferred("UISndNewIncomingIMSession");
    }

    //writes out empty .xml file (since LLCommunicationChannel::mHistory is empty)
	saveNotifications();

	LL_INFOS("LLDoNotDisturbNotificationStorage") << "finished loading notifications" << LL_ENDL;
}

void LLDoNotDisturbNotificationStorage::updateNotifications()
{

	LLNotificationChannelPtr channelPtr = getCommunicationChannel();
	LLCommunicationChannel *commChannel = dynamic_cast<LLCommunicationChannel*>(channelPtr.get());
	llassert(commChannel != NULL);

    LLNotifications& instance = LLNotifications::instance();
    bool imToastExists = false;
    bool offerExists = false;

    for (LLCommunicationChannel::history_list_t::const_iterator it = commChannel->beginHistory();
        it != commChannel->endHistory();
        ++it)
    {
        LLNotificationPtr notification = it->second;
        std::string notificationName = notification->getName();

        if(notificationName == toastName)
        {
            imToastExists = true;
        }
        else if(notificationName == offerName)
        {
            offerExists = true;
        }

        //Notification already exists in notification pipeline (same instance of app running)
        if (notification)
        {
            notification->setDND(true);
            instance.update(notification);
        }
    }

    if(imToastExists)
    {
        LLFloaterReg::showInstance("im_container");
    }

    if(imToastExists || offerExists)
    {
        make_ui_sound("UISndNewIncomingIMSession");
    }

    //When exit DND mode, write empty notifications file
    if(commChannel->getHistorySize())
    {
	    commChannel->clearHistory();
	    saveNotifications();
    }
}

LLNotificationChannelPtr LLDoNotDisturbNotificationStorage::getCommunicationChannel() const
{
	LLNotificationChannelPtr channelPtr = LLNotifications::getInstance()->getChannel("Communication");
	llassert(channelPtr);
	return channelPtr;
}

void LLDoNotDisturbNotificationStorage::removeNotification(const char * name, const LLUUID& id)
{
    LLNotifications& instance = LLNotifications::instance();
    LLNotificationChannelPtr channelPtr = getCommunicationChannel();
    LLCommunicationChannel *commChannel = dynamic_cast<LLCommunicationChannel*>(channelPtr.get());
    LLNotificationPtr notification;
    LLSD payload;
    LLUUID notificationObjectID;
    std::string notificationName;
    std::string payloadVariable = nameToPayloadParameterMap[name];
    LLCommunicationChannel::history_list_t::iterator it;
    std::vector<LLCommunicationChannel::history_list_t::iterator> itemsToRemove;

    //Find notification with the matching session id
    for (it = commChannel->beginHistory();
        it != commChannel->endHistory();
        ++it)
    {
        notification = it->second;
        payload = notification->getPayload();
        notificationObjectID = payload[payloadVariable].asUUID();
        notificationName = notification->getName();

        if((notificationName == name)
            && id == notificationObjectID)
        {
            itemsToRemove.push_back(it);
        }
    }

    //Remove the notifications
    if(itemsToRemove.size())
    {
        while(itemsToRemove.size())
        {
            it = itemsToRemove.back();
            notification = it->second;
            commChannel->removeItemFromHistory(notification);
            instance.cancel(notification);
            itemsToRemove.pop_back();
        }
        //Trigger saving of notifications to xml once all have been removed
        saveNotifications();
    }
}

bool LLDoNotDisturbNotificationStorage::onChannelChanged(const LLSD& pPayload)
{
	if (pPayload["sigtype"].asString() != "load")
	{
        mDirty = true;
	}

	return false;
}
<|endoftext|>


<commit_before>#include <iostream> // must go before other things because R defines a "length" macro
#include "nimble/dists.h"
#include "nimble/nimDists.h"

bool R_IsNA(NimArr<1, double> &P) {
  int s = P.size();
  for(int i = 0; i < s; ++i) if(R_IsNA(P[i])) return(true);
  return(false);
}

bool R_isnancpp(NimArr<1, double> &P) {
  int s = P.size();
  for(int i = 0; i < s; ++i) if(R_isnancpp(P[i])) return(true);
  return(false);
}

template<int nDim, class T>
NimArr<nDim, T> &nimArrCopyIfNeeded(NimArr<nDim, T> &orig, NimArr<nDim, T> &possibleCopy) {
  if(orig.isMap()) {
    possibleCopy = orig;
    return(possibleCopy);
  } else {
    return(orig);
  }
}

double nimArr_dmulti(NimArr<1, double> &x, int size, NimArr<1, double> &prob, int give_log) {
  int K = prob.size();
  if(K == 0) return(0.);
  if(x.size() != K) std::cout<<"Error in nimArr_dmulti: incompatible sizes for x ("<<x.size()<<") and prob("<<K<<").\n";
  int *xptr;
  double *probptr;
  NimArr<1, int> xCopy;
  NimArr<1, double> probCopy;
  xCopy = x; // copy from double to int
  xptr = xCopy.getPtr();
  probptr = nimArrCopyIfNeeded<1, double>(prob, probCopy).getPtr();
  double ans = dmulti(xptr, size, probptr, K, give_log);
  return(ans);
}

void nimArr_rmulti(NimArr<1, double> &ans, int size, NimArr<1, double> &prob) {
  int K = prob.size();
  if(K == 0) return;
  int *ansptr;
  double *probptr;
  NimArr<1, int> ansCopy;
  NimArr<1, double> probCopy;

  if(ans.isMap()) {
    if(ans.size() != K) {
      std::cout<<"Error in nimArr_rmulti: ans size does not match prob.\n";
    }
  }
  ansCopy.setSize(K);
  ansptr = ansCopy.getPtr();
  probptr = nimArrCopyIfNeeded<1, double>(prob, probCopy).getPtr();
  rmulti(ansptr, size, probptr, K);
  ans = ansCopy; // copy from int to double
}

double nimArr_dcat(int x, NimArr<1, double> &prob, int give_log) {
  int K = prob.size();
  double *probptr;
  NimArr<1, double> probCopy;
  probptr = nimArrCopyIfNeeded<1, double>(prob, probCopy).getPtr();
  double ans = dcat(x, probptr, K, give_log);
  return(ans);
}

int nimArr_rcat(NimArr<1, double> &prob) {
  int K = prob.size();
  double *probptr;
  NimArr<1, double> probCopy;
  probptr = nimArrCopyIfNeeded<1, double>(prob, probCopy).getPtr();
  int ans = rcat(probptr, K);
  return(ans);
}

double nimArr_ddirch(NimArr<1, double> &x, NimArr<1, double> &alpha, int give_log) {
  double *xptr, *alphaptr;
  NimArr<1, double> xCopy, alphaCopy;

  int K = alpha.size();
  if(K == 0) return(0.);
  if(x.size() != K) {
    std::cout<<"Error in nimArr_ddirch: length of x must equal length of alpha.\n";
  }

  xptr = nimArrCopyIfNeeded<1, double>(x, xCopy).getPtr();
  alphaptr = nimArrCopyIfNeeded<1, double>(alpha, alphaCopy).getPtr();
  double ans = ddirch(xptr, alphaptr, K, give_log);
  return(ans);
}

void nimArr_rdirch(NimArr<1, double> &ans, NimArr<1, double> &alpha) {
  double *ansptr, *alphaptr;
  NimArr<1, double> ansCopy, alphaCopy;

  int K = alpha.size();
  if(K == 0) return;
  if(!ans.isMap()) {
    ans.setSize(K);
  } else {
    if(ans.size() != K) {
      std::cout<<"Error in nimArr_rdirch: ans size does not match alpha.\n";
    }
  }
  ansptr = nimArrCopyIfNeeded<1, double>(ans, ansCopy).getPtr();
  alphaptr = nimArrCopyIfNeeded<1, double>(alpha, alphaCopy).getPtr();

  rdirch(ansptr, alphaptr, K);
  if(ans.isMap()) {ans = ansCopy;}
}

double nimArr_dwish_chol(NimArr<2, double> &x, NimArr<2, double> &chol, double df, int scale_param, int give_log) {
  double *xptr, *cholptr;
  NimArr<2, double> xCopy, cholCopy;
  int p = x.dim()[0];
  if((x.dim()[1] != p) | (chol.dim()[0] != p) | (chol.dim()[1] != p)) {
    std::cout<<"Error in nimArr_dwish_chol: some dimensions are not right\n";
  }
  if(df < p) {
    std::cout<<"Error in nimArr_dwish_chol: inconsistent degrees of freedom and dimension.\n";
  }
  xptr = nimArrCopyIfNeeded<2, double>(x, xCopy).getPtr();
  cholptr = nimArrCopyIfNeeded<2, double>(chol, cholCopy).getPtr();
  double ans = dwish_chol(xptr, cholptr, df, p, scale_param, give_log);
  return(ans);
}

void nimArr_rwish_chol(NimArr<2, double> &ans, NimArr<2, double> &chol, double df, int prec_param) {
  double *ansptr, *cholptr;
  NimArr<2, double> ansCopy, cholCopy;
  int p = chol.dim()[0];
  if(chol.dim()[1] != p) {
    std::cout<<"Error in nimArr_rwish_chol: chol is not square\n";
  }
  if(df < p) {
    std::cout<<"Error in nimArr_rwish_chol: inconsistent degrees of freedom and dimension.\n";
  }
  if(!ans.isMap()) {
    ans.setSize(p, p);
  } else {
    if((ans.dim()[0] != p) | (ans.dim()[1] != p)) {
      std::cout<<"Error in nimArr_rwish_chol: ans sizes do not match chol.\n";
    }
  }
  ansptr = nimArrCopyIfNeeded<2, double>(ans, ansCopy).getPtr();
  cholptr = nimArrCopyIfNeeded<2, double>(chol, cholCopy).getPtr();

  rwish_chol(ansptr, cholptr, df, p, prec_param);
  if(ans.isMap()) {ans = ansCopy;}
}

double nimArr_dmnorm_chol(NimArr<1, double> &x, NimArr<1, double> &mean, NimArr<2, double> &chol, int prec_param, int give_log ) {

  double *xptr, *meanptr, *cholptr;
  NimArr<1, double> xCopy, meanCopy;
  NimArr<2, double> cholCopy;
  xptr = nimArrCopyIfNeeded<1, double>(x, xCopy).getPtr();
  int n = x.size();
  meanptr = nimArrCopyIfNeeded<1, double>(mean, meanCopy).getPtr();
  if(mean.size() != n) {std::cout<<"Error in nimArr_dmnorm_chol: mean and x and different sizes.\n";}
  cholptr = nimArrCopyIfNeeded<2, double>(chol, cholCopy).getPtr();
  if((chol.dim()[0] != n) | (chol.dim()[1] != n)) {std::cout<<"Error in nimArr_dmnorm_chol: chol does not match size size of x.\n";}

  double ans;
  ans = dmnorm_chol(xptr, meanptr, cholptr, n, prec_param, give_log);

  return(ans);
}

void nimArr_rmnorm_chol(NimArr<1, double> &ans, NimArr<1, double> &mean, NimArr<2, double> &chol, int prec_param) {

  NimArr<1, double> ansCopy, meanCopy;
  NimArr<2, double> cholCopy;
  double *ansPtr, *meanPtr, *cholPtr;

  int n = mean.size();
  if(!ans.isMap()) {
    ans.setSize(n);
  } else {
    if(ans.size() != n) {
      std::cout<<"Error in nimArr_rmnorm_chol: answer size ("<< ans.size() <<") does not match mean size ("<<n<<").\n";
    }
  }
  ansPtr = nimArrCopyIfNeeded<1, double>(ans, ansCopy).getPtr();
  meanPtr = nimArrCopyIfNeeded<1, double>(mean, meanCopy).getPtr();
  cholPtr = nimArrCopyIfNeeded<2, double>(chol, cholCopy).getPtr();
  rmnorm_chol(ansPtr, meanPtr, cholPtr, n, prec_param);

  if(ans.isMap()) {
    ans = ansCopy;
  }
}
<commit_msg>added overloaded nimArr_{d,r}interval to nimDists.cpp<commit_after>#include <iostream> // must go before other things because R defines a "length" macro
#include "nimble/dists.h"
#include "nimble/nimDists.h"

bool R_IsNA(NimArr<1, double> &P) {
  int s = P.size();
  for(int i = 0; i < s; ++i) if(R_IsNA(P[i])) return(true);
  return(false);
}

bool R_isnancpp(NimArr<1, double> &P) {
  int s = P.size();
  for(int i = 0; i < s; ++i) if(R_isnancpp(P[i])) return(true);
  return(false);
}

template<int nDim, class T>
NimArr<nDim, T> &nimArrCopyIfNeeded(NimArr<nDim, T> &orig, NimArr<nDim, T> &possibleCopy) {
  if(orig.isMap()) {
    possibleCopy = orig;
    return(possibleCopy);
  } else {
    return(orig);
  }
}

double nimArr_dmulti(NimArr<1, double> &x, int size, NimArr<1, double> &prob, int give_log) {
  int K = prob.size();
  if(K == 0) return(0.);
  if(x.size() != K) std::cout<<"Error in nimArr_dmulti: incompatible sizes for x ("<<x.size()<<") and prob("<<K<<").\n";
  int *xptr;
  double *probptr;
  NimArr<1, int> xCopy;
  NimArr<1, double> probCopy;
  xCopy = x; // copy from double to int
  xptr = xCopy.getPtr();
  probptr = nimArrCopyIfNeeded<1, double>(prob, probCopy).getPtr();
  double ans = dmulti(xptr, size, probptr, K, give_log);
  return(ans);
}

void nimArr_rmulti(NimArr<1, double> &ans, int size, NimArr<1, double> &prob) {
  int K = prob.size();
  if(K == 0) return;
  int *ansptr;
  double *probptr;
  NimArr<1, int> ansCopy;
  NimArr<1, double> probCopy;

  if(ans.isMap()) {
    if(ans.size() != K) {
      std::cout<<"Error in nimArr_rmulti: ans size does not match prob.\n";
    }
  }
  ansCopy.setSize(K);
  ansptr = ansCopy.getPtr();
  probptr = nimArrCopyIfNeeded<1, double>(prob, probCopy).getPtr();
  rmulti(ansptr, size, probptr, K);
  ans = ansCopy; // copy from int to double
}

double nimArr_dcat(int x, NimArr<1, double> &prob, int give_log) {
  int K = prob.size();
  double *probptr;
  NimArr<1, double> probCopy;
  probptr = nimArrCopyIfNeeded<1, double>(prob, probCopy).getPtr();
  double ans = dcat(x, probptr, K, give_log);
  return(ans);
}

int nimArr_rcat(NimArr<1, double> &prob) {
  int K = prob.size();
  double *probptr;
  NimArr<1, double> probCopy;
  probptr = nimArrCopyIfNeeded<1, double>(prob, probCopy).getPtr();
  int ans = rcat(probptr, K);
  return(ans);
}

double nimArr_ddirch(NimArr<1, double> &x, NimArr<1, double> &alpha, int give_log) {
  double *xptr, *alphaptr;
  NimArr<1, double> xCopy, alphaCopy;

  int K = alpha.size();
  if(K == 0) return(0.);
  if(x.size() != K) {
    std::cout<<"Error in nimArr_ddirch: length of x must equal length of alpha.\n";
  }

  xptr = nimArrCopyIfNeeded<1, double>(x, xCopy).getPtr();
  alphaptr = nimArrCopyIfNeeded<1, double>(alpha, alphaCopy).getPtr();
  double ans = ddirch(xptr, alphaptr, K, give_log);
  return(ans);
}

void nimArr_rdirch(NimArr<1, double> &ans, NimArr<1, double> &alpha) {
  double *ansptr, *alphaptr;
  NimArr<1, double> ansCopy, alphaCopy;

  int K = alpha.size();
  if(K == 0) return;
  if(!ans.isMap()) {
    ans.setSize(K);
  } else {
    if(ans.size() != K) {
      std::cout<<"Error in nimArr_rdirch: ans size does not match alpha.\n";
    }
  }
  ansptr = nimArrCopyIfNeeded<1, double>(ans, ansCopy).getPtr();
  alphaptr = nimArrCopyIfNeeded<1, double>(alpha, alphaCopy).getPtr();

  rdirch(ansptr, alphaptr, K);
  if(ans.isMap()) {ans = ansCopy;}
}

double nimArr_dwish_chol(NimArr<2, double> &x, NimArr<2, double> &chol, double df, int scale_param, int give_log) {
  double *xptr, *cholptr;
  NimArr<2, double> xCopy, cholCopy;
  int p = x.dim()[0];
  if((x.dim()[1] != p) | (chol.dim()[0] != p) | (chol.dim()[1] != p)) {
    std::cout<<"Error in nimArr_dwish_chol: some dimensions are not right\n";
  }
  if(df < p) {
    std::cout<<"Error in nimArr_dwish_chol: inconsistent degrees of freedom and dimension.\n";
  }
  xptr = nimArrCopyIfNeeded<2, double>(x, xCopy).getPtr();
  cholptr = nimArrCopyIfNeeded<2, double>(chol, cholCopy).getPtr();
  double ans = dwish_chol(xptr, cholptr, df, p, scale_param, give_log);
  return(ans);
}

void nimArr_rwish_chol(NimArr<2, double> &ans, NimArr<2, double> &chol, double df, int prec_param) {
  double *ansptr, *cholptr;
  NimArr<2, double> ansCopy, cholCopy;
  int p = chol.dim()[0];
  if(chol.dim()[1] != p) {
    std::cout<<"Error in nimArr_rwish_chol: chol is not square\n";
  }
  if(df < p) {
    std::cout<<"Error in nimArr_rwish_chol: inconsistent degrees of freedom and dimension.\n";
  }
  if(!ans.isMap()) {
    ans.setSize(p, p);
  } else {
    if((ans.dim()[0] != p) | (ans.dim()[1] != p)) {
      std::cout<<"Error in nimArr_rwish_chol: ans sizes do not match chol.\n";
    }
  }
  ansptr = nimArrCopyIfNeeded<2, double>(ans, ansCopy).getPtr();
  cholptr = nimArrCopyIfNeeded<2, double>(chol, cholCopy).getPtr();

  rwish_chol(ansptr, cholptr, df, p, prec_param);
  if(ans.isMap()) {ans = ansCopy;}
}

double nimArr_dmnorm_chol(NimArr<1, double> &x, NimArr<1, double> &mean, NimArr<2, double> &chol, int prec_param, int give_log ) {

  double *xptr, *meanptr, *cholptr;
  NimArr<1, double> xCopy, meanCopy;
  NimArr<2, double> cholCopy;
  xptr = nimArrCopyIfNeeded<1, double>(x, xCopy).getPtr();
  int n = x.size();
  meanptr = nimArrCopyIfNeeded<1, double>(mean, meanCopy).getPtr();
  if(mean.size() != n) {std::cout<<"Error in nimArr_dmnorm_chol: mean and x and different sizes.\n";}
  cholptr = nimArrCopyIfNeeded<2, double>(chol, cholCopy).getPtr();
  if((chol.dim()[0] != n) | (chol.dim()[1] != n)) {std::cout<<"Error in nimArr_dmnorm_chol: chol does not match size size of x.\n";}

  double ans;
  ans = dmnorm_chol(xptr, meanptr, cholptr, n, prec_param, give_log);

  return(ans);
}

void nimArr_rmnorm_chol(NimArr<1, double> &ans, NimArr<1, double> &mean, NimArr<2, double> &chol, int prec_param) {

  NimArr<1, double> ansCopy, meanCopy;
  NimArr<2, double> cholCopy;
  double *ansPtr, *meanPtr, *cholPtr;

  int n = mean.size();
  if(!ans.isMap()) {
    ans.setSize(n);
  } else {
    if(ans.size() != n) {
      std::cout<<"Error in nimArr_rmnorm_chol: answer size ("<< ans.size() <<") does not match mean size ("<<n<<").\n";
    }
  }
  ansPtr = nimArrCopyIfNeeded<1, double>(ans, ansCopy).getPtr();
  meanPtr = nimArrCopyIfNeeded<1, double>(mean, meanCopy).getPtr();
  cholPtr = nimArrCopyIfNeeded<2, double>(chol, cholCopy).getPtr();
  rmnorm_chol(ansPtr, meanPtr, cholPtr, n, prec_param);

  if(ans.isMap()) {
    ans = ansCopy;
  }
}

// the next two handle when 'c' is a vector (e.g., interval censoring)
//  and the following two when 'c' is a scalar (e.g., left- and right-censoring)
double nimArr_dinterval(int x, double t, NimArr<1, double> &c, int give_log) {
  int K = c.size();
  double *cptr;
  NimArr<1, double> cCopy;
  cptr = nimArrCopyIfNeeded<1, double>(c, cCopy).getPtr();
  double ans = dinterval(x, t, cptr, K, give_log);
  return(ans);
}

int nimArr_rinterval(double t, NimArr<1, double> &c) {
  int K = c.size();
  double *cptr;
  NimArr<1, double> cCopy;
  cptr = nimArrCopyIfNeeded<1, double>(c, cCopy).getPtr();
  int ans = rinterval(t, cptr, K);
  return(ans);
}

double nimArr_dinterval(int x, double t, double c, int give_log) {
  double ans = dinterval(x, t, &c, 1, give_log);
  return(ans);
}

int nimArr_rinterval(double t, double c) {
  int ans = rinterval(t, &c, 1);
  return(ans);
}
<|endoftext|>