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

/* Title: Streaming */

#include "config.h"

#include "main.h"

#include <string.h>

#include <memory>

static bool SizeIsUS = false;

static alureStream *InitStream(alureStream *instream, ALsizei chunkLength, ALsizei numBufs, ALuint *bufs)
{
    std::auto_ptr<alureStream> stream(instream);
    ALenum format;
    ALuint freq, blockAlign;

    if(!stream->GetFormat(&format, &freq, &blockAlign))
    {
        SetError("Could not get stream format");
        return NULL;
    }

    if(format == AL_NONE)
    {
        SetError("No valid format");
        return NULL;
    }
    if(blockAlign == 0)
    {
        SetError("Invalid block size");
        return NULL;
    }
    if(freq == 0)
    {
        SetError("Invalid sample rate");
        return NULL;
    }

    alureUInt64 len64 = chunkLength;
    if(SizeIsUS)
    {
        ALuint framesPerBlock = DetectCompressionRate(format);
        if(framesPerBlock == 0)
        {
            SetError("Unknown compression rate");
            return NULL;
        }

        len64 = len64 * freq / 1000000 / framesPerBlock * blockAlign;
        if(len64 > 0xFFFFFFFF)
        {
            SetError("Chunk length too large");
            return NULL;
        }
    }

    chunkLength = len64 - (len64%blockAlign);
    if(chunkLength <= 0)
    {
        SetError("Chunk length too small");
        return NULL;
    }

    stream->chunkLen = chunkLength;
    stream->dataChunk = new ALubyte[stream->chunkLen];

    alGenBuffers(numBufs, bufs);
    if(alGetError() != AL_NO_ERROR)
    {
        SetError("Buffer creation failed");
        return NULL;
    }

    ALsizei filled;
    for(filled = 0;filled < numBufs;filled++)
    {
        ALuint got = stream->GetData(stream->dataChunk, stream->chunkLen);
        got -= got%blockAlign;
        if(got == 0) break;

        alBufferData(bufs[filled], format, stream->dataChunk, got, freq);
    }

    while(filled < numBufs)
    {
        alBufferData(bufs[filled], format, stream->dataChunk, 0, freq);
        filled++;
    }
    if(alGetError() != AL_NO_ERROR)
    {
        alDeleteBuffers(numBufs, bufs);
        alGetError();

        SetError("Buffering error");
        return NULL;
    }

    return stream.release();
}

extern "C" {

/* Function: alureStreamSizeIsMicroSec
 *
 * Specifies if the chunk size value given to the alureCreateStream functions
 * is in bytes (default) or microseconds. Specifying the size in microseconds
 * can help manage the time needed in between needed updates (since the format
 * and sample rate of the stream may not be known), while specifying the size
 * in bytes can help control memory usage.
 *
 * Returns:
 * Previously set value.
 *
 * *Version Added*: 1.1
 *
 * See Also:
 * <alureCreateStreamFromFile>, <alureCreateStreamFromMemory>,
 * <alureCreateStreamFromStaticMemory>, <alureCreateStreamFromCallback>
 */
ALURE_API ALboolean ALURE_APIENTRY alureStreamSizeIsMicroSec(ALboolean useUS)
{
    ALboolean old = (SizeIsUS ? AL_TRUE : AL_FALSE);
    SizeIsUS = !!useUS;
    return old;
}

/* Function: alureCreateStreamFromFile
 *
 * Opens a file and sets it up for streaming. The given chunkLength is the
 * number of bytes, or microseconds worth of bytes if
 * <alureStreamSizeIsMicroSec> was last called with AL_TRUE, each buffer will
 * fill with. ALURE will optionally generate the specified number of buffer
 * objects, fill them with the beginning of the data, then place the new IDs
 * into the provided storage, before returning. Requires an active context.
 *
 * Returns:
 * An opaque handle used to control the opened stream, or NULL on error.
 *
 * See Also:
 * <alureStreamSizeIsMicroSec>, <alureCreateStreamFromMemory>,
 * <alureCreateStreamFromStaticMemory>, <alureCreateStreamFromCallback>
 */
ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromFile(const ALchar *fname, ALsizei chunkLength, ALsizei numBufs, ALuint *bufs)
{
    if(alGetError() != AL_NO_ERROR)
    {
        SetError("Existing OpenAL error");
        return NULL;
    }

    if(chunkLength < 0)
    {
        SetError("Invalid chunk length");
        return NULL;
    }

    if(numBufs < 0)
    {
        SetError("Invalid buffer count");
        return NULL;
    }

    alureStream *stream = create_stream(fname);
    if(!stream->IsValid())
    {
        delete stream;
        return NULL;
    }

    return InitStream(stream, chunkLength, numBufs, bufs);
}

/* Function: alureCreateStreamFromMemory
 *
 * Opens a file image from memory and sets it up for streaming, similar to
 * <alureCreateStreamFromFile>. The given data buffer can be safely deleted
 * after calling this function. Requires an active context.
 *
 * Returns:
 * An opaque handle used to control the opened stream, or NULL on error.
 *
 * See Also:
 * <alureStreamSizeIsMicroSec>, <alureCreateStreamFromFile>,
 * <alureCreateStreamFromStaticMemory>, <alureCreateStreamFromCallback>
 */
ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromMemory(const ALubyte *fdata, ALuint length, ALsizei chunkLength, ALsizei numBufs, ALuint *bufs)
{
    if(alGetError() != AL_NO_ERROR)
    {
        SetError("Existing OpenAL error");
        return NULL;
    }

    if(chunkLength < 0)
    {
        SetError("Invalid chunk length");
        return NULL;
    }

    if(numBufs < 0)
    {
        SetError("Invalid buffer count");
        return NULL;
    }

    if(length <= 0)
    {
        SetError("Invalid data length");
        return NULL;
    }

    ALubyte *streamData = new ALubyte[length];
    memcpy(streamData, fdata, length);

    MemDataInfo memData;
    memData.Data = streamData;
    memData.Length = length;
    memData.Pos = 0;

    alureStream *stream = create_stream(memData);
    stream->data = streamData;
    if(!stream->IsValid())
    {
        delete stream;
        return NULL;
    }

    return InitStream(stream, chunkLength, numBufs, bufs);
}

/* Function: alureCreateStreamFromStaticMemory
 *
 * Identical to <alureCreateStreamFromMemory>, except the given memory is used
 * directly and not duplicated. As a consequence, the data buffer must remain
 * valid while the stream is alive. Requires an active context.
 *
 * Returns:
 * An opaque handle used to control the opened stream, or NULL on error.
 *
 * See Also:
 * <alureStreamSizeIsMicroSec>, <alureCreateStreamFromFile>,
 * <alureCreateStreamFromMemory>, <alureCreateStreamFromCallback>
 */
ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromStaticMemory(const ALubyte *fdata, ALuint length, ALsizei chunkLength, ALsizei numBufs, ALuint *bufs)
{
    if(alGetError() != AL_NO_ERROR)
    {
        SetError("Existing OpenAL error");
        return NULL;
    }

    if(chunkLength < 0)
    {
        SetError("Invalid chunk length");
        return NULL;
    }

    if(numBufs < 0)
    {
        SetError("Invalid buffer count");
        return NULL;
    }

    if(length <= 0)
    {
        SetError("Invalid data length");
        return NULL;
    }

    MemDataInfo memData;
    memData.Data = fdata;
    memData.Length = length;
    memData.Pos = 0;

    alureStream *stream = create_stream(memData);
    if(!stream->IsValid())
    {
        delete stream;
        return NULL;
    }

    return InitStream(stream, chunkLength, numBufs, bufs);
}

/* Function: alureCreateStreamFromCallback
 *
 * Creates a stream using the specified callback to retrieve data. Requires an
 * active context.
 *
 * Parameters:
 * callback - This is called when more data is needed from the stream. Up to
 *            the specified number of bytes should be written to the data
 *            pointer, and the number of bytes actually written should be
 *            returned. The number of bytes written must be block aligned for
 *            the format (eg. a multiple of 4 for AL_FORMAT_STEREO16), or an
 *            OpenAL error may occur during buffering.
 * userdata - A handle passed through to the callback.
 * format - The format of the data the callback will be giving. The format must
 *          be valid for the context.
 * samplerate - The sample rate (frequency) of the stream
 *
 * Returns:
 * An opaque handle used to control the opened stream, or NULL on error.
 *
 * See Also:
 * <alureStreamSizeIsMicroSec>, <alureCreateStreamFromFile>,
 * <alureCreateStreamFromMemory>, <alureCreateStreamFromStaticMemory>
 */
ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromCallback(
      ALuint (*callback)(void *userdata, ALubyte *data, ALuint bytes),
      void *userdata, ALenum format, ALuint samplerate,
      ALsizei chunkLength, ALsizei numBufs, ALuint *bufs)
{
    if(alGetError() != AL_NO_ERROR)
    {
        SetError("Existing OpenAL error");
        return NULL;
    }

    if(callback == NULL)
    {
        SetError("Invalid callback");
        return NULL;
    }

    if(chunkLength < 0)
    {
        SetError("Invalid chunk length");
        return NULL;
    }

    if(numBufs < 0)
    {
        SetError("Invalid buffer count");
        return NULL;
    }

    UserCallbacks newcb;
    newcb.open_file = NULL;
    newcb.open_mem  = NULL;
    newcb.get_fmt   = NULL;
    newcb.decode    = callback;
    newcb.rewind    = NULL;
    newcb.close     = NULL;

    alureStream *stream = create_stream(userdata, format, samplerate, newcb);
    return InitStream(stream, chunkLength, numBufs, bufs);
}

/* Function: alureGetStreamFrequency
 *
 * Retrieves the frequency used for the given stream.
 *
 * Returns:
 * 0 on error.
 *
 * *Version Added*: 1.1
 */
ALURE_API ALsizei ALURE_APIENTRY alureGetStreamFrequency(alureStream *stream)
{
    ALenum format;
    ALuint rate, balign;

    if(!alureStream::Verify(stream))
    {
        SetError("Invalid stream pointer");
        return 0;
    }

    if(!stream->GetFormat(&format, &rate, &balign))
    {
        SetError("Could not get stream format");
        return 0;
    }

    return rate;
}

/* Function: alureBufferDataFromStream
 *
 * Buffers the given buffer objects with the next chunks of data from the
 * stream. The given buffer objects do not need to be ones given by the
 * alureCreateStreamFrom* functions. Requires an active context.
 *
 * Returns:
 * The number of buffers filled with new data, or -1 on error. If the value
 * returned is less than the number requested, the end of the stream has been
 * reached.
 */
ALURE_API ALsizei ALURE_APIENTRY alureBufferDataFromStream(alureStream *stream, ALsizei numBufs, ALuint *bufs)
{
    if(alGetError() != AL_NO_ERROR)
    {
        SetError("Existing OpenAL error");
        return -1;
    }

    if(!alureStream::Verify(stream))
    {
        SetError("Invalid stream pointer");
        return -1;
    }

    if(numBufs < 0)
    {
        SetError("Invalid buffer count");
        return -1;
    }

    ALenum format;
    ALuint freq, blockAlign;

    if(!stream->GetFormat(&format, &freq, &blockAlign))
    {
        SetError("Could not get stream format");
        return -1;
    }

    ALsizei filled;
    for(filled = 0;filled < numBufs;filled++)
    {
        ALuint got = stream->GetData(stream->dataChunk, stream->chunkLen);
        got -= got%blockAlign;
        if(got == 0) break;

        alBufferData(bufs[filled], format, stream->dataChunk, got, freq);
        if(alGetError() != AL_NO_ERROR)
        {
            SetError("Buffer load failed");
            return -1;
        }
    }

    return filled;
}

/* Function: alureRewindStream
 *
 * Rewinds the stream so that the next alureBufferDataFromStream call will
 * restart from the beginning of the audio file.
 *
 * Returns:
 * AL_FALSE on error.
 *
 * See Also:
 * <alureSetStreamOrder>
 */
ALURE_API ALboolean ALURE_APIENTRY alureRewindStream(alureStream *stream)
{
    if(!alureStream::Verify(stream))
    {
        SetError("Invalid stream pointer");
        return AL_FALSE;
    }

    return stream->Rewind();
}

/* Function: alureSetStreamOrder
 *
 * Skips the module decoder to the specified order, so following buffering
 * calls will decode from the specified order. For non-module formats, setting
 * order 0 is identical to rewinding the stream (other orders will fail).
 *
 * Returns:
 * AL_FALSE on error.
 *
 * *Version Added*: 1.1
 *
 * See Also:
 * <alureRewindStream>
 */
ALURE_API ALboolean ALURE_APIENTRY alureSetStreamOrder(alureStream *stream, ALuint order)
{
    if(!alureStream::Verify(stream))
    {
        SetError("Invalid stream pointer");
        return AL_FALSE;
    }

    return stream->SetOrder(order);
}

/* Function: alureDestroyStream
 *
 * Closes an opened stream. For convenience, it will also delete the given
 * buffer objects. The given buffer objects do not need to be ones given by the
 * alureCreateStreamFrom* functions. Requires an active context.
 *
 * Returns:
 * AL_FALSE on error.
 */
ALURE_API ALboolean ALURE_APIENTRY alureDestroyStream(alureStream *stream, ALsizei numBufs, ALuint *bufs)
{
    if(alGetError() != AL_NO_ERROR)
    {
        SetError("Existing OpenAL error");
        return AL_FALSE;
    }

    if(numBufs < 0)
    {
        SetError("Invalid buffer count");
        return AL_FALSE;
    }

    if(stream && !alureStream::Verify(stream))
    {
        SetError("Invalid stream pointer");
        return AL_FALSE;
    }

    alDeleteBuffers(numBufs, bufs);
    if(alGetError() != AL_NO_ERROR)
    {
        SetError("Buffer deletion failed");
        return AL_FALSE;
    }

    if(stream)
    {
        StopStream(stream);
        std::istream *f = stream->fstream;
        delete stream;
        delete f;
    }
    return AL_TRUE;
}

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

/* Title: Streaming */

#include "config.h"

#include "main.h"

#include <string.h>

#include <memory>

static bool SizeIsUS = false;

static alureStream *InitStream(alureStream *instream, ALsizei chunkLength, ALsizei numBufs, ALuint *bufs)
{
    std::auto_ptr<std::istream> fstream(instream->fstream);
    std::auto_ptr<alureStream> stream(instream);
    ALenum format;
    ALuint freq, blockAlign;

    if(!stream->GetFormat(&format, &freq, &blockAlign))
    {
        SetError("Could not get stream format");
        return NULL;
    }

    if(format == AL_NONE)
    {
        SetError("No valid format");
        return NULL;
    }
    if(blockAlign == 0)
    {
        SetError("Invalid block size");
        return NULL;
    }
    if(freq == 0)
    {
        SetError("Invalid sample rate");
        return NULL;
    }

    alureUInt64 len64 = chunkLength;
    if(SizeIsUS)
    {
        ALuint framesPerBlock = DetectCompressionRate(format);
        if(framesPerBlock == 0)
        {
            SetError("Unknown compression rate");
            return NULL;
        }

        len64 = len64 * freq / 1000000 / framesPerBlock * blockAlign;
        if(len64 > 0xFFFFFFFF)
        {
            SetError("Chunk length too large");
            return NULL;
        }
    }

    chunkLength = len64 - (len64%blockAlign);
    if(chunkLength <= 0)
    {
        SetError("Chunk length too small");
        return NULL;
    }

    stream->chunkLen = chunkLength;
    stream->dataChunk = new ALubyte[stream->chunkLen];

    alGenBuffers(numBufs, bufs);
    if(alGetError() != AL_NO_ERROR)
    {
        SetError("Buffer creation failed");
        return NULL;
    }

    ALsizei filled;
    for(filled = 0;filled < numBufs;filled++)
    {
        ALuint got = stream->GetData(stream->dataChunk, stream->chunkLen);
        got -= got%blockAlign;
        if(got == 0) break;

        alBufferData(bufs[filled], format, stream->dataChunk, got, freq);
    }

    while(filled < numBufs)
    {
        alBufferData(bufs[filled], format, stream->dataChunk, 0, freq);
        filled++;
    }
    if(alGetError() != AL_NO_ERROR)
    {
        alDeleteBuffers(numBufs, bufs);
        alGetError();

        SetError("Buffering error");
        return NULL;
    }

    fstream.release();
    return stream.release();
}

extern "C" {

/* Function: alureStreamSizeIsMicroSec
 *
 * Specifies if the chunk size value given to the alureCreateStream functions
 * is in bytes (default) or microseconds. Specifying the size in microseconds
 * can help manage the time needed in between needed updates (since the format
 * and sample rate of the stream may not be known), while specifying the size
 * in bytes can help control memory usage.
 *
 * Returns:
 * Previously set value.
 *
 * *Version Added*: 1.1
 *
 * See Also:
 * <alureCreateStreamFromFile>, <alureCreateStreamFromMemory>,
 * <alureCreateStreamFromStaticMemory>, <alureCreateStreamFromCallback>
 */
ALURE_API ALboolean ALURE_APIENTRY alureStreamSizeIsMicroSec(ALboolean useUS)
{
    ALboolean old = (SizeIsUS ? AL_TRUE : AL_FALSE);
    SizeIsUS = !!useUS;
    return old;
}

/* Function: alureCreateStreamFromFile
 *
 * Opens a file and sets it up for streaming. The given chunkLength is the
 * number of bytes, or microseconds worth of bytes if
 * <alureStreamSizeIsMicroSec> was last called with AL_TRUE, each buffer will
 * fill with. ALURE will optionally generate the specified number of buffer
 * objects, fill them with the beginning of the data, then place the new IDs
 * into the provided storage, before returning. Requires an active context.
 *
 * Returns:
 * An opaque handle used to control the opened stream, or NULL on error.
 *
 * See Also:
 * <alureStreamSizeIsMicroSec>, <alureCreateStreamFromMemory>,
 * <alureCreateStreamFromStaticMemory>, <alureCreateStreamFromCallback>
 */
ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromFile(const ALchar *fname, ALsizei chunkLength, ALsizei numBufs, ALuint *bufs)
{
    if(alGetError() != AL_NO_ERROR)
    {
        SetError("Existing OpenAL error");
        return NULL;
    }

    if(chunkLength < 0)
    {
        SetError("Invalid chunk length");
        return NULL;
    }

    if(numBufs < 0)
    {
        SetError("Invalid buffer count");
        return NULL;
    }

    alureStream *stream = create_stream(fname);
    if(!stream->IsValid())
    {
        delete stream;
        return NULL;
    }

    return InitStream(stream, chunkLength, numBufs, bufs);
}

/* Function: alureCreateStreamFromMemory
 *
 * Opens a file image from memory and sets it up for streaming, similar to
 * <alureCreateStreamFromFile>. The given data buffer can be safely deleted
 * after calling this function. Requires an active context.
 *
 * Returns:
 * An opaque handle used to control the opened stream, or NULL on error.
 *
 * See Also:
 * <alureStreamSizeIsMicroSec>, <alureCreateStreamFromFile>,
 * <alureCreateStreamFromStaticMemory>, <alureCreateStreamFromCallback>
 */
ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromMemory(const ALubyte *fdata, ALuint length, ALsizei chunkLength, ALsizei numBufs, ALuint *bufs)
{
    if(alGetError() != AL_NO_ERROR)
    {
        SetError("Existing OpenAL error");
        return NULL;
    }

    if(chunkLength < 0)
    {
        SetError("Invalid chunk length");
        return NULL;
    }

    if(numBufs < 0)
    {
        SetError("Invalid buffer count");
        return NULL;
    }

    if(length <= 0)
    {
        SetError("Invalid data length");
        return NULL;
    }

    ALubyte *streamData = new ALubyte[length];
    memcpy(streamData, fdata, length);

    MemDataInfo memData;
    memData.Data = streamData;
    memData.Length = length;
    memData.Pos = 0;

    alureStream *stream = create_stream(memData);
    stream->data = streamData;
    if(!stream->IsValid())
    {
        delete stream;
        return NULL;
    }

    return InitStream(stream, chunkLength, numBufs, bufs);
}

/* Function: alureCreateStreamFromStaticMemory
 *
 * Identical to <alureCreateStreamFromMemory>, except the given memory is used
 * directly and not duplicated. As a consequence, the data buffer must remain
 * valid while the stream is alive. Requires an active context.
 *
 * Returns:
 * An opaque handle used to control the opened stream, or NULL on error.
 *
 * See Also:
 * <alureStreamSizeIsMicroSec>, <alureCreateStreamFromFile>,
 * <alureCreateStreamFromMemory>, <alureCreateStreamFromCallback>
 */
ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromStaticMemory(const ALubyte *fdata, ALuint length, ALsizei chunkLength, ALsizei numBufs, ALuint *bufs)
{
    if(alGetError() != AL_NO_ERROR)
    {
        SetError("Existing OpenAL error");
        return NULL;
    }

    if(chunkLength < 0)
    {
        SetError("Invalid chunk length");
        return NULL;
    }

    if(numBufs < 0)
    {
        SetError("Invalid buffer count");
        return NULL;
    }

    if(length <= 0)
    {
        SetError("Invalid data length");
        return NULL;
    }

    MemDataInfo memData;
    memData.Data = fdata;
    memData.Length = length;
    memData.Pos = 0;

    alureStream *stream = create_stream(memData);
    if(!stream->IsValid())
    {
        delete stream;
        return NULL;
    }

    return InitStream(stream, chunkLength, numBufs, bufs);
}

/* Function: alureCreateStreamFromCallback
 *
 * Creates a stream using the specified callback to retrieve data. Requires an
 * active context.
 *
 * Parameters:
 * callback - This is called when more data is needed from the stream. Up to
 *            the specified number of bytes should be written to the data
 *            pointer, and the number of bytes actually written should be
 *            returned. The number of bytes written must be block aligned for
 *            the format (eg. a multiple of 4 for AL_FORMAT_STEREO16), or an
 *            OpenAL error may occur during buffering.
 * userdata - A handle passed through to the callback.
 * format - The format of the data the callback will be giving. The format must
 *          be valid for the context.
 * samplerate - The sample rate (frequency) of the stream
 *
 * Returns:
 * An opaque handle used to control the opened stream, or NULL on error.
 *
 * See Also:
 * <alureStreamSizeIsMicroSec>, <alureCreateStreamFromFile>,
 * <alureCreateStreamFromMemory>, <alureCreateStreamFromStaticMemory>
 */
ALURE_API alureStream* ALURE_APIENTRY alureCreateStreamFromCallback(
      ALuint (*callback)(void *userdata, ALubyte *data, ALuint bytes),
      void *userdata, ALenum format, ALuint samplerate,
      ALsizei chunkLength, ALsizei numBufs, ALuint *bufs)
{
    if(alGetError() != AL_NO_ERROR)
    {
        SetError("Existing OpenAL error");
        return NULL;
    }

    if(callback == NULL)
    {
        SetError("Invalid callback");
        return NULL;
    }

    if(chunkLength < 0)
    {
        SetError("Invalid chunk length");
        return NULL;
    }

    if(numBufs < 0)
    {
        SetError("Invalid buffer count");
        return NULL;
    }

    UserCallbacks newcb;
    newcb.open_file = NULL;
    newcb.open_mem  = NULL;
    newcb.get_fmt   = NULL;
    newcb.decode    = callback;
    newcb.rewind    = NULL;
    newcb.close     = NULL;

    alureStream *stream = create_stream(userdata, format, samplerate, newcb);
    return InitStream(stream, chunkLength, numBufs, bufs);
}

/* Function: alureGetStreamFrequency
 *
 * Retrieves the frequency used for the given stream.
 *
 * Returns:
 * 0 on error.
 *
 * *Version Added*: 1.1
 */
ALURE_API ALsizei ALURE_APIENTRY alureGetStreamFrequency(alureStream *stream)
{
    ALenum format;
    ALuint rate, balign;

    if(!alureStream::Verify(stream))
    {
        SetError("Invalid stream pointer");
        return 0;
    }

    if(!stream->GetFormat(&format, &rate, &balign))
    {
        SetError("Could not get stream format");
        return 0;
    }

    return rate;
}

/* Function: alureBufferDataFromStream
 *
 * Buffers the given buffer objects with the next chunks of data from the
 * stream. The given buffer objects do not need to be ones given by the
 * alureCreateStreamFrom* functions. Requires an active context.
 *
 * Returns:
 * The number of buffers filled with new data, or -1 on error. If the value
 * returned is less than the number requested, the end of the stream has been
 * reached.
 */
ALURE_API ALsizei ALURE_APIENTRY alureBufferDataFromStream(alureStream *stream, ALsizei numBufs, ALuint *bufs)
{
    if(alGetError() != AL_NO_ERROR)
    {
        SetError("Existing OpenAL error");
        return -1;
    }

    if(!alureStream::Verify(stream))
    {
        SetError("Invalid stream pointer");
        return -1;
    }

    if(numBufs < 0)
    {
        SetError("Invalid buffer count");
        return -1;
    }

    ALenum format;
    ALuint freq, blockAlign;

    if(!stream->GetFormat(&format, &freq, &blockAlign))
    {
        SetError("Could not get stream format");
        return -1;
    }

    ALsizei filled;
    for(filled = 0;filled < numBufs;filled++)
    {
        ALuint got = stream->GetData(stream->dataChunk, stream->chunkLen);
        got -= got%blockAlign;
        if(got == 0) break;

        alBufferData(bufs[filled], format, stream->dataChunk, got, freq);
        if(alGetError() != AL_NO_ERROR)
        {
            SetError("Buffer load failed");
            return -1;
        }
    }

    return filled;
}

/* Function: alureRewindStream
 *
 * Rewinds the stream so that the next alureBufferDataFromStream call will
 * restart from the beginning of the audio file.
 *
 * Returns:
 * AL_FALSE on error.
 *
 * See Also:
 * <alureSetStreamOrder>
 */
ALURE_API ALboolean ALURE_APIENTRY alureRewindStream(alureStream *stream)
{
    if(!alureStream::Verify(stream))
    {
        SetError("Invalid stream pointer");
        return AL_FALSE;
    }

    return stream->Rewind();
}

/* Function: alureSetStreamOrder
 *
 * Skips the module decoder to the specified order, so following buffering
 * calls will decode from the specified order. For non-module formats, setting
 * order 0 is identical to rewinding the stream (other orders will fail).
 *
 * Returns:
 * AL_FALSE on error.
 *
 * *Version Added*: 1.1
 *
 * See Also:
 * <alureRewindStream>
 */
ALURE_API ALboolean ALURE_APIENTRY alureSetStreamOrder(alureStream *stream, ALuint order)
{
    if(!alureStream::Verify(stream))
    {
        SetError("Invalid stream pointer");
        return AL_FALSE;
    }

    return stream->SetOrder(order);
}

/* Function: alureDestroyStream
 *
 * Closes an opened stream. For convenience, it will also delete the given
 * buffer objects. The given buffer objects do not need to be ones given by the
 * alureCreateStreamFrom* functions. Requires an active context.
 *
 * Returns:
 * AL_FALSE on error.
 */
ALURE_API ALboolean ALURE_APIENTRY alureDestroyStream(alureStream *stream, ALsizei numBufs, ALuint *bufs)
{
    if(alGetError() != AL_NO_ERROR)
    {
        SetError("Existing OpenAL error");
        return AL_FALSE;
    }

    if(numBufs < 0)
    {
        SetError("Invalid buffer count");
        return AL_FALSE;
    }

    if(stream && !alureStream::Verify(stream))
    {
        SetError("Invalid stream pointer");
        return AL_FALSE;
    }

    alDeleteBuffers(numBufs, bufs);
    if(alGetError() != AL_NO_ERROR)
    {
        SetError("Buffer deletion failed");
        return AL_FALSE;
    }

    if(stream)
    {
        StopStream(stream);
        std::istream *f = stream->fstream;
        delete stream;
        delete f;
    }
    return AL_TRUE;
}

}
<|endoftext|>


<commit_before>#include<iostream>
#include<string.h>
#include<string>
#include<vector>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<cstring>
#include<boost/tokenizer.hpp>
#include<algorithm>
#include<iterator>
#include<sstream>

using namespace std;
using namespace boost;

void parse_line(char c_line[], char *command_line[]);
void run_line(char *command_line[]);

 int main()
{
	string str;
	string arg = "";
	 while(1)
	{
		str = "";
		char userName[100] = "";
		if(getlogin_r(userName, sizeof(userName)-1) != 0) //Getting username, and returns null if cant be found
		{
			perror("Error getting username");
		}
		cout << '['  << userName << '@';
		char hostName[100] = "";
		if(gethostname(hostName, sizeof(hostName)-1) != 0) // Getting host name, returns numm if it cannot be found
		{
			perror("Error getting hostname");
		}
		cout << hostName << ']';
		cout << "$";
		getline(cin,str);  //Gets a command
		if(str == "exit")  //If the command is exit the program stops
		{
			 break;
		}
		if(str.size() != 0 && str.at(0) == '#')
		{
			str = "";
		}
		if(str != "")
		{
			for(unsigned i = 0; i < str.size(); i++)
			{
				if(str.at(i) == ';')  //Looks for semicolons and adds a space in order to make parsing easier
				{
					str.insert(i, " ");
					i++;
				}
				if(str.at(i) == '#')  //Removes all part of the command after the comment
				{
					str = str.substr(0,i);
				}
			}
			while(str.find("  ") != string::npos)
			{
				str.erase(str.find(" "));
			}
			if(str.at(str.size() - 1 ) == ' ')
			{
				str = str.substr(0,str.size()-1);
			}
			char c_line[64];
			char *command_line[64];
			strcpy(c_line,str.c_str());
			c_line[str.size()] = '\0';

			parse_line(c_line, command_line);
			run_line(command_line);
		}

	}
	  return 0;
}

int k = 0;

void parse_line(char c_line[], char *command_line[])
{
	while(*c_line != '\0')
	{
		while(*c_line == ' ' || *c_line == '\n' || *c_line == '\t')
		{
			*c_line++ = '\0';
		}
		if(*c_line == ';')
		{
			run_line(command_line);
			//for(int i = 0; i < 64; i++)
			//{
			//	command_line[i] = new char[16];
			//}
			//command_line = new char*[64];
			//for(int i = 0; i < 64; i++)
			//{
			//	delete [] command_line[i];
			//}
			//delete [] command_line;
			c_line++;
		}
		*command_line++ = c_line;
		while(*c_line != '\0' && *c_line != ' ' && *c_line != '\n' && *c_line != '\t')
		{
			c_line++;
		}
		*command_line = '\0';
	}
	return;
}

void run_line(char *command_line[])
{
	pid_t pid;
	int status;
	if((pid = fork()) < 0)
	{
		perror("forking failed");
	}
	else if(pid == 0)
	{
		if(execvp(*command_line,command_line) < 0)
		{
			perror("execvp failed");
			exit(1);
		}
	}
	else
	{
		while(wait(&status) != pid)
		;
	}
	return;
}
<commit_msg>tried to fix rshell.cpp<commit_after>#include<iostream>
#include<string.h>
#include<string>
#include<vector>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<cstring>
#include<boost/tokenizer.hpp>
#include<algorithm>
#include<iterator>
#include<sstream>

using namespace std;
using namespace boost;

void parse_line(char c_line[], char *command_line[]);
void run_line(char *command_line[]);

 int main()
{
	string str;
	string arg = "";
	 while(1)
	{
		str = "";
		char userName[100] = "";
		if(getlogin_r(userName, sizeof(userName)-1) != 0) //Getting username, and returns null if cant be found
		{
			perror("Error getting username");
		}
		cout << '['  << userName << '@';
		char hostName[100] = "";
		if(gethostname(hostName, sizeof(hostName)-1) != 0) // Getting host name, returns numm if it cannot be found
		{
			perror("Error getting hostname");
		}
		cout << hostName << ']';
		cout << "$";
		getline(cin,str);  //Gets a command
		if(str == "exit")  //If the command is exit the program stops
		{
			 break;
		}
		if(str.size() != 0 && str.at(0) == '#')
		{
			str = "";
		}
		if(str != "")
		{
			for(unsigned i = 0; i < str.size(); i++)
			{
				if(str.at(i) == ';')  //Looks for semicolons and adds a space in order to make parsing easier
				{
					str.insert(i, " ");
					i++;
				}
				if(str.at(i) == '#')  //Removes all part of the command after the comment
				{
					str = str.substr(0,i);
				}
			}
			while(str.find(' ') != string::npos)
			{
				str.erase(str.find("  ") + 1);
			}
			if(str.at(str.size() - 1 ) == ' ')
			{
				str = str.substr(0,str.size()-1);
			}
			char c_line[100];
			char *command_line[64];
			strcpy(c_line,str.c_str());
			c_line[str.size()] = '\0';

			parse_line(c_line, command_line);
			run_line(command_line);
		}

	}
	  return 0;
}

void parse_line(char c_line[], char *command_line[])
{
	while(*c_line != '\0')
	{
		while(*c_line == ' ' || *c_line == '\n' || *c_line == '\t')
		{
			*c_line++ = '\0';
		}
		if(*c_line == ';')
		{
			run_line(command_line);
			//for(int i = 0; i < 64; i++)
			//{
			//	command_line[i] = new char[16];
			//}
			//command_line = new char*[64];
			//for(int i = 0; i < 64; i++)
			//{
			//	delete [] command_line[i];
			//}
			//delete [] command_line;
			c_line++;
		}
		*command_line++ = c_line;
		while(*c_line != '\0' && *c_line != ' ' && *c_line != '\n' && *c_line != '\t')
		{
			c_line++;
		}
		*command_line = '\0';
	}
	return;
}

void run_line(char *command_line[])
{
	pid_t pid;
	int status;
	if((pid = fork()) < 0)
	{
		perror("forking failed");
	}
	else if(pid == 0)
	{
		if(execvp(*command_line,command_line) < 0)
		{
			perror("execvp failed");
			exit(1);
		}
	}
	else
	{
		while(wait(&status) != pid)
		;
	}
	return;
}
<|endoftext|>


<commit_before>/*
 ***********************************************************************************************************************
 *
 *  Copyright (c) 2016-2021 Advanced Micro Devices, Inc. All Rights Reserved.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 *
 **********************************************************************************************************************/
/*
 ***********************************************************************************************************************
 *
 *  Copyright (c) 2021 Google LLC. All Rights Reserved.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 *
 **********************************************************************************************************************/
/**
 ***********************************************************************************************************************
 * @file  llpcCompilationUtils.cpp
 * @brief LLPC source file: contains the implementation LLPC pipeline compilation logic for standalone LLPC compilers.
 ***********************************************************************************************************************
 */
#ifdef WIN_OS
// NOTE: Disable Windows-defined min()/max() because we use STL-defined std::min()/std::max() in LLPC.
#define NOMINMAX
#endif

#include "llpcPipelineBuilder.h"
#include "llpcAutoLayout.h"
#include "llpcDebug.h"
#include "llpcInputUtils.h"
#include "vkgcUtil.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringExtras.h"

using namespace llvm;
using namespace Vkgc;

namespace Llpc {
namespace StandaloneCompiler {

// =====================================================================================================================
// Returns true iff the compiled pipeline is a graphics pipeline.
//
// @returns : True if the compiled pipeline is a graphics pipeline, false if compute.
bool PipelineBuilder::isGraphicsPipeline() const {
  return (m_compileInfo.stageMask & (shaderStageToMask(ShaderStageCompute) - 1)) != 0;
}

// =====================================================================================================================
// Builds pipeline using the provided build info and performs linking.
//
// @returns : Result::Success on success, other status on failure.
Result PipelineBuilder::build() {
  llvm::SmallVector<BinaryData, 1> pipelines;
  pipelines.push_back(BinaryData());
  pipelines[0] = {};
  const bool isGraphics = isGraphicsPipeline();
  if (isGraphics) {
    Result result = buildGraphicsPipeline(pipelines[0]);
    if (result != Result::Success)
      return result;
  } else {
    Result result = buildComputePipeline(pipelines[0]);
    if (result != Result::Success)
      return result;
  }

  for (const auto &pipeline : pipelines) {
    decodePipelineBinary(&pipeline, &m_compileInfo, isGraphics);
  }
  return Result::Success;
}

// =====================================================================================================================
// Build the graphics pipeline.
//
// @param [in/out] outBinaryData : The compiled pipeline. The caller must value-initialize this parameter.
// @returns : Result::Success on success, other status on failure.
Result PipelineBuilder::buildGraphicsPipeline(BinaryData &outBinaryData) {
  GraphicsPipelineBuildInfo *pipelineInfo = &m_compileInfo.gfxPipelineInfo;
  GraphicsPipelineBuildOut *pipelineOut = &m_compileInfo.gfxPipelineOut;

  // Fill pipeline shader info.
  PipelineShaderInfo *shaderInfos[ShaderStageGfxCount] = {
      &pipelineInfo->vs, &pipelineInfo->tcs, &pipelineInfo->tes, &pipelineInfo->gs, &pipelineInfo->fs,
  };

  ResourceMappingNodeMap nodeSets;
  unsigned pushConstSize = 0;
  for (StandaloneCompiler::ShaderModuleData &moduleData : m_compileInfo.shaderModuleDatas) {
    const ShaderStage stage = moduleData.shaderStage;
    PipelineShaderInfo *shaderInfo = shaderInfos[stage];
    const ShaderModuleBuildOut *shaderOut = &moduleData.shaderOut;

    // If entry target is not specified, use the one from command line option.
    if (!shaderInfo->pEntryTarget)
      shaderInfo->pEntryTarget = m_compileInfo.entryTarget.c_str();

    shaderInfo->pModuleData = shaderOut->pModuleData;
    shaderInfo->entryStage = stage;

    // If not compiling from pipeline, lay out user data now.
    if (m_compileInfo.doAutoLayout)
      doAutoLayoutDesc(stage, moduleData.spirvBin, pipelineInfo, shaderInfo, nodeSets, pushConstSize,
                       /*autoLayoutDesc = */ m_compileInfo.autoLayoutDesc);
  }

  if (m_compileInfo.doAutoLayout)
    buildTopLevelMapping(m_compileInfo.stageMask, nodeSets, pushConstSize, &pipelineInfo->resourceMapping,
                         m_compileInfo.autoLayoutDesc);

  pipelineInfo->pInstance = nullptr; // Placeholder, unused.
  pipelineInfo->pUserData = &m_compileInfo.pipelineBuf;
  pipelineInfo->pfnOutputAlloc = allocateBuffer;
  pipelineInfo->unlinked = m_compileInfo.unlinked;

  // NOTE: If number of patch control points is not specified, we set it to 3.
  if (pipelineInfo->iaState.patchControlPoints == 0)
    pipelineInfo->iaState.patchControlPoints = 3;

  pipelineInfo->options.robustBufferAccess = m_compileInfo.robustBufferAccess;
  pipelineInfo->options.enableRelocatableShaderElf = m_compileInfo.relocatableShaderElf;
  pipelineInfo->options.scalarBlockLayout = m_compileInfo.scalarBlockLayout;
  pipelineInfo->options.enableScratchAccessBoundsChecks = m_compileInfo.scratchAccessBoundsChecks;

  PipelineBuildInfo localPipelineInfo = {};
  localPipelineInfo.pGraphicsInfo = pipelineInfo;
  void *pipelineDumpHandle = runPreBuildActions(localPipelineInfo);
  auto onExit = make_scope_exit([&] { runPostBuildActions(pipelineDumpHandle, outBinaryData); });

  Result result = m_compiler.BuildGraphicsPipeline(pipelineInfo, pipelineOut, pipelineDumpHandle);
  if (result != Result::Success)
    return result;

  outBinaryData = pipelineOut->pipelineBin;
  return Result::Success;
}

// =====================================================================================================================
// Build the compute pipeline.
//
// @param [in/out] outBinaryData : The compiled pipeline. The caller must value-initialize this parameter.
// @returns : Result::Success on success, other status on failure.
Result PipelineBuilder::buildComputePipeline(BinaryData &outBinaryData) {
  assert(m_compileInfo.shaderModuleDatas.size() == 1);
  assert(m_compileInfo.shaderModuleDatas[0].shaderStage == ShaderStageCompute);

  ComputePipelineBuildInfo *pipelineInfo = &m_compileInfo.compPipelineInfo;
  ComputePipelineBuildOut *pipelineOut = &m_compileInfo.compPipelineOut;

  PipelineShaderInfo *shaderInfo = &pipelineInfo->cs;
  const ShaderModuleBuildOut *shaderOut = &m_compileInfo.shaderModuleDatas[0].shaderOut;

  // If entry target is not specified, use the one from command line option.
  if (!shaderInfo->pEntryTarget)
    shaderInfo->pEntryTarget = m_compileInfo.entryTarget.c_str();

  shaderInfo->entryStage = ShaderStageCompute;
  shaderInfo->pModuleData = shaderOut->pModuleData;

  // If not compiling from pipeline, lay out user data now.
  if (m_compileInfo.doAutoLayout) {
    ResourceMappingNodeMap nodeSets;
    unsigned pushConstSize = 0;
    doAutoLayoutDesc(ShaderStageCompute, m_compileInfo.shaderModuleDatas[0].spirvBin, nullptr, shaderInfo, nodeSets,
                     pushConstSize, /*autoLayoutDesc =*/m_compileInfo.autoLayoutDesc);

    buildTopLevelMapping(ShaderStageComputeBit, nodeSets, pushConstSize, &pipelineInfo->resourceMapping,
                         m_compileInfo.autoLayoutDesc);
  }

  pipelineInfo->pInstance = nullptr; // Placeholder, unused.
  pipelineInfo->pUserData = &m_compileInfo.pipelineBuf;
  pipelineInfo->pfnOutputAlloc = allocateBuffer;
  pipelineInfo->unlinked = m_compileInfo.unlinked;
  pipelineInfo->options.robustBufferAccess = m_compileInfo.robustBufferAccess;
  pipelineInfo->options.enableRelocatableShaderElf = m_compileInfo.relocatableShaderElf;
  pipelineInfo->options.scalarBlockLayout = m_compileInfo.scalarBlockLayout;
  pipelineInfo->options.enableScratchAccessBoundsChecks = m_compileInfo.scratchAccessBoundsChecks;

  PipelineBuildInfo localPipelineInfo = {};
  localPipelineInfo.pComputeInfo = pipelineInfo;
  void *pipelineDumpHandle = runPreBuildActions(localPipelineInfo);
  auto onExit = make_scope_exit([&] { runPostBuildActions(pipelineDumpHandle, outBinaryData); });

  Result result = m_compiler.BuildComputePipeline(pipelineInfo, pipelineOut, pipelineDumpHandle);
  if (result != Result::Success)
    return result;

  outBinaryData = pipelineOut->pipelineBin;
  return Result::Success;
}

// =====================================================================================================================
// Runs pre-compilation actions: starts a pipeline dump (if requested) and prints pipeline info (if requested).
// The caller must call `runPostBuildActions` after calling this function to perform the necessary cleanup.
//
// @param buildInfo : Build info of the pipeline.
// @returns : Handle to the started pipeline dump, nullptr if pipeline dump was not started.
void *PipelineBuilder::runPreBuildActions(PipelineBuildInfo buildInfo) {
  void *pipelineDumpHandle = nullptr;
  if (shouldDumpPipelines())
    pipelineDumpHandle = IPipelineDumper::BeginPipelineDump(m_dumpOptions.getPointer(), buildInfo);

  if (m_printPipelineInfo)
    printPipelineInfo(buildInfo);

  return pipelineDumpHandle;
}

// =====================================================================================================================
// Runs post-compilation actions: finalizes the pipeline dump, if started. Must be called after `runPreBuildActions`.
//
// @param pipelineDumpHandle : Handle to the started pipeline dump.
// @param pipeline : The compiled pipeline.
void PipelineBuilder::runPostBuildActions(void *pipelineDumpHandle, BinaryData pipeline) {
  if (!pipelineDumpHandle)
    return;

  if (pipeline.pCode)
    IPipelineDumper::DumpPipelineBinary(pipelineDumpHandle, m_compileInfo.gfxIp, &pipeline);

  IPipelineDumper::EndPipelineDump(pipelineDumpHandle);
}

// =====================================================================================================================
// Prints pipeline dump hash code and filenames. Can be called before pipeline compilation.
//
// @param buildInfo : Build info of the pipeline.
void PipelineBuilder::printPipelineInfo(PipelineBuildInfo buildInfo) {
  uint64_t hash = 0;
  if (isGraphicsPipeline())
    hash = IPipelineDumper::GetPipelineHash(buildInfo.pGraphicsInfo);
  else
    hash = IPipelineDumper::GetPipelineHash(buildInfo.pComputeInfo);

  LLPC_OUTS("LLPC PipelineHash: " << format("0x%016" PRIX64, hash) << " Files: " << join(m_compileInfo.fileNames, " ")
                                  << "\n");
}

} // namespace StandaloneCompiler
} // namespace Llpc
<commit_msg>Address review points<commit_after>/*
 ***********************************************************************************************************************
 *
 *  Copyright (c) 2016-2021 Advanced Micro Devices, Inc. All Rights Reserved.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 *
 **********************************************************************************************************************/
/*
 ***********************************************************************************************************************
 *
 *  Copyright (c) 2021 Google LLC. All Rights Reserved.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 *
 **********************************************************************************************************************/
/**
 ***********************************************************************************************************************
 * @file  llpcCompilationUtils.cpp
 * @brief LLPC source file: contains the implementation LLPC pipeline compilation logic for standalone LLPC compilers.
 ***********************************************************************************************************************
 */
#ifdef WIN_OS
// NOTE: Disable Windows-defined min()/max() because we use STL-defined std::min()/std::max() in LLPC.
#define NOMINMAX
#endif

#include "llpcPipelineBuilder.h"
#include "llpcAutoLayout.h"
#include "llpcDebug.h"
#include "llpcInputUtils.h"
#include "vkgcUtil.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringExtras.h"

using namespace llvm;
using namespace Vkgc;

namespace Llpc {
namespace StandaloneCompiler {

// =====================================================================================================================
// Returns true iff the compiled pipeline is a graphics pipeline.
//
// @returns : True if the compiled pipeline is a graphics pipeline, false if compute.
bool PipelineBuilder::isGraphicsPipeline() const {
  return (m_compileInfo.stageMask & (shaderStageToMask(ShaderStageCompute) - 1)) != 0;
}

// =====================================================================================================================
// Builds pipeline using the provided build info and performs linking.
//
// @returns : Result::Success on success, other status on failure.
Result PipelineBuilder::build() {
  // Use vector of BinaryData for future pipeline type
  SmallVector<BinaryData, 1> pipelines;
  pipelines.push_back({});
  const bool isGraphics = isGraphicsPipeline();
  if (isGraphics) {
    Result result = buildGraphicsPipeline(pipelines[0]);
    if (result != Result::Success)
      return result;
  } else {
    Result result = buildComputePipeline(pipelines[0]);
    if (result != Result::Success)
      return result;
  }

  for (const auto &pipeline : pipelines) {
    auto result = decodePipelineBinary(&pipeline, &m_compileInfo, isGraphics);
    if (result != Result::Success)
      return result;
  }
  return Result::Success;
}

// =====================================================================================================================
// Build the graphics pipeline.
//
// @param [in/out] outBinaryData : The compiled pipeline. The caller must value-initialize this parameter.
// @returns : Result::Success on success, other status on failure.
Result PipelineBuilder::buildGraphicsPipeline(BinaryData &outBinaryData) {
  GraphicsPipelineBuildInfo *pipelineInfo = &m_compileInfo.gfxPipelineInfo;
  GraphicsPipelineBuildOut *pipelineOut = &m_compileInfo.gfxPipelineOut;

  // Fill pipeline shader info.
  PipelineShaderInfo *shaderInfos[ShaderStageGfxCount] = {
      &pipelineInfo->vs, &pipelineInfo->tcs, &pipelineInfo->tes, &pipelineInfo->gs, &pipelineInfo->fs,
  };

  ResourceMappingNodeMap nodeSets;
  unsigned pushConstSize = 0;
  for (StandaloneCompiler::ShaderModuleData &moduleData : m_compileInfo.shaderModuleDatas) {
    const ShaderStage stage = moduleData.shaderStage;
    PipelineShaderInfo *shaderInfo = shaderInfos[stage];
    const ShaderModuleBuildOut *shaderOut = &moduleData.shaderOut;

    // If entry target is not specified, use the one from command line option.
    if (!shaderInfo->pEntryTarget)
      shaderInfo->pEntryTarget = m_compileInfo.entryTarget.c_str();

    shaderInfo->pModuleData = shaderOut->pModuleData;
    shaderInfo->entryStage = stage;

    // If not compiling from pipeline, lay out user data now.
    if (m_compileInfo.doAutoLayout)
      doAutoLayoutDesc(stage, moduleData.spirvBin, pipelineInfo, shaderInfo, nodeSets, pushConstSize,
                       /*autoLayoutDesc = */ m_compileInfo.autoLayoutDesc);
  }

  if (m_compileInfo.doAutoLayout)
    buildTopLevelMapping(m_compileInfo.stageMask, nodeSets, pushConstSize, &pipelineInfo->resourceMapping,
                         m_compileInfo.autoLayoutDesc);

  pipelineInfo->pInstance = nullptr; // Placeholder, unused.
  pipelineInfo->pUserData = &m_compileInfo.pipelineBuf;
  pipelineInfo->pfnOutputAlloc = allocateBuffer;
  pipelineInfo->unlinked = m_compileInfo.unlinked;

  // NOTE: If number of patch control points is not specified, we set it to 3.
  if (pipelineInfo->iaState.patchControlPoints == 0)
    pipelineInfo->iaState.patchControlPoints = 3;

  pipelineInfo->options.robustBufferAccess = m_compileInfo.robustBufferAccess;
  pipelineInfo->options.enableRelocatableShaderElf = m_compileInfo.relocatableShaderElf;
  pipelineInfo->options.scalarBlockLayout = m_compileInfo.scalarBlockLayout;
  pipelineInfo->options.enableScratchAccessBoundsChecks = m_compileInfo.scratchAccessBoundsChecks;

  PipelineBuildInfo localPipelineInfo = {};
  localPipelineInfo.pGraphicsInfo = pipelineInfo;
  void *pipelineDumpHandle = runPreBuildActions(localPipelineInfo);
  auto onExit = make_scope_exit([&] { runPostBuildActions(pipelineDumpHandle, outBinaryData); });

  Result result = m_compiler.BuildGraphicsPipeline(pipelineInfo, pipelineOut, pipelineDumpHandle);
  if (result != Result::Success)
    return result;

  outBinaryData = pipelineOut->pipelineBin;
  return Result::Success;
}

// =====================================================================================================================
// Build the compute pipeline.
//
// @param [in/out] outBinaryData : The compiled pipeline. The caller must value-initialize this parameter.
// @returns : Result::Success on success, other status on failure.
Result PipelineBuilder::buildComputePipeline(BinaryData &outBinaryData) {
  assert(m_compileInfo.shaderModuleDatas.size() == 1);
  assert(m_compileInfo.shaderModuleDatas[0].shaderStage == ShaderStageCompute);

  ComputePipelineBuildInfo *pipelineInfo = &m_compileInfo.compPipelineInfo;
  ComputePipelineBuildOut *pipelineOut = &m_compileInfo.compPipelineOut;

  PipelineShaderInfo *shaderInfo = &pipelineInfo->cs;
  const ShaderModuleBuildOut *shaderOut = &m_compileInfo.shaderModuleDatas[0].shaderOut;

  // If entry target is not specified, use the one from command line option.
  if (!shaderInfo->pEntryTarget)
    shaderInfo->pEntryTarget = m_compileInfo.entryTarget.c_str();

  shaderInfo->entryStage = ShaderStageCompute;
  shaderInfo->pModuleData = shaderOut->pModuleData;

  // If not compiling from pipeline, lay out user data now.
  if (m_compileInfo.doAutoLayout) {
    ResourceMappingNodeMap nodeSets;
    unsigned pushConstSize = 0;
    doAutoLayoutDesc(ShaderStageCompute, m_compileInfo.shaderModuleDatas[0].spirvBin, nullptr, shaderInfo, nodeSets,
                     pushConstSize, /*autoLayoutDesc =*/m_compileInfo.autoLayoutDesc);

    buildTopLevelMapping(ShaderStageComputeBit, nodeSets, pushConstSize, &pipelineInfo->resourceMapping,
                         m_compileInfo.autoLayoutDesc);
  }

  pipelineInfo->pInstance = nullptr; // Placeholder, unused.
  pipelineInfo->pUserData = &m_compileInfo.pipelineBuf;
  pipelineInfo->pfnOutputAlloc = allocateBuffer;
  pipelineInfo->unlinked = m_compileInfo.unlinked;
  pipelineInfo->options.robustBufferAccess = m_compileInfo.robustBufferAccess;
  pipelineInfo->options.enableRelocatableShaderElf = m_compileInfo.relocatableShaderElf;
  pipelineInfo->options.scalarBlockLayout = m_compileInfo.scalarBlockLayout;
  pipelineInfo->options.enableScratchAccessBoundsChecks = m_compileInfo.scratchAccessBoundsChecks;

  PipelineBuildInfo localPipelineInfo = {};
  localPipelineInfo.pComputeInfo = pipelineInfo;
  void *pipelineDumpHandle = runPreBuildActions(localPipelineInfo);
  auto onExit = make_scope_exit([&] { runPostBuildActions(pipelineDumpHandle, outBinaryData); });

  Result result = m_compiler.BuildComputePipeline(pipelineInfo, pipelineOut, pipelineDumpHandle);
  if (result != Result::Success)
    return result;

  outBinaryData = pipelineOut->pipelineBin;
  return Result::Success;
}

// =====================================================================================================================
// Runs pre-compilation actions: starts a pipeline dump (if requested) and prints pipeline info (if requested).
// The caller must call `runPostBuildActions` after calling this function to perform the necessary cleanup.
//
// @param buildInfo : Build info of the pipeline.
// @returns : Handle to the started pipeline dump, nullptr if pipeline dump was not started.
void *PipelineBuilder::runPreBuildActions(PipelineBuildInfo buildInfo) {
  void *pipelineDumpHandle = nullptr;
  if (shouldDumpPipelines())
    pipelineDumpHandle = IPipelineDumper::BeginPipelineDump(m_dumpOptions.getPointer(), buildInfo);

  if (m_printPipelineInfo)
    printPipelineInfo(buildInfo);

  return pipelineDumpHandle;
}

// =====================================================================================================================
// Runs post-compilation actions: finalizes the pipeline dump, if started. Must be called after `runPreBuildActions`.
//
// @param pipelineDumpHandle : Handle to the started pipeline dump.
// @param pipeline : The compiled pipeline.
void PipelineBuilder::runPostBuildActions(void *pipelineDumpHandle, BinaryData pipeline) {
  if (!pipelineDumpHandle)
    return;

  if (pipeline.pCode)
    IPipelineDumper::DumpPipelineBinary(pipelineDumpHandle, m_compileInfo.gfxIp, &pipeline);

  IPipelineDumper::EndPipelineDump(pipelineDumpHandle);
}

// =====================================================================================================================
// Prints pipeline dump hash code and filenames. Can be called before pipeline compilation.
//
// @param buildInfo : Build info of the pipeline.
void PipelineBuilder::printPipelineInfo(PipelineBuildInfo buildInfo) {
  uint64_t hash = 0;
  if (isGraphicsPipeline())
    hash = IPipelineDumper::GetPipelineHash(buildInfo.pGraphicsInfo);
  else
    hash = IPipelineDumper::GetPipelineHash(buildInfo.pComputeInfo);

  LLPC_OUTS("LLPC PipelineHash: " << format("0x%016" PRIX64, hash) << " Files: " << join(m_compileInfo.fileNames, " ")
                                  << "\n");
}

} // namespace StandaloneCompiler
} // namespace Llpc
<|endoftext|>


<commit_before>//  largest_palindrome_product.cpp : algorithm to find the largest palindrome product
//
// Copyright (C) 2017-2020 Stillwater Supercomputing, Inc.
//
// This file is part of the universal numbers project, which is released under an MIT Open Source license.
#include <iostream>
#include <universal/integer/integer.hpp>

/*
 * A palinddrome number reads the same both ways. The largest palindrome made from the product
 * of two 2-digit numbers is 9009 = 91 x 99.
 *
 * Find the largest palindrome made from the product of two n-digit numbers.
 */

template<size_t nbits>
bool Largest2DigitPalindromeProduct() {
	using namespace std;
	using namespace sw::unum;

	using Integer = integer<nbits>;
	using Real = long double;

	int nrOfSteps = 0;
	// construct palindromes starting from the largest descending to the smallest
	for (Integer i = 9; i >= 0; --i) {
		for (Integer j = 9; j >= 0; --j) {
			// construct the palindrome
			Integer palindrome = (i * 1000) + (j * 100) + (j * 10) + i;
//			cout << palindrome << endl;
			// generate guidance on the scale of the product terms
			Real squareRoot = std::sqrt((long double)palindrome);
//			cout << "sqrt guidance is " << squareRoot << endl;
			Integer a, b, c;
			a = squareRoot;
			while (a < 100) {
				b = palindrome / a;
				if ((palindrome % a) == 0 && b < 100) {
					cout << "In step " << nrOfSteps << " found largest 2-digit palindrome product: " << a << " * " << b << " = " << palindrome << " check product: " << a * b << endl;
					return true;
				}
				else {
					++a;
					++nrOfSteps;
				}
			}
		}
	}
	return false; // didn't find a solution
}

template<size_t nbits>
bool Largest3DigitPalindromeProduct() {
	using namespace std;
	using namespace sw::unum;

	using Integer = integer<nbits>;
	using Real = long double;

	int nrOfSteps = 0;
	// construct palindromes starting from the largest descending to the smallest
	for (Integer i = 9; i >= 0; --i) {
		for (Integer j = 9; j >= 0; --j) {
			for (Integer k = 9; k >= 0; --k) {
				// construct the palindrome
				Integer palindrome = (i * 100000) + (j * 10000) + (k * 1000) + (k * 100) + (j * 10) + i;
// 				cout << palindrome << endl;
				// generate guidance on the scale of the product terms
				Real squareRoot = std::sqrt((long double)palindrome);
//				cout << "sqrt guidance is " << squareRoot << endl;
				Integer a, b, c;
				a = squareRoot;
				while (a < 1000) {
					b = palindrome / a;
					if ((palindrome % a) == 0 && b < 1000) {
						cout << "In step " << nrOfSteps << " found largest 3-digit palindrome product: " << a << " * " << b << " = " << palindrome << " check product: " << a * b << endl;
						return true;
					}
					else {
						++a;
						++nrOfSteps;
					}
				}
			}
		}
	}
	return false; // didn't find a solution
}

template<size_t nbits>
bool Largest4DigitPalindromeProduct() {
	using namespace std;
	using namespace sw::unum;

	using Integer = integer<nbits>;
	using Real = long double;

	int nrOfSteps = 0;
	// construct palindromes starting from the largest descending to the smallest
	for (Integer i = 9; i >= 0; --i) {
		for (Integer j = 9; j >= 0; --j) {
			for (Integer k = 9; k >= 0; --k) {
				for (Integer m = 9; m >= 0; --m) {
					// construct the palindrome
					Integer palindrome = (i * 10000000) + (j * 1000000) + (k * 100000) + (m * 10000) + (m * 1000) + (k * 100) + (j * 10) + i;
					// cout << palindrome << endl;
					// generate guidance on the scale of the product terms
					Real squareRoot = std::sqrt((long double)palindrome);
					// cout << "sqrt guidance is " << squareRoot << endl;
					Integer a, b;
					a = squareRoot;
					while (a < 10000) {
						b = palindrome / a;
						if ((palindrome % a) == 0 && b < 10000) {
							cout << "In step " << nrOfSteps << " found largest 4-digit palindrome product: " << a << " * " << b << " = " << palindrome << " check product: " << a * b << endl;
							return true;
						}
						else {
							++a;
							++nrOfSteps;
						}
					}
				}
			}
		}
	}
	return false; // didn't find a solution
}

template<size_t nbits>
bool Largest5DigitPalindromeProduct() {
	using namespace std;
	using namespace sw::unum;

	using Integer = integer<nbits>;
	using Real = long double;

	int nrOfSteps = 0;
	// construct palindromes starting from the largest descending to the smallest
	for (Integer i = 9; i >= 0; --i) {
		for (Integer j = 9; j >= 0; --j) {
			for (Integer k = 9; k >= 0; --k) {
				for (Integer m = 9; m >= 0; --m) {
					for (Integer n = 9; n >= 0; --n) {
						// construct the palindrome
						Integer palindrome = (i * 1000000000) + (j * 100000000) + (k * 10000000) + (m * 1000000) + (n * 100000) + (n * 10000) + (m * 1000) + (k * 100) + (j * 10) + i;
						// cout << palindrome << endl;
						// generate guidance on the scale of the product terms
						Real squareRoot = std::sqrt((long double)palindrome);
						// cout << "sqrt guidance is " << squareRoot << endl;
						Integer a, b;
						a = squareRoot;
						while (a < 10000) {
							b = palindrome / a;
							if ((palindrome % a) == 0 && b < 10000) {
								cout << "In step " << nrOfSteps << " found largest 5-digit palindrome product: " << a << " * " << b << " = " << palindrome << " check product: " << a * b << endl;
								return true;
							}
							else {
								++a;
								++nrOfSteps;
							}
						}
					}
				}
			}
		}
	}
	return false; // didn't find a solution
}

int main()
try {
	using namespace std;
	using namespace sw::unum;

	constexpr size_t nbits = 32;
	using Integer = integer<nbits>;
	using Real = long double;

	Largest2DigitPalindromeProduct<nbits>();
	Largest3DigitPalindromeProduct<nbits>();
	Largest4DigitPalindromeProduct<nbits>();
	Largest5DigitPalindromeProduct<nbits>();

	return EXIT_SUCCESS;
}
catch (char const* msg) {
	std::cerr << msg << std::endl;
	return EXIT_FAILURE;
}
catch (const std::runtime_error& err) {
	std::cerr << "Uncaught runtime exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (...) {
	std::cerr << "Caught unknown exception" << std::endl;
	return EXIT_FAILURE;
}
<commit_msg>compilation fix for g++<commit_after>//  largest_palindrome_product.cpp : algorithm to find the largest palindrome product
//
// Copyright (C) 2017-2020 Stillwater Supercomputing, Inc.
//
// This file is part of the universal numbers project, which is released under an MIT Open Source license.
#include <iostream>
#include <cmath>
#include <universal/integer/integer.hpp>

/*
 * A palinddrome number reads the same both ways. The largest palindrome made from the product
 * of two 2-digit numbers is 9009 = 91 x 99.
 *
 * Find the largest palindrome made from the product of two n-digit numbers.
 */

template<size_t nbits>
bool Largest2DigitPalindromeProduct() {
	using namespace std;
	using namespace sw::unum;

	using Integer = integer<nbits>;
	using Real = long double;

	int nrOfSteps = 0;
	// construct palindromes starting from the largest descending to the smallest
	for (Integer i = 9; i >= 0; --i) {
		for (Integer j = 9; j >= 0; --j) {
			// construct the palindrome
			Integer palindrome = (i * 1000) + (j * 100) + (j * 10) + i;
//			cout << palindrome << endl;
			// generate guidance on the scale of the product terms
			Real squareRoot = std::sqrt((long double)palindrome);
//			cout << "sqrt guidance is " << squareRoot << endl;
			Integer a, b, c;
			a = squareRoot;
			while (a < 100) {
				b = palindrome / a;
				if ((palindrome % a) == 0 && b < 100) {
					cout << "In step " << nrOfSteps << " found largest 2-digit palindrome product: " << a << " * " << b << " = " << palindrome << " check product: " << a * b << endl;
					return true;
				}
				else {
					++a;
					++nrOfSteps;
				}
			}
		}
	}
	return false; // didn't find a solution
}

template<size_t nbits>
bool Largest3DigitPalindromeProduct() {
	using namespace std;
	using namespace sw::unum;

	using Integer = integer<nbits>;
	using Real = long double;

	int nrOfSteps = 0;
	// construct palindromes starting from the largest descending to the smallest
	for (Integer i = 9; i >= 0; --i) {
		for (Integer j = 9; j >= 0; --j) {
			for (Integer k = 9; k >= 0; --k) {
				// construct the palindrome
				Integer palindrome = (i * 100000) + (j * 10000) + (k * 1000) + (k * 100) + (j * 10) + i;
// 				cout << palindrome << endl;
				// generate guidance on the scale of the product terms
				Real squareRoot = std::sqrt((long double)palindrome);
//				cout << "sqrt guidance is " << squareRoot << endl;
				Integer a, b, c;
				a = squareRoot;
				while (a < 1000) {
					b = palindrome / a;
					if ((palindrome % a) == 0 && b < 1000) {
						cout << "In step " << nrOfSteps << " found largest 3-digit palindrome product: " << a << " * " << b << " = " << palindrome << " check product: " << a * b << endl;
						return true;
					}
					else {
						++a;
						++nrOfSteps;
					}
				}
			}
		}
	}
	return false; // didn't find a solution
}

template<size_t nbits>
bool Largest4DigitPalindromeProduct() {
	using namespace std;
	using namespace sw::unum;

	using Integer = integer<nbits>;
	using Real = long double;

	int nrOfSteps = 0;
	// construct palindromes starting from the largest descending to the smallest
	for (Integer i = 9; i >= 0; --i) {
		for (Integer j = 9; j >= 0; --j) {
			for (Integer k = 9; k >= 0; --k) {
				for (Integer m = 9; m >= 0; --m) {
					// construct the palindrome
					Integer palindrome = (i * 10000000) + (j * 1000000) + (k * 100000) + (m * 10000) + (m * 1000) + (k * 100) + (j * 10) + i;
					// cout << palindrome << endl;
					// generate guidance on the scale of the product terms
					Real squareRoot = std::sqrt((long double)palindrome);
					// cout << "sqrt guidance is " << squareRoot << endl;
					Integer a, b;
					a = squareRoot;
					while (a < 10000) {
						b = palindrome / a;
						if ((palindrome % a) == 0 && b < 10000) {
							cout << "In step " << nrOfSteps << " found largest 4-digit palindrome product: " << a << " * " << b << " = " << palindrome << " check product: " << a * b << endl;
							return true;
						}
						else {
							++a;
							++nrOfSteps;
						}
					}
				}
			}
		}
	}
	return false; // didn't find a solution
}

template<size_t nbits>
bool Largest5DigitPalindromeProduct() {
	using namespace std;
	using namespace sw::unum;

	using Integer = integer<nbits>;
	using Real = long double;

	int nrOfSteps = 0;
	// construct palindromes starting from the largest descending to the smallest
	for (Integer i = 9; i >= 0; --i) {
		for (Integer j = 9; j >= 0; --j) {
			for (Integer k = 9; k >= 0; --k) {
				for (Integer m = 9; m >= 0; --m) {
					for (Integer n = 9; n >= 0; --n) {
						// construct the palindrome
						Integer palindrome = (i * 1000000000) + (j * 100000000) + (k * 10000000) + (m * 1000000) + (n * 100000) + (n * 10000) + (m * 1000) + (k * 100) + (j * 10) + i;
						// cout << palindrome << endl;
						// generate guidance on the scale of the product terms
						Real squareRoot = std::sqrt((long double)palindrome);
						// cout << "sqrt guidance is " << squareRoot << endl;
						Integer a, b;
						a = squareRoot;
						while (a < 10000) {
							b = palindrome / a;
							if ((palindrome % a) == 0 && b < 10000) {
								cout << "In step " << nrOfSteps << " found largest 5-digit palindrome product: " << a << " * " << b << " = " << palindrome << " check product: " << a * b << endl;
								return true;
							}
							else {
								++a;
								++nrOfSteps;
							}
						}
					}
				}
			}
		}
	}
	return false; // didn't find a solution
}

int main()
try {
	using namespace std;
	using namespace sw::unum;

	constexpr size_t nbits = 32;
	using Integer = integer<nbits>;
	using Real = long double;

	Largest2DigitPalindromeProduct<nbits>();
	Largest3DigitPalindromeProduct<nbits>();
	Largest4DigitPalindromeProduct<nbits>();
	Largest5DigitPalindromeProduct<nbits>();

	return EXIT_SUCCESS;
}
catch (char const* msg) {
	std::cerr << msg << std::endl;
	return EXIT_FAILURE;
}
catch (const std::runtime_error& err) {
	std::cerr << "Uncaught runtime exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (...) {
	std::cerr << "Caught unknown exception" << std::endl;
	return EXIT_FAILURE;
}
<|endoftext|>


<commit_before>#include<iostream>
#include<string.h>
#include<string>
#include<vector>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/stat.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<cstring>
#include<algorithm>
#include<iterator>
#include<sstream>

using namespace std;

bool run_test(char command[]);
bool run_word_test(char command[]);
bool test_word(const char command[]);
bool test_check_brackets(const char command[], bool &brackets);
void parse_line(char c_line[], char *command_line[]);
void run_line(char *command_line[]);

 int main()
{
	string str;
	string arg = "";
	 while(1)
	{
		str = "";
		char userName[100] = "";
		if(getlogin_r(userName, sizeof(userName)-1) != 0) //Getting username, and returns null if cant be found
		{
			perror("Error getting username");
		}
		cout << '['  << userName << '@';
		char hostName[100] = "";
		if(gethostname(hostName, sizeof(hostName)-1) != 0) // Getting host name, returns numm if it cannot be found
		{
			perror("Error getting hostname");
		}
		cout << hostName << ']';
		cout << "$";
		getline(cin,str);  //Gets a command
		if(str == "exit")  //If the command is exit the program stops
		{
			 break;
		}
		if(str.size() != 0 && str.at(0) == '#')
		{
			str = "";
		}
		if(str != "")
		{
			for(unsigned i = 0; i < str.size(); i++)
			{
				if(str.at(i) == '#')  //Removes all part of the command after the comment
				{
					str = str.substr(0,i);
				}
			}
			while(str.at(0) == ' ')
			{
				str = str.substr(1,str.size()-1);
			}
			if(str.at(str.size() - 1 ) == ' ')
			{
				str = str.substr(0,str.size()- 1);
			}
			bool extra_brac = false;
			bool testBool_brac = false;
			bool testBool = false;
			char c_line[100];
			char *command_line[64];
			strcpy(c_line,str.c_str());
			c_line[str.size()] = '\0';
			testBool_brac = test_check_brackets(c_line, extra_brac);

			if(testBool_brac && extra_brac)
			{
				run_test(c_line);
			}
			else if(!testBool_brac && !extra_brac)
			{
				testBool = test_word(c_line);
				if(testBool)
				{
					run_word_test(c_line);
				}
				else
				{
					parse_line(c_line, command_line);
					run_line(command_line);
				}
			}
		}

	}
	  return 0;
}

void parse_line(char c_line[], char *command_line[])
{
	while(*c_line != '\0')
	{
		while(*c_line == ' ' || *c_line == '\n' || *c_line == '\t')
		{
			*c_line++ = '\0';
		}
		*command_line++ = c_line;
		while(*c_line != '\0' && *c_line != ' ' && *c_line != '\n' && *c_line != '\t')
		{
			c_line++;
		}
		*command_line = NULL;
	}
	return;
}

bool test_word(const char command[])
{
	int i = 0;
	if(command[i] == 't' && command[i + 1] == 'e')
	{
		if(command[i + 3] == 't')
		{
			return true;
		}
	}
	return false;
}

bool run_word_test(char command[])
{
	bool file = false;
	bool dir = false;
	bool exist = false;
	int i = 3;
	char fix_command[100];
	i++;
	for(; command[i] == ' '; ++i){} // to skip all the spaces between test and the flag
	if(command[i] == '-' && command[i + 1] == 'f')
	{
		file = true;
		i++;
		i++;
	}
	else if(command[i] == '-' && command[i + 1] == 'd')
	{
		dir = true;
		i++;
		i++;
	}
	else if(command[i] == '-' && (command[i + 1] != 'e' && command[i + 1] != ' '))
	{
		cout << "Invalid Flag\n";
		return false;
	}
	else if(command[i] == '-' && (command[i + 1] == 'e' || command[i + 1] == ' '))
	{
		exist = true;
		i++;
		i++;
	}
	else
	{
		cout << "Error missing Flag\n";
		return false;
	}
	for(; command[i] == ' '; ++i){} // skip all spaces between flag and argument

	if(command[i] != '\0')
	{
		int j = 0;
		for(; command[i] != '\0' && command[i] != ' '; ++i)
		{
			fix_command[j] = command[i];
			j++;
		}
		fix_command[j] = '\0';
	}
	if(exist)
	{
		struct stat exist;
		if(stat(fix_command, &exist) == 0)
		{
			cout << "(True)\n";
			return true;
		}
		else
		{
			cout << "(False)\n";
			return false;
		}
	}
	else if(file)
	{
		struct stat file;
		stat(fix_command, &file);
		if(S_ISREG(file.st_mode) != 0)
		{
			cout << "(True)\n";
			return true;
		}
		else
		{
			cout << "(False)\n";
			return false;
		}
	}
	else if(dir)
	{
		struct stat dir;
		stat(fix_command, &dir);
		if(S_ISDIR(dir.st_mode) != 0)
		{
			cout << "(True)\n";
			return true;
		}
		else
		{
			cout << "(False)\n";
			return false;
		}
	}
	return false;
}

bool test_check_brackets(const char command[], bool &brackets)
{
	bool endBracket = true;
	int i = 0;
	if(command[i] == '[')
	{
		i++;
		if(command[i] == ' ')
		{
			for(; command[i] != '\0'; i++)
			{
				if(command[i] == ']')
				{
					endBracket = false;
					if(command[i - 1] == ' ')
					{
						brackets = true;
						return true;
					}
					else
					{
						brackets = true;
						cout << "Need a space before ]\n";
						return false;
					}
				}
			}
			if(endBracket)
			{
				cout << "Missing ]\n";
				brackets = true;
				return false;
			}

		}
		else
		{
			brackets = true;
			cout << "Need a space after [\n";
			return false;
		}
	}
	return false;
}

bool run_test(char command[])
{
	bool file = false;
	bool dir = false;
	bool exist = false;

	int i = 1;
	for(; command[i] == ' '; i++){} // gets rid of spaces between [ and flag

	if(command[i] == '-')
	{
		i++;
		if(command[i] == 'f')
		{
			file = true;
			i++;
		}
		else if(command[i] == 'd')
		{
			dir = true;
			i++;
		}
		else if(command[i] == 'e' || command[i] == ' ')
		{
			exist = true;
			i++;
		}
		else
		{
			cout << "Error, invalid flag\n";
			return false;
		}
	}
	else if(command[i] != '-')
	{
		cout << "Error, missing flag\n";
		return false;
	}

	char fix_command[100];
	for(; command[i] == ' '; i++){} // to skip all the spaces between the flag and the argument
	if(command[i] != '\0')
	{
		int j = 0;
		for(; command[i] != '\0' && command[i] != ' '; i++)
		{
			fix_command[j] = command[i];
			j++;
		}
		fix_command[j] = '\0';

	}
	else
	{
		cout << "Invalid argument with flag\n";
		return false;
	}
	if(exist)
	{
		struct stat exist;
		if(stat(fix_command, &exist) == 0)
		{
			cout << "(True)\n";
			return true;
		}
		else
		{
			cout << "(False)\n";
			return false;
		}
	}
	else if(file)
	{
		struct stat file;
		stat(fix_command, &file);
		if(S_ISREG(file.st_mode) != 0)
		{
			cout << "(True)\n";
			return true;
		}
		else
		{
			cout << "(False)\n";
			return false;
		}
	}
	else if(dir)
	{
		struct stat dir;
		stat(fix_command, &dir);
		if(S_ISDIR(dir.st_mode) != 0)
		{
			cout << "(True)\n";
			return true;
		}
		else
		{
			cout << "(False)\n";
			return false;
		}
	}
	return false;
}
void run_line(char *command_line[])
{
	pid_t pid;
	int status;
	if((pid = fork()) < 0)
	{
		perror("forking failed");
	}
	else if(pid == 0)
	{
		if(execvp(*command_line,command_line) < 0)
		{
			perror("execvp failed");
			exit(1);
		}
	}
	else
	{
		while(wait(&status) != pid)
		;
	}
	return;
}
<commit_msg>Updated the comments for rshell.cpp<commit_after>#include<iostream>
#include<string.h>
#include<string>
#include<vector>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/stat.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<cstring>
#include<algorithm>
#include<iterator>
#include<sstream>

using namespace std;

bool run_test(char command[]);
bool run_word_test(char command[]);
bool test_word(const char command[]);
bool test_check_brackets(const char command[], bool &brackets);
void parse_line(char c_line[], char *command_line[]);
void run_line(char *command_line[]);

 int main()
{
	string str;
	string arg = "";
	 while(1)
	{
		str = "";
		char userName[100] = "";
		if(getlogin_r(userName, sizeof(userName)-1) != 0) //Getting username, and returns null if cant be found
		{
			perror("Error getting username");
		}
		cout << '['  << userName << '@';
		char hostName[100] = "";
		if(gethostname(hostName, sizeof(hostName)-1) != 0) // Getting host name, returns numm if it cannot be found
		{
			perror("Error getting hostname");
		}
		cout << hostName << ']';
		cout << "$";
		getline(cin,str);  //Gets a command
		if(str == "exit")  //If the command is exit the program stops
		{
			 break;
		}
		if(str.size() != 0 && str.at(0) == '#')
		{
			str = "";
		}
		if(str != "")
		{
			for(unsigned i = 0; i < str.size(); i++)
			{
				if(str.at(i) == '#')  //Removes all part of the command after the comment
				{
					str = str.substr(0,i);
				}
			}
			while(str.at(0) == ' ')
			{
				str = str.substr(1,str.size()-1);
			}
			if(str.at(str.size() - 1 ) == ' ')
			{
				str = str.substr(0,str.size()- 1);
			}
			bool extra_brac = false;
			bool testBool_brac = false;
			bool testBool = false;
			char c_line[100];
			char *command_line[64];
			strcpy(c_line,str.c_str());
			c_line[str.size()] = '\0';
			testBool_brac = test_check_brackets(c_line, extra_brac);

			if(testBool_brac && extra_brac) // This is to check if there were brackets and it passed with both
			{
				run_test(c_line);
			}
			else if(!testBool_brac && !extra_brac) // If there werent brackets then it checks for test
			{
				testBool = test_word(c_line);
				if(testBool)
				{
					run_word_test(c_line);
				}
				else // if there were neither test or brackets then it runs the command by execvp
				{
					parse_line(c_line, command_line);
					run_line(command_line);
				}
			}
		}

	}
	  return 0;
}

void parse_line(char c_line[], char *command_line[])
{
	while(*c_line != '\0')
	{
		while(*c_line == ' ' || *c_line == '\n' || *c_line == '\t')
		{
			*c_line++ = '\0';
		}
		*command_line++ = c_line;
		while(*c_line != '\0' && *c_line != ' ' && *c_line != '\n' && *c_line != '\t')
		{
			c_line++;
		}
		*command_line = NULL;
	}
	return;
}

bool test_word(const char command[])
{
	int i = 0;
	if(command[i] == 't' && command[i + 1] == 'e')
	{
		if(command[i + 3] == 't')
		{
			return true;
		}
	}
	return false;
}

bool run_word_test(char command[])
{
	bool file = false;
	bool dir = false;
	bool exist = false;
	int i = 3;
	char fix_command[100];
	i++;
	for(; command[i] == ' '; ++i){} // to skip all the spaces between test and the flag
	if(command[i] == '-' && command[i + 1] == 'f')
	{
		file = true;
		i++;
		i++;
	}
	else if(command[i] == '-' && command[i + 1] == 'd')
	{
		dir = true;
		i++;
		i++;
	}
	else if(command[i] == '-' && (command[i + 1] != 'e' && command[i + 1] != ' '))
	{
		cout << "Invalid Flag\n";
		return false;
	}
	else if(command[i] == '-' && (command[i + 1] == 'e' || command[i + 1] == ' '))
	{
		exist = true;
		i++;
		i++;
	}
	else
	{
		cout << "Error missing Flag\n";
		return false;
	}
	for(; command[i] == ' '; ++i){} // skip all spaces between flag and argument

	if(command[i] != '\0')
	{
		int j = 0; // This transfers the argument to a new c_str
		for(; command[i] != '\0' && command[i] != ' '; ++i)
		{
			fix_command[j] = command[i];
			j++;
		}
		fix_command[j] = '\0';
	}
	if(exist) // This works on each different flag, and returns True or False depending on the flag
	{
		struct stat exist;
		if(stat(fix_command, &exist) == 0)
		{
			cout << "(True)\n";
			return true;
		}
		else
		{
			cout << "(False)\n";
			return false;
		}
	}
	else if(file)
	{
		struct stat file;
		stat(fix_command, &file);
		if(S_ISREG(file.st_mode) != 0)
		{
			cout << "(True)\n";
			return true;
		}
		else
		{
			cout << "(False)\n";
			return false;
		}
	}
	else if(dir)
	{
		struct stat dir;
		stat(fix_command, &dir);
		if(S_ISDIR(dir.st_mode) != 0)
		{
			cout << "(True)\n";
			return true;
		}
		else
		{
			cout << "(False)\n";
			return false;
		}
	}
	return false;
}

bool test_check_brackets(const char command[], bool &brackets)
{
	bool endBracket = true;
	int i = 0;
	if(command[i] == '[')
	{
		i++;
		if(command[i] == ' ')
		{
			for(; command[i] != '\0'; i++)
			{
				if(command[i] == ']')
				{
					endBracket = false; // this bool is to remind that the first bracket was found and end
					if(command[i - 1] == ' ')
					{
						brackets = true;
						return true;
					}
					else
					{
						brackets = true;
						cout << "Need a space before ]\n";
						return false;
					}
				}
			}
			if(endBracket)
			{ // Since open bracket was found, but not the end one. It is an error
				cout << "Missing ]\n";
				brackets = true;
				return false;
			}

		}
		else
		{
			brackets = true;
			cout << "Need a space after [\n";
			return false;
		}
	}
	return false;
}

bool run_test(char command[])
{
	bool file = false;
	bool dir = false;
	bool exist = false;

	int i = 1;
	for(; command[i] == ' '; i++){} // gets rid of spaces between [ and flag

	if(command[i] == '-')
	{
		i++;
		if(command[i] == 'f')
		{
			file = true;
			i++;
		}
		else if(command[i] == 'd')
		{
			dir = true;
			i++;
		}
		else if(command[i] == 'e' || command[i] == ' ')
		{
			exist = true;
			i++;
		}
		else
		{
			cout << "Error, invalid flag\n";
			return false;
		}
	}
	else if(command[i] != '-')
	{
		cout << "Error, missing flag\n";
		return false;
	}

	char fix_command[100];
	for(; command[i] == ' '; i++){} // to skip all the spaces between the flag and the argument
	if(command[i] != '\0')
	{
		int j = 0; // Transfers the argument to new c_str
		for(; command[i] != '\0' && command[i] != ' '; i++)
		{
			fix_command[j] = command[i];
			j++;
		}
		fix_command[j] = '\0';

	}
	else
	{
		cout << "Invalid argument with flag\n";
		return false;
	}
	if(exist)
	{
		struct stat exist;
		if(stat(fix_command, &exist) == 0)
		{
			cout << "(True)\n";
			return true;
		}
		else
		{
			cout << "(False)\n";
			return false;
		}
	}
	else if(file)
	{
		struct stat file;
		stat(fix_command, &file);
		if(S_ISREG(file.st_mode) != 0)
		{
			cout << "(True)\n";
			return true;
		}
		else
		{
			cout << "(False)\n";
			return false;
		}
	}
	else if(dir)
	{
		struct stat dir;
		stat(fix_command, &dir);
		if(S_ISDIR(dir.st_mode) != 0)
		{
			cout << "(True)\n";
			return true;
		}
		else
		{
			cout << "(False)\n";
			return false;
		}
	}
	return false;
}
void run_line(char *command_line[])
{
	pid_t pid;
	int status;
	if((pid = fork()) < 0) //forks process
	{
		perror("forking failed"); //error if forking failed
	}
	else if(pid == 0)
	{
		if(execvp(*command_line,command_line) < 0)  //executes command
		{
			perror("execvp failed"); //error if execution failes
			exit(1);
		}
	}
	else
	{
		while(wait(&status) != pid) //waits to return to parent process
		;
	}
	return;
}
<|endoftext|>


<commit_before>// Time:  O(1), per operation.
// Space: O(k), k is the capacity of cache.

class LFUCache {
public:
    LFUCache(int capacity) : capa_(capacity), size_(0) {
    }

    int get(int key) {
        if (!key_to_val_freq_.count(key)) {
            return -1;
        }

        freq_to_keys_[key_to_val_freq_[key].second].erase(key_to_it_[key]);
        if (freq_to_keys_[key_to_val_freq_[key].second].empty()) {
            freq_to_keys_.erase(key_to_val_freq_[key].second);
            if (min_freq_ == key_to_val_freq_[key].second) {
                ++min_freq_;
            }
        }

        ++key_to_val_freq_[key].second;
        freq_to_keys_[key_to_val_freq_[key].second].emplace_back(key);
        key_to_it_[key] = prev(freq_to_keys_[key_to_val_freq_[key].second].end());

        return key_to_val_freq_[key].first;
    }

   void put(int key, int value) {
        if (capa_ <= 0) {
            return;
        }

        if (get(key) != -1) {
            key_to_val_freq_[key].first = value;
            return;
        }

        if (size_ == capa_) {
            key_to_val_freq_.erase(freq_to_keys_[min_freq_].front());
            key_to_it_.erase(freq_to_keys_[min_freq_].front());
            freq_to_keys_[min_freq_].pop_front();
            if (freq_to_keys_[min_freq_].empty()) {
                freq_to_keys_.erase(min_freq_);
            }
            --size_;
        }

        min_freq_ = 1;
        key_to_val_freq_[key] = {value, min_freq_};
        freq_to_keys_[min_freq_].emplace_back(key);
        key_to_it_[key] = prev(freq_to_keys_[min_freq_].end());
        ++size_;
    }

private:
    int capa_;
    int size_;
    int min_freq_;
    unordered_map<int, list<int>> freq_to_keys_;         // freq to list of keys
    unordered_map<int, list<int>::iterator> key_to_it_;  // key to list iterator
    unordered_map<int, pair<int, int>> key_to_val_freq_; // key to {value, freq}
};

/**
 * Your LFUCache object will be instantiated and called as such:
 * LFUCache obj = new LFUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */
<commit_msg>Update lfu-cache.cpp<commit_after>// Time:  O(1), per operation.
// Space: O(k), k is the capacity of cache.

class LFUCache {
public:
    LFUCache(int capacity) : capa_(capacity), size_(0) {
    }

    int get(int key) {
        if (!key_to_nodeit_.count(key)) {
            return -1;
        }

        auto new_node = *key_to_nodeit_[key];
        auto& freq = std::get<2>(new_node);
        freq_to_nodes_[freq].erase(key_to_nodeit_[key]);
        if (freq_to_nodes_[freq].empty()) {
            freq_to_nodes_.erase(freq);
            if (min_freq_ == freq) {
                ++min_freq_;
            }
        }
        ++freq;
        freq_to_nodes_[freq].emplace_back(new_node);
        key_to_nodeit_[key] = prev(freq_to_nodes_[freq].end());

        return std::get<1>(*key_to_nodeit_[key]);
    }

   void put(int key, int value) {
        if (capa_ <= 0) {
            return;
        }

        if (get(key) != -1) {
            std::get<1>(*key_to_nodeit_[key]) = value;
            return;
        }

        if (size_ == capa_) {
            key_to_nodeit_.erase(std::get<0>(freq_to_nodes_[min_freq_].front()));
            freq_to_nodes_[min_freq_].pop_front();
            if (freq_to_nodes_[min_freq_].empty()) {
                freq_to_nodes_.erase(min_freq_);
            }
            --size_;
        }

        min_freq_ = 1;
        freq_to_nodes_[min_freq_].emplace_back(make_tuple(key, value, min_freq_));
        key_to_nodeit_[key] = prev(freq_to_nodes_[min_freq_].end());
        ++size_;
    }

private:
    int capa_;
    int size_;
    int min_freq_;
    unordered_map<int, list<tuple<int, int, int>>> freq_to_nodes_;            // freq to list of {key, val, freq}
    unordered_map<int, list<tuple<int, int, int>>::iterator> key_to_nodeit_;  // key to list iterator
};

/**
 * Your LFUCache object will be instantiated and called as such:
 * LFUCache obj = new LFUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */
<|endoftext|>


<commit_before>#include "MpptUnit.h"

MpptUnit::MpptUnit()
    : mpptStatus_(0)
    , arrayVoltage_(0)
    , arrayCurrent_(0)
    , batteryVoltage_(0)
    , temperature_(0)
{
    //  Initialize to 0
}

MpptUnit::~MpptUnit()
{
}

/* MpptUnit Gets */
unsigned char MpptUnit::getMpptStatus() const
{
    return mpptStatus_;
}

unsigned short MpptUnit::getArrayVoltage() const
{
    return arrayVoltage_;
}

unsigned short MpptUnit::getArrayCurrent() const
{
    return arrayCurrent_;
}

unsigned short MpptUnit::getBatteryVoltage() const
{
    return batteryVoltage_;
}

unsigned short MpptUnit::getTemperature() const
{
    return temperature_;
}

/* MpptUnit Sets */
void MpptUnit::setMpptStatus(const unsigned char& mpptStatus)
{
    mpptStatus_ = mpptStatus;
    emit mpptStatusReceived(mpptStatus_);
}

void MpptUnit::setArrayVoltage(const unsigned short& arrayVoltage)
{
    arrayVoltage_ = (arrayVoltage * 100);
    emit arrayVoltageReceived(arrayVoltage_);
}

void MpptUnit::setArrayCurrent(const unsigned short& arrayCurrent)
{
    arrayCurrent_ = arrayCurrent;
    emit arrayCurrentReceived(arrayCurrent_);
}

void MpptUnit::setBatteryVoltage(const unsigned short& batteryVoltage)
{
    batteryVoltage_ = batteryVoltage;
    emit batteryVoltageReceived(batteryVoltage_);
}

void MpptUnit::setTemperature(const unsigned short& temperature)
{
    temperature_ = temperature;
    emit temperatureReceived(temperature_);
}

<commit_msg>added MPPT conversions<commit_after>#include "MpptUnit.h"

MpptUnit::MpptUnit()
    : mpptStatus_(0)
    , arrayVoltage_(0)
    , arrayCurrent_(0)
    , batteryVoltage_(0)
    , temperature_(0)
{
    //  Initialize to 0
}

MpptUnit::~MpptUnit()
{
}

/* MpptUnit Gets */
unsigned char MpptUnit::getMpptStatus() const
{
    return mpptStatus_;
}

unsigned short MpptUnit::getArrayVoltage() const
{
    return arrayVoltage_;
}

unsigned short MpptUnit::getArrayCurrent() const
{
    return arrayCurrent_;
}

unsigned short MpptUnit::getBatteryVoltage() const
{
    return batteryVoltage_;
}

unsigned short MpptUnit::getTemperature() const
{
    return temperature_;
}

/* MpptUnit Sets */
void MpptUnit::setMpptStatus(const unsigned char& mpptStatus)
{
    mpptStatus_ = mpptStatus;
    emit mpptStatusReceived(mpptStatus_);
}

void MpptUnit::setArrayVoltage(const unsigned short& arrayVoltage)
{
    arrayVoltage_ = (arrayVoltage * 100);
    emit arrayVoltageReceived(arrayVoltage_);
}

void MpptUnit::setArrayCurrent(const unsigned short& arrayCurrent)
{
    arrayCurrent_ = (arrayCurrent * 1000);
    emit arrayCurrentReceived(arrayCurrent_);
}

void MpptUnit::setBatteryVoltage(const unsigned short& batteryVoltage)
{
    batteryVoltage_ = (batteryVoltage * 100);
    emit batteryVoltageReceived(batteryVoltage_);
}

void MpptUnit::setTemperature(const unsigned short& temperature)
{
    temperature_ = (temperature * 100);
    emit temperatureReceived(temperature_);
}

<|endoftext|>