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

#include "iceoryx_utils/cxx/expected.hpp"
#include "iceoryx_utils/cxx/optional.hpp"

#include "benchmark.hpp"

uint64_t globalCounter{0U};

enum class BenchmarkError : uint64_t
{
    INVALID_STATE,

};

template <uint64_t Size>
struct LargeObject
{
    uint64_t value;
    char dataBlob[Size];
};

template <uint64_t Size>
struct LargeObjectComplexCTor
{
    LargeObjectComplexCTor()
    {
        for (uint64_t i = 0u; i < Size; ++i)
        {
            dataBlob[i] = static_cast<char>((++globalCounter) % 256);
        }
    };
    uint64_t value;
    char dataBlob[Size];
};

uint64_t simpleReturn()
{
    uint64_t returnValue = globalCounter + 1;
    return returnValue;
}

iox::cxx::optional<uint64_t> simpleReturnOptional()
{
    uint64_t returnValue = globalCounter + 1;
    return returnValue;
}

bool popFromFiFoImpl(uint64_t& value)
{
    ++globalCounter;
    uint64_t mod = globalCounter % 8;

    if (mod >= 4)
    {
        return false;
    }

    value = mod;
    return true;
}

void popFromFiFo()
{
    uint64_t maybeValue;
    if (popFromFiFoImpl(maybeValue))
    {
        globalCounter += maybeValue;
    }
    else
    {
        --globalCounter;
    }
}

iox::cxx::optional<uint64_t> popFromFiFoOptionalImpl()
{
    ++globalCounter;
    uint64_t mod = globalCounter % 8;

    if (mod >= 4)
    {
        return iox::cxx::nullopt;
    }

    return mod;
}

void popFromFiFoOptional()
{
    popFromFiFoOptionalImpl().and_then([](uint64_t value) { globalCounter += value; }).or_else([] { --globalCounter; });
}

uint64_t complexErrorValueImpl(uint64_t& value)
{
    ++globalCounter;
    uint64_t mod = globalCounter % 8;

    if (mod >= 4)
    {
        return mod;
    }

    value = mod;
    return 0;
}

void complexErrorValue()
{
    uint64_t maybeValue;
    uint64_t returnValue = complexErrorValueImpl(maybeValue);
    if (returnValue == 0)
    {
        globalCounter += maybeValue;
    }
    else
    {
        globalCounter -= returnValue;
    }
}

iox::cxx::expected<uint64_t, BenchmarkError> complexErrorValueExpectedImpl()
{
    ++globalCounter;
    uint64_t mod = globalCounter % 8;

    if (mod >= 4)
    {
        return iox::cxx::error<BenchmarkError>();
    }

    return iox::cxx::success<uint64_t>(mod);
}

void complexErrorValueExpected()
{
    complexErrorValueExpectedImpl()
        .and_then([](uint64_t value) { globalCounter += value; })
        .or_else([](BenchmarkError error) { /*globalCounter -= error;*/ });
}

template <typename T>
bool largeObjectPopPlainImpl(T& value)
{
    ++globalCounter;

    if (globalCounter % 3 == 0)
    {
        return false;
    }

    T returnValue;
    returnValue.value = globalCounter;
    value = returnValue;

    return true;
}

template <typename T>
iox::cxx::optional<T> largeObjectPopOptionalImpl()
{
    ++globalCounter;

    if (globalCounter % 3 == 0)
    {
        return iox::cxx::nullopt;
    }

    T returnValue;
    returnValue.value = globalCounter;

    return returnValue;
}

template <typename T>
iox::cxx::expected<T, uint64_t> largeObjectPopExpectedImpl()
{
    ++globalCounter;

    if (globalCounter % 3 == 0)
    {
        return iox::cxx::error<uint64_t>(globalCounter);
    }

    T returnValue;
    returnValue.value = globalCounter;

    return iox::cxx::success<T>(returnValue);
}

template <typename T>
void largeObjectPopPlain()
{
    T value;
    if (largeObjectPopPlainImpl(value))
    {
        globalCounter += value.value;
    }
    else
    {
        --globalCounter;
    }
}

template <typename T>
void largeObjectPopOptional()
{
    largeObjectPopOptionalImpl<T>().and_then([](T& value) { globalCounter += value.value; }).or_else([] {
        --globalCounter;
    });
}

template <typename T>
void largeObjectPopExpected()
{
    largeObjectPopExpectedImpl<T>().and_then([](T& value) { globalCounter += value.value; }).or_else([](uint64_t) {
        --globalCounter;
    });
}

int main()
{
    using namespace iox::units::duration_literals;
    auto timeout = 1_s;

    BENCHMARK(simpleReturn, timeout);
    BENCHMARK(simpleReturnOptional, timeout);
    BENCHMARK(popFromFiFo, timeout);
    BENCHMARK(popFromFiFoOptional, timeout);
    BENCHMARK(complexErrorValue, timeout);
    BENCHMARK(complexErrorValueExpected, timeout);

    // constexpr uint64_t LargeObjectSize = 1024;
    // BENCHMARK(largeObjectPopPlain<LargeObject<LargeObjectSize>>, timeout);
    // BENCHMARK(largeObjectPopOptional<LargeObject<LargeObjectSize>>, timeout);
    // BENCHMARK(largeObjectPopExpected<LargeObject<LargeObjectSize>>, timeout);

    // BENCHMARK(largeObjectPopPlain<LargeObjectComplexCTor<LargeObjectSize>>, timeout);
    // BENCHMARK(largeObjectPopOptional<LargeObjectComplexCTor<LargeObjectSize>>, timeout);
    // BENCHMARK(largeObjectPopExpected<LargeObjectComplexCTor<LargeObjectSize>>, timeout);
}
<commit_msg>iox-#542 Add ErrorTypeAdapter for benchmark tests<commit_after>// Copyright (c) 2020 by Robert Bosch GmbH. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

#include "iceoryx_utils/cxx/expected.hpp"
#include "iceoryx_utils/cxx/optional.hpp"

#include "benchmark.hpp"

#include <limits>

uint64_t globalCounter{0U};

namespace iox
{
namespace cxx
{
template <>
struct ErrorTypeAdapter<uint64_t>
{
    static uint64_t getInvalidState()
    {
        return 0;
    };
};
} // namespace cxx
} // namespace iox

template <uint64_t Size>
struct LargeObject
{
    uint64_t value;
    char dataBlob[Size];
};

template <uint64_t Size>
struct LargeObjectComplexCTor
{
    LargeObjectComplexCTor()
    {
        for (uint64_t i = 0u; i < Size; ++i)
        {
            dataBlob[i] = static_cast<char>((++globalCounter) % 256);
        }
    };
    uint64_t value;
    char dataBlob[Size];
};

uint64_t simpleReturn()
{
    uint64_t returnValue = globalCounter + 1;
    return returnValue;
}

iox::cxx::optional<uint64_t> simpleReturnOptional()
{
    uint64_t returnValue = globalCounter + 1;
    return returnValue;
}

bool popFromFiFoImpl(uint64_t& value)
{
    ++globalCounter;
    uint64_t mod = globalCounter % 8;

    if (mod >= 4)
    {
        return false;
    }

    value = mod;
    return true;
}

void popFromFiFo()
{
    uint64_t maybeValue;
    if (popFromFiFoImpl(maybeValue))
    {
        globalCounter += maybeValue;
    }
    else
    {
        --globalCounter;
    }
}

iox::cxx::optional<uint64_t> popFromFiFoOptionalImpl()
{
    ++globalCounter;
    uint64_t mod = globalCounter % 8;

    if (mod >= 4)
    {
        return iox::cxx::nullopt;
    }

    return mod;
}

void popFromFiFoOptional()
{
    popFromFiFoOptionalImpl().and_then([](uint64_t value) { globalCounter += value; }).or_else([] { --globalCounter; });
}

uint64_t complexErrorValueImpl(uint64_t& value)
{
    ++globalCounter;
    uint64_t mod = globalCounter % 8;

    if (mod >= 4)
    {
        return mod;
    }

    value = mod;
    return 0;
}

void complexErrorValue()
{
    uint64_t maybeValue;
    uint64_t returnValue = complexErrorValueImpl(maybeValue);
    if (returnValue == 0)
    {
        globalCounter += maybeValue;
    }
    else
    {
        globalCounter -= returnValue;
    }
}

iox::cxx::expected<uint64_t, uint64_t> complexErrorValueExpectedImpl()
{
    ++globalCounter;
    uint64_t mod = globalCounter % 8;

    if (mod >= 4)
    {
        return iox::cxx::error<uint64_t>(mod);
    }

    return iox::cxx::success<uint64_t>(mod);
}

void complexErrorValueExpected()
{
    complexErrorValueExpectedImpl()
        .and_then([](uint64_t value) { globalCounter += value; })
        .or_else([](uint64_t error) { globalCounter -= error; });
}

template <typename T>
bool largeObjectPopPlainImpl(T& value)
{
    ++globalCounter;

    if (globalCounter % 3 == 0)
    {
        return false;
    }

    T returnValue;
    returnValue.value = globalCounter;
    value = returnValue;

    return true;
}

template <typename T>
iox::cxx::optional<T> largeObjectPopOptionalImpl()
{
    ++globalCounter;

    if (globalCounter % 3 == 0)
    {
        return iox::cxx::nullopt;
    }

    T returnValue;
    returnValue.value = globalCounter;

    return returnValue;
}

template <typename T>
iox::cxx::expected<T, uint64_t> largeObjectPopExpectedImpl()
{
    ++globalCounter;

    if (globalCounter % 3 == 0)
    {
        return iox::cxx::error<uint64_t>(globalCounter);
    }

    T returnValue;
    returnValue.value = globalCounter;

    return iox::cxx::success<T>(returnValue);
}

template <typename T>
void largeObjectPopPlain()
{
    T value;
    if (largeObjectPopPlainImpl(value))
    {
        globalCounter += value.value;
    }
    else
    {
        --globalCounter;
    }
}

template <typename T>
void largeObjectPopOptional()
{
    largeObjectPopOptionalImpl<T>().and_then([](T& value) { globalCounter += value.value; }).or_else([] {
        --globalCounter;
    });
}

template <typename T>
void largeObjectPopExpected()
{
    largeObjectPopExpectedImpl<T>().and_then([](T& value) { globalCounter += value.value; }).or_else([](uint64_t) {
        --globalCounter;
    });
}

int main()
{
    using namespace iox::units::duration_literals;
    auto timeout = 1_s;

    BENCHMARK(simpleReturn, timeout);
    BENCHMARK(simpleReturnOptional, timeout);
    BENCHMARK(popFromFiFo, timeout);
    BENCHMARK(popFromFiFoOptional, timeout);
    BENCHMARK(complexErrorValue, timeout);
    BENCHMARK(complexErrorValueExpected, timeout);

    constexpr uint64_t LargeObjectSize = 1024;
    BENCHMARK(largeObjectPopPlain<LargeObject<LargeObjectSize>>, timeout);
    BENCHMARK(largeObjectPopOptional<LargeObject<LargeObjectSize>>, timeout);
    BENCHMARK(largeObjectPopExpected<LargeObject<LargeObjectSize>>, timeout);

    BENCHMARK(largeObjectPopPlain<LargeObjectComplexCTor<LargeObjectSize>>, timeout);
    BENCHMARK(largeObjectPopOptional<LargeObjectComplexCTor<LargeObjectSize>>, timeout);
    BENCHMARK(largeObjectPopExpected<LargeObjectComplexCTor<LargeObjectSize>>, timeout);
}
<|endoftext|>


<commit_before>/*
 * A simple resizable circular buffer.
 */

#include "rust_internal.h"

circular_buffer::circular_buffer(rust_kernel *kernel, size_t unit_sz) :
    kernel(kernel),
    unit_sz(unit_sz),
    _buffer_sz(initial_size()),
    _next(0),
    _unread(0),
    _buffer((uint8_t *)kernel->malloc(_buffer_sz, "circular_buffer")) {

    assert(unit_sz && "Unit size must be larger than zero.");

    KLOG(kernel, mem, "new circular_buffer(buffer_sz=%d, unread=%d)"
         "-> circular_buffer=0x%" PRIxPTR,
         _buffer_sz, _unread, this);

    assert(_buffer && "Failed to allocate buffer.");
}

circular_buffer::~circular_buffer() {
    KLOG(kernel, mem, "~circular_buffer 0x%" PRIxPTR, this);
    assert(_buffer);
    assert(_unread != 0 && "didn't expect bytes in the circular buffer");

    kernel->free(_buffer);
}

size_t
circular_buffer::initial_size() {
    assert(unit_sz > 0);
    return INITIAL_CIRCULAR_BUFFER_SIZE_IN_UNITS * unit_sz;
}

/**
 * Copies the unread data from this buffer to the "dst" address.
 */
void
circular_buffer::transfer(void *dst) {
    assert(dst);
    assert(_unread <= _buffer_sz);

    uint8_t *ptr = (uint8_t *) dst;

    // First copy from _next to either the end of the unread
    // items or the end of the buffer
    size_t head_sz;
    if (_next + _unread <= _buffer_sz) {
        head_sz = _unread;
    } else {
        head_sz = _buffer_sz - _next;
    }
    assert(_next + head_sz <= _buffer_sz);
    memcpy(ptr, _buffer + _next, head_sz);

    // Then copy any other items from the beginning of the buffer
    assert(_unread >= head_sz);
    size_t tail_sz = _unread - head_sz;
    assert(head_sz + tail_sz <= _buffer_sz);
    memcpy(ptr + head_sz, _buffer, tail_sz);
}

/**
 * Copies the data at the "src" address into this buffer. The buffer is
 * grown if it isn't large enough.
 */
void
circular_buffer::enqueue(void *src) {
    assert(src);
    assert(_unread <= _buffer_sz);
    assert(_buffer);

    // Grow if necessary.
    if (_unread == _buffer_sz) {
        grow();
    }

    KLOG(kernel, mem, "circular_buffer enqueue "
         "unread: %d, next: %d, buffer_sz: %d, unit_sz: %d",
         _unread, _next, _buffer_sz, unit_sz);

    assert(_unread < _buffer_sz);
    assert(_unread + unit_sz <= _buffer_sz);

    // Copy data
    size_t dst_idx = _next + _unread;
    assert(dst_idx >= _buffer_sz || dst_idx + unit_sz <= _buffer_sz);
    if (dst_idx >= _buffer_sz) {
        dst_idx -= _buffer_sz;

        assert(_next >= unit_sz);
        assert(dst_idx <= _next - unit_sz);
    }

    assert(dst_idx + unit_sz <= _buffer_sz);
    memcpy(&_buffer[dst_idx], src, unit_sz);
    _unread += unit_sz;

    KLOG(kernel, mem, "circular_buffer pushed data at index: %d", dst_idx);
}

/**
 * Copies data from this buffer to the "dst" address. The buffer is
 * shrunk if possible. If the "dst" address is NULL, then the message
 * is dequeued but is not copied.
 */
void
circular_buffer::dequeue(void *dst) {
    assert(unit_sz > 0);
    assert(_unread >= unit_sz);
    assert(_unread <= _buffer_sz);
    assert(_buffer);

    KLOG(kernel, mem,
             "circular_buffer dequeue "
             "unread: %d, next: %d, buffer_sz: %d, unit_sz: %d",
             _unread, _next, _buffer_sz, unit_sz);

    assert(_next + unit_sz <= _buffer_sz);
    if (dst != NULL) {
        memcpy(dst, &_buffer[_next], unit_sz);
    }
    KLOG(kernel, mem, "shifted data from index %d", _next);
    _unread -= unit_sz;
    _next += unit_sz;
    if (_next == _buffer_sz) {
        _next = 0;
    }

    // Shrink if possible.
    if (_buffer_sz > initial_size() && _unread <= _buffer_sz / 4) {
        shrink();
    }
}

void
circular_buffer::grow() {
    size_t new_buffer_sz = _buffer_sz * 2;
    KLOG(kernel, mem, "circular_buffer is growing to %d bytes",
         new_buffer_sz);
    void *new_buffer = kernel->malloc(new_buffer_sz,
                                    "new circular_buffer (grow)");
    transfer(new_buffer);
    kernel->free(_buffer);
    _buffer = (uint8_t *)new_buffer;
    _next = 0;
    _buffer_sz = new_buffer_sz;
}

void
circular_buffer::shrink() {
    size_t new_buffer_sz = _buffer_sz / 2;
    assert(initial_size() <= new_buffer_sz);
    KLOG(kernel, mem, "circular_buffer is shrinking to %d bytes",
         new_buffer_sz);
    void *new_buffer = kernel->malloc(new_buffer_sz,
                                    "new circular_buffer (shrink)");
    transfer(new_buffer);
    kernel->free(_buffer);
    _buffer = (uint8_t *)new_buffer;
    _next = 0;
    _buffer_sz = new_buffer_sz;
}

uint8_t *
circular_buffer::peek() {
    return &_buffer[_next];
}

bool
circular_buffer::is_empty() {
    return _unread == 0;
}

size_t
circular_buffer::size() {
    return _unread;
}

//
// Local Variables:
// mode: C++
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
<commit_msg>rt: Assert things that are true<commit_after>/*
 * A simple resizable circular buffer.
 */

#include "rust_internal.h"

circular_buffer::circular_buffer(rust_kernel *kernel, size_t unit_sz) :
    kernel(kernel),
    unit_sz(unit_sz),
    _buffer_sz(initial_size()),
    _next(0),
    _unread(0),
    _buffer((uint8_t *)kernel->malloc(_buffer_sz, "circular_buffer")) {

    assert(unit_sz && "Unit size must be larger than zero.");

    KLOG(kernel, mem, "new circular_buffer(buffer_sz=%d, unread=%d)"
         "-> circular_buffer=0x%" PRIxPTR,
         _buffer_sz, _unread, this);

    assert(_buffer && "Failed to allocate buffer.");
}

circular_buffer::~circular_buffer() {
    KLOG(kernel, mem, "~circular_buffer 0x%" PRIxPTR, this);
    assert(_buffer);
    assert(_unread == 0 && "didn't expect bytes in the circular buffer");

    kernel->free(_buffer);
}

size_t
circular_buffer::initial_size() {
    assert(unit_sz > 0);
    return INITIAL_CIRCULAR_BUFFER_SIZE_IN_UNITS * unit_sz;
}

/**
 * Copies the unread data from this buffer to the "dst" address.
 */
void
circular_buffer::transfer(void *dst) {
    assert(dst);
    assert(_unread <= _buffer_sz);

    uint8_t *ptr = (uint8_t *) dst;

    // First copy from _next to either the end of the unread
    // items or the end of the buffer
    size_t head_sz;
    if (_next + _unread <= _buffer_sz) {
        head_sz = _unread;
    } else {
        head_sz = _buffer_sz - _next;
    }
    assert(_next + head_sz <= _buffer_sz);
    memcpy(ptr, _buffer + _next, head_sz);

    // Then copy any other items from the beginning of the buffer
    assert(_unread >= head_sz);
    size_t tail_sz = _unread - head_sz;
    assert(head_sz + tail_sz <= _buffer_sz);
    memcpy(ptr + head_sz, _buffer, tail_sz);
}

/**
 * Copies the data at the "src" address into this buffer. The buffer is
 * grown if it isn't large enough.
 */
void
circular_buffer::enqueue(void *src) {
    assert(src);
    assert(_unread <= _buffer_sz);
    assert(_buffer);

    // Grow if necessary.
    if (_unread == _buffer_sz) {
        grow();
    }

    KLOG(kernel, mem, "circular_buffer enqueue "
         "unread: %d, next: %d, buffer_sz: %d, unit_sz: %d",
         _unread, _next, _buffer_sz, unit_sz);

    assert(_unread < _buffer_sz);
    assert(_unread + unit_sz <= _buffer_sz);

    // Copy data
    size_t dst_idx = _next + _unread;
    assert(dst_idx >= _buffer_sz || dst_idx + unit_sz <= _buffer_sz);
    if (dst_idx >= _buffer_sz) {
        dst_idx -= _buffer_sz;

        assert(_next >= unit_sz);
        assert(dst_idx <= _next - unit_sz);
    }

    assert(dst_idx + unit_sz <= _buffer_sz);
    memcpy(&_buffer[dst_idx], src, unit_sz);
    _unread += unit_sz;

    KLOG(kernel, mem, "circular_buffer pushed data at index: %d", dst_idx);
}

/**
 * Copies data from this buffer to the "dst" address. The buffer is
 * shrunk if possible. If the "dst" address is NULL, then the message
 * is dequeued but is not copied.
 */
void
circular_buffer::dequeue(void *dst) {
    assert(unit_sz > 0);
    assert(_unread >= unit_sz);
    assert(_unread <= _buffer_sz);
    assert(_buffer);

    KLOG(kernel, mem,
             "circular_buffer dequeue "
             "unread: %d, next: %d, buffer_sz: %d, unit_sz: %d",
             _unread, _next, _buffer_sz, unit_sz);

    assert(_next + unit_sz <= _buffer_sz);
    if (dst != NULL) {
        memcpy(dst, &_buffer[_next], unit_sz);
    }
    KLOG(kernel, mem, "shifted data from index %d", _next);
    _unread -= unit_sz;
    _next += unit_sz;
    if (_next == _buffer_sz) {
        _next = 0;
    }

    // Shrink if possible.
    if (_buffer_sz > initial_size() && _unread <= _buffer_sz / 4) {
        shrink();
    }
}

void
circular_buffer::grow() {
    size_t new_buffer_sz = _buffer_sz * 2;
    KLOG(kernel, mem, "circular_buffer is growing to %d bytes",
         new_buffer_sz);
    void *new_buffer = kernel->malloc(new_buffer_sz,
                                    "new circular_buffer (grow)");
    transfer(new_buffer);
    kernel->free(_buffer);
    _buffer = (uint8_t *)new_buffer;
    _next = 0;
    _buffer_sz = new_buffer_sz;
}

void
circular_buffer::shrink() {
    size_t new_buffer_sz = _buffer_sz / 2;
    assert(initial_size() <= new_buffer_sz);
    KLOG(kernel, mem, "circular_buffer is shrinking to %d bytes",
         new_buffer_sz);
    void *new_buffer = kernel->malloc(new_buffer_sz,
                                    "new circular_buffer (shrink)");
    transfer(new_buffer);
    kernel->free(_buffer);
    _buffer = (uint8_t *)new_buffer;
    _next = 0;
    _buffer_sz = new_buffer_sz;
}

uint8_t *
circular_buffer::peek() {
    return &_buffer[_next];
}

bool
circular_buffer::is_empty() {
    return _unread == 0;
}

size_t
circular_buffer::size() {
    return _unread;
}

//
// Local Variables:
// mode: C++
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
<|endoftext|>


<commit_before>
#include <string>
#include <sstream>
#include <vector>
#include <stdio.h>
#include <cstdarg>

#include <sys/ioctl.h>
#include <stdio.h>

#include "string.h"     // Own definitions

NAMESPACE_BEGIN(au)

std::string tabs(int t)
{
    std::ostringstream output;
    for ( int i = 0 ; i < t ; i ++)
        output << "\t";
    return output.str();
}

std::string percentage_string( double p )
{
    char line[2000];
    sprintf(line, "%05.1f%%",p*100);
    return std::string(line);
}

std::string percentage_string( double value , double total )
{
    if ( total == 0)
        return percentage_string( 0 );
    else
        return percentage_string( value / total);
}

std::string int_string(int value, int digits)
{

    char line[100];
    char format[100];

    sprintf(format, "%%%dd",digits);
    sprintf(line, format,value );
    return std::string(line);
}

std::string time_string( size_t seconds )
{

    int days = 0;
    while( seconds > (3600*24) )
    {
        days++;
        seconds-= (3600*24);
    }

    int minutes = seconds/60;
    seconds -= minutes*60;

    int hours = minutes/60;
    minutes -= hours*60;

    if( days > 0 )
        return au::str( "%02dd %02d:%02d" , days , hours , minutes );

    return au::str( " %02d:%02d:%02d" , hours , minutes , (int)seconds);

}

std::string progress_bar( double p , int len )
{
    std::ostringstream output;

    if( p < 0 )
        p = 0;
    if( p > 1 )
        p = 1;

    int pos = len * p;

    output << " [ ";
    for (int s = 0 ; s < pos ; s++ )
        output << "*";
    for (int s = pos ; s < len ; s++ )
        output << ".";
    output << " ] ";

    return  output.str();
}

std::string progress_bar( double p , int len , char c , char c2 )
{
    std::ostringstream output;

    if( p < 0 )
        p = 0;
    if( p > 1 )
        p = 1;

    int pos = len * p;

    output << " [ ";
    for (int s = 0 ; s < pos ; s++ )
        output << c;
    for (int s = pos ; s < len ; s++ )
        output << c2;
    output << " ] ";

    return  output.str();
}

std::string double_progress_bar( double p1 , double p2 , char c1 ,char c2 , char c3, int len )
{
    std::ostringstream output;

    if( p1 < 0 )
        p1 = 0;
    if( p1 > 1 )
        p1 = 1;

    if( p2 < 0 )
        p2 = 0;
    if( p2 > 1 )
        p2 = 1;

    if( p2 < p1 )
        p2 = p1;    // no sense

    int pos1 = (double)len * p1;
    int pos2 = (double)len * p2;

    output << " [ ";

    for (int s = 0 ; s < pos1 ; s++ )
        output << c1;

    for (int s = pos1 ; s < pos2 ; s++ )
        output << c2;

    for (int s = pos2 ; s < len ; s++ )
        output << c3;

    output << " ] ";

    return  output.str();
}

void find_and_replace( std::string &source, const std::string find, std::string replace )
{
    size_t pos = 0;

    //LM_M(("Finding string of %d bytes at position %lu of a string with length %lu" , find.length() , pos , source.length() ));
    pos = source.find( find , pos );
    //LM_M(("Position found %lu bytes" , find.length() ));

    while(pos != std::string::npos )
    {
        source.replace( pos, find.length(), replace );

        // Go forward in the input string
        pos += replace.length();

        //LM_M(("Finding string of %d bytes at position %lu of a string with length %lu" , find.length() , pos , source.length() ));
        pos = source.find( find , pos );
        //LM_M(("Position found %lu bytes" , find.length() ));

    }
}

std::string getRoot( std::string& path )
{
    size_t pos = path.find( "." , 0 );

    if( pos == std::string::npos )
        return path;

    return path.substr( 0 , pos );
}

std::string getRest( std::string& path )
{
    size_t pos = path.find( "." , 0 );

    if( pos == std::string::npos )
        return "";

    return path.substr( pos+1 , path.length() );
}

std::string indent( std::string txt )
{
    // Replace all "returns" by "return and tab"
    find_and_replace( txt , "\n" , "\n\t" );

    // Insert the first tab
    txt.insert(0, "\t");
    return txt;
}

std::string indent( std::string txt , int num_spaces )
{
    std::string sep;
    for (int i = 0 ; i < num_spaces ; i++ )
        sep.insert(0, " ");

    // Replace all "returns" by "return and tab"
    find_and_replace( txt , "\n" , "\n" + sep );

    // Insert the first tab
    txt.insert(0, sep);
    return txt;
}

std::string str( double value, char  letter )
{
    char line[2000];

    if ( value < 10 )
        sprintf(line, "%4.2f%c",value,letter);
    else if ( value < 100 )
        sprintf(line, "%4.1f%c",value,letter);
    else
        sprintf(line, "%4.0f%c",value,letter);

    return std::string( line );
}

std::string str(const char* format, ...)
{
    va_list        args;
    char           vmsg[2048];

    /* "Parse" the varible arguments */
    va_start(args, format);

    /* Print message to variable */
    vsnprintf(vmsg, sizeof(vmsg), format, args);
    //vmsg[2047] = 0;
    va_end(args);

    return std::string(vmsg);
}

std::string str( size_t value )
{

    if (value < 1000)
    {
        // Special case
        return au::str("%4d ", (int)value );
        //return au::str( (double)value , ' ' );
    }
    else if( value < 1000000)
        return au::str( (double)value/ 1000.0 , 'K');
    else if( value < 1000000000)
        return au::str( (double)value/ 1000000.0 , 'M');
    else if( value < 1000000000000)
        return au::str( (double)value/ 1000000000.0 , 'G');
    else if( value < 1000000000000000)
        return au::str( (double)value/ 1000000000000.0 , 'T');
    else
        return au::str( (double)value/ 1000000000000000.0 , 'P');

}

std::string str( size_t value , std::string postfix )
{
    return str( value ) + postfix;
}

std::string str_detail( size_t value )
{
    if( value < 1000 )
        return str(value);

    return str("%lu (%s)" , value, au::str( value ).c_str() );
}

std::string str_detail( size_t value , std::string postfix )
{
    if( value < 1000 )
        return str(value,postfix);

    return str("%lu %s (%s)" , value , postfix.c_str() , au::str( value, postfix ).c_str() );
}

bool isOneOf( char c , std::string s )
{
    for (size_t i = 0 ; i < s.size() ; i++)
        if( s[i] == c )
            return true;

    return false;
}

std::vector<std::string> simpleTockenize( std::string txt )
{
    std::string tockens = " #\r\t\r\n{};\"";//All possible delimiters

    std::vector<std::string> items;

    // Simple parser
    size_t pos = 0;
    for (size_t i = 0 ; i < txt.size() ; i++)
    {
        if ( isOneOf( txt[i] , tockens ) )
        {
            if ( i > pos )
                items.push_back(txt.substr(pos, i - pos ));
            /*
             //Emit the literal with one letter if that is the case
             std::ostringstream o;
             o << txt[i];
             items.push_back( o.str() );
             */
            pos = i+1;
        }
    }

    if ( txt.size() > pos )
        items.push_back(txt.substr(pos, txt.size() - pos ));

    return items;
}

std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems)
{
    std::stringstream ss(s);
    std::string item;
    while(std::getline(ss, item, delim))
        if( item.length() > 0 )
            elems.push_back(item);
    return elems;
}

std::vector<std::string> split(const std::string &s, char delim)
{
    std::vector<std::string> elems;
    return split(s, delim, elems);
}

int get_term_size (int fd, int *x, int *y)
{
#ifdef TIOCGSIZE
	struct ttysize win;

#elif defined(TIOCGWINSZ)
	struct winsize win;

#endif

#ifdef TIOCGSIZE
	if (ioctl (fd, TIOCGSIZE, &win))
	    return 0;
	if (y)
	    *y=win.ts_lines;
    if (x)
        *x=win.ts_cols;
#elif defined TIOCGWINSZ
    if (ioctl (fd, TIOCGWINSZ, &win))
        return 0;
    if (y)
        *y=win.ws_row;
    if (x)
        *x=win.ws_col;
#else
    {
        const char *s;
        s=getenv("LINES");
        if (s)
            *y=strtol(s,NULL,10);
        else
            *y=25;
        s=getenv("COLUMNS");
        if (s)
            *x=strtol(s,NULL,10);
        else
            *x=80;
    }
#endif

    return 1;

}

int getTerminalWidth()
{
	int x,y;
	if( get_term_size (0, &x, &y) )
	    return x;
	else
        return 0;

}

std::string lineInConsole( char c )
{
    std::ostringstream output;
    for (int i = 0 ; i < getTerminalWidth() ; i++ )
        output << c;
    return output.str();
}

std::string strWithMaxLineLength( std::string& txt , int max_line_length )
{
    std::istringstream input_stream( txt );

    std::ostringstream output;

    char line[1024];

    while( input_stream.getline( line, 1023 ) )
    {

        int line_length = (int)strlen(line);

        if( line_length > max_line_length )
        {
            line[max_line_length-1] = '\0';
            line[max_line_length-2] = '.';
            line[max_line_length-3] = '.';
            line[max_line_length-4] = '.';

            //LM_M(("Exesive line %d / %d ", line_length , max_line_length ));
        }
        else
        {
            //LM_M(("Normal line %d / %d", line_length , max_line_length ));
        }

        output << line << "\n";
    }
    return output.str();
}

std::string strToConsole( std::string& txt )
{
    return strWithMaxLineLength( txt , getTerminalWidth() );
}

// Backward look up for a sequence
const char *laststrstr(const char *source ,const  char *target )
{
    return laststrstr( source , strlen(source) , target );
}

const char *laststrstr(const char *source , size_t source_length , const char *target )
{
    const char *sp;

    /* Step backward through the source string - one character at a time */
    for( sp = source + source_length - strlen(target) ; sp >= source ; sp --)
    {
        const char *tp, *spt ;
        /* go forward through the search string and source checking characters
         Stop the loop if the character are unequal or you reach the end of the target (or string) */
        for( tp = target, spt = sp ;  (*tp == *spt)  && (*spt != '\0') && (*tp != '\0') ; spt++, tp++ ) ;

        /* if the loop above gets to the end of the target string then it must have matched all the characters */
        if (*tp == '\0')
            break ;
    }
    /* If the outer loop finished before getting to the start of the source string then
     it must have found a matching sub string */
    return (sp < source) ? NULL : sp ;
}

std::string str_rate( size_t value , size_t time ,  std::string postLabel   )
{
    if( time == 0)
    {
        if( value == 0)
            return au::str( 0 , postLabel );
        else
            return "[Inf]" + postLabel;
    }

    double _rate = (double) value / (double) time;
    return au::str( (size_t) _rate , postLabel );

}

std::string str_rate( size_t value , size_t time  )
{
    return str_rate(value, time , "");

}

int getCommonChars( std::string& txt , std::string& txt2 )
{
    size_t l = std::min( txt.length() , txt2.length() );
    for (size_t i=0;i<l;i++)
        if ( txt[i] != txt2[i] )
            return i;
    return l;
}

bool isCharInRange( char c , char lower , char higher )
{
    return ((c>=lower) && (c<=higher));
}

bool strings_begin_equal( std::string txt , std::string txt2 )
{
    size_t l = std::min( txt.length() , txt2.length() );
    for (size_t i=0;i<l;i++)
        if ( txt[i] != txt2[i] )
            return false;
    return true;
}

std::string path_from_directory( std::string directory , std::string file )
{
    if ( directory.length() == 0)
        return file;

    if( directory[ directory.length() - 1 ] == '/' )
        return  directory + file;
    else
        return  directory + "/" + file;

}

NAMESPACE_END
<commit_msg>Gorgot a file in last commit ...<commit_after>
#include <string>
#include <sstream>
#include <vector>
#include <stdio.h>
#include <cstdarg>

#include <sys/ioctl.h>
#include <stdio.h>

#include "string.h"     // Own definitions

NAMESPACE_BEGIN(au)

std::string tabs(int t)
{
    std::ostringstream output;
    for ( int i = 0 ; i < t ; i ++)
        output << "\t";
    return output.str();
}

std::string percentage_string( double p )
{
    char line[2000];
    sprintf(line, "%05.1f%%",p*100);
    return std::string(line);
}

std::string percentage_string( double value , double total )
{
    if ( total == 0)
        return percentage_string( 0 );
    else
        return percentage_string( value / total);
}

std::string int_string(int value, int digits)
{

    char line[100];
    char format[100];

    sprintf(format, "%%%dd",digits);
    sprintf(line, format,value );
    return std::string(line);
}

std::string time_string( size_t seconds )
{

    int days = 0;
    while( seconds > (3600*24) )
    {
        days++;
        seconds-= (3600*24);
    }

    int minutes = seconds/60;
    seconds -= minutes*60;

    int hours = minutes/60;
    minutes -= hours*60;

    if( days > 0 )
        return au::str( "%02dd %02d:%02d" , days , hours , minutes );

    return au::str( " %02d:%02d:%02d" , hours , minutes , (int)seconds);

}

std::string progress_bar( double p , int len )
{
    std::ostringstream output;

    if( p < 0 )
        p = 0;
    if( p > 1 )
        p = 1;

    int pos = len * p;

    output << " [ ";
    for (int s = 0 ; s < pos ; s++ )
        output << "*";
    for (int s = pos ; s < len ; s++ )
        output << ".";
    output << " ] ";

    return  output.str();
}

std::string progress_bar( double p , int len , char c , char c2 )
{
    std::ostringstream output;

    if( p < 0 )
        p = 0;
    if( p > 1 )
        p = 1;

    int pos = len * p;

    output << " [ ";
    for (int s = 0 ; s < pos ; s++ )
        output << c;
    for (int s = pos ; s < len ; s++ )
        output << c2;
    output << " ] ";

    return  output.str();
}

std::string double_progress_bar( double p1 , double p2 , char c1 ,char c2 , char c3, int len )
{
    std::ostringstream output;

    if( p1 < 0 )
        p1 = 0;
    if( p1 > 1 )
        p1 = 1;

    if( p2 < 0 )
        p2 = 0;
    if( p2 > 1 )
        p2 = 1;

    if( p2 < p1 )
        p2 = p1;    // no sense

    int pos1 = (double)len * p1;
    int pos2 = (double)len * p2;

    output << " [ ";

    for (int s = 0 ; s < pos1 ; s++ )
        output << c1;

    for (int s = pos1 ; s < pos2 ; s++ )
        output << c2;

    for (int s = pos2 ; s < len ; s++ )
        output << c3;

    output << " ] ";

    return  output.str();
}

void find_and_replace( std::string &source, const std::string find, std::string replace )
{
    size_t pos = 0;

    //LM_M(("Finding string of %d bytes at position %lu of a string with length %lu" , find.length() , pos , source.length() ));
    pos = source.find( find , pos );
    //LM_M(("Position found %lu bytes" , find.length() ));

    while(pos != std::string::npos )
    {
        source.replace( pos, find.length(), replace );

        // Go forward in the input string
        pos += replace.length();

        //LM_M(("Finding string of %d bytes at position %lu of a string with length %lu" , find.length() , pos , source.length() ));
        pos = source.find( find , pos );
        //LM_M(("Position found %lu bytes" , find.length() ));

    }
}

std::string getRoot( std::string& path )
{
    size_t pos = path.find( "." , 0 );

    if( pos == std::string::npos )
        return path;

    return path.substr( 0 , pos );
}

std::string getRest( std::string& path )
{
    size_t pos = path.find( "." , 0 );

    if( pos == std::string::npos )
        return "";

    return path.substr( pos+1 , path.length() );
}

std::string indent( std::string txt )
{
    // Replace all "returns" by "return and tab"
    find_and_replace( txt , "\n" , "\n\t" );

    // Insert the first tab
    txt.insert(0, "\t");
    return txt;
}

std::string indent( std::string txt , int num_spaces )
{
    std::string sep;
    for (int i = 0 ; i < num_spaces ; i++ )
        sep.insert(0, " ");

    // Replace all "returns" by "return and tab"
    find_and_replace( txt , "\n" , "\n" + sep );

    // Insert the first tab
    txt.insert(0, sep);
    return txt;
}

std::string str( double value, char  letter )
{
    char line[2000];

    if ( value < 10 )
        sprintf(line, "%4.2f%c",value,letter);
    else if ( value < 100 )
        sprintf(line, "%4.1f%c",value,letter);
    else
        sprintf(line, "%4.0f%c",value,letter);

    return std::string( line );
}

std::string str(const char* format, ...)
{
    va_list        args;
    char           vmsg[2048];

    /* "Parse" the varible arguments */
    va_start(args, format);

    /* Print message to variable */
    vsnprintf(vmsg, sizeof(vmsg), format, args);
    //vmsg[2047] = 0;
    va_end(args);

    return std::string(vmsg);
}

std::string str( size_t value )
{

    if (value < 1000)
    {
        // Special case
        return au::str("%4d ", (int)value );
        //return au::str( (double)value , ' ' );
    }
    else if( value < 1000000)
        return au::str( (double)value/ 1000.0 , 'K');
    else if( value < 1000000000)
        return au::str( (double)value/ 1000000.0 , 'M');
#ifdef __LP64__
    else if( value < 1000000000000)
        return au::str( (double)value/ 1000000000.0 , 'G');
    else if( value < 1000000000000000)
        return au::str( (double)value/ 1000000000000.0 , 'T');
#endif
    else
        return au::str( (double)value/ 1000000000000000.0 , 'P');

}

std::string str( size_t value , std::string postfix )
{
    return str( value ) + postfix;
}

std::string str_detail( size_t value )
{
    if( value < 1000 )
        return str(value);

    return str("%lu (%s)" , value, au::str( value ).c_str() );
}

std::string str_detail( size_t value , std::string postfix )
{
    if( value < 1000 )
        return str(value,postfix);

    return str("%lu %s (%s)" , value , postfix.c_str() , au::str( value, postfix ).c_str() );
}

bool isOneOf( char c , std::string s )
{
    for (size_t i = 0 ; i < s.size() ; i++)
        if( s[i] == c )
            return true;

    return false;
}

std::vector<std::string> simpleTockenize( std::string txt )
{
    std::string tockens = " #\r\t\r\n{};\"";//All possible delimiters

    std::vector<std::string> items;

    // Simple parser
    size_t pos = 0;
    for (size_t i = 0 ; i < txt.size() ; i++)
    {
        if ( isOneOf( txt[i] , tockens ) )
        {
            if ( i > pos )
                items.push_back(txt.substr(pos, i - pos ));
            /*
             //Emit the literal with one letter if that is the case
             std::ostringstream o;
             o << txt[i];
             items.push_back( o.str() );
             */
            pos = i+1;
        }
    }

    if ( txt.size() > pos )
        items.push_back(txt.substr(pos, txt.size() - pos ));

    return items;
}

std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems)
{
    std::stringstream ss(s);
    std::string item;
    while(std::getline(ss, item, delim))
        if( item.length() > 0 )
            elems.push_back(item);
    return elems;
}

std::vector<std::string> split(const std::string &s, char delim)
{
    std::vector<std::string> elems;
    return split(s, delim, elems);
}

int get_term_size (int fd, int *x, int *y)
{
#ifdef TIOCGSIZE
	struct ttysize win;

#elif defined(TIOCGWINSZ)
	struct winsize win;

#endif

#ifdef TIOCGSIZE
	if (ioctl (fd, TIOCGSIZE, &win))
	    return 0;
	if (y)
	    *y=win.ts_lines;
    if (x)
        *x=win.ts_cols;
#elif defined TIOCGWINSZ
    if (ioctl (fd, TIOCGWINSZ, &win))
        return 0;
    if (y)
        *y=win.ws_row;
    if (x)
        *x=win.ws_col;
#else
    {
        const char *s;
        s=getenv("LINES");
        if (s)
            *y=strtol(s,NULL,10);
        else
            *y=25;
        s=getenv("COLUMNS");
        if (s)
            *x=strtol(s,NULL,10);
        else
            *x=80;
    }
#endif

    return 1;

}

int getTerminalWidth()
{
	int x,y;
	if( get_term_size (0, &x, &y) )
	    return x;
	else
        return 0;

}

std::string lineInConsole( char c )
{
    std::ostringstream output;
    for (int i = 0 ; i < getTerminalWidth() ; i++ )
        output << c;
    return output.str();
}

std::string strWithMaxLineLength( std::string& txt , int max_line_length )
{
    std::istringstream input_stream( txt );

    std::ostringstream output;

    char line[1024];

    while( input_stream.getline( line, 1023 ) )
    {

        int line_length = (int)strlen(line);

        if( line_length > max_line_length )
        {
            line[max_line_length-1] = '\0';
            line[max_line_length-2] = '.';
            line[max_line_length-3] = '.';
            line[max_line_length-4] = '.';

            //LM_M(("Exesive line %d / %d ", line_length , max_line_length ));
        }
        else
        {
            //LM_M(("Normal line %d / %d", line_length , max_line_length ));
        }

        output << line << "\n";
    }
    return output.str();
}

std::string strToConsole( std::string& txt )
{
    return strWithMaxLineLength( txt , getTerminalWidth() );
}

// Backward look up for a sequence
const char *laststrstr(const char *source ,const  char *target )
{
    return laststrstr( source , strlen(source) , target );
}

const char *laststrstr(const char *source , size_t source_length , const char *target )
{
    const char *sp;

    /* Step backward through the source string - one character at a time */
    for( sp = source + source_length - strlen(target) ; sp >= source ; sp --)
    {
        const char *tp, *spt ;
        /* go forward through the search string and source checking characters
         Stop the loop if the character are unequal or you reach the end of the target (or string) */
        for( tp = target, spt = sp ;  (*tp == *spt)  && (*spt != '\0') && (*tp != '\0') ; spt++, tp++ ) ;

        /* if the loop above gets to the end of the target string then it must have matched all the characters */
        if (*tp == '\0')
            break ;
    }
    /* If the outer loop finished before getting to the start of the source string then
     it must have found a matching sub string */
    return (sp < source) ? NULL : sp ;
}

std::string str_rate( size_t value , size_t time ,  std::string postLabel   )
{
    if( time == 0)
    {
        if( value == 0)
            return au::str( 0 , postLabel );
        else
            return "[Inf]" + postLabel;
    }

    double _rate = (double) value / (double) time;
    return au::str( (size_t) _rate , postLabel );

}

std::string str_rate( size_t value , size_t time  )
{
    return str_rate(value, time , "");

}

int getCommonChars( std::string& txt , std::string& txt2 )
{
    size_t l = std::min( txt.length() , txt2.length() );
    for (size_t i=0;i<l;i++)
        if ( txt[i] != txt2[i] )
            return i;
    return l;
}

bool isCharInRange( char c , char lower , char higher )
{
    return ((c>=lower) && (c<=higher));
}

bool strings_begin_equal( std::string txt , std::string txt2 )
{
    size_t l = std::min( txt.length() , txt2.length() );
    for (size_t i=0;i<l;i++)
        if ( txt[i] != txt2[i] )
            return false;
    return true;
}

std::string path_from_directory( std::string directory , std::string file )
{
    if ( directory.length() == 0)
        return file;

    if( directory[ directory.length() - 1 ] == '/' )
        return  directory + file;
    else
        return  directory + "/" + file;

}

NAMESPACE_END
<|endoftext|>


<commit_before>/***************************************************************************

 HTMLview.mcc - HTMLview MUI Custom Class
 Copyright (C) 1997-2000 Allan Odgaard
 Copyright (C) 2005-2007 by HTMLview.mcc Open Source Team

 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; either
 version 2.1 of the License, or (at your option) any later version.

 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.

 HTMLview class Support Site:  http://www.sf.net/projects/htmlview-mcc/

 $Id$

***************************************************************************/

#include "FormClass.h"

#include "Forms.h"
#include "ParseMessage.h"
//#include "private.h"
#include "ScanArgs.h"
#include "SharedData.h"
#include <stdio.h>
#include <new>

VOID FormClass::AppendGadget (struct AppendGadgetMessage &amsg)
{
  class FormClass *oldform = amsg.Form;
  amsg.Form = this;
  TreeClass::AppendGadget(amsg);
  amsg.Form = oldform;
}

VOID FormClass::ExportForm (struct ExportFormMessage &emsg)
{
  if(&emsg == NULL)
  {
    struct HTMLviewData *data;

    data = (struct HTMLviewData *)xget(HTMLview, MUIA_HTMLview_InstanceData);

    if(Method == Form_Get && Action)
    {
      struct ExportFormMessage emsg2;
      TreeClass::ExportForm(emsg2);

      STRPTR base = (STRPTR)DoMethod(HTMLview, MUIM_HTMLview_AddPart, (ULONG)Action);
      ULONG len = strlen(base) + emsg2.StrLength + 1;
      STRPTR url = new (std::nothrow) char[len];
      if (!url) return;
      ULONG index = sprintf(url, "%s?", base ? base : "");
      if (base) delete base;

      emsg2.GetElements(url+index);

      SetAttrs(data->Share->Obj,
          MUIA_HTMLview_ClickedURL, (ULONG)url,
          MUIA_HTMLview_Target,     (ULONG)FindTarget(HTMLview, Target, data),
          MUIA_HTMLview_Qualifier,  0L,
          TAG_DONE);

      delete url;
    }
    else if(Method == Form_Post && Action)
    {
      struct ExportFormMessage emsg2;
      TreeClass::ExportForm(emsg2);

      STRPTR base = (STRPTR)DoMethod(HTMLview, MUIM_HTMLview_AddPart, (ULONG)Action);
      STRPTR contents = new (std::nothrow) char[emsg2.StrLength + 1];
      if (!contents) return;
      emsg2.GetElements(contents);

      DoMethod(HTMLview, MUIM_HTMLview_Post, (ULONG)base, (ULONG)Target, (ULONG)contents, (ULONG)(EncType ? EncType : "application/x-www-form-urlencoded"));
      delete base;
//      This is deleted by the ParseThread
//      delete contents;
    }
  }
  else
  {
    TreeClass::ExportForm(emsg);
  }
}

VOID FormClass::ResetForm ()
{
  TreeClass::ResetForm();
}

VOID FormClass::Parse(REG(a2, struct ParseMessage &pmsg))
{
  pmsg.SetLock();
  pmsg.NextEndBracket();
#ifdef OUTPUT
  PrintTag(pmsg.Locked);
#endif

  const char *MethodKeywords[] = { "GET", "POST", NULL };
  struct ArgList args[] =
  {
    { "METHOD",   &Method,  ARG_KEYWORD, MethodKeywords },
    { "ACTION",   &Action,  ARG_URL,     NULL           },
    { "TARGET",   &Target,  ARG_URL,     NULL           },
    { "ENCTYPE",  &EncType, ARG_STRING,  NULL           },
    { NULL,       NULL,     0,           NULL           }
  };
  ScanArgs(pmsg.Locked, args);

  HTMLview = pmsg.HTMLview;

  UBYTE p = pmsg.OpenCounts[tag_P];
  pmsg.OpenCounts[tag_P] = 0;
  TreeClass::Parse(pmsg);
  pmsg.OpenCounts[tag_P] = p;
}

<commit_msg>Fixed a buffer overflow in FormClass.cpp<commit_after>/***************************************************************************

 HTMLview.mcc - HTMLview MUI Custom Class
 Copyright (C) 1997-2000 Allan Odgaard
 Copyright (C) 2005-2007 by HTMLview.mcc Open Source Team

 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; either
 version 2.1 of the License, or (at your option) any later version.

 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.

 HTMLview class Support Site:  http://www.sf.net/projects/htmlview-mcc/

 $Id$

***************************************************************************/

#include "FormClass.h"

#include "Forms.h"
#include "ParseMessage.h"
//#include "private.h"
#include "ScanArgs.h"
#include "SharedData.h"
#include <stdio.h>
#include <new>

VOID FormClass::AppendGadget (struct AppendGadgetMessage &amsg)
{
  class FormClass *oldform = amsg.Form;
  amsg.Form = this;
  TreeClass::AppendGadget(amsg);
  amsg.Form = oldform;
}

VOID FormClass::ExportForm (struct ExportFormMessage &emsg)
{
  if(&emsg == NULL)
  {
    struct HTMLviewData *data;

    data = (struct HTMLviewData *)xget(HTMLview, MUIA_HTMLview_InstanceData);

    if(Method == Form_Get && Action)
    {
      struct ExportFormMessage emsg2;
      TreeClass::ExportForm(emsg2);

      STRPTR base = (STRPTR)DoMethod(HTMLview, MUIM_HTMLview_AddPart, (ULONG)Action);
      ULONG len = strlen(base) + emsg2.StrLength + 2; /* alfie - bad overflow */
      STRPTR url = new (std::nothrow) char[len];
      if (!url)
      {
        if (base) delete base;
      	return;
      }
      ULONG index = sprintf(url, "%s?", base ? base : "");
      if (base) delete base;

      emsg2.GetElements(url+index);

      SetAttrs(data->Share->Obj,
          MUIA_HTMLview_ClickedURL, (ULONG)url,
          MUIA_HTMLview_Target,     (ULONG)FindTarget(HTMLview, Target, data),
          MUIA_HTMLview_Qualifier,  0L,
          TAG_DONE);

      delete url;
    }
    else if(Method == Form_Post && Action)
    {
      struct ExportFormMessage emsg2;
      TreeClass::ExportForm(emsg2);

      STRPTR base = (STRPTR)DoMethod(HTMLview, MUIM_HTMLview_AddPart, (ULONG)Action);
      STRPTR contents = new (std::nothrow) char[emsg2.StrLength + 1];
      if (!contents) return;
      emsg2.GetElements(contents);

      DoMethod(HTMLview, MUIM_HTMLview_Post, (ULONG)base, (ULONG)Target, (ULONG)contents, (ULONG)(EncType ? EncType : "application/x-www-form-urlencoded"));
      delete base;
//      This is deleted by the ParseThread
//      delete contents;
    }
  }
  else
  {
    TreeClass::ExportForm(emsg);
  }
}

VOID FormClass::ResetForm ()
{
  TreeClass::ResetForm();
}

VOID FormClass::Parse(REG(a2, struct ParseMessage &pmsg))
{
  pmsg.SetLock();
  pmsg.NextEndBracket();
#ifdef OUTPUT
  PrintTag(pmsg.Locked);
#endif

  const char *MethodKeywords[] = { "GET", "POST", NULL };
  struct ArgList args[] =
  {
    { "METHOD",   &Method,  ARG_KEYWORD, MethodKeywords },
    { "ACTION",   &Action,  ARG_URL,     NULL           },
    { "TARGET",   &Target,  ARG_URL,     NULL           },
    { "ENCTYPE",  &EncType, ARG_STRING,  NULL           },
    { NULL,       NULL,     0,           NULL           }
  };
  ScanArgs(pmsg.Locked, args);

  HTMLview = pmsg.HTMLview;

  UBYTE p = pmsg.OpenCounts[tag_P];
  pmsg.OpenCounts[tag_P] = 0;
  TreeClass::Parse(pmsg);
  pmsg.OpenCounts[tag_P] = p;
}

<|endoftext|>


<commit_before>#include "curl_easy.h"

using curl::curl_easy;
using curl::curl_easy_exception;

/*
 * This example shows how to make a simple request with
 * curl.
 */

int main() {
    // Easy object to handle the connection.
    curl_easy easy;
    // Add some options.
    easy.add<CURLOPT_URL>("http://www.google.it");
    easy.add<CURLOPT_FOLLOWLOCATION>(1L);
    easy.add<CURLOPT_HTTP_VERSION>(2);
    try {
        // Execute the request.
        easy.perform();
    } catch (curl_easy_exception error) {
        // If you want to get the entire error stack we can do:
        auto errors = error.what();
        // Otherwise we could print the stack like this:
        error.print_traceback();
        // Note that the printing the stack will erase it
    }
    return 0;
}
<commit_msg>Update easy.cpp<commit_after>#include "curl_easy.h"

using curl::curl_easy;
using curl::curl_easy_exception;

/*
 * This example shows how to make a simple request with
 * curl.
 */

int main() {
    // Easy object to handle the connection.
    curl_easy easy;
    // Add some options.
    easy.add<CURLOPT_URL>("http://www.google.it");
    easy.add<CURLOPT_FOLLOWLOCATION>(1L);
    try {
        // Execute the request.
        easy.perform();
    } catch (curl_easy_exception error) {
        // If you want to get the entire error stack we can do:
        auto errors = error.what();
        // Otherwise we could print the stack like this:
        error.print_traceback();
        // Note that the printing the stack will erase it
    }
    return 0;
}
<|endoftext|>


<commit_before>#include <cstdio>
#include <cstdlib>
#include <pthread.h>
//#include "easyperf.h"
//#include "carbon_user.h"
#include <time.h>
#include <sys/timeb.h>

#define MAX            100000000
#define INT_MAX        100000000
// #define DEBUG              1
#define BILLION 1E9

int _W[8][8] =
{
  {0,   2,      1,      17,     MAX,    MAX,    MAX,    MAX},
  {2,   0,      MAX,    MAX,    2,      6,      MAX,    MAX},
  {1,   MAX,    0,      MAX,    MAX,    MAX,    MAX,    8},
  {17,  MAX,    MAX,    0,      MAX,    2,      1,      9},
  {MAX, 2,      MAX,    MAX,    0,      4,      MAX,    MAX},
  {MAX, 6,      MAX,    2,      4,      0,      5,      MAX},
  {MAX, MAX,    MAX,    1,      MAX,    5,      0,      3},
  {MAX, MAX,    8,      9,      MAX,    MAX,    3,      0}
};

int min = INT_MAX;
int min_index = 0;
pthread_mutex_t lock;
pthread_mutex_t locks[4194304];
int u = 0;

  void init_weights(int N, int DEG, int** W, int** W_index)
  {
          int range = DEG + (N - DEG)/16;

          // Initialize to -1
          for(int i = 0; i < N; i++)
                  for(int j = 0; j < DEG; j++)
                          W_index[i][j]= -1;

          // Populate Index Array
          for(int i = 0; i < N; i++)
          {
                  int last = 0;
                  int min = 0;
                  int max = DEG;
                  for(int j = 0; j < DEG; j++)
                  {
                          if(W_index[i][j] == -1)
                          {
                                  int neighbor = i + j;//rand()%(max);
                                  if(neighbor > last)
                                  {
                                          W_index[i][j] = neighbor;
                                          last = W_index[i][j];
                                  }
                                  else
                                  {
                                          if(last < (N-1))
                                          {
                                                  W_index[i][j] = (last + 1);
                                                  last = W_index[i][j];
                                          }
                                  }
                          }
                          else
                          {
                                  last = W_index[i][j];
                          }
                          if(W_index[i][j]>=N)
                          {
                                  W_index[i][j] = N-1;
                          }
                  }
          }

          // Populate Cost Array
          for(int i = 0; i < N; i++)
          {
                  for(int j = 0; j < DEG; j++)
                  {
                          double v = drand48();
                          /*if(v > 0.8 || W_index[i][j] == -1)
                          {       W[i][j] = MAX;
                                  W_index[i][j] = -1;
                          }

                          else*/ if(W_index[i][j] == i)
                                  W[i][j] = 0;

                          else
                                  W[i][j] = (int) (v*100) + 1;
                          //printf("   %d  ",W_index[i][j]);
                  }
                  //printf("\n");
          }
  }

int initialize_single_source(int* D, int* Q, int* S, int source, int N);
void relax(int u, int i, volatile int* D, int* S, int** W, int** W_index, int N);
int get_local_min(volatile int* Q, volatile int* D, int start, int stop, int N, int** W_index, int** W, int u);

typedef struct
{
  int*      local_min;
  int*      global_min;
  int*      Q;
  int*      D;
	int*      S;
  int**     W;
  int**     W_index;
  int*      d_count;
  int       tid;
  int       P;
  int       N;
  int       DEG;
  pthread_barrier_t* barrier;
} thread_arg_t;

int local_min_buffer[1024];
int global_min_buffer;
int terminate = 0;
int range=1;
int old_range =1;
int difference=0;
int pid=0;
thread_arg_t thread_arg[1024];
pthread_t   thread_handle[1024];

void* do_work(void* args)
{
  volatile thread_arg_t* arg = (thread_arg_t*) args;

  volatile int* count      = arg->d_count;
  volatile int* global_min = arg->global_min;
  volatile int* local_min  = arg->local_min;
  int tid                  = arg->tid;
  int P                    = arg->P;
  volatile int* Q          = arg->Q;
  int* D                   = arg->D;
	int* S                   = arg->S;
  int** W                  = arg->W;
  int** W_index            = arg->W_index;
  const int N              = arg->N;
  const int DEG            = arg->DEG;
  int local_count          = N;
  int i, j, po;
	int uu = 0;

  int a = 0;
  int i_start =  0;  //tid    * DEG / (arg->P);
  int i_stop  = 0;   //(tid+1) * DEG / (arg->P);
	int start = 0;
	int stop = 1;
  //int difference =0;

	pthread_barrier_wait(arg->barrier);

  while(terminate==0)
  {
	  for(uu=start;uu<stop;uu++)
		{
    for(int i = 0; i < DEG; i++)
    {
      int neighbor = W_index[uu][i];
			//
			pthread_mutex_lock(&locks[neighbor]);

			if(uu>=N)
				terminate=1;

			if((D[W_index[uu][i]] > (D[uu] + W[uu][i]) && W_index[uu][i]!=-1 && W[uu][i]!=INT_MAX/* && Q[uu]==1*/))
			{
				D[W_index[uu][i]] = D[uu] + W[uu][i];
				S[W_index[uu][i]] = uu;
			}
     Q[uu]=0;// po=u;
		//if(W_index[uu][i]==-1)
		 //W[uu][i]=INT_MAX;

			pthread_mutex_unlock(&locks[neighbor]);
    }
		}

   //pthread_barrier_wait(arg->barrier);

	 if(tid==0)
		{  //pthread_mutex_lock(&lock);
			 old_range=range;
		   range = range*DEG;

			 if(old_range==1)
				 old_range=0;

			 if(range>=N)
				 range=N;
       //pthread_mutex_unlock(&lock);
			 //printf("\nold:%d new:%d",old_range,range);

			 difference = range-old_range;
			if(difference<P)
			{
					pid=difference;
		  }
			else
				  pid=P;
			if(pid==0)
				pid=P;
		}

	 //pthread_mutex_lock(&lock);
	 //if(u<=N)
     //u++;
	 //pthread_mutex_unlock(&lock);

    /*pthread_mutex_lock(&lock);
		if(uu>=N-1 || range>=N)
		{
			//pthread_mutex_lock(&lock);
			terminate=1;
			//pthread_mutex_unlock(&lock);
		}
	  pthread_mutex_unlock(&lock);*/

		pthread_barrier_wait(arg->barrier);

		start = old_range  +  (difference/P)*(tid);            //(tid    * range)  / (arg->P)    + old_range;
		stop  = old_range  +  (difference/P)*(tid+1);            //((tid+1) * range)  / (arg->P)   + old_range;

		if(stop>range)
		 stop=range;

    //if(tid==0)
		{ pthread_mutex_lock(&lock);
       if(start==N || uu>N-1)
				 terminate=1;
		} pthread_mutex_unlock(&lock);

    //pthread_barrier_wait(arg->barrier);

		//printf("\n TID:%d   start:%d stop:%d terminate:%d",tid,start,stop,terminate);
	}
  //printf("\n %d %d",tid,terminate);
  return NULL;
}

int main(int argc, char** argv)
{ //int mul = W_index[0][0];
  /*if (argc != 3)
  {
    fprintf(stderr, "Usage: ./dijkstra <Number of Processors> <Number of Vertices>\n");
    exit(EXIT_FAILURE);
  }*/
//printf("main start\n");
  // Start the simulator
  //CarbonStartSim(argc, argv);

  const int P = atoi(argv[1]);
  const int N = atoi(argv[2]);
  const int DEG = atoi(argv[3]);
//printf("P: %d",P);
//printf("N: %d",N);
//printf("DEG: %d",DEG);

        if (DEG > N)
        {
                fprintf(stderr, "Degree of graph cannot be grater than number of Vertices\n");
                exit(EXIT_FAILURE);
        }

  int* D;
  int* Q;
	int* S;
  posix_memalign((void**) &D, 64, N * sizeof(int));
  posix_memalign((void**) &Q, 64, N * sizeof(int));
	posix_memalign((void**) &S, 64, N * sizeof(int));
  int d_count = N;
  pthread_barrier_t barrier;

  int** W = (int**) malloc(N*sizeof(int*));
  int** W_index = (int**) malloc(N*sizeof(int*));
  for(int i = 0; i < N; i++)
  {
    //W[i] = (int *)malloc(sizeof(int)*N);
    int ret = posix_memalign((void**) &W[i], 64, DEG*sizeof(int));
    int re1 = posix_memalign((void**) &W_index[i], 64, DEG*sizeof(int));
    if (ret != 0 || re1!=0)
    {
       fprintf(stderr, "Could not allocate memory\n");
       exit(EXIT_FAILURE);
    }
  }
  init_weights(N, DEG, W, W_index);
  /*for(int i = 0;i<N;i++)
  {
        for(int j = 0;j<N;j++)
        {
                printf(" %d ",W[i][j]);
        }
        printf("\n");
  }*/

  pthread_barrier_init(&barrier, NULL, P);
  pthread_mutex_init(&lock, NULL);
	for(int i=0; i<N; i++)
		pthread_mutex_init(&locks[i], NULL);

	initialize_single_source(D, Q, S, 0, N);

  for(int j = 0; j < P; j++) {
    thread_arg[j].local_min  = local_min_buffer;
    thread_arg[j].global_min = &global_min_buffer;
    thread_arg[j].Q          = Q;
    thread_arg[j].D          = D;
		thread_arg[j].S          = S;
    thread_arg[j].W          = W;
    thread_arg[j].W_index    = W_index;
    thread_arg[j].d_count    = &d_count;
    thread_arg[j].tid        = j;
    thread_arg[j].P          = P;
    thread_arg[j].N          = N;
    thread_arg[j].DEG        = DEG;
    thread_arg[j].barrier    = &barrier;
  }
int mul = 2;
  // Enable performance and energy models
  //CarbonEnableModels();

struct timespec requestStart, requestEnd;
clock_gettime(CLOCK_REALTIME, &requestStart);

         //For the easyperf performance counter API
         //uint64_t start[4], end[4];
         //unsigned long i;
		     //perf_init(4, I7_L2_MISS, I7_L3_REFS, I7_L3_MISS, EV_INSTR);
				 //perf_read_all(start);

  for(int j = 1; j < P; j++) {
    pthread_create(thread_handle+j,
                   NULL,
                   do_work,
                   (void*)&thread_arg[j]);
  }
  do_work((void*) &thread_arg[0]);

  for(int j = 1; j < P; j++) { //mul = mul*2;
    pthread_join(thread_handle[j],NULL);
  }

	//For the easyperf performance counter API
	//perf_read_all(end);
	//printf("\nL2-Misses: %10lu, \nL3-Refs: %10lu, \nL3-Misses: %10lu, \nInst.: %10lu", end[0] - start[0], end[1] - start[1], end[2] - start[2], end[3] - start[3]);
  //perf_close();

	clock_gettime(CLOCK_REALTIME, &requestEnd);
	  double accum = ( requestEnd.tv_sec - requestStart.tv_sec ) + ( requestEnd.tv_nsec - requestStart.tv_nsec ) / BILLION;
		  printf( "\n%lf\n", accum );

  // Enable performance and energy models
  //CarbonDisableModels();
  //printf("\ndistance:%d \n",D[N-1]);

    /*for(int i = 0; i < N; i++) {
      printf(" %d ", D[i]);
    }
    printf("\n");
*/
  // Stop the simulator
  //CarbonStopSim();
  return 0;
}

int initialize_single_source(int*  D,
                             int*  Q,
														 int*  S,
                             int   source,
                             int   N)
{
  for(int i = 0; i < N+1; i++)
  {
    D[i] = INT_MAX;
    Q[i] = 1;
		S[i] = INT_MAX;
  }

  D[source] = 0;
	S[source] = 0;
  return 0;
}

int get_local_min(volatile int* Q, volatile int* D, int start, int stop, int N, int** W_index, int** W, int u)
{
  int min = INT_MAX;
  int min_index = N;

  for(int i = start; i < stop; i++)
  {
   if(W_index[u][i]==-1 || W[u][i]==INT_MAX)
     continue;
    if(D[i] < min && Q[i])
    {
      min = D[i];
      min_index = W_index[u][i];
    }
  }
  return min_index;
}

void relax(int u, int i, volatile int* D, int* S, int** W, int** W_index, int N)
{
  if((D[W_index[u][i]] > (D[u] + W[u][i]) && (W_index[u][i]!=-1 && W_index[u][i]<N && W[u][i]!=INT_MAX)))
    D[W_index[u][i]] = D[u] + W[u][i];
}
<commit_msg>Update range_dijk.cc<commit_after>#include <cstdio>
#include <cstdlib>
#include <pthread.h>
//#include "easyperf.h"
//#include "carbon_user.h"
#include <time.h>
#include <sys/timeb.h>

#define MAX            100000000
#define INT_MAX        100000000
// #define DEBUG              1
#define BILLION 1E9

int _W[8][8] =
{
  {0,   2,      1,      17,     MAX,    MAX,    MAX,    MAX},
  {2,   0,      MAX,    MAX,    2,      6,      MAX,    MAX},
  {1,   MAX,    0,      MAX,    MAX,    MAX,    MAX,    8},
  {17,  MAX,    MAX,    0,      MAX,    2,      1,      9},
  {MAX, 2,      MAX,    MAX,    0,      4,      MAX,    MAX},
  {MAX, 6,      MAX,    2,      4,      0,      5,      MAX},
  {MAX, MAX,    MAX,    1,      MAX,    5,      0,      3},
  {MAX, MAX,    8,      9,      MAX,    MAX,    3,      0}
};

int min = INT_MAX;
int min_index = 0;
pthread_mutex_t lock;
pthread_mutex_t locks[4194304];
int u = 0;

  void init_weights(int N, int DEG, int** W, int** W_index)
  {
          int range = DEG + (N - DEG)/16;

          // Initialize to -1
          for(int i = 0; i < N; i++)
                  for(int j = 0; j < DEG; j++)
                          W_index[i][j]= -1;

          // Populate Index Array
          for(int i = 0; i < N; i++)
          {
                  int last = 0;
                  int min = 0;
                  int max = DEG;
                  for(int j = 0; j < DEG; j++)
                  {
                          if(W_index[i][j] == -1)
                          {
                                  int neighbor = i + j;//rand()%(max);
                                  if(neighbor > last)
                                  {
                                          W_index[i][j] = neighbor;
                                          last = W_index[i][j];
                                  }
                                  else
                                  {
                                          if(last < (N-1))
                                          {
                                                  W_index[i][j] = (last + 1);
                                                  last = W_index[i][j];
                                          }
                                  }
                          }
                          else
                          {
                                  last = W_index[i][j];
                          }
                          if(W_index[i][j]>=N)
                          {
                                  W_index[i][j] = N-1;
                          }
                  }
          }

          // Populate Cost Array
          for(int i = 0; i < N; i++)
          {
                  for(int j = 0; j < DEG; j++)
                  {
                          double v = drand48();
                          /*if(v > 0.8 || W_index[i][j] == -1)
                          {       W[i][j] = MAX;
                                  W_index[i][j] = -1;
                          }

                          else*/ if(W_index[i][j] == i)
                                  W[i][j] = 0;

                          else
                                  W[i][j] = (int) (v*100) + 1;
                          //printf("   %d  ",W_index[i][j]);
                  }
                  //printf("\n");
          }
  }

int initialize_single_source(int* D, int* Q, int* S, int source, int N);
void relax(int u, int i, volatile int* D, int* S, int** W, int** W_index, int N);
int get_local_min(volatile int* Q, volatile int* D, int start, int stop, int N, int** W_index, int** W, int u);

typedef struct
{
  int*      local_min;
  int*      global_min;
  int*      Q;
  int*      D;
	int*      S;
  int**     W;
  int**     W_index;
  int*      d_count;
  int       tid;
  int       P;
  int       N;
  int       DEG;
  pthread_barrier_t* barrier;
} thread_arg_t;

int local_min_buffer[1024];
int global_min_buffer;
int terminate = 0;
int range=1;
int old_range =1;
int difference=0;
int pid=0;
thread_arg_t thread_arg[1024];
pthread_t   thread_handle[1024];

void* do_work(void* args)
{
  volatile thread_arg_t* arg = (thread_arg_t*) args;

  volatile int* count      = arg->d_count;
  volatile int* global_min = arg->global_min;
  volatile int* local_min  = arg->local_min;
  int tid                  = arg->tid;
  int P                    = arg->P;
  volatile int* Q          = arg->Q;
  int* D                   = arg->D;
	int* S                   = arg->S;
  int** W                  = arg->W;
  int** W_index            = arg->W_index;
  const int N              = arg->N;
  const int DEG            = arg->DEG;
  int local_count          = N;
  int i, j, po;
	int uu = 0;

  int a = 0;
  int i_start =  0;  //tid    * DEG / (arg->P);
  int i_stop  = 0;   //(tid+1) * DEG / (arg->P);
	int start = 0;
	int stop = 1;
  //int difference =0;

	pthread_barrier_wait(arg->barrier);

  while(terminate==0)
  {
	  for(uu=start;uu<stop;uu++)
		{
    for(int i = 0; i < DEG; i++)
    {
      int neighbor = W_index[uu][i];
			//
			pthread_mutex_lock(&locks[neighbor]);

			if(uu>=N)
				terminate=1;

			if((D[W_index[uu][i]] > (D[uu] + W[uu][i]) && W_index[uu][i]!=-1 && W[uu][i]!=INT_MAX/* && Q[uu]==1*/))
			{
				D[W_index[uu][i]] = D[uu] + W[uu][i];
				S[W_index[uu][i]] = uu;
			}
     Q[uu]=0;// po=u;
		//if(W_index[uu][i]==-1)
		 //W[uu][i]=INT_MAX;

			pthread_mutex_unlock(&locks[neighbor]);
    }
		}

   pthread_barrier_wait(arg->barrier);

	 if(tid==0)
		{  //pthread_mutex_lock(&lock);
			 old_range=range;
		   range = range*DEG;

			 if(old_range==1)
				 old_range=0;

			 if(range>=N)
				 range=N;
       //pthread_mutex_unlock(&lock);
			 //printf("\nold:%d new:%d",old_range,range);

			 difference = range-old_range;
			if(difference<P)
			{
					pid=difference;
		  }
			else
				  pid=P;
			if(pid==0)
				pid=P;
		}

	 //pthread_mutex_lock(&lock);
	 //if(u<=N)
     //u++;
	 //pthread_mutex_unlock(&lock);

    /*pthread_mutex_lock(&lock);
		if(uu>=N-1 || range>=N)
		{
			//pthread_mutex_lock(&lock);
			terminate=1;
			//pthread_mutex_unlock(&lock);
		}
	  pthread_mutex_unlock(&lock);*/

		pthread_barrier_wait(arg->barrier);

		start = old_range  +  (difference/P)*(tid);            //(tid    * range)  / (arg->P)    + old_range;
		stop  = old_range  +  (difference/P)*(tid+1);            //((tid+1) * range)  / (arg->P)   + old_range;

		if(stop>range)
		 stop=range;

    //if(tid==0)
		{ pthread_mutex_lock(&lock);
       if(start==N || uu>N-1)
				 terminate=1;
		} pthread_mutex_unlock(&lock);

    //pthread_barrier_wait(arg->barrier);

		//printf("\n TID:%d   start:%d stop:%d terminate:%d",tid,start,stop,terminate);
	}
  //printf("\n %d %d",tid,terminate);
  return NULL;
}

int main(int argc, char** argv)
{ //int mul = W_index[0][0];
  /*if (argc != 3)
  {
    fprintf(stderr, "Usage: ./dijkstra <Number of Processors> <Number of Vertices>\n");
    exit(EXIT_FAILURE);
  }*/
//printf("main start\n");
  // Start the simulator
  //CarbonStartSim(argc, argv);

  const int P = atoi(argv[1]);
  const int N = atoi(argv[2]);
  const int DEG = atoi(argv[3]);
//printf("P: %d",P);
//printf("N: %d",N);
//printf("DEG: %d",DEG);

        if (DEG > N)
        {
                fprintf(stderr, "Degree of graph cannot be grater than number of Vertices\n");
                exit(EXIT_FAILURE);
        }

  int* D;
  int* Q;
	int* S;
  posix_memalign((void**) &D, 64, N * sizeof(int));
  posix_memalign((void**) &Q, 64, N * sizeof(int));
	posix_memalign((void**) &S, 64, N * sizeof(int));
  int d_count = N;
  pthread_barrier_t barrier;

  int** W = (int**) malloc(N*sizeof(int*));
  int** W_index = (int**) malloc(N*sizeof(int*));
  for(int i = 0; i < N; i++)
  {
    //W[i] = (int *)malloc(sizeof(int)*N);
    int ret = posix_memalign((void**) &W[i], 64, DEG*sizeof(int));
    int re1 = posix_memalign((void**) &W_index[i], 64, DEG*sizeof(int));
    if (ret != 0 || re1!=0)
    {
       fprintf(stderr, "Could not allocate memory\n");
       exit(EXIT_FAILURE);
    }
  }
  init_weights(N, DEG, W, W_index);
  /*for(int i = 0;i<N;i++)
  {
        for(int j = 0;j<N;j++)
        {
                printf(" %d ",W[i][j]);
        }
        printf("\n");
  }*/

  pthread_barrier_init(&barrier, NULL, P);
  pthread_mutex_init(&lock, NULL);
	for(int i=0; i<N; i++)
		pthread_mutex_init(&locks[i], NULL);

	initialize_single_source(D, Q, S, 0, N);

  for(int j = 0; j < P; j++) {
    thread_arg[j].local_min  = local_min_buffer;
    thread_arg[j].global_min = &global_min_buffer;
    thread_arg[j].Q          = Q;
    thread_arg[j].D          = D;
		thread_arg[j].S          = S;
    thread_arg[j].W          = W;
    thread_arg[j].W_index    = W_index;
    thread_arg[j].d_count    = &d_count;
    thread_arg[j].tid        = j;
    thread_arg[j].P          = P;
    thread_arg[j].N          = N;
    thread_arg[j].DEG        = DEG;
    thread_arg[j].barrier    = &barrier;
  }
int mul = 2;
  // Enable performance and energy models
  //CarbonEnableModels();

struct timespec requestStart, requestEnd;
clock_gettime(CLOCK_REALTIME, &requestStart);

         //For the easyperf performance counter API
         //uint64_t start[4], end[4];
         //unsigned long i;
		     //perf_init(4, I7_L2_MISS, I7_L3_REFS, I7_L3_MISS, EV_INSTR);
				 //perf_read_all(start);

  for(int j = 1; j < P; j++) {
    pthread_create(thread_handle+j,
                   NULL,
                   do_work,
                   (void*)&thread_arg[j]);
  }
  do_work((void*) &thread_arg[0]);

  for(int j = 1; j < P; j++) { //mul = mul*2;
    pthread_join(thread_handle[j],NULL);
  }

	//For the easyperf performance counter API
	//perf_read_all(end);
	//printf("\nL2-Misses: %10lu, \nL3-Refs: %10lu, \nL3-Misses: %10lu, \nInst.: %10lu", end[0] - start[0], end[1] - start[1], end[2] - start[2], end[3] - start[3]);
  //perf_close();

	clock_gettime(CLOCK_REALTIME, &requestEnd);
	  double accum = ( requestEnd.tv_sec - requestStart.tv_sec ) + ( requestEnd.tv_nsec - requestStart.tv_nsec ) / BILLION;
		  printf( "\n%lf\n", accum );

  // Enable performance and energy models
  //CarbonDisableModels();
  //printf("\ndistance:%d \n",D[N-1]);

    /*for(int i = 0; i < N; i++) {
      printf(" %d ", D[i]);
    }
    printf("\n");
*/
  // Stop the simulator
  //CarbonStopSim();
  return 0;
}

int initialize_single_source(int*  D,
                             int*  Q,
														 int*  S,
                             int   source,
                             int   N)
{
  for(int i = 0; i < N+1; i++)
  {
    D[i] = INT_MAX;
    Q[i] = 1;
		S[i] = INT_MAX;
  }

  D[source] = 0;
	S[source] = 0;
  return 0;
}

int get_local_min(volatile int* Q, volatile int* D, int start, int stop, int N, int** W_index, int** W, int u)
{
  int min = INT_MAX;
  int min_index = N;

  for(int i = start; i < stop; i++)
  {
   if(W_index[u][i]==-1 || W[u][i]==INT_MAX)
     continue;
    if(D[i] < min && Q[i])
    {
      min = D[i];
      min_index = W_index[u][i];
    }
  }
  return min_index;
}

void relax(int u, int i, volatile int* D, int* S, int** W, int** W_index, int N)
{
  if((D[W_index[u][i]] > (D[u] + W[u][i]) && (W_index[u][i]!=-1 && W_index[u][i]<N && W[u][i]!=INT_MAX)))
    D[W_index[u][i]] = D[u] + W[u][i];
}
<|endoftext|>


<commit_before>/*
 * Copyright 2015 - 2021 gary@drinkingtea.net
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#if defined(OX_USE_STDLIB)
#include <string>
#endif

#include "buffer.hpp"
#include "memops.hpp"
#include "strops.hpp"
#include "typetraits.hpp"
#include "vector.hpp"

namespace ox {

template<std::size_t SmallStringSize = 0>
class BasicString {
	private:
		Vector<char, SmallStringSize> m_buff;

	public:
		constexpr BasicString() noexcept;

		constexpr explicit BasicString(std::size_t cap) noexcept;

		constexpr BasicString(const char *str) noexcept;

		constexpr BasicString(const char *str, std::size_t size) noexcept;

		constexpr BasicString(const BasicString&) noexcept;

		constexpr BasicString(BasicString&&) noexcept;

		BasicString &operator=(const char *str) noexcept;

		BasicString &operator=(char *str) noexcept;

		BasicString &operator=(char c) noexcept;

		BasicString &operator=(int i) noexcept;

		BasicString &operator=(int64_t i) noexcept;

		BasicString &operator=(uint64_t i) noexcept;

		BasicString &operator=(const BasicString &src) noexcept;

		BasicString &operator=(BasicString &&src) noexcept;

		constexpr BasicString &operator+=(const char *str) noexcept;

		constexpr BasicString &operator+=(char *str) noexcept;

		constexpr BasicString &operator+=(char c) noexcept;

		constexpr BasicString &operator+=(int i) noexcept;

		constexpr BasicString &operator+=(int64_t i) noexcept;

		constexpr BasicString &operator+=(uint64_t i) noexcept;

		constexpr BasicString &operator+=(const BasicString &src) noexcept;

		BasicString operator+(const char *str) const noexcept;

		BasicString operator+(char *str) const noexcept;

		BasicString operator+(char c) const noexcept;

		BasicString operator+(int i) const noexcept;

		BasicString operator+(int64_t i) const noexcept;

		BasicString operator+(uint64_t i) const noexcept;

		BasicString operator+(const BasicString &src) const noexcept;

		bool operator==(const BasicString &other) const noexcept;

		bool operator!=(const BasicString &other) const noexcept;

		char operator[](std::size_t i) const noexcept;

		char &operator[](std::size_t i) noexcept;

		constexpr Error append(const char *str, std::size_t strLen) noexcept {
			auto currentLen = len();
			m_buff.resize(m_buff.size() + strLen);
			ox_memcpy(&m_buff[currentLen], str, strLen);
			// make sure last element is a null terminator
			m_buff[currentLen + strLen] = 0;
			// this can't fail, but it returns an Error to match BString::append
			return OxError(0);
		}

		[[nodiscard]]
		BasicString substr(std::size_t pos) const noexcept;

		[[nodiscard]]
		bool endsWith(const char *ending) const noexcept;

		[[nodiscard]]
		bool endsWith(const BasicString &ending) const noexcept;

		[[nodiscard]]
		constexpr const char *data() const noexcept {
			return m_buff.data();
		}

		[[nodiscard]]
		constexpr char *data() noexcept {
			return m_buff.data();
		}

		[[nodiscard]]
		constexpr const char *c_str() const noexcept {
			return static_cast<const char*>(m_buff.data());
		}

#ifdef OX_USE_STDLIB
		[[nodiscard]]
		inline std::string toStdString() const {
			return c_str();
		}
#endif

		/**
		 * Returns the number of characters in this string.
		 */
		[[nodiscard]]
		constexpr std::size_t len() const noexcept;

		/**
		 * Returns the number of bytes used for this string.
		 */
		[[nodiscard]]
		std::size_t bytes() const noexcept;

};

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize>::BasicString() noexcept {
	if (m_buff.size()) {
		m_buff[0] = 0;
	} else {
		m_buff.push_back(0);
	}
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize>::BasicString(std::size_t cap) noexcept {
	m_buff.resize(cap + 1);
	m_buff[0] = 0;
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize>::BasicString(const char *str) noexcept {
	if (m_buff.size()) {
		m_buff[0] = 0;
	} else {
		m_buff.push_back(0);
	}
	*this = str;
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize>::BasicString(const char *str, std::size_t size) noexcept {
	m_buff.resize(size + 1);
	memcpy(m_buff.data(), str, size);
	m_buff[size] = 0;
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize>::BasicString(const BasicString &other) noexcept {
	m_buff = other.m_buff;
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize>::BasicString(BasicString &&other) noexcept {
	m_buff = move(other.m_buff);
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(const char *str) noexcept {
	std::size_t strLen = ox_strlen(str) + 1;
	m_buff.resize(strLen + 1);
	memcpy(m_buff.data(), str, strLen);
	// make sure last element is a null terminator
	m_buff[m_buff.size() - 1] = 0;
	return *this;
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(char *str) noexcept {
	return *this = const_cast<const char*>(str);
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(char c) noexcept {
	char str[] = {c, 0};
	return this->operator=(str);
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(int i) noexcept {
	return this->operator=(static_cast<int64_t>(i));
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(int64_t i) noexcept {
	char str[65] = {};
	ox_itoa(i, str);
	return this->operator=(str);
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(uint64_t i) noexcept {
	char str[65] = {};
	ox_itoa(i, str);
	return this->operator=(str);
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(const BasicString &src) noexcept {
	return *this = src.c_str();
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(BasicString &&src) noexcept {
	m_buff = move(src.m_buff);
	return *this;
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator+=(const char *str) noexcept {
	std::size_t strLen = ox_strlen(str);
	oxIgnoreError(append(str, strLen));
	return *this;
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator+=(char *str) noexcept {
	return *this += static_cast<const char*>(str);
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator+=(char c) noexcept {
	const char str[] = {c, 0};
	return this->operator+=(str);
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator+=(int i) noexcept {
	return this->operator+=(static_cast<int64_t>(i));
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator+=(int64_t i) noexcept {
	char str[65] = {};
	ox_itoa(i, str);
	return this->operator+=(str);
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator+=(uint64_t i) noexcept {
	char str[65] = {};
	ox_itoa(i, str);
	return this->operator+=(str);
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator+=(const BasicString &src) noexcept {
	return *this += src.c_str();
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> BasicString<SmallStringSize>::operator+(const char *str) const noexcept {
	const std::size_t strLen = ox_strlen(str);
	const auto currentLen = len();
	BasicString<SmallStringSize> cpy(currentLen + strLen);
	cpy.m_buff.resize(m_buff.size() + strLen);
	memcpy(&cpy.m_buff[0], m_buff.data(), currentLen);
	memcpy(&cpy.m_buff[currentLen], str, strLen);
	// make sure last element is a null terminator
	cpy.m_buff[currentLen + strLen] = 0;
	return move(cpy);
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> BasicString<SmallStringSize>::operator+(char *str) const noexcept {
	return *this + static_cast<const char*>(str);
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> BasicString<SmallStringSize>::operator+(char c) const noexcept {
	const char str[] = {c, 0};
	return *this + str;
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> BasicString<SmallStringSize>::operator+(int i) const noexcept {
	return this->operator+(static_cast<int64_t>(i));
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> BasicString<SmallStringSize>::operator+(int64_t i) const noexcept {
	char str[65] = {};
	ox_itoa(i, str);
	return *this + str;
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> BasicString<SmallStringSize>::operator+(uint64_t i) const noexcept {
	char str[65] = {};
	ox_itoa(i, str);
	return *this + str;
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> BasicString<SmallStringSize>::operator+(const BasicString &src) const noexcept {
	return *this + src.c_str();
}

template<std::size_t SmallStringSize>
bool BasicString<SmallStringSize>::operator==(const BasicString &other) const noexcept {
	bool retval = true;
	std::size_t i = 0;
	while (i < m_buff.size() && (m_buff[i] || other.m_buff[i])) {
		if (m_buff[i] != other.m_buff[i]) {
			retval = false;
			break;
		}
		i++;
	}
	return retval;
}

template<std::size_t SmallStringSize>
bool BasicString<SmallStringSize>::operator!=(const BasicString &other) const noexcept {
	return !operator==(other);
}

template<std::size_t SmallStringSize>
char BasicString<SmallStringSize>::operator[](std::size_t i) const noexcept {
	return m_buff[i];
}

template<std::size_t SmallStringSize>
char &BasicString<SmallStringSize>::operator[](std::size_t i) noexcept {
	return m_buff[i];
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> BasicString<SmallStringSize>::substr(std::size_t pos) const noexcept {
	return m_buff.data() + pos;
}

template<std::size_t SmallStringSize>
bool BasicString<SmallStringSize>::endsWith(const char *ending) const noexcept {
	const auto endingLen = ox_strlen(ending);
	return len() >= endingLen && ox_strcmp(data() + (len() - endingLen), ending) == 0;
}

template<std::size_t SmallStringSize>
bool BasicString<SmallStringSize>::endsWith(const BasicString &ending) const noexcept {
	const auto endingLen = ending.len();
	return len() >= endingLen && ox_strcmp(data() + (len() - endingLen), ending.c_str()) == 0;
}

template<std::size_t SmallStringSize>
std::size_t BasicString<SmallStringSize>::bytes() const noexcept {
	std::size_t i;
	for (i = 0; i < m_buff.size() && m_buff[i]; i++);
	return i + 1; // add one for null terminator
}

template<std::size_t SmallStringSize>
constexpr std::size_t BasicString<SmallStringSize>::len() const noexcept {
	std::size_t length = 0;
	for (const auto c : m_buff) {
		auto b = static_cast<uint8_t>(c);
		if (b) {
			if ((b & 128) == 0) { // normal ASCII character
				++length;
			} else if ((b & (256 << 6)) == (256 << 6)) { // start of UTF-8 character
				++length;
			}
		} else {
			break;
		}
	}
	return length;
}

extern template class BasicString<0>;

using String = BasicString<0>;

}
<commit_msg>[ox/std] Add BasicString::substr(begin, end)<commit_after>/*
 * Copyright 2015 - 2021 gary@drinkingtea.net
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#if defined(OX_USE_STDLIB)
#include <string>
#endif

#include "buffer.hpp"
#include "memops.hpp"
#include "strops.hpp"
#include "typetraits.hpp"
#include "vector.hpp"

namespace ox {

template<std::size_t SmallStringSize = 0>
class BasicString {
	private:
		Vector<char, SmallStringSize> m_buff;

	public:
		constexpr BasicString() noexcept;

		constexpr explicit BasicString(std::size_t cap) noexcept;

		constexpr BasicString(const char *str) noexcept;

		constexpr BasicString(const char *str, std::size_t size) noexcept;

		constexpr BasicString(const BasicString&) noexcept;

		constexpr BasicString(BasicString&&) noexcept;

		BasicString &operator=(const char *str) noexcept;

		BasicString &operator=(char *str) noexcept;

		BasicString &operator=(char c) noexcept;

		BasicString &operator=(int i) noexcept;

		BasicString &operator=(int64_t i) noexcept;

		BasicString &operator=(uint64_t i) noexcept;

		BasicString &operator=(const BasicString &src) noexcept;

		BasicString &operator=(BasicString &&src) noexcept;

		constexpr BasicString &operator+=(const char *str) noexcept;

		constexpr BasicString &operator+=(char *str) noexcept;

		constexpr BasicString &operator+=(char c) noexcept;

		constexpr BasicString &operator+=(int i) noexcept;

		constexpr BasicString &operator+=(int64_t i) noexcept;

		constexpr BasicString &operator+=(uint64_t i) noexcept;

		constexpr BasicString &operator+=(const BasicString &src) noexcept;

		BasicString operator+(const char *str) const noexcept;

		BasicString operator+(char *str) const noexcept;

		BasicString operator+(char c) const noexcept;

		BasicString operator+(int i) const noexcept;

		BasicString operator+(int64_t i) const noexcept;

		BasicString operator+(uint64_t i) const noexcept;

		BasicString operator+(const BasicString &src) const noexcept;

		bool operator==(const BasicString &other) const noexcept;

		bool operator!=(const BasicString &other) const noexcept;

		char operator[](std::size_t i) const noexcept;

		char &operator[](std::size_t i) noexcept;

		constexpr Error append(const char *str, std::size_t strLen) noexcept {
			auto currentLen = len();
			m_buff.resize(m_buff.size() + strLen);
			ox_memcpy(&m_buff[currentLen], str, strLen);
			// make sure last element is a null terminator
			m_buff[currentLen + strLen] = 0;
			// this can't fail, but it returns an Error to match BString::append
			return OxError(0);
		}

		[[nodiscard]]
		BasicString substr(std::size_t pos) const noexcept;

		[[nodiscard]]
		BasicString substr(std::size_t begin, std::size_t end) const noexcept;

		[[nodiscard]]
		bool endsWith(const char *ending) const noexcept;

		[[nodiscard]]
		bool endsWith(const BasicString &ending) const noexcept;

		[[nodiscard]]
		constexpr const char *data() const noexcept {
			return m_buff.data();
		}

		[[nodiscard]]
		constexpr char *data() noexcept {
			return m_buff.data();
		}

		[[nodiscard]]
		constexpr const char *c_str() const noexcept {
			return static_cast<const char*>(m_buff.data());
		}

#ifdef OX_USE_STDLIB
		[[nodiscard]]
		inline std::string toStdString() const {
			return c_str();
		}
#endif

		/**
		 * Returns the number of characters in this string.
		 */
		[[nodiscard]]
		constexpr std::size_t len() const noexcept;

		/**
		 * Returns the number of bytes used for this string.
		 */
		[[nodiscard]]
		std::size_t bytes() const noexcept;

};

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize>::BasicString() noexcept {
	if (m_buff.size()) {
		m_buff[0] = 0;
	} else {
		m_buff.push_back(0);
	}
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize>::BasicString(std::size_t cap) noexcept {
	m_buff.resize(cap + 1);
	m_buff[0] = 0;
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize>::BasicString(const char *str) noexcept {
	if (m_buff.size()) {
		m_buff[0] = 0;
	} else {
		m_buff.push_back(0);
	}
	*this = str;
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize>::BasicString(const char *str, std::size_t size) noexcept {
	m_buff.resize(size + 1);
	memcpy(m_buff.data(), str, size);
	m_buff[size] = 0;
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize>::BasicString(const BasicString &other) noexcept {
	m_buff = other.m_buff;
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize>::BasicString(BasicString &&other) noexcept {
	m_buff = move(other.m_buff);
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(const char *str) noexcept {
	std::size_t strLen = ox_strlen(str) + 1;
	m_buff.resize(strLen + 1);
	memcpy(m_buff.data(), str, strLen);
	// make sure last element is a null terminator
	m_buff[m_buff.size() - 1] = 0;
	return *this;
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(char *str) noexcept {
	return *this = const_cast<const char*>(str);
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(char c) noexcept {
	char str[] = {c, 0};
	return this->operator=(str);
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(int i) noexcept {
	return this->operator=(static_cast<int64_t>(i));
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(int64_t i) noexcept {
	char str[65] = {};
	ox_itoa(i, str);
	return this->operator=(str);
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(uint64_t i) noexcept {
	char str[65] = {};
	ox_itoa(i, str);
	return this->operator=(str);
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(const BasicString &src) noexcept {
	return *this = src.c_str();
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(BasicString &&src) noexcept {
	m_buff = move(src.m_buff);
	return *this;
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator+=(const char *str) noexcept {
	std::size_t strLen = ox_strlen(str);
	oxIgnoreError(append(str, strLen));
	return *this;
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator+=(char *str) noexcept {
	return *this += static_cast<const char*>(str);
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator+=(char c) noexcept {
	const char str[] = {c, 0};
	return this->operator+=(str);
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator+=(int i) noexcept {
	return this->operator+=(static_cast<int64_t>(i));
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator+=(int64_t i) noexcept {
	char str[65] = {};
	ox_itoa(i, str);
	return this->operator+=(str);
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator+=(uint64_t i) noexcept {
	char str[65] = {};
	ox_itoa(i, str);
	return this->operator+=(str);
}

template<std::size_t SmallStringSize>
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator+=(const BasicString &src) noexcept {
	return *this += src.c_str();
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> BasicString<SmallStringSize>::operator+(const char *str) const noexcept {
	const std::size_t strLen = ox_strlen(str);
	const auto currentLen = len();
	BasicString<SmallStringSize> cpy(currentLen + strLen);
	cpy.m_buff.resize(m_buff.size() + strLen);
	memcpy(&cpy.m_buff[0], m_buff.data(), currentLen);
	memcpy(&cpy.m_buff[currentLen], str, strLen);
	// make sure last element is a null terminator
	cpy.m_buff[currentLen + strLen] = 0;
	return move(cpy);
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> BasicString<SmallStringSize>::operator+(char *str) const noexcept {
	return *this + static_cast<const char*>(str);
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> BasicString<SmallStringSize>::operator+(char c) const noexcept {
	const char str[] = {c, 0};
	return *this + str;
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> BasicString<SmallStringSize>::operator+(int i) const noexcept {
	return this->operator+(static_cast<int64_t>(i));
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> BasicString<SmallStringSize>::operator+(int64_t i) const noexcept {
	char str[65] = {};
	ox_itoa(i, str);
	return *this + str;
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> BasicString<SmallStringSize>::operator+(uint64_t i) const noexcept {
	char str[65] = {};
	ox_itoa(i, str);
	return *this + str;
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> BasicString<SmallStringSize>::operator+(const BasicString &src) const noexcept {
	return *this + src.c_str();
}

template<std::size_t SmallStringSize>
bool BasicString<SmallStringSize>::operator==(const BasicString &other) const noexcept {
	bool retval = true;
	std::size_t i = 0;
	while (i < m_buff.size() && (m_buff[i] || other.m_buff[i])) {
		if (m_buff[i] != other.m_buff[i]) {
			retval = false;
			break;
		}
		i++;
	}
	return retval;
}

template<std::size_t SmallStringSize>
bool BasicString<SmallStringSize>::operator!=(const BasicString &other) const noexcept {
	return !operator==(other);
}

template<std::size_t SmallStringSize>
char BasicString<SmallStringSize>::operator[](std::size_t i) const noexcept {
	return m_buff[i];
}

template<std::size_t SmallStringSize>
char &BasicString<SmallStringSize>::operator[](std::size_t i) noexcept {
	return m_buff[i];
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> BasicString<SmallStringSize>::substr(std::size_t pos) const noexcept {
	return m_buff.data() + pos;
}

template<std::size_t SmallStringSize>
BasicString<SmallStringSize> BasicString<SmallStringSize>::substr(std::size_t begin, std::size_t end) const noexcept {
	const auto src = m_buff.data() + begin;
	const auto size = end - begin;
	BasicString<SmallStringSize> out(size);
	const auto buff = out.data();
	memcpy(buff, src, size);
	buff[size] = 0;
	return move(out);
}

template<std::size_t SmallStringSize>
bool BasicString<SmallStringSize>::endsWith(const char *ending) const noexcept {
	const auto endingLen = ox_strlen(ending);
	return len() >= endingLen && ox_strcmp(data() + (len() - endingLen), ending) == 0;
}

template<std::size_t SmallStringSize>
bool BasicString<SmallStringSize>::endsWith(const BasicString &ending) const noexcept {
	const auto endingLen = ending.len();
	return len() >= endingLen && ox_strcmp(data() + (len() - endingLen), ending.c_str()) == 0;
}

template<std::size_t SmallStringSize>
std::size_t BasicString<SmallStringSize>::bytes() const noexcept {
	std::size_t i;
	for (i = 0; i < m_buff.size() && m_buff[i]; i++);
	return i + 1; // add one for null terminator
}

template<std::size_t SmallStringSize>
constexpr std::size_t BasicString<SmallStringSize>::len() const noexcept {
	std::size_t length = 0;
	for (const auto c : m_buff) {
		auto b = static_cast<uint8_t>(c);
		if (b) {
			if ((b & 128) == 0) { // normal ASCII character
				++length;
			} else if ((b & (256 << 6)) == (256 << 6)) { // start of UTF-8 character
				++length;
			}
		} else {
			break;
		}
	}
	return length;
}

extern template class BasicString<0>;

using String = BasicString<0>;

}
<|endoftext|>