<commit_before>///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2012, ShumaTech
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the <organization> nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
///////////////////////////////////////////////////////////////////////////////
#include <string>
#include <exception>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#include "Flasher.h"

using namespace std;

void
Flasher::progressBar(int num, int div)
{
    int ticks;
    int bars = 30;

    printf("\r[");
    ticks = num * bars / div;
    while (ticks-- > 0)
    {
        putchar('=');
        bars--;
    }
    while (bars-- > 0)
    {
        putchar(' ');
    }
    printf("] %d%% (%d/%d pages)", num * 100 / div, num, div);
    fflush(stdout);
}

void
Flasher::erase()
{
    printf("Erase flash\n");
    _flash->eraseAll();
    _flash->eraseAuto(false);
}

void
Flasher::write(const char* filename)
{
    FILE* infile;
    uint32_t pageSize = _flash->pageSize();
    uint32_t pageNum = 0;
    uint32_t numPages;
    long fsize;
    size_t fbytes;

    infile = fopen(filename, "rb");
    if (!infile)
        throw FileOpenError(errno);

    try
    {
        if (fseek(infile, 0, SEEK_END) != 0 ||
            (fsize = ftell(infile)) < 0)
            throw FileIoError(errno);
        rewind(infile);

        numPages = (fsize + pageSize - 1) / pageSize;
        if (numPages > _flash->numPages())
            throw FileSizeError();

        printf("Write %ld bytes to flash (%u pages)\n", fsize, numPages);

        if (_flash->isWriteBufferAvailable()) {

            // If multi-page write is available....

            const uint32_t BLK_SIZE = 4096;
            uint32_t offset = 0;
            uint8_t buffer[BLK_SIZE];
            memset(buffer, 0, BLK_SIZE);
            while ((fbytes = fread(buffer, 1, BLK_SIZE, infile)) > 0)
            {
                if (fbytes < BLK_SIZE) {
                    // Ceil to nearest pagesize
                    fbytes = (fbytes + pageSize - 1) / pageSize * pageSize;
                }
                _flash->loadBuffer(buffer, fbytes);
                _flash->writeBuffer(offset, fbytes);
                offset += fbytes;
                progressBar(offset/pageSize, numPages);

                memset(buffer, 0, BLK_SIZE);
            }

        } else {

            // ...otherwise go with the legacy slow method

            uint8_t buffer[pageSize];
            while ((fbytes = fread(buffer, 1, pageSize, infile)) > 0)
            {
                // print once every 10%
                if ((pageNum % (numPages/10)) == 0)
                    progressBar(pageNum, numPages);

                _flash->loadBuffer(buffer, fbytes);
                _flash->writePage(pageNum);

                pageNum++;
                if (pageNum == numPages || fbytes != pageSize)
                    break;
            }
            progressBar(pageNum, numPages);

        }
        printf("\n");
    }
    catch(...)
    {
        fclose(infile);
        throw;
    }
    fclose(infile);
}

bool
Flasher::verify(const char* filename)
{
    FILE* infile;
    uint32_t pageSize = _flash->pageSize();
    uint8_t bufferA[pageSize];
    uint8_t bufferB[pageSize];
    uint32_t pageNum = 0;
    uint32_t numPages;
    uint32_t byteErrors = 0;
    uint32_t pageErrors = 0;
    uint32_t totalErrors = 0;
    long fsize;
    size_t fbytes;

    infile = fopen(filename, "rb");
    if (!infile)
        throw FileOpenError(errno);

    if (fseek(infile, 0, SEEK_END) != 0 || (fsize = ftell(infile)) < 0)
        throw FileIoError(errno);
    rewind(infile);

    // If checksum buffer is available, use it...
    if (_flash->isChecksumBufferAvailable()) {

        bool failed = false;
        try
        {
            printf("Verify %ld bytes of flash with checksum.\n", fsize);

            // Perform checksum every 4096 bytes
            uint32_t BLK_SIZE = 4096;
            uint8_t buffer[BLK_SIZE];
            uint32_t offset = 0;
            while ((fbytes = fread(buffer, 1, BLK_SIZE, infile)) > 0) {
                uint32_t i;
                uint16_t crc = 0;
                for (i=0; i<fbytes; i++)
                    crc = _flash->crc16AddByte(buffer[i], crc);
                uint16_t flashCrc = _flash->checksumBuffer(offset, fbytes);
                offset += fbytes;

                if (crc != flashCrc) {
                    failed = true;
                    break;
                }
            }
        }
        catch(...)
        {
            fclose(infile);
            throw;
        }
        fclose(infile);

        if (failed)
        {
            printf("Verify failed\n");
            return false;
        }

        printf("Verify successful\n");
        return true;
    }

    // ...otherwise go with the slow legacy method...

    try
    {
        numPages = (fsize + pageSize - 1) / pageSize;
        if (numPages > _flash->numPages())
            throw FileSizeError();

        printf("Verify %ld bytes of flash\n", fsize);

        while ((fbytes = fread(bufferA, 1, pageSize, infile)) > 0)
        {
            // print once every 10%
            if ((pageNum % (numPages/10)) == 0)
                progressBar(pageNum, numPages);

            _flash->readPage(pageNum, bufferB);

            byteErrors = 0;
            for (uint32_t i = 0; i < fbytes; i++)
            {
                if (bufferA[i] != bufferB[i])
                    byteErrors++;
            }
            if (byteErrors != 0)
            {
                pageErrors++;
                totalErrors += byteErrors;
            }

            pageNum++;
            if (pageNum == numPages || fbytes != pageSize)
                break;
        }
        progressBar(pageNum, numPages);
        printf("\n");
    }
    catch(...)
    {
        fclose(infile);
        throw;
    }
    fclose(infile);

    if (byteErrors != 0)
    {
        printf("Verify failed\n");
        printf("Page errors: %d\n", pageErrors);
        printf("Byte errors: %d\n", totalErrors);
        return false;
    }

    printf("Verify successful\n");
    return true;
}

void
Flasher::read(const char* filename, long fsize)
{
    FILE* outfile;
    uint32_t pageSize = _flash->pageSize();
    uint8_t buffer[pageSize];
    uint32_t pageNum = 0;
    uint32_t numPages;
    size_t fbytes;

    if (fsize == 0)
        fsize = pageSize * _flash->numPages();

    outfile = fopen(filename, "wb");
    if (!outfile)
        throw FileOpenError(errno);

    try
    {
        numPages = (fsize + pageSize - 1) / pageSize;
        if (numPages > _flash->numPages())
            throw FileSizeError();

        printf("Read %ld bytes from flash\n", fsize);

        for (pageNum = 0; pageNum < numPages; pageNum++)
        {
            // updated from one print per 10 pages to one per 10 percent
            if ((pageNum < 10) || (pageNum % (numPages/10) == 0))
                progressBar(pageNum, numPages);

            _flash->readPage(pageNum, buffer);

            if (pageNum == numPages - 1 && fsize % pageSize > 0)
                pageSize = fsize % pageSize;
            fbytes = fwrite(buffer, 1, pageSize, outfile);
            if (fbytes != pageSize)
                throw FileShortError();
        }
        progressBar(pageNum, numPages);
        printf("\n");
    }
    catch(...)
    {
        fclose(outfile);
        throw;
    }
    fclose(outfile);
}

void
Flasher::lock(string& regionArg, bool enable)
{
    if (regionArg.empty())
    {
        printf("%s all regions\n", enable ? "Lock" : "Unlock");
        if (enable)
            _flash->lockAll();
        else
            _flash->unlockAll();
    }
    else
    {
        size_t pos = 0;
        size_t delim;
        uint32_t region;
        string sub;

        do
        {
            delim = regionArg.find(',', pos);
            sub = regionArg.substr(pos, delim - pos);
            region = strtol(sub.c_str(), NULL, 0);
            printf("%s region %d\n", enable ? "Lock" : "Unlock", region);
            _flash->setLockRegion(region, enable);
            pos = delim + 1;
        } while (delim != string::npos);
    }
}

void
Flasher::info(Samba& samba)
{
    bool first;

    printf("Device       : %s\n", _flash->name().c_str());
    printf("Chip ID      : %08x\n", samba.chipId());
    printf("Version      : %s\n", samba.version().c_str());
    printf("Address      : %d\n", _flash->address());
    printf("Pages        : %d\n", _flash->numPages());
    printf("Page Size    : %d bytes\n", _flash->pageSize());
    printf("Total Size   : %dKB\n", _flash->numPages() * _flash->pageSize() / 1024);
    printf("Planes       : %d\n", _flash->numPlanes());
    printf("Lock Regions : %d\n", _flash->lockRegions());
    printf("Locked       : ");
    first = true;
    for (uint32_t region = 0; region < _flash->lockRegions(); region++)
    {
        if (_flash->getLockRegion(region))
        {
            printf("%s%d", first ? "" : ",", region);
            first = false;
        }
    }
    printf("%s\n", first ? "none" : "");
    printf("Security     : %s\n", _flash->getSecurity() ? "true" : "false");
    if (_flash->canBootFlash())
        printf("Boot Flash   : %s\n", _flash->getBootFlash() ? "true" : "false");
    if (_flash->canBod())
        printf("BOD          : %s\n", _flash->getBod() ? "true" : "false");
    if (_flash->canBor())
        printf("BOR          : %s\n", _flash->getBor() ? "true" : "false");
    if (samba.isChipEraseAvailable())
        printf("Arduino      : FAST_CHIP_ERASE\n");
    if (samba.isWriteBufferAvailable())
        printf("Arduino      : FAST_MULTI_PAGE_WRITE\n");
    if (samba.isChecksumBufferAvailable())
        printf("Arduino      : CAN_CHECKSUM_MEMORY_BUFFER\n");
}
<commit_msg>Fix division by zero<commit_after>///////////////////////////////////////////////////////////////////////////////
// BOSSA
//
// Copyright (c) 2011-2012, ShumaTech
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the <organization> nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
///////////////////////////////////////////////////////////////////////////////
#include <string>
#include <exception>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#include "Flasher.h"

using namespace std;

void
Flasher::progressBar(int num, int div)
{
    int ticks;
    int bars = 30;

    printf("\r[");
    ticks = num * bars / div;
    while (ticks-- > 0)
    {
        putchar('=');
        bars--;
    }
    while (bars-- > 0)
    {
        putchar(' ');
    }
    printf("] %d%% (%d/%d pages)", num * 100 / div, num, div);
    fflush(stdout);
}

void
Flasher::erase()
{
    printf("Erase flash\n");
    _flash->eraseAll();
    _flash->eraseAuto(false);
}

void
Flasher::write(const char* filename)
{
    FILE* infile;
    uint32_t pageSize = _flash->pageSize();
    uint32_t pageNum = 0;
    uint32_t numPages;
    long fsize;
    size_t fbytes;

    infile = fopen(filename, "rb");
    if (!infile)
        throw FileOpenError(errno);

    try
    {
        if (fseek(infile, 0, SEEK_END) != 0 ||
            (fsize = ftell(infile)) < 0)
            throw FileIoError(errno);
        rewind(infile);

        numPages = (fsize + pageSize - 1) / pageSize;
        if (numPages > _flash->numPages())
            throw FileSizeError();

        printf("Write %ld bytes to flash (%u pages)\n", fsize, numPages);

        if (_flash->isWriteBufferAvailable()) {

            // If multi-page write is available....

            const uint32_t BLK_SIZE = 4096;
            uint32_t offset = 0;
            uint8_t buffer[BLK_SIZE];
            memset(buffer, 0, BLK_SIZE);
            while ((fbytes = fread(buffer, 1, BLK_SIZE, infile)) > 0)
            {
                if (fbytes < BLK_SIZE) {
                    // Ceil to nearest pagesize
                    fbytes = (fbytes + pageSize - 1) / pageSize * pageSize;
                }
                _flash->loadBuffer(buffer, fbytes);
                _flash->writeBuffer(offset, fbytes);
                offset += fbytes;
                progressBar(offset/pageSize, numPages);

                memset(buffer, 0, BLK_SIZE);
            }

        } else {

            // ...otherwise go with the legacy slow method

            uint8_t buffer[pageSize];
            const uint32_t divisor = (numPages / 10) ? (numPages / 10) : 1;
            while ((fbytes = fread(buffer, 1, pageSize, infile)) > 0)
            {
                if ((pageNum % divisor) == 0)
                    progressBar(pageNum, numPages);

                _flash->loadBuffer(buffer, fbytes);
                _flash->writePage(pageNum);

                pageNum++;
                if (pageNum == numPages || fbytes != pageSize)
                    break;
            }
            progressBar(pageNum, numPages);

        }
        printf("\n");
    }
    catch(...)
    {
        fclose(infile);
        throw;
    }
    fclose(infile);
}

bool
Flasher::verify(const char* filename)
{
    FILE* infile;
    uint32_t pageSize = _flash->pageSize();
    uint8_t bufferA[pageSize];
    uint8_t bufferB[pageSize];
    uint32_t pageNum = 0;
    uint32_t numPages;
    uint32_t byteErrors = 0;
    uint32_t pageErrors = 0;
    uint32_t totalErrors = 0;
    long fsize;
    size_t fbytes;

    infile = fopen(filename, "rb");
    if (!infile)
        throw FileOpenError(errno);

    if (fseek(infile, 0, SEEK_END) != 0 || (fsize = ftell(infile)) < 0)
        throw FileIoError(errno);
    rewind(infile);

    // If checksum buffer is available, use it...
    if (_flash->isChecksumBufferAvailable()) {

        bool failed = false;
        try
        {
            printf("Verify %ld bytes of flash with checksum.\n", fsize);

            // Perform checksum every 4096 bytes
            uint32_t BLK_SIZE = 4096;
            uint8_t buffer[BLK_SIZE];
            uint32_t offset = 0;
            while ((fbytes = fread(buffer, 1, BLK_SIZE, infile)) > 0) {
                uint32_t i;
                uint16_t crc = 0;
                for (i=0; i<fbytes; i++)
                    crc = _flash->crc16AddByte(buffer[i], crc);
                uint16_t flashCrc = _flash->checksumBuffer(offset, fbytes);
                offset += fbytes;

                if (crc != flashCrc) {
                    failed = true;
                    break;
                }
            }
        }
        catch(...)
        {
            fclose(infile);
            throw;
        }
        fclose(infile);

        if (failed)
        {
            printf("Verify failed\n");
            return false;
        }

        printf("Verify successful\n");
        return true;
    }

    // ...otherwise go with the slow legacy method...

    try
    {
        numPages = (fsize + pageSize - 1) / pageSize;
        if (numPages > _flash->numPages())
            throw FileSizeError();

        printf("Verify %ld bytes of flash\n", fsize);

        const uint32_t divisor = (numPages / 10) ? (numPages / 10) : 1;
        while ((fbytes = fread(bufferA, 1, pageSize, infile)) > 0)
        {
            if ((pageNum % divisor) == 0)
                progressBar(pageNum, numPages);

            _flash->readPage(pageNum, bufferB);

            byteErrors = 0;
            for (uint32_t i = 0; i < fbytes; i++)
            {
                if (bufferA[i] != bufferB[i])
                    byteErrors++;
            }
            if (byteErrors != 0)
            {
                pageErrors++;
                totalErrors += byteErrors;
            }

            pageNum++;
            if (pageNum == numPages || fbytes != pageSize)
                break;
        }
        progressBar(pageNum, numPages);
        printf("\n");
    }
    catch(...)
    {
        fclose(infile);
        throw;
    }
    fclose(infile);

    if (byteErrors != 0)
    {
        printf("Verify failed\n");
        printf("Page errors: %d\n", pageErrors);
        printf("Byte errors: %d\n", totalErrors);
        return false;
    }

    printf("Verify successful\n");
    return true;
}

void
Flasher::read(const char* filename, long fsize)
{
    FILE* outfile;
    uint32_t pageSize = _flash->pageSize();
    uint8_t buffer[pageSize];
    uint32_t pageNum = 0;
    uint32_t numPages;
    size_t fbytes;

    if (fsize == 0)
        fsize = pageSize * _flash->numPages();

    outfile = fopen(filename, "wb");
    if (!outfile)
        throw FileOpenError(errno);

    try
    {
        numPages = (fsize + pageSize - 1) / pageSize;
        if (numPages > _flash->numPages())
            throw FileSizeError();

        printf("Read %ld bytes from flash\n", fsize);

        for (pageNum = 0; pageNum < numPages; pageNum++)
        {
            // updated from one print per 10 pages to one per 10 percent
            if ((pageNum < 10) || (pageNum % (numPages/10) == 0))
                progressBar(pageNum, numPages);

            _flash->readPage(pageNum, buffer);

            if (pageNum == numPages - 1 && fsize % pageSize > 0)
                pageSize = fsize % pageSize;
            fbytes = fwrite(buffer, 1, pageSize, outfile);
            if (fbytes != pageSize)
                throw FileShortError();
        }
        progressBar(pageNum, numPages);
        printf("\n");
    }
    catch(...)
    {
        fclose(outfile);
        throw;
    }
    fclose(outfile);
}

void
Flasher::lock(string& regionArg, bool enable)
{
    if (regionArg.empty())
    {
        printf("%s all regions\n", enable ? "Lock" : "Unlock");
        if (enable)
            _flash->lockAll();
        else
            _flash->unlockAll();
    }
    else
    {
        size_t pos = 0;
        size_t delim;
        uint32_t region;
        string sub;

        do
        {
            delim = regionArg.find(',', pos);
            sub = regionArg.substr(pos, delim - pos);
            region = strtol(sub.c_str(), NULL, 0);
            printf("%s region %d\n", enable ? "Lock" : "Unlock", region);
            _flash->setLockRegion(region, enable);
            pos = delim + 1;
        } while (delim != string::npos);
    }
}

void
Flasher::info(Samba& samba)
{
    bool first;

    printf("Device       : %s\n", _flash->name().c_str());
    printf("Chip ID      : %08x\n", samba.chipId());
    printf("Version      : %s\n", samba.version().c_str());
    printf("Address      : %d\n", _flash->address());
    printf("Pages        : %d\n", _flash->numPages());
    printf("Page Size    : %d bytes\n", _flash->pageSize());
    printf("Total Size   : %dKB\n", _flash->numPages() * _flash->pageSize() / 1024);
    printf("Planes       : %d\n", _flash->numPlanes());
    printf("Lock Regions : %d\n", _flash->lockRegions());
    printf("Locked       : ");
    first = true;
    for (uint32_t region = 0; region < _flash->lockRegions(); region++)
    {
        if (_flash->getLockRegion(region))
        {
            printf("%s%d", first ? "" : ",", region);
            first = false;
        }
    }
    printf("%s\n", first ? "none" : "");
    printf("Security     : %s\n", _flash->getSecurity() ? "true" : "false");
    if (_flash->canBootFlash())
        printf("Boot Flash   : %s\n", _flash->getBootFlash() ? "true" : "false");
    if (_flash->canBod())
        printf("BOD          : %s\n", _flash->getBod() ? "true" : "false");
    if (_flash->canBor())
        printf("BOR          : %s\n", _flash->getBor() ? "true" : "false");
    if (samba.isChipEraseAvailable())
        printf("Arduino      : FAST_CHIP_ERASE\n");
    if (samba.isWriteBufferAvailable())
        printf("Arduino      : FAST_MULTI_PAGE_WRITE\n");
    if (samba.isChecksumBufferAvailable())
        printf("Arduino      : CAN_CHECKSUM_MEMORY_BUFFER\n");
}
<|endoftext|>


<commit_before>#ifdef STAN_OPENCL
#include <stan/math/prim/mat.hpp>
#include <gtest/gtest.h>
#include <CL/cl.hpp>

TEST(MathMatrix, kernel_initialize) {
  stan::math::get_context();
  cl::Kernel kernel_transpose = stan::math::get_kernel("transpose");
      EXPECT_NO_THROW(cl::Kernel kernel_transpose
                      = stan::math::get_kernel("transpose"));
  EXPECT_NO_THROW(cl::Kernel kernel_copy = stan::math::get_kernel("copy"));
  EXPECT_NO_THROW(cl::Kernel kernel_zeros = stan::math::get_kernel("zeros"));
  EXPECT_NO_THROW(cl::Kernel kernel_identity
                  = stan::math::get_kernel("identity"));
  EXPECT_NO_THROW(cl::Kernel kernel_copy_triangular
                  = stan::math::get_kernel("copy_triangular"));
  EXPECT_NO_THROW(cl::Kernel kernel_scalar_copy_triangular_transposed
                  = stan::math::get_kernel("copy_triangular_transposed"));
  EXPECT_NO_THROW(cl::Kernel kernel_add = stan::math::get_kernel("add"));
  EXPECT_NO_THROW(cl::Kernel kernel_subtract
                  = stan::math::get_kernel("subtract"));
  EXPECT_NO_THROW(cl::Kernel kernel_copy_submatrix
                  = stan::math::get_kernel("copy_submatrix"));
  EXPECT_NO_THROW(cl::Kernel kernel_scalar_mul_diagonal
                  = stan::math::get_kernel("scalar_mul_diagonal"));
  EXPECT_NO_THROW(cl::Kernel kernel_scalar_mul
                  = stan::math::get_kernel("scalar_mul"));
  EXPECT_NO_THROW(cl::Kernel kernel_basic_multiply
                  = stan::math::get_kernel("basic_multiply"));
  EXPECT_NO_THROW(cl::Kernel kernel_multiply_self_transposed
                  = stan::math::get_kernel("multiply_self_transposed"));
  EXPECT_NO_THROW(cl::Kernel kernel_lower_tri_inv_step1
                  = stan::math::get_kernel("lower_tri_inv_step1"));
  EXPECT_NO_THROW(cl::Kernel kernel_lower_tri_inv_step2
                  = stan::math::get_kernel("lower_tri_inv_step2"));
  EXPECT_NO_THROW(cl::Kernel kernel_lower_tri_inv_step3
                  = stan::math::get_kernel("lower_tri_inv_step3"));
  EXPECT_NO_THROW(cl::Kernel kernel_chol_block
                  = stan::math::get_kernel("cholesky_block"));
  EXPECT_NO_THROW(cl::Kernel kernel_check_nan
                  = stan::math::get_kernel("check_nan"));
  EXPECT_NO_THROW(cl::Kernel kernel_check_diagonal_zeros
                  = stan::math::get_kernel("check_diagonal_zeros"));
  EXPECT_NO_THROW(cl::Kernel kernel_check_symmetric
                  = stan::math::get_kernel("check_symmetric"));
}

#else

#include <gtest/gtest.h>
TEST(MathMatrix, kernel_initializeDummy) { EXPECT_NO_THROW(); }
#endif
<commit_msg>[Jenkins] auto-formatting by clang-format version 5.0.1-svn319952-1~exp1 (branches/release_50)<commit_after>#ifdef STAN_OPENCL
#include <stan/math/prim/mat.hpp>
#include <gtest/gtest.h>
#include <CL/cl.hpp>

TEST(MathMatrix, kernel_initialize) {
  stan::math::get_context();
  cl::Kernel kernel_transpose = stan::math::get_kernel("transpose");
  EXPECT_NO_THROW(cl::Kernel kernel_transpose
                  = stan::math::get_kernel("transpose"));
  EXPECT_NO_THROW(cl::Kernel kernel_copy = stan::math::get_kernel("copy"));
  EXPECT_NO_THROW(cl::Kernel kernel_zeros = stan::math::get_kernel("zeros"));
  EXPECT_NO_THROW(cl::Kernel kernel_identity
                  = stan::math::get_kernel("identity"));
  EXPECT_NO_THROW(cl::Kernel kernel_copy_triangular
                  = stan::math::get_kernel("copy_triangular"));
  EXPECT_NO_THROW(cl::Kernel kernel_scalar_copy_triangular_transposed
                  = stan::math::get_kernel("copy_triangular_transposed"));
  EXPECT_NO_THROW(cl::Kernel kernel_add = stan::math::get_kernel("add"));
  EXPECT_NO_THROW(cl::Kernel kernel_subtract
                  = stan::math::get_kernel("subtract"));
  EXPECT_NO_THROW(cl::Kernel kernel_copy_submatrix
                  = stan::math::get_kernel("copy_submatrix"));
  EXPECT_NO_THROW(cl::Kernel kernel_scalar_mul_diagonal
                  = stan::math::get_kernel("scalar_mul_diagonal"));
  EXPECT_NO_THROW(cl::Kernel kernel_scalar_mul
                  = stan::math::get_kernel("scalar_mul"));
  EXPECT_NO_THROW(cl::Kernel kernel_basic_multiply
                  = stan::math::get_kernel("basic_multiply"));
  EXPECT_NO_THROW(cl::Kernel kernel_multiply_self_transposed
                  = stan::math::get_kernel("multiply_self_transposed"));
  EXPECT_NO_THROW(cl::Kernel kernel_lower_tri_inv_step1
                  = stan::math::get_kernel("lower_tri_inv_step1"));
  EXPECT_NO_THROW(cl::Kernel kernel_lower_tri_inv_step2
                  = stan::math::get_kernel("lower_tri_inv_step2"));
  EXPECT_NO_THROW(cl::Kernel kernel_lower_tri_inv_step3
                  = stan::math::get_kernel("lower_tri_inv_step3"));
  EXPECT_NO_THROW(cl::Kernel kernel_chol_block
                  = stan::math::get_kernel("cholesky_block"));
  EXPECT_NO_THROW(cl::Kernel kernel_check_nan
                  = stan::math::get_kernel("check_nan"));
  EXPECT_NO_THROW(cl::Kernel kernel_check_diagonal_zeros
                  = stan::math::get_kernel("check_diagonal_zeros"));
  EXPECT_NO_THROW(cl::Kernel kernel_check_symmetric
                  = stan::math::get_kernel("check_symmetric"));
}

#else

#include <gtest/gtest.h>
TEST(MathMatrix, kernel_initializeDummy) { EXPECT_NO_THROW(); }
#endif
<|endoftext|>


<commit_before>/* Copyright (c) 2016, Fengping Bao <jamol@live.com>
 *
 * 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" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "HPacker.h"
#include "hpack_huffman_table.h"

#include <math.h>

namespace hpack {

static char *huffDecodeBits(char *dst, uint8_t bits, uint8_t *state, bool *ending) {
    const auto &entry = huff_decode_table[*state][bits];

    if ((entry.flags & NGHTTP2_HUFF_FAIL) != 0)
        return nullptr;
    if ((entry.flags & NGHTTP2_HUFF_SYM) != 0)
        *dst++ = entry.sym;
    *state = entry.state;
    *ending = (entry.flags & NGHTTP2_HUFF_ACCEPTED) != 0;

    return dst;
}

static int huffDecode(const uint8_t *src, size_t len, std::string &str) {
    uint8_t state = 0;
    bool ending = false;
    const uint8_t *src_end = src + len;

    std::vector<char> sbuf;
    sbuf.resize(2*len);
    char *ptr = &sbuf[0];

    for (; src != src_end; ++src) {
        if ((ptr = huffDecodeBits(ptr, *src >> 4, &state, &ending)) == nullptr)
            return -1;
        if ((ptr = huffDecodeBits(ptr, *src & 0xf, &state, &ending)) == nullptr)
            return -1;
    }
    if (!ending) {
        return -1;
    }
    int slen = int(ptr - &sbuf[0]);
    str.assign(&sbuf[0], slen);
    return slen;
}

static int huffEncode(const std::string &str, uint8_t *buf, size_t len) {
    uint8_t *ptr = buf;
    const uint8_t *end = buf + len;
    const char* src = str.c_str();
    const char* src_end = src + str.length();

    uint64_t current = 0;
    uint32_t n = 0;

    for (; src != src_end;) {
        const auto &sym = huff_sym_table[*src++];
        uint32_t code = sym.code;
        uint32_t nbits = sym.nbits;

        current <<= nbits;
        current |= code;
        n += nbits;

        while (n >= 8) {
            n -= 8;
            *ptr++ = current >> n;
        }
    }

    if (n > 0) {
        current <<= (8 - n);
        current |= (0xFF >> n);
        *ptr++ = current;
    }

    return int(ptr - buf);
}

static uint32_t huffEncodeLength(const std::string &str)
{
    uint32_t len = 0;
    for (char c : str) {
        len += huff_sym_table[c].nbits;
    }
    return (len + 7) >> 3;
}

static int encodeInteger(uint8_t N, uint64_t I, uint8_t *buf, size_t len) {
    uint8_t *ptr = buf;
    const uint8_t *end = buf + len;
    if (ptr == end) {
        return -1;
    }
    uint8_t NF = (1 << N) - 1;
    if (I < NF) {
        *ptr &= NF ^ 0xFF;
        *ptr |= I;
        return 1;
    }
    *ptr++ |= NF;
    I -= NF;
    while (ptr < end && I >= 128) {
        *ptr++ = I % 128 + 128;
        I /= 128;
    }
    if (ptr == end) {
        return -1;
    }
    *ptr++ = I;

    return int(ptr - buf);
}

static int encodeString(const std::string &str, uint8_t *buf, size_t len) {
    uint8_t *ptr = buf;
    uint8_t *end = buf + len;

    int slen = int(str.length());
    int hlen = huffEncodeLength(str);
    if (hlen < slen) {
        *ptr = 0x80;
        int ret = encodeInteger(7, hlen, ptr, end - ptr);
        if (ret <= 0) {
            return -1;
        }
        ptr += ret;
        ret = huffEncode(str, ptr, end - ptr);
        if (ret < 0) {
            return -1;
        }
        ptr += ret;
    } else {
        *ptr = 0;
        int ret = encodeInteger(7, slen, ptr, end - ptr);
        if (ret <= 0) {
            return -1;
        }
        ptr += ret;
        if (end - ptr < str.length()) {
            return -1;
        }
        memcpy(ptr, str.c_str(), str.length());
        ptr += str.length();
    }

    return int(ptr - buf);
}

static int decodeInteger(uint8_t N, const uint8_t *buf, size_t len, uint64_t &I) {
    if (N > 8) {
        return -1;
    }
    const uint8_t *ptr = buf;
    const uint8_t *end = buf + len;
    if (ptr == end) {
        return -1;
    }
    uint8_t NF = (1 << N) - 1;
    uint8_t prefix = (*ptr++) & NF;
    if (prefix < NF) {
        I = prefix;
        return 1;
    }
    if (ptr == end) {
        return -1;
    }
    int m = 0;
    uint64_t u64 = prefix;
    uint8_t b = 0;
    do {
        b = *ptr++;
        u64 += (b & 127) * pow(2, m);
        m += 7;
    } while (ptr < end && (b & 128));
    if (ptr == end && (b & 128)) {
        return -1;
    }
    I = u64;

    return int(ptr - buf);
}

static int decodeString(const uint8_t *buf, size_t len, std::string &str)
{
    const uint8_t *ptr = buf;
    const uint8_t *end = buf + len;
    if (ptr == end) {
        return -1;
    }
    bool H = *ptr & 0x80;
    uint64_t slen = 0;
    int ret = decodeInteger(7, ptr, end - ptr, slen);
    if (ret <= 0) {
        return -1;
    }
    ptr += ret;
    if ( slen > end - ptr) {
        return -1;
    }
    if (H) {
        if(huffDecode(ptr, slen, str) < 0) {
            return -1;
        }
    } else {
        str.assign((const char*)ptr, slen);
    }
    ptr += slen;

    return int(ptr - buf);
}

enum class PrefixType {
    INDEXED_HEADER,
    LITERAL_HEADER_WITH_INDEXING,
    LITERAL_HEADER_WITHOUT_INDEXING,
    TABLE_SIZE_UPDATE
};

static int decodePrefix(const uint8_t *buf, size_t len, PrefixType &type, uint64_t &I) {
    const uint8_t *ptr = buf;
    const uint8_t *end = buf + len;
    uint8_t N = 0;
    if (*ptr & 0x80) {
        N = 7;
        type = PrefixType::INDEXED_HEADER;
    } else if (*ptr & 0x40) {
        N = 6;
        type = PrefixType::LITERAL_HEADER_WITH_INDEXING;
    } else if (*ptr & 0x20) {
        N = 5;
        type = PrefixType::TABLE_SIZE_UPDATE;
    } else {
        N = 4;
        type = PrefixType::LITERAL_HEADER_WITHOUT_INDEXING;
    }
    int ret = decodeInteger(N, ptr, end - ptr, I);
    if (ret <= 0) {
        return -1;
    }
    ptr += ret;
    return int(ptr - buf);
}

HPacker::IndexingType HPacker::getIndexingType(const std::string &name, const std::string &value)
{
    if (query_cb_) {
        return query_cb_(name, value);
    }
    if (name == "cookie" || name == ":authority" || name == "user-agent" || name == "pragma") {
        return IndexingType::ALL;
    }
    return IndexingType::NONE;
}

int HPacker::encodeSizeUpdate(int sz, uint8_t *buf, size_t len)
{
    uint8_t *ptr = buf;
    const uint8_t *end = buf + len;
    *ptr = 0x20;
    int ret = encodeInteger(5, sz, ptr, end - ptr);
    if (ret <= 0) {
        return -1;
    }
    ptr += ret;
    return int(ptr - buf);
}

int HPacker::encodeHeader(const std::string &name, const std::string &value, uint8_t *buf, size_t len)
{
    uint8_t *ptr = buf;
    const uint8_t *end = buf + len;

    bool valueIndexed = false;
    int index = table_.getIndex(name, value, valueIndexed);
    bool addToTable = false;
    if (index != -1) {
        uint8_t N = 0;
        if (valueIndexed) { // name and value indexed
            *ptr = 0x80;
            N = 7;
        } else { // name indexed
            IndexingType idxType = getIndexingType(name, value);
            if (idxType == IndexingType::ALL) {
                *ptr = 0x40;
                N = 6;
                addToTable = true;
            } else {
                *ptr = 0x10;
                N = 4;
            }
        }
        // encode prefix Bits
        int ret = encodeInteger(N, index, ptr, end - ptr);
        if (ret <= 0) {
            return -1;
        }
        ptr += ret;
        if (!valueIndexed) {
            ret = encodeString(value, ptr, end - ptr);
            if (ret <= 0) {
                return -1;
            }
            ptr += ret;
        }
    } else {
        IndexingType idxType = getIndexingType(name, value);
        if (idxType == IndexingType::ALL) {
            *ptr++ = 0x40;
            addToTable = true;
        } else {
            *ptr++ = 0x10;
        }
        int ret = encodeString(name, ptr, end - ptr);
        if (ret <= 0) {
            return -1;
        }
        ptr += ret;
        ret = encodeString(value, ptr, end - ptr);
        if (ret <= 0) {
            return -1;
        }
        ptr += ret;
    }
    if (addToTable) {
        table_.addHeader(name, value);
    }
    return int(ptr - buf);
}

int HPacker::encode(const KeyValueVector &headers, uint8_t *buf, size_t len) {
    table_.setMode(true);
    uint8_t *ptr = buf;
    const uint8_t *end = buf + len;

    if (updateTableSize_) {
        updateTableSize_ = false;
        int ret = encodeSizeUpdate(int(table_.getLimitSize()), ptr, end - ptr);
        if (ret <= 0) {
            return -1;
        }
        ptr += ret;
    }
    for (const auto &hdr : headers) {
        int ret = encodeHeader(hdr.first, hdr.second, ptr, end - ptr);
        if (ret <= 0) {
            return -1;
        }
        ptr += ret;
    }
    return int(ptr - buf);
}

int HPacker::decode(const uint8_t *buf, size_t len, KeyValueVector &headers) {
    table_.setMode(false);
    const uint8_t *ptr = buf;
    const uint8_t *end = buf + len;
    headers.clear();

    while (ptr < end) {
        std::string name;
        std::string value;
        PrefixType type;
        uint64_t I = 0;
        int ret = decodePrefix(ptr, end - ptr, type, I);
        if (ret <= 0) {
            return -1;
        }
        ptr += ret;
        if (PrefixType::INDEXED_HEADER == type) {
            if (!table_.getIndexedName(int(I), name) || !table_.getIndexedValue(int(I), value)) {
                return -1;
            }
        } else if (PrefixType::LITERAL_HEADER_WITH_INDEXING == type ||
                   PrefixType::LITERAL_HEADER_WITHOUT_INDEXING == type) {
            if (0 == I) {
                ret = decodeString(ptr, end - ptr, name);
                if (ret <= 0) {
                    return -1;
                }
                ptr += ret;
            } else if (!table_.getIndexedName(int(I), name)) {
                return -1;
            }
            ret = decodeString(ptr, end - ptr, value);
            if (ret <= 0) {
                return -1;
            }
            ptr += ret;
            if (PrefixType::LITERAL_HEADER_WITH_INDEXING == type) {
                table_.addHeader(name, value);
            }
        } else if (PrefixType::TABLE_SIZE_UPDATE == type) {
            if (I > table_.getMaxSize()) {
                return -1;
            }
            table_.updateLimitSize(I);
            continue;
        }
        headers.emplace_back(std::make_pair(name, value));
    }
    return int(len);
}

} // namespace hpack
<commit_msg>fix build failure on linux<commit_after>/* Copyright (c) 2016, Fengping Bao <jamol@live.com>
 *
 * 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" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "HPacker.h"
#include "hpack_huffman_table.h"

#include <math.h>
#include <string.h> // for memcpy

namespace hpack {

static char *huffDecodeBits(char *dst, uint8_t bits, uint8_t *state, bool *ending) {
    const auto &entry = huff_decode_table[*state][bits];

    if ((entry.flags & NGHTTP2_HUFF_FAIL) != 0)
        return nullptr;
    if ((entry.flags & NGHTTP2_HUFF_SYM) != 0)
        *dst++ = entry.sym;
    *state = entry.state;
    *ending = (entry.flags & NGHTTP2_HUFF_ACCEPTED) != 0;

    return dst;
}

static int huffDecode(const uint8_t *src, size_t len, std::string &str) {
    uint8_t state = 0;
    bool ending = false;
    const uint8_t *src_end = src + len;

    std::vector<char> sbuf;
    sbuf.resize(2*len);
    char *ptr = &sbuf[0];

    for (; src != src_end; ++src) {
        if ((ptr = huffDecodeBits(ptr, *src >> 4, &state, &ending)) == nullptr)
            return -1;
        if ((ptr = huffDecodeBits(ptr, *src & 0xf, &state, &ending)) == nullptr)
            return -1;
    }
    if (!ending) {
        return -1;
    }
    int slen = int(ptr - &sbuf[0]);
    str.assign(&sbuf[0], slen);
    return slen;
}

static int huffEncode(const std::string &str, uint8_t *buf, size_t len) {
    uint8_t *ptr = buf;
    const uint8_t *end = buf + len;
    const char* src = str.c_str();
    const char* src_end = src + str.length();

    uint64_t current = 0;
    uint32_t n = 0;

    for (; src != src_end;) {
        const auto &sym = huff_sym_table[*src++];
        uint32_t code = sym.code;
        uint32_t nbits = sym.nbits;

        current <<= nbits;
        current |= code;
        n += nbits;

        while (n >= 8) {
            n -= 8;
            *ptr++ = current >> n;
        }
    }

    if (n > 0) {
        current <<= (8 - n);
        current |= (0xFF >> n);
        *ptr++ = current;
    }

    return int(ptr - buf);
}

static uint32_t huffEncodeLength(const std::string &str)
{
    uint32_t len = 0;
    for (char c : str) {
        len += huff_sym_table[c].nbits;
    }
    return (len + 7) >> 3;
}

static int encodeInteger(uint8_t N, uint64_t I, uint8_t *buf, size_t len) {
    uint8_t *ptr = buf;
    const uint8_t *end = buf + len;
    if (ptr == end) {
        return -1;
    }
    uint8_t NF = (1 << N) - 1;
    if (I < NF) {
        *ptr &= NF ^ 0xFF;
        *ptr |= I;
        return 1;
    }
    *ptr++ |= NF;
    I -= NF;
    while (ptr < end && I >= 128) {
        *ptr++ = I % 128 + 128;
        I /= 128;
    }
    if (ptr == end) {
        return -1;
    }
    *ptr++ = I;

    return int(ptr - buf);
}

static int encodeString(const std::string &str, uint8_t *buf, size_t len) {
    uint8_t *ptr = buf;
    uint8_t *end = buf + len;

    int slen = int(str.length());
    int hlen = huffEncodeLength(str);
    if (hlen < slen) {
        *ptr = 0x80;
        int ret = encodeInteger(7, hlen, ptr, end - ptr);
        if (ret <= 0) {
            return -1;
        }
        ptr += ret;
        ret = huffEncode(str, ptr, end - ptr);
        if (ret < 0) {
            return -1;
        }
        ptr += ret;
    } else {
        *ptr = 0;
        int ret = encodeInteger(7, slen, ptr, end - ptr);
        if (ret <= 0) {
            return -1;
        }
        ptr += ret;
        if (end - ptr < str.length()) {
            return -1;
        }
        memcpy(ptr, str.c_str(), str.length());
        ptr += str.length();
    }

    return int(ptr - buf);
}

static int decodeInteger(uint8_t N, const uint8_t *buf, size_t len, uint64_t &I) {
    if (N > 8) {
        return -1;
    }
    const uint8_t *ptr = buf;
    const uint8_t *end = buf + len;
    if (ptr == end) {
        return -1;
    }
    uint8_t NF = (1 << N) - 1;
    uint8_t prefix = (*ptr++) & NF;
    if (prefix < NF) {
        I = prefix;
        return 1;
    }
    if (ptr == end) {
        return -1;
    }
    int m = 0;
    uint64_t u64 = prefix;
    uint8_t b = 0;
    do {
        b = *ptr++;
        u64 += (b & 127) * pow(2, m);
        m += 7;
    } while (ptr < end && (b & 128));
    if (ptr == end && (b & 128)) {
        return -1;
    }
    I = u64;

    return int(ptr - buf);
}

static int decodeString(const uint8_t *buf, size_t len, std::string &str)
{
    const uint8_t *ptr = buf;
    const uint8_t *end = buf + len;
    if (ptr == end) {
        return -1;
    }
    bool H = *ptr & 0x80;
    uint64_t slen = 0;
    int ret = decodeInteger(7, ptr, end - ptr, slen);
    if (ret <= 0) {
        return -1;
    }
    ptr += ret;
    if ( slen > end - ptr) {
        return -1;
    }
    if (H) {
        if(huffDecode(ptr, slen, str) < 0) {
            return -1;
        }
    } else {
        str.assign((const char*)ptr, slen);
    }
    ptr += slen;

    return int(ptr - buf);
}

enum class PrefixType {
    INDEXED_HEADER,
    LITERAL_HEADER_WITH_INDEXING,
    LITERAL_HEADER_WITHOUT_INDEXING,
    TABLE_SIZE_UPDATE
};

static int decodePrefix(const uint8_t *buf, size_t len, PrefixType &type, uint64_t &I) {
    const uint8_t *ptr = buf;
    const uint8_t *end = buf + len;
    uint8_t N = 0;
    if (*ptr & 0x80) {
        N = 7;
        type = PrefixType::INDEXED_HEADER;
    } else if (*ptr & 0x40) {
        N = 6;
        type = PrefixType::LITERAL_HEADER_WITH_INDEXING;
    } else if (*ptr & 0x20) {
        N = 5;
        type = PrefixType::TABLE_SIZE_UPDATE;
    } else {
        N = 4;
        type = PrefixType::LITERAL_HEADER_WITHOUT_INDEXING;
    }
    int ret = decodeInteger(N, ptr, end - ptr, I);
    if (ret <= 0) {
        return -1;
    }
    ptr += ret;
    return int(ptr - buf);
}

HPacker::IndexingType HPacker::getIndexingType(const std::string &name, const std::string &value)
{
    if (query_cb_) {
        return query_cb_(name, value);
    }
    if (name == "cookie" || name == ":authority" || name == "user-agent" || name == "pragma") {
        return IndexingType::ALL;
    }
    return IndexingType::NONE;
}

int HPacker::encodeSizeUpdate(int sz, uint8_t *buf, size_t len)
{
    uint8_t *ptr = buf;
    const uint8_t *end = buf + len;
    *ptr = 0x20;
    int ret = encodeInteger(5, sz, ptr, end - ptr);
    if (ret <= 0) {
        return -1;
    }
    ptr += ret;
    return int(ptr - buf);
}

int HPacker::encodeHeader(const std::string &name, const std::string &value, uint8_t *buf, size_t len)
{
    uint8_t *ptr = buf;
    const uint8_t *end = buf + len;

    bool valueIndexed = false;
    int index = table_.getIndex(name, value, valueIndexed);
    bool addToTable = false;
    if (index != -1) {
        uint8_t N = 0;
        if (valueIndexed) { // name and value indexed
            *ptr = 0x80;
            N = 7;
        } else { // name indexed
            IndexingType idxType = getIndexingType(name, value);
            if (idxType == IndexingType::ALL) {
                *ptr = 0x40;
                N = 6;
                addToTable = true;
            } else {
                *ptr = 0x10;
                N = 4;
            }
        }
        // encode prefix Bits
        int ret = encodeInteger(N, index, ptr, end - ptr);
        if (ret <= 0) {
            return -1;
        }
        ptr += ret;
        if (!valueIndexed) {
            ret = encodeString(value, ptr, end - ptr);
            if (ret <= 0) {
                return -1;
            }
            ptr += ret;
        }
    } else {
        IndexingType idxType = getIndexingType(name, value);
        if (idxType == IndexingType::ALL) {
            *ptr++ = 0x40;
            addToTable = true;
        } else {
            *ptr++ = 0x10;
        }
        int ret = encodeString(name, ptr, end - ptr);
        if (ret <= 0) {
            return -1;
        }
        ptr += ret;
        ret = encodeString(value, ptr, end - ptr);
        if (ret <= 0) {
            return -1;
        }
        ptr += ret;
    }
    if (addToTable) {
        table_.addHeader(name, value);
    }
    return int(ptr - buf);
}

int HPacker::encode(const KeyValueVector &headers, uint8_t *buf, size_t len) {
    table_.setMode(true);
    uint8_t *ptr = buf;
    const uint8_t *end = buf + len;

    if (updateTableSize_) {
        updateTableSize_ = false;
        int ret = encodeSizeUpdate(int(table_.getLimitSize()), ptr, end - ptr);
        if (ret <= 0) {
            return -1;
        }
        ptr += ret;
    }
    for (const auto &hdr : headers) {
        int ret = encodeHeader(hdr.first, hdr.second, ptr, end - ptr);
        if (ret <= 0) {
            return -1;
        }
        ptr += ret;
    }
    return int(ptr - buf);
}

int HPacker::decode(const uint8_t *buf, size_t len, KeyValueVector &headers) {
    table_.setMode(false);
    const uint8_t *ptr = buf;
    const uint8_t *end = buf + len;
    headers.clear();

    while (ptr < end) {
        std::string name;
        std::string value;
        PrefixType type;
        uint64_t I = 0;
        int ret = decodePrefix(ptr, end - ptr, type, I);
        if (ret <= 0) {
            return -1;
        }
        ptr += ret;
        if (PrefixType::INDEXED_HEADER == type) {
            if (!table_.getIndexedName(int(I), name) || !table_.getIndexedValue(int(I), value)) {
                return -1;
            }
        } else if (PrefixType::LITERAL_HEADER_WITH_INDEXING == type ||
                   PrefixType::LITERAL_HEADER_WITHOUT_INDEXING == type) {
            if (0 == I) {
                ret = decodeString(ptr, end - ptr, name);
                if (ret <= 0) {
                    return -1;
                }
                ptr += ret;
            } else if (!table_.getIndexedName(int(I), name)) {
                return -1;
            }
            ret = decodeString(ptr, end - ptr, value);
            if (ret <= 0) {
                return -1;
            }
            ptr += ret;
            if (PrefixType::LITERAL_HEADER_WITH_INDEXING == type) {
                table_.addHeader(name, value);
            }
        } else if (PrefixType::TABLE_SIZE_UPDATE == type) {
            if (I > table_.getMaxSize()) {
                return -1;
            }
            table_.updateLimitSize(I);
            continue;
        }
        headers.emplace_back(std::make_pair(name, value));
    }
    return int(len);
}

} // namespace hpack
<|endoftext|>


<commit_before>/*
    Flexisip, a flexible SIP proxy server with media capabilities.
    Copyright (C) 2014  Belledonne Communications SARL.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    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/>.
*/

#include "monitor.hh"
#include "configmanager.hh"

using namespace std;

Monitor::Init Monitor::sInit;
const string Monitor::PYTHON_INTERPRETOR = "/usr/bin/python2";
const string Monitor::SCRIPT_PATH = "/home/francois/projects/flexisip/flexisip_monitor/flexisip_monitor.py";

Monitor::Init::Init() {
	ConfigItemDescriptor items[] = {
		{ Boolean   , "enable"       , "Enable or disable the Flexisip monitor daemon", "false" },
		{ StringList, "identities"   , "List of SIP identities which will be used to test the Flexisip nodes. There must be exactly as many SIP identities as Flexisip nodes", ""},
		{ Integer   , "test-interval", "Time between two consecutive tests", "30"},
		{ String    , "logfile"      , "Path to the log file", "/etc/flexisip/flexisip_monitor.log"},
		{ Integer   , "switch-port"  , "Port to open/close folowing the test succeed or not", "12345"},
		config_item_end
	};

	GenericStruct *s = new GenericStruct("monitor", "Flexisip monitor parameters", 0);
	GenericManager::get()->getRoot()->addChild(s);
	s->addChildrenValues(items);
}

void Monitor::exec(int socket) {
	GenericStruct *monitorParams;
	try{
		monitorParams = GenericManager::get()->getRoot()->get<GenericStruct>("monitor");
	}catch(FlexisipException &e) {
		LOGE(e.str().c_str());
		exit(-1);
	}
	string interval = monitorParams->get<ConfigValue>("test-interval")->get();
	string logfile = monitorParams->get<ConfigString>("logfile")->read();
	string port = monitorParams->get<ConfigValue>("switch-port")->get();

	GenericStruct *authParams;
	try{
		authParams = GenericManager::get()->getRoot()->get<GenericStruct>("module::Authentication");
	}catch(FlexisipException &e){
		LOGE(e.str().c_str());
		exit(-1);
	}

	list<string> identities = monitorParams->get<ConfigStringList>("identities")->read();
	list<string> trustedHosts = authParams->get<ConfigStringList>("trusted-hosts")->read();
	if(identities.size() != trustedHosts.size()) {
		LOGE("Flexisip monitor: there is not as many SIP indentities as trusted-hosts");
		exit(-1);
	}

	list<string> proxyConfigs;
	list<string>::const_iterator itI;
	list<string>::const_iterator itH;
	for(itI = identities.cbegin(), itH = trustedHosts.cbegin();
		itI != identities.cend();
		itI++, itH++) {
		string proxyURI = string("sip:") + itH->data() + string(";transport=tls");
		string proxyConfig = itI->data() + string("/") + proxyURI;
		proxyConfigs.push_back(proxyConfig);
	}

	char **args = new char *[proxyConfigs.size() + 9];
	args[0] = strdup(PYTHON_INTERPRETOR.c_str());
	args[1] = strdup(SCRIPT_PATH.c_str());
	args[2] = strdup("--interval");
	args[3] = strdup(interval.c_str());
	args[4] = strdup("--log");
	args[5] = strdup(logfile.c_str());
	args[6] = strdup("--port");
	args[7] = strdup(port.c_str());
	int i=6;
	for(string proxyConfig : proxyConfigs) {
		args[i] = strdup(proxyConfig.c_str());
		i++;
	}
	args[i] = NULL;

	if(write(socket, "ok", 3) == -1) {
		exit(-1);
	}
	close(socket);

	execvp(args[0], args);
}
<commit_msg>Fix conf reading issue<commit_after>/*
    Flexisip, a flexible SIP proxy server with media capabilities.
    Copyright (C) 2014  Belledonne Communications SARL.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    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/>.
*/

#include "monitor.hh"
#include "configmanager.hh"
#include "agent.hh"

using namespace std;

Monitor::Init Monitor::sInit;
const string Monitor::PYTHON_INTERPRETOR = "/usr/bin/python2";
const string Monitor::SCRIPT_PATH = "/home/francois/projects/flexisip/flexisip_monitor/flexisip_monitor.py";

Monitor::Init::Init() {
	ConfigItemDescriptor items[] = {
		{ Boolean   , "enable"       , "Enable or disable the Flexisip monitor daemon", "false" },
		{ StringList, "identities"   , "List of SIP identities which will be used to test the Flexisip nodes. There must be exactly as many SIP identities as Flexisip nodes", ""},
		{ Integer   , "test-interval", "Time between two consecutive tests", "30"},
		{ String    , "logfile"      , "Path to the log file", "/etc/flexisip/flexisip_monitor.log"},
		{ Integer   , "switch-port"  , "Port to open/close folowing the test succeed or not", "12345"},
		config_item_end
	};

	GenericStruct *s = new GenericStruct("monitor", "Flexisip monitor parameters", 0);
	GenericManager::get()->getRoot()->addChild(s);
	s->addChildrenValues(items);
}

void Monitor::exec(int socket) {
	// Create a temporary agent to load all modules
	su_root_t *root = NULL;
	shared_ptr<Agent> a = make_shared<Agent>(root);
	GenericManager::get()->loadStrict();

	GenericStruct *monitorParams = GenericManager::get()->getRoot()->get<GenericStruct>("monitor");
	string interval = monitorParams->get<ConfigValue>("test-interval")->get();
	string logfile = monitorParams->get<ConfigString>("logfile")->read();
	string port = monitorParams->get<ConfigValue>("switch-port")->get();

	GenericStruct *authParams = GenericManager::get()->getRoot()->get<GenericStruct>("module::Authentication");
	list<string> trustedHosts = authParams->get<ConfigStringList>("trusted-hosts")->read();
	list<string> identities = monitorParams->get<ConfigStringList>("identities")->read();

	if(identities.size() != trustedHosts.size()) {
		LOGE("Flexisip monitor: there is not as many SIP indentities as trusted-hosts");
		exit(-1);
	}

	list<string> proxyConfigs;
	list<string>::const_iterator itI;
	list<string>::const_iterator itH;
	for(itI = identities.cbegin(), itH = trustedHosts.cbegin();
		itI != identities.cend();
		itI++, itH++) {
		string proxyURI = string("sip:") + itH->data() + string(";transport=tls");
		string proxyConfig = itI->data() + string("/") + proxyURI;
		proxyConfigs.push_back(proxyConfig);
	}

	char **args = new char *[proxyConfigs.size() + 9];
	args[0] = strdup(PYTHON_INTERPRETOR.c_str());
	args[1] = strdup(SCRIPT_PATH.c_str());
	args[2] = strdup("--interval");
	args[3] = strdup(interval.c_str());
	args[4] = strdup("--log");
	args[5] = strdup(logfile.c_str());
	args[6] = strdup("--port");
	args[7] = strdup(port.c_str());
	int i=6;
	for(string proxyConfig : proxyConfigs) {
		args[i] = strdup(proxyConfig.c_str());
		i++;
	}
	args[i] = NULL;

	if(write(socket, "ok", 3) == -1) {
		exit(-1);
	}
	close(socket);

	execvp(args[0], args);
}
<|endoftext|>


<commit_before>/*
 * A wrapper for hstock/stock that allows multiple users of one
 * stock_item.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "mstock.h"
#include "hstock.h"
#include "stock.h"
#include "hashmap.h"
#include "pool.h"
#include "lease.h"

#include <daemon/log.h>

#include <map>
#include <list>
#include <string>

#include <assert.h>

struct mstock {};

class MultiStock : public mstock {
    class Domain;
    typedef std::map<std::string, Domain> DomainMap;

    class Domain {
        class Item;
        typedef std::list<Item> ItemList;

        class Item {
            struct Lease : list_head {
                static const struct lease lease;

                const ItemList::iterator item;

                Lease(ItemList::iterator _item):item(_item) {}

                void Release(bool _reuse) {
                    item->DeleteLease(this, _reuse);
                }

                static void Release(bool reuse, void *ctx) {
                    ((Lease *)ctx)->Release(reuse);
                }
            };

            const DomainMap::iterator domain;

            const unsigned max_leases;

            stock_item &item;

            unsigned n_leases;
            list_head leases;

            bool reuse;

        public:
            Item(DomainMap::iterator _domain, unsigned _max_leases,
                 stock_item &_item)
                :domain(_domain), max_leases(_max_leases), item(_item),
                 n_leases(0), reuse(true) {
                list_init(&leases);
            }

            Item(const Item &) = delete;

            ~Item() {
                assert(n_leases == 0);
                assert(list_empty(&leases));

                domain->second.Put(domain->first.c_str(), item, reuse);
            }

            bool IsFull() const {
                return n_leases >= max_leases;
            }

            bool CanUse() const {
                return reuse && !IsFull();
            }

        private:
            Lease &AddLease(ItemList::iterator i) {
                assert(&*i == this);

                ++n_leases;

                Lease *lease = new Lease(i);
                list_add(lease, &leases);
                return *lease;
            }

        public:
            void AddLease(ItemList::iterator i,
                          const stock_get_handler &handler, void *ctx,
                          struct lease_ref &lease_ref) {
                assert(&*i == this);

                Lease &lease = AddLease(i);
                lease_ref_set(&lease_ref, &Lease::lease, &lease);

                handler.ready(&item, ctx);
            }

            stock_item *AddLease(ItemList::iterator i,
                                 struct lease_ref &lease_ref) {
                assert(&*i == this);

                Lease &lease = AddLease(i);
                lease_ref_set(&lease_ref, &Lease::lease, &lease);
                return &item;
            }

            void DeleteLease(Lease *lease, bool _reuse) {
                reuse &= _reuse;

                auto ii = lease->item;

                assert(n_leases > 0);
                list_remove(lease);
                delete lease;

                --n_leases;

                if (n_leases == 0)
                    domain->second.DeleteItem(ii);
            }
        };

        MultiStock &stock;

        struct pool *pool;

        ItemList items;

    public:
        Domain(MultiStock &_stock, struct pool *_pool)
            :stock(_stock), pool(_pool) {
        }

        Domain(Domain &&other)
            :stock(other.stock), pool(other.pool) {
            assert(other.items.empty());

            other.pool = nullptr;
        }

        Domain(const Domain &) = delete;

        ~Domain() {
            assert(items.empty());

            if (pool != nullptr)
                pool_unref(pool);
        }

        ItemList::iterator FindUsableItem() {
            for (auto i = items.begin(), end = items.end(); i != end; ++i)
                if (i->CanUse())
                    return i;

            return items.end();
        }

        ItemList::iterator AddItem(DomainMap::iterator di,
                                   unsigned max_leases,
                                   stock_item &si) {
            assert(&di->second == this);

            items.emplace_front(di, max_leases, si);
            return items.begin();
        }

        stock_item *GetNow(DomainMap::iterator di,
                           struct pool *caller_pool,
                           const char *uri, void *info,
                           unsigned max_leases,
                           struct lease_ref &lease_ref,
                           GError **error_r);

        void DeleteItem(ItemList::iterator &ii) {
            ii = items.erase(ii);
        }

        void Put(const char *uri, stock_item &item, bool reuse) {
            stock.Put(uri, item, reuse);
        }
    };

    struct pool *pool;

    DomainMap domains;

    struct hstock *hstock;

public:
    MultiStock(struct pool *_pool, struct hstock *_hstock)
        :pool(pool_new_libc(_pool, "mstock")),
         hstock(_hstock) {}

    MultiStock(const MultiStock &) = delete;

    ~MultiStock() {
        hstock_free(hstock);
        pool_unref(pool);
    }

    void AddStats(stock_stats &data) const {
        hstock_add_stats(hstock, &data);
    }

    stock_item *GetNow(struct pool *caller_pool, const char *uri, void *info,
                       unsigned max_leases,
                       struct lease_ref &lease_ref,
                       GError **error_r);

    void Put(const char *uri, stock_item &item, bool reuse) {
        hstock_put(hstock, uri, &item, !reuse);
    }
};

const lease MultiStock::Domain::Item::Lease::lease = {
    Release,
};

stock_item *
MultiStock::Domain::GetNow(DomainMap::iterator di,
                           struct pool *caller_pool,
                           const char *uri, void *info,
                           unsigned max_leases,
                           struct lease_ref &lease_ref,
                           GError **error_r)
{
    auto i = FindUsableItem();
    if (i == items.end()) {
        stock_item *item =
            hstock_get_now(stock.hstock, caller_pool, uri, info,
                           error_r);
        items.emplace_front(di, max_leases, *item);
        i = items.begin();
    }

    return i->AddLease(i, lease_ref);
}

inline stock_item *
MultiStock::GetNow(struct pool *caller_pool, const char *uri, void *info,
                   unsigned max_leases,
                   struct lease_ref &lease_ref,
                   GError **error_r)
{
    struct pool *domain_pool = pool_new_libc(pool, "mstock_domain");
    auto di = domains.insert(std::make_pair(uri, Domain(*this, domain_pool)))
        .first;
    return di->second.GetNow(di, caller_pool, uri, info, max_leases,
                             lease_ref, error_r);
}

/*
 * constructor
 *
 */

struct mstock *
mstock_new(struct pool *pool, struct hstock *hstock)
{
    return new MultiStock(pool, hstock);
}

void
mstock_free(struct mstock *_m)
{
    MultiStock *m = (MultiStock *)_m;
    delete m;
}

void
mstock_add_stats(const struct mstock *_m, stock_stats *data)
{
    const MultiStock &m = *(const MultiStock *)_m;
    m.AddStats(*data);
}

struct stock_item *
mstock_get_now(struct mstock *_m, struct pool *caller_pool,
               const char *uri, void *info, unsigned max_leases,
               struct lease_ref *lease_ref,
               GError **error_r)
{
    MultiStock &m = *(MultiStock *)_m;
    return m.GetNow(caller_pool, uri, info, max_leases,
                    *lease_ref, error_r);
}
<commit_msg>mstock: use class boost::intrusive::list instead of struct list_head<commit_after>/*
 * A wrapper for hstock/stock that allows multiple users of one
 * stock_item.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "mstock.h"
#include "hstock.h"
#include "stock.h"
#include "hashmap.h"
#include "pool.h"
#include "lease.h"

#include <daemon/log.h>

#include <boost/intrusive/list.hpp>

#include <map>
#include <list>
#include <string>

#include <assert.h>

struct mstock {};

class MultiStock : public mstock {
    class Domain;
    typedef std::map<std::string, Domain> DomainMap;

    class Domain {
        class Item;
        typedef std::list<Item> ItemList;

        class Item {
            struct Lease {
                static constexpr auto link_mode = boost::intrusive::normal_link;
                typedef boost::intrusive::link_mode<link_mode> LinkMode;
                typedef boost::intrusive::list_member_hook<LinkMode> SiblingsListHook;

                SiblingsListHook siblings;

                typedef boost::intrusive::member_hook<Lease,
                                                      Lease::SiblingsListHook,
                                                      &Lease::siblings> SiblingsListMemberHook;

                static const struct lease lease;

                const ItemList::iterator item;

                Lease(ItemList::iterator _item):item(_item) {}

                void Release(bool _reuse) {
                    item->DeleteLease(this, _reuse);
                }

                static void Release(bool reuse, void *ctx) {
                    ((Lease *)ctx)->Release(reuse);
                }

                static void Dispose(Lease *l) {
                    delete l;
                }
            };

            const DomainMap::iterator domain;

            const unsigned max_leases;

            stock_item &item;

            boost::intrusive::list<Lease, Lease::SiblingsListMemberHook,
                                   boost::intrusive::constant_time_size<true>> leases;

            bool reuse;

        public:
            Item(DomainMap::iterator _domain, unsigned _max_leases,
                 stock_item &_item)
                :domain(_domain), max_leases(_max_leases), item(_item),
                 reuse(true) {
            }

            Item(const Item &) = delete;

            ~Item() {
                assert(leases.empty());

                domain->second.Put(domain->first.c_str(), item, reuse);
            }

            bool IsFull() const {
                return leases.size() >= max_leases;
            }

            bool CanUse() const {
                return reuse && !IsFull();
            }

        private:
            Lease &AddLease(ItemList::iterator i) {
                assert(&*i == this);

                Lease *lease = new Lease(i);
                leases.push_front(*lease);
                return *lease;
            }

        public:
            void AddLease(ItemList::iterator i,
                          const stock_get_handler &handler, void *ctx,
                          struct lease_ref &lease_ref) {
                assert(&*i == this);

                Lease &lease = AddLease(i);
                lease_ref_set(&lease_ref, &Lease::lease, &lease);

                handler.ready(&item, ctx);
            }

            stock_item *AddLease(ItemList::iterator i,
                                 struct lease_ref &lease_ref) {
                assert(&*i == this);

                Lease &lease = AddLease(i);
                lease_ref_set(&lease_ref, &Lease::lease, &lease);
                return &item;
            }

            void DeleteLease(Lease *lease, bool _reuse) {
                reuse &= _reuse;

                auto ii = lease->item;

                assert(!leases.empty());
                leases.erase_and_dispose(leases.iterator_to(*lease),
                                         Lease::Dispose);

                if (leases.empty())
                    domain->second.DeleteItem(ii);
            }
        };

        MultiStock &stock;

        struct pool *pool;

        ItemList items;

    public:
        Domain(MultiStock &_stock, struct pool *_pool)
            :stock(_stock), pool(_pool) {
        }

        Domain(Domain &&other)
            :stock(other.stock), pool(other.pool) {
            assert(other.items.empty());

            other.pool = nullptr;
        }

        Domain(const Domain &) = delete;

        ~Domain() {
            assert(items.empty());

            if (pool != nullptr)
                pool_unref(pool);
        }

        ItemList::iterator FindUsableItem() {
            for (auto i = items.begin(), end = items.end(); i != end; ++i)
                if (i->CanUse())
                    return i;

            return items.end();
        }

        ItemList::iterator AddItem(DomainMap::iterator di,
                                   unsigned max_leases,
                                   stock_item &si) {
            assert(&di->second == this);

            items.emplace_front(di, max_leases, si);
            return items.begin();
        }

        stock_item *GetNow(DomainMap::iterator di,
                           struct pool *caller_pool,
                           const char *uri, void *info,
                           unsigned max_leases,
                           struct lease_ref &lease_ref,
                           GError **error_r);

        void DeleteItem(ItemList::iterator &ii) {
            ii = items.erase(ii);
        }

        void Put(const char *uri, stock_item &item, bool reuse) {
            stock.Put(uri, item, reuse);
        }
    };

    struct pool *pool;

    DomainMap domains;

    struct hstock *hstock;

public:
    MultiStock(struct pool *_pool, struct hstock *_hstock)
        :pool(pool_new_libc(_pool, "mstock")),
         hstock(_hstock) {}

    MultiStock(const MultiStock &) = delete;

    ~MultiStock() {
        hstock_free(hstock);
        pool_unref(pool);
    }

    void AddStats(stock_stats &data) const {
        hstock_add_stats(hstock, &data);
    }

    stock_item *GetNow(struct pool *caller_pool, const char *uri, void *info,
                       unsigned max_leases,
                       struct lease_ref &lease_ref,
                       GError **error_r);

    void Put(const char *uri, stock_item &item, bool reuse) {
        hstock_put(hstock, uri, &item, !reuse);
    }
};

const lease MultiStock::Domain::Item::Lease::lease = {
    Release,
};

stock_item *
MultiStock::Domain::GetNow(DomainMap::iterator di,
                           struct pool *caller_pool,
                           const char *uri, void *info,
                           unsigned max_leases,
                           struct lease_ref &lease_ref,
                           GError **error_r)
{
    auto i = FindUsableItem();
    if (i == items.end()) {
        stock_item *item =
            hstock_get_now(stock.hstock, caller_pool, uri, info,
                           error_r);
        items.emplace_front(di, max_leases, *item);
        i = items.begin();
    }

    return i->AddLease(i, lease_ref);
}

inline stock_item *
MultiStock::GetNow(struct pool *caller_pool, const char *uri, void *info,
                   unsigned max_leases,
                   struct lease_ref &lease_ref,
                   GError **error_r)
{
    struct pool *domain_pool = pool_new_libc(pool, "mstock_domain");
    auto di = domains.insert(std::make_pair(uri, Domain(*this, domain_pool)))
        .first;
    return di->second.GetNow(di, caller_pool, uri, info, max_leases,
                             lease_ref, error_r);
}

/*
 * constructor
 *
 */

struct mstock *
mstock_new(struct pool *pool, struct hstock *hstock)
{
    return new MultiStock(pool, hstock);
}

void
mstock_free(struct mstock *_m)
{
    MultiStock *m = (MultiStock *)_m;
    delete m;
}

void
mstock_add_stats(const struct mstock *_m, stock_stats *data)
{
    const MultiStock &m = *(const MultiStock *)_m;
    m.AddStats(*data);
}

struct stock_item *
mstock_get_now(struct mstock *_m, struct pool *caller_pool,
               const char *uri, void *info, unsigned max_leases,
               struct lease_ref *lease_ref,
               GError **error_r)
{
    MultiStock &m = *(MultiStock *)_m;
    return m.GetNow(caller_pool, uri, info, max_leases,
                    *lease_ref, error_r);
}
<|endoftext|>


<commit_before>/*
** NDS 2SF utility class.
*/

#ifdef _WIN32
#define ZLIB_WINAPI
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <string>
#include <sstream>
#include <map>

#include <zlib.h>

#include "nds2sf.h"
#include "cbyteio.h"
#include "cpath.h"

#ifdef _WIN32
#define NOMINMAX
#include <windows.h>
#include <sys/stat.h>
#include <direct.h>
#else
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define _chdir(s)	chdir((s))
#define _mkdir(s)	mkdir((s), 0777)
#define _rmdir(s)	rmdir((s))
#endif

void NDS2SF::put_2sf_exe_header(uint8_t *exe, uint32_t load_offset, uint32_t rom_size)
{
	mput4l(load_offset, &exe[0]);
	mput4l(rom_size, &exe[4]);
}

bool NDS2SF::exe2sf(const std::string& nds2sf_path, uint8_t *exe, size_t exe_size)
{
	std::map<std::string, std::string> tags;
	return exe2sf(nds2sf_path, exe, exe_size, tags);
}

#define CHUNK 16384
bool NDS2SF::exe2sf(const std::string& nds2sf_path, uint8_t *exe, size_t exe_size, std::map<std::string, std::string>& tags)
{
	FILE *nds2sf_file = NULL;

	z_stream z;
	uint8_t zbuf[CHUNK];
	uLong zcrc;
	uLong zlen;
	int zflush;
	int zret;

	// check exe size
	if (exe_size > MAX_NDS2SF_EXE_SIZE)
	{
		return false;
	}

	// open output file
	nds2sf_file = fopen(nds2sf_path.c_str(), "wb");
	if (nds2sf_file == NULL)
	{
		return false;
	}

	// write PSF header
	// (EXE length and CRC will be set later)
	fwrite(PSF_SIGNATURE, strlen(PSF_SIGNATURE), 1, nds2sf_file);
	fputc(NDS2SF_PSF_VERSION, nds2sf_file);
	fput4l(0, nds2sf_file);
	fput4l(0, nds2sf_file);
	fput4l(0, nds2sf_file);

	// init compression
	z.zalloc = Z_NULL;
	z.zfree = Z_NULL;
	z.opaque = Z_NULL;
	if (deflateInit(&z, Z_BEST_COMPRESSION) != Z_OK)
	{
		return false;
	}

	// compress exe
	z.next_in = exe;
	z.avail_in = (uInt) exe_size;
	z.next_out = zbuf;
	z.avail_out = CHUNK;
	zcrc = crc32(0L, Z_NULL, 0);
	do
	{
		if (z.avail_in == 0)
		{
			zflush = Z_FINISH;
		}
		else
		{
			zflush = Z_NO_FLUSH;
		}

		// compress
		zret = deflate(&z, zflush);
		if (zret != Z_STREAM_END && zret != Z_OK)
		{
			deflateEnd(&z);
			fclose(nds2sf_file);
			return false;
		}

		// write compressed data
		zlen = CHUNK - z.avail_out;
		if (zlen != 0)
		{
			if (fwrite(zbuf, zlen, 1, nds2sf_file) != 1)
			{
				deflateEnd(&z);
				fclose(nds2sf_file);
				return false;
			}
			zcrc = crc32(zcrc, zbuf, zlen);
		}

		// give space for next chunk
		z.next_out = zbuf;
		z.avail_out = CHUNK;
	} while (zret != Z_STREAM_END);

	// set EXE info to PSF header
	fseek(nds2sf_file, 8, SEEK_SET);
	fput4l(z.total_out, nds2sf_file);
	fput4l(zcrc, nds2sf_file);
	fseek(nds2sf_file, 0, SEEK_END);

	// end compression
	deflateEnd(&z);

	// write tags
	if (!tags.empty())
	{
		fwrite(PSF_TAG_SIGNATURE, strlen(PSF_TAG_SIGNATURE), 1, nds2sf_file);

		for (std::map<std::string, std::string>::iterator it = tags.begin(); it != tags.end(); ++it)
		{
			const std::string& key = it->first;
			const std::string& value = it->second;
			std::istringstream value_reader(value);
			std::string line;

			// process for each lines
			while (std::getline(value_reader, line))
			{
				if (fprintf(nds2sf_file, "%s=%s\n", key.c_str(), line.c_str()) < 0)
				{
					fclose(nds2sf_file);
					return false;
				}
			}
		}
	}

	fclose(nds2sf_file);
	return true;
}

bool NDS2SF::exe2sf_file(const std::string& nds_path, const std::string& nds2sf_path)
{
	off_t rom_size_off = path_getfilesize(nds_path.c_str());
	if (rom_size_off == -1) {
		return false;
	}

	if (rom_size_off > MAX_NDS_ROM_SIZE) {
		return false;
	}

	uint32_t rom_size = (uint32_t)rom_size_off;

	FILE * rom_file = fopen(nds_path.c_str(), "rb");
	if (rom_file == NULL) {
		return false;
	}

	uint8_t * exe = new uint8_t[NDS2SF_EXE_HEADER_SIZE + rom_size];
	if (exe == NULL) {
		fclose(rom_file);
		return false;
	}

	put_2sf_exe_header(exe, 0, rom_size);
	if (fread(&exe[NDS2SF_EXE_HEADER_SIZE], 1, rom_size, rom_file) != rom_size) {
		delete[] exe;
		fclose(rom_file);
		return false;
	}

	if (!exe2sf(nds2sf_path, exe, NDS2SF_EXE_HEADER_SIZE + rom_size)) {
		delete[] exe;
		fclose(rom_file);
		return false;
	}

	delete[] exe;
	fclose(rom_file);
	return true;
}

bool NDS2SF::make_mini2sf(const std::string& nds2sf_path, uint32_t address, size_t size, uint32_t num, std::map<std::string, std::string>& tags)
{
	uint8_t exe[NDS2SF_EXE_HEADER_SIZE + 4];

	// limit size
	if (size > 4)
	{
		return false;
	}

	// make exe
	put_2sf_exe_header(exe, address, (uint32_t)size);
	mput4l(num, &exe[NDS2SF_EXE_HEADER_SIZE]);

	// write mini2sf file
	return exe2sf(nds2sf_path, exe, NDS2SF_EXE_HEADER_SIZE + size, tags);
}
<commit_msg>Increase the size limit<commit_after>/*
** NDS 2SF utility class.
*/

#ifdef _WIN32
#define ZLIB_WINAPI
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <string>
#include <sstream>
#include <map>

#include <zlib.h>

#include "nds2sf.h"
#include "cbyteio.h"
#include "cpath.h"

#ifdef _WIN32
#define NOMINMAX
#include <windows.h>
#include <sys/stat.h>
#include <direct.h>
#else
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define _chdir(s)	chdir((s))
#define _mkdir(s)	mkdir((s), 0777)
#define _rmdir(s)	rmdir((s))
#endif

void NDS2SF::put_2sf_exe_header(uint8_t *exe, uint32_t load_offset, uint32_t rom_size)
{
	mput4l(load_offset, &exe[0]);
	mput4l(rom_size, &exe[4]);
}

bool NDS2SF::exe2sf(const std::string& nds2sf_path, uint8_t *exe, size_t exe_size)
{
	std::map<std::string, std::string> tags;
	return exe2sf(nds2sf_path, exe, exe_size, tags);
}

#define CHUNK 16384
bool NDS2SF::exe2sf(const std::string& nds2sf_path, uint8_t *exe, size_t exe_size, std::map<std::string, std::string>& tags)
{
	FILE *nds2sf_file = NULL;

	z_stream z;
	uint8_t zbuf[CHUNK];
	uLong zcrc;
	uLong zlen;
	int zflush;
	int zret;

	// check exe size
	if (exe_size > MAX_NDS2SF_EXE_SIZE)
	{
		return false;
	}

	// open output file
	nds2sf_file = fopen(nds2sf_path.c_str(), "wb");
	if (nds2sf_file == NULL)
	{
		return false;
	}

	// write PSF header
	// (EXE length and CRC will be set later)
	fwrite(PSF_SIGNATURE, strlen(PSF_SIGNATURE), 1, nds2sf_file);
	fputc(NDS2SF_PSF_VERSION, nds2sf_file);
	fput4l(0, nds2sf_file);
	fput4l(0, nds2sf_file);
	fput4l(0, nds2sf_file);

	// init compression
	z.zalloc = Z_NULL;
	z.zfree = Z_NULL;
	z.opaque = Z_NULL;
	if (deflateInit(&z, Z_BEST_COMPRESSION) != Z_OK)
	{
		return false;
	}

	// compress exe
	z.next_in = exe;
	z.avail_in = (uInt) exe_size;
	z.next_out = zbuf;
	z.avail_out = CHUNK;
	zcrc = crc32(0L, Z_NULL, 0);
	do
	{
		if (z.avail_in == 0)
		{
			zflush = Z_FINISH;
		}
		else
		{
			zflush = Z_NO_FLUSH;
		}

		// compress
		zret = deflate(&z, zflush);
		if (zret != Z_STREAM_END && zret != Z_OK)
		{
			deflateEnd(&z);
			fclose(nds2sf_file);
			return false;
		}

		// write compressed data
		zlen = CHUNK - z.avail_out;
		if (zlen != 0)
		{
			if (fwrite(zbuf, zlen, 1, nds2sf_file) != 1)
			{
				deflateEnd(&z);
				fclose(nds2sf_file);
				return false;
			}
			zcrc = crc32(zcrc, zbuf, zlen);
		}

		// give space for next chunk
		z.next_out = zbuf;
		z.avail_out = CHUNK;
	} while (zret != Z_STREAM_END);

	// set EXE info to PSF header
	fseek(nds2sf_file, 8, SEEK_SET);
	fput4l(z.total_out, nds2sf_file);
	fput4l(zcrc, nds2sf_file);
	fseek(nds2sf_file, 0, SEEK_END);

	// end compression
	deflateEnd(&z);

	// write tags
	if (!tags.empty())
	{
		fwrite(PSF_TAG_SIGNATURE, strlen(PSF_TAG_SIGNATURE), 1, nds2sf_file);

		for (std::map<std::string, std::string>::iterator it = tags.begin(); it != tags.end(); ++it)
		{
			const std::string& key = it->first;
			const std::string& value = it->second;
			std::istringstream value_reader(value);
			std::string line;

			// process for each lines
			while (std::getline(value_reader, line))
			{
				if (fprintf(nds2sf_file, "%s=%s\n", key.c_str(), line.c_str()) < 0)
				{
					fclose(nds2sf_file);
					return false;
				}
			}
		}
	}

	fclose(nds2sf_file);
	return true;
}

bool NDS2SF::exe2sf_file(const std::string& nds_path, const std::string& nds2sf_path)
{
	off_t rom_size_off = path_getfilesize(nds_path.c_str());
	if (rom_size_off == -1) {
		return false;
	}

	if (rom_size_off > MAX_NDS_ROM_SIZE) {
		return false;
	}

	uint32_t rom_size = (uint32_t)rom_size_off;

	FILE * rom_file = fopen(nds_path.c_str(), "rb");
	if (rom_file == NULL) {
		return false;
	}

	uint8_t * exe = new uint8_t[NDS2SF_EXE_HEADER_SIZE + rom_size];
	if (exe == NULL) {
		fclose(rom_file);
		return false;
	}

	put_2sf_exe_header(exe, 0, rom_size);
	if (fread(&exe[NDS2SF_EXE_HEADER_SIZE], 1, rom_size, rom_file) != rom_size) {
		delete[] exe;
		fclose(rom_file);
		return false;
	}

	if (!exe2sf(nds2sf_path, exe, NDS2SF_EXE_HEADER_SIZE + rom_size)) {
		delete[] exe;
		fclose(rom_file);
		return false;
	}

	delete[] exe;
	fclose(rom_file);
	return true;
}

bool NDS2SF::make_mini2sf(const std::string& nds2sf_path, uint32_t address, size_t size, uint32_t num, std::map<std::string, std::string>& tags)
{
	uint8_t exe[NDS2SF_EXE_HEADER_SIZE + 256];
	memset(exe, 0, NDS2SF_EXE_HEADER_SIZE + 256);

	// limit size
	if (size > 256)
	{
		return false;
	}

	// make exe
	put_2sf_exe_header(exe, address, (uint32_t)size);
	mput4l(num, &exe[NDS2SF_EXE_HEADER_SIZE]);

	// write mini2sf file
	return exe2sf(nds2sf_path, exe, NDS2SF_EXE_HEADER_SIZE + size, tags);
}
<|endoftext|>