Windows Bitmap encoder only writing bottom few thousand pixels - c++

The ReadBmpFromFile/Stream functions work fine. (Still a little slow but they otherwise work). The WriteBmpToFile/Stream functions work in that they successfully create a valid .bmp file but only the bottom few thousands of pixels, the rest of the file is black.
It shouldn't be that hard to see why, the pixel data is stored from bottom to top so the problem should be near the top of the file.
Reference: BMP File structure
Original:
Copy:
I stepped through with a debugger and the data is successfully being copied from the containing object. It shouldn't fail when I am reading from a file and then immediately writing it back:
if(_keyboard->KeyDown(KEY_S)) {
BitmapFileType bmp_test;
ReadBmpFromFile("maglot.bmp_test", bmp_test);
//Change filename to not destroy original!
WriteBmpToFile("maglot_copy.bmp_test", bmp_test);
//Allegro's implementation to test correct output against.
//save_bmp("maglot_copy.bmp", image->GetImage(), nullptr);
}
Bitmap class definition:
class BitmapFileType {
public:
struct Header {
std::vector<unsigned char> file_signature;
unsigned int file_size;
unsigned short unused1;
unsigned short unused2;
unsigned int pixel_array_offset;
unsigned int DIB_header_size;
unsigned int width;
unsigned int height;
unsigned short plane_count;
unsigned short bpp;
unsigned int compression_method;
unsigned int raw_size;
unsigned int print_resolution_horizontal;
unsigned int print_resolution_vertical;
unsigned int pallete_colors_count;
unsigned int important_colors_count;
Header() :
file_signature(2),
file_size(0),
unused1(0),
unused2(0),
pixel_array_offset(0),
DIB_header_size(0),
width(0),
height(0),
plane_count(0),
bpp(0),
compression_method(0),
raw_size(0),
print_resolution_horizontal(0),
print_resolution_vertical(0),
pallete_colors_count(0),
important_colors_count(0)
{ /* DO NOTHING */ }
Header(const Header& other) :
file_signature(other.file_signature),
file_size(other.file_size),
unused1(other.unused1),
unused2(other.unused2),
pixel_array_offset(other.pixel_array_offset),
DIB_header_size(other.DIB_header_size),
width(other.width),
height(other.height),
plane_count(other.plane_count),
bpp(other.bpp),
compression_method(other.compression_method),
raw_size(other.raw_size),
print_resolution_horizontal(other.print_resolution_horizontal),
print_resolution_vertical(other.print_resolution_vertical),
pallete_colors_count(other.pallete_colors_count),
important_colors_count(other.important_colors_count)
{ /* DO NOTHING */ }
Header& operator=(const Header& rhs) {
if(this == &rhs) return *this;
this->file_signature = rhs.file_signature;
this->file_size = rhs.file_size;
this->unused1 = rhs.unused1;
this->unused2 = rhs.unused2;
this->pixel_array_offset = rhs.pixel_array_offset;
this->DIB_header_size = rhs.DIB_header_size;
this->width = rhs.width;
this->height = rhs.height;
this->plane_count = rhs.plane_count;
this->bpp = rhs.bpp;
this->compression_method = rhs.compression_method;
this->raw_size = rhs.raw_size;
this->print_resolution_horizontal = rhs.print_resolution_horizontal;
this->print_resolution_vertical = rhs.print_resolution_vertical;
this->pallete_colors_count = rhs.pallete_colors_count;
this->important_colors_count = rhs.important_colors_count;
return *this;
}
};
struct PixelData {
std::vector<unsigned char> _pixel_data;
PixelData() : _pixel_data() { /* DO NOTHING */ }
PixelData(const PixelData& other) : _pixel_data(other._pixel_data) { /* DO NOTHING */ }
PixelData(const std::vector<unsigned char>& pixel_data) : _pixel_data(pixel_data) { /* DO NOTHING */ }
};
BitmapFileType() : _header(), _data() { /* DO NOTHING */ }
BitmapFileType(const BitmapFileType::Header& header) : _header(header), _data() { /* DO NOTHING */ }
BitmapFileType(const BitmapFileType::Header& header, const PixelData& data) : _header(header), _data(data) { /* DO NOTHING */ }
BitmapFileType& operator=(const BitmapFileType& rhs) {
if(this == &rhs) return *this;
_header = rhs._header;
_data = rhs._data;
return *this;
}
const Header& GetHeader() const {
return _header;
}
Header& GetHeader() {
return const_cast<Header&>(static_cast<const BitmapFileType&>(*this).GetHeader());
}
const PixelData& GetPixelData() const {
return _data;
}
PixelData& GetPixelData() {
return const_cast<PixelData&>(static_cast<const BitmapFileType&>(*this).GetPixelData());
}
protected:
private:
Header _header;
PixelData _data;
};
Function definitions:
#include "FileTypeUtility.h"
#include <fstream>
void WriteBmpToFile(const std::string& filename, const BitmapFileType& bmp) {
std::ofstream ofs;
ofs.open(filename);
WriteBmpToStream(ofs, bmp);
ofs.close();
}
void ReadBmpFromFile(const std::string& filename, BitmapFileType& bmp) {
std::ifstream ifs;
ifs.open(filename);
ReadBmpFromStream(ifs, bmp);
ifs.close();
}
void ReadBmpFromStream(std::istream& input_stream, BitmapFileType& bmp) {
if(input_stream.fail() || input_stream.bad() || input_stream.eof()) return;
std::vector<unsigned char> file_signature(2);
input_stream.read(reinterpret_cast<char*>(file_signature.data()), file_signature.size());
if((file_signature[0] != 'B' || file_signature[1] != 'M')) {
input_stream.seekg(-2, std::ios_base::cur);
input_stream.setstate(std::ios_base::failbit);
return;
}
unsigned int file_size = 0;
input_stream.read(reinterpret_cast<char*>(&file_size), sizeof(file_size));
unsigned short unused1 = 0;
input_stream.read(reinterpret_cast<char*>(&unused1), sizeof(unused1));
unsigned short unused2 = 0;
input_stream.read(reinterpret_cast<char*>(&unused2), sizeof(unused2));
unsigned int pixel_array_offset = 0;
input_stream.read(reinterpret_cast<char*>(&pixel_array_offset), sizeof(pixel_array_offset));
unsigned int DIB_header_size = 0;
input_stream.read(reinterpret_cast<char*>(&DIB_header_size), sizeof(DIB_header_size));
unsigned int width = 0;
input_stream.read(reinterpret_cast<char*>(&width), sizeof(width));
unsigned int height = 0;
input_stream.read(reinterpret_cast<char*>(&height), sizeof(height));
unsigned short plane_count = 0;
input_stream.read(reinterpret_cast<char*>(&plane_count), sizeof(plane_count));
unsigned short bpp = 0;
input_stream.read(reinterpret_cast<char*>(&bpp), sizeof(bpp));
unsigned int compression_method = 0;
input_stream.read(reinterpret_cast<char*>(&compression_method), sizeof(compression_method));
unsigned int raw_size = 0;
input_stream.read(reinterpret_cast<char*>(&raw_size), sizeof(raw_size));
unsigned int print_resolution_horizontal = 0;
input_stream.read(reinterpret_cast<char*>(&print_resolution_horizontal), sizeof(print_resolution_horizontal));
unsigned int print_resolution_vertical = 0;
input_stream.read(reinterpret_cast<char*>(&print_resolution_vertical), sizeof(print_resolution_vertical));
unsigned int pallete_colors_count = 0;
input_stream.read(reinterpret_cast<char*>(&pallete_colors_count), sizeof(pallete_colors_count));
unsigned int important_colors_count = 0;
input_stream.read(reinterpret_cast<char*>(&important_colors_count), sizeof(important_colors_count));
std::vector<unsigned char> pixel_array(raw_size);
input_stream.read(reinterpret_cast<char*>(pixel_array.data()), pixel_array.size());
BitmapFileType::PixelData bmpPixels(pixel_array);
BitmapFileType::Header bmpHeader;
bmpHeader.file_signature = file_signature;
bmpHeader.file_size = file_size;
bmpHeader.unused1 = unused1;
bmpHeader.unused2 = unused2;
bmpHeader.pixel_array_offset = pixel_array_offset;
bmpHeader.DIB_header_size = DIB_header_size;
bmpHeader.width = width;
bmpHeader.height = height;
bmpHeader.plane_count = plane_count;
bmpHeader.bpp = bpp;
bmpHeader.compression_method = compression_method;
bmpHeader.raw_size = raw_size;
bmpHeader.print_resolution_horizontal = print_resolution_horizontal;
bmpHeader.print_resolution_vertical = print_resolution_vertical;
bmpHeader.pallete_colors_count = pallete_colors_count;
bmpHeader.important_colors_count = important_colors_count;
bmp = BitmapFileType(bmpHeader, bmpPixels);
return;
}
void WriteBmpToStream(std::ostream& output_stream, const BitmapFileType& bmp) {
if(output_stream.fail() || output_stream.bad() || output_stream.eof()) return;
const BitmapFileType::Header& bmpHeader(bmp.GetHeader());
output_stream.write(reinterpret_cast<const char*>(bmpHeader.file_signature.data()), bmpHeader.file_signature.size());
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.file_size), sizeof(bmpHeader.file_size));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.unused1), sizeof(bmpHeader.unused1));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.unused2), sizeof(bmpHeader.unused2));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.pixel_array_offset), sizeof(bmpHeader.pixel_array_offset));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.DIB_header_size), sizeof(bmpHeader.DIB_header_size));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.width), sizeof(bmpHeader.width));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.height), sizeof(bmpHeader.height));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.plane_count), sizeof(bmpHeader.plane_count));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.bpp), sizeof(bmpHeader.bpp));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.compression_method), sizeof(bmpHeader.compression_method));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.raw_size), sizeof(bmpHeader.raw_size));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.print_resolution_horizontal), sizeof(bmpHeader.print_resolution_horizontal));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.print_resolution_vertical), sizeof(bmpHeader.print_resolution_vertical));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.pallete_colors_count), sizeof(bmpHeader.pallete_colors_count));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.important_colors_count), sizeof(bmpHeader.important_colors_count));
const BitmapFileType::PixelData& bmpPixelData(bmp.GetPixelData());
output_stream.write(reinterpret_cast<const char*>(bmpPixelData._pixel_data.data()), bmpPixelData._pixel_data.size());
return;
}

Related

DX12) Part of the Constants buffer is cut off

This is my Constant buffer for Object Drawing.
actually, gWorld and gOldWorld have correct values, but gCubemapOn, gMotionBlurOn, gRimLightOn values are going wrong.
gCubemapOn must be TRUE and it looks like, but actually that value is 65537.
and gRimLightOn must be TRUE, but as you see, actual value is FALSE.
The code below is how I use Constant Buffer.
template<typename Cnst>
class ConstantBuffer
{
public:
ConstantBuffer(ID3D12Device* device, UINT count, bool isConstant=true)
{
if (isConstant)
mByteSize = (sizeof(Cnst) + 255) & ~255;
else
mByteSize = sizeof(Cnst);
ThrowIfFailed(device->CreateCommittedResource(
&Extension::HeapProperties(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&Extension::BufferResourceDesc(D3D12_RESOURCE_DIMENSION_BUFFER, mByteSize * count),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr, IID_PPV_ARGS(&mUploadBuffer)));
ThrowIfFailed(mUploadBuffer->Map(0, nullptr, (void**)(&mData)));
}
ConstantBuffer(const ConstantBuffer& rhs) = delete;
ConstantBuffer& operator=(const ConstantBuffer& rhs) = delete;
virtual ~ConstantBuffer()
{
if (mUploadBuffer)
mUploadBuffer->Unmap(0, nullptr);
mData = nullptr;
}
D3D12_GPU_VIRTUAL_ADDRESS GetGPUVirtualAddress(int idx) const
{
return mUploadBuffer->GetGPUVirtualAddress() + idx * mByteSize;
}
void CopyData(int index, const Cnst& data)
{
memcpy(&mData[index * mByteSize], &data, sizeof(Cnst));
}
UINT GetByteSize() const
{
return mByteSize;
}
private:
ComPtr<ID3D12Resource> mUploadBuffer = nullptr;
BYTE* mData = nullptr;
UINT mByteSize = 0;
};
and this is how I Update Constant Buffer
void Pipeline::UpdateConstants()
{
UINT matOffset = 0;
for (int i = 0; i < mRenderObjects.size(); i++)
{
mObjectCB->CopyData(i, mRenderObjects[i]->GetObjectConstants());
mRenderObjects[i]->UpdateMatConstants(mMaterialCB.get(), matOffset);
matOffset += mRenderObjects[i]->GetMeshCount();
}
}
ObjectConstants GameObject::GetObjectConstants()
{
ObjectConstants objCnst = {};
if (mReflected)
{
objCnst.World = Matrix4x4::Transpose(Matrix4x4::Multiply(mWorld, mReflectMatrix));
objCnst.oldWorld = Matrix4x4::Transpose(Matrix4x4::Multiply(mOldWorld, mReflectMatrix));
}
else
{
objCnst.World = Matrix4x4::Transpose(mWorld);
objCnst.oldWorld = Matrix4x4::Transpose(mOldWorld);
}
objCnst.cubemapOn = mCubemapOn;
objCnst.motionBlurOn = mMotionBlurOn;
objCnst.rimLightOn = mRimLightOn;
return objCnst;
}
struct ObjectConstants
{
XMFLOAT4X4 World;
XMFLOAT4X4 oldWorld;
bool cubemapOn;
bool motionBlurOn;
bool rimLightOn;
};
I believe this is the same problem as seen here. HLSL bool is 4 bytes and C++ bool is 1 byte. If you declare your CPU struct as
struct ObjectConstants
{
XMFLOAT4X4 World;
XMFLOAT4X4 oldWorld;
int32_t cubemapOn;
int32_t motionBlurOn;
int32_t rimLightOn;
};
it should work.

Boost ASIO - How to perpend header in front of TCP Message

Here is my code minimized for the purpose of readability.
I was following this guide: https://www.boost.org/doc/libs/1_63_0/doc/html/boost_asio/example/cpp11/chat/chat_server.cpp
Packet.h:
#ifndef VIBRANIUM_CORE_PACKET_H
#define VIBRANIUM_CORE_PACKET_H
#include <cstdio>
#include <cstdlib>
#include <cstring>
class Packet {
public:
Packet() : body_length_(0)
{
}
enum { max_body_length = 1024 };
enum { header_length = 8 };
char header_[header_length];
const char* data() const;
char* data();
size_t length() const;
const char* body() const;
char* body();
size_t body_length() const;
void body_length(std::size_t new_length);
bool decode_header();
void encode_header();
private:
char data_[header_length + max_body_length];
size_t body_length_;
};
#endif //VIBRANIUM_CORE_PACKET_H
Packet.cpp:
#include "Packet.h"
const char *Packet::data() const {
return data_;
}
char *Packet::data() {
return data_;
}
size_t Packet::length() const {
return header_length + body_length_;
}
const char *Packet::body() const {
return data_ + header_length;
}
char *Packet::body() {
return data_ + header_length;
}
size_t Packet::body_length() const {
return body_length_;
}
void Packet::body_length(std::size_t new_length) {
body_length_ = new_length;
if (body_length_ > max_body_length)
body_length_ = max_body_length;
}
bool Packet::decode_header() {
char header[header_length + 1] = "";
std::strncat(header, data_, header_length);
body_length_ = std::atoi(header);
if (body_length_ > max_body_length)
{
body_length_ = 0;
return false;
}
return true;
}
void Packet::encode_header() {
char header[header_length + 1] = "";
std::sprintf(header, "%4d", static_cast<int>(body_length_));
std::memcpy(data_, header, header_length);
}
ServerOpcode.h:
#ifndef VIBRANIUM_CORE_SERVEROPCODE_H
#define VIBRANIUM_CORE_SERVEROPCODE_H
#include <cstdint>
enum ServerOpcode : uint16_t{
SMSG_AUTH_CONNECTION_RESPONSE = 0x001,
SMSG_LOGIN_REQUEST_RESPONSE = 0x002,
};
#endif //VIBRANIUM_CORE_SERVEROPCODE_H
So I would like to modify encode_header() to set a ServerOpcode as a packet header. I was trying this but it's not working:
void Packet::encode_header(ServerOpcode serverOpcode) {
char header[header_length + 1] = "";
std::strcat(header, static_cast<char>(serverOpcode));
std::memcpy(data_, header, header_length);
}
I have two questions:
How can I make encode header prepend the ServerOpcode? Where is my mistake how can I fix it?
How can I decode an incoming message header than with decode_header()?

c++ can not get value from map

I have implemented a serializer to send data over network. And I have implemented a system that can deserialize primitive data, string, map(string, string), map(string, float), but the error happens with map(string, int) when the deserialized map is used to fetch the value from key. In the debugger I can see that map receive correct value but when I'm trying to get data, I get an error "std::out_of_range at memory location".
Here is my code
#include <stdint.h>
#include <memory>
#include <string>
#include <map>
#include <algorithm>
#define STREAM_ENDIANNESS 0
#define PLATFORM_ENDIANNESS 0
using namespace std;
class OutputMemoryStream
{
void ReallocBuffer(uint32_t inNewLength)
{
mBuffer = static_cast<char*>(std::realloc(mBuffer, inNewLength));
mCapacity = inNewLength;
}
char* mBuffer = nullptr;
uint32_t mHead;
uint32_t mCapacity;
public:
OutputMemoryStream() : mHead(0) { ReallocBuffer(32); }
~OutputMemoryStream()
{
if (mBuffer) { mBuffer = nullptr; }
}
char* GetBufferPtr() const { return mBuffer; }
uint32_t GetLength() const { return mHead; }
void Write(const void* inData, size_t inByteCount)
{
//make sure we have space...
uint32_t resultHead = mHead + static_cast<uint32_t>(inByteCount);
if (resultHead > mCapacity)
{
ReallocBuffer(std::max(mCapacity * 2, resultHead));
}
//copy into buffer at head
std::memcpy(mBuffer + mHead, inData, inByteCount);
//increment head for next write
mHead = resultHead;
}
template< typename T > void Write(T inData)
{
static_assert(std::is_arithmetic< T >::value || std::is_enum< T >::value, "Generic Write only supports primitive data types");
if (STREAM_ENDIANNESS == PLATFORM_ENDIANNESS)
{
Write(&inData, sizeof(inData));
}
else { }
}
template< typename T >
void Write(const std::map< string, T >& inMap)
{
uint32_t elementCount = inMap.size();
Write(elementCount);
for (std::pair<string, T> element : inMap)
{
Write(element.first);
Write(element.second);
}
}
void Write(const std::string& inString)
{
size_t elementCount = inString.size();
Write(elementCount + 1);
Write(inString.data(), (elementCount + 1) * sizeof(char));
}
};
class InputMemoryStream
{
private:
char* mBuffer;
uint32_t mHead;
uint32_t mCapacity;
public:
InputMemoryStream() {}
InputMemoryStream(char* inBuffer, uint32_t inByteCount) : mBuffer(inBuffer), mCapacity(inByteCount), mHead(0) { }
~InputMemoryStream()
{
if (mBuffer) { mBuffer = nullptr; }
}
uint32_t GetRemainingDataSize() const
{
return mCapacity - mHead;
}
void Read(void* outData, uint32_t inByteCount)
{
uint32_t resultHead = mHead + inByteCount;
if (resultHead > mCapacity)
{
//handle error, no data to read!
//...
}
std::memcpy(outData, mBuffer + mHead, inByteCount);
mHead = resultHead;
}
template< typename T > void Read(T& outData)
{
static_assert(std::is_arithmetic< T >::value || std::is_enum< T >::value, "Generic Read only supports primitive data types");
Read(&outData, sizeof(outData));
}
template<typename T1>
void Read(std::map<string, T1> &mapP)
{
size_t elemenCount;
Read(elemenCount);
for (int i = 0; i < elemenCount; i++)
{
string key; T1 value;
Read(key);
Read(value);
std::pair<string, T1> pair(key, value);
mapP.insert(pair);
}
}
void Read(string &outString)
{
size_t strSize;
Read(strSize);
outString.resize(strSize);
for (int i = 0; i < strSize; i++)
{
Read(&outString[i], 1);
}
}
};
class ServerObject
{
OutputMemoryStream outStream;
InputMemoryStream inStream;
map<std::string, int> mapInt;
public:
ServerObject() {};
ServerObject(char* byteArray, int byteCount)
{
InputMemoryStream inStream(byteArray, byteCount);
Deserialize(inStream);
}
~ServerObject() {};
void Serialize()
{
outStream.Write(mapInt);
}
void Deserialize(InputMemoryStream inStream)
{
inStream.Read(mapInt);
}
OutputMemoryStream GetOutStream()
{
return outStream;
}
int GetInt(string key)
{
return mapInt.at(key);
}
void PutInt(string key, int value)
{
mapInt.insert(std::pair<string, int>(key, value));
}
};
int main()
{
ServerObject * so = new ServerObject();
so->PutInt("test", 10);
so->Serialize();
ServerObject * so1 = new ServerObject(so->GetOutStream().GetBufferPtr(), so->GetOutStream().GetLength());
int i = so1->GetInt("test");
system("pause>NULL");
return 0;
}
Your void Write(const std::string& inString) function of OutputMemoryStream should not store additional byte of buffer for null terminator because std::string will not contain null terminator but if you use c_str(), a null terminator will be included in the return from this method. Don't get confused with the internal structure of the memory. std::string stores the length of the string in its member variable so there is no need of null terminator. The function should be as shown below.
void Write(const std::string& inString)
{
size_t elementCount = inString.size();
Write(elementCount);
Write(inString.data(), elementCount * sizeof(char));
}

exc_bad_access code 1 error

After a bit of bug searching, I've found that my code leaves with exit code 11 at a certain point, and this is because an EXC_BAD_ACCESS error with code 1. After some googling, I see this must be due to some memory mismanagement, but I'm new to C++ and nothing seems obvious to me.
The code is exiting at the line
fieldFuncts[field](string, equal, validOps, length, difficulty, rng, opGen);
in the file (last function)
//
// Created by Anthony Monterrosa on 4/17/18.
//
#include "MathExpr.h"
#include <list>
#include <iostream>
#include <random>
std::vector<std::function<void(std::vector<MathExpr::CharType> &, MathExpr::NumType &, std::vector<MathExpr::NumType> &)>> MathExpr::layerFuncts;
std::vector<std::function<void(std::vector<MathExpr::CharType> &, MathExpr::NumType &, std::vector<MathExpr::Op> &, unsigned char, unsigned char, std::mt19937 &, std::uniform_int_distribution<MathExpr::OpType> &)>> MathExpr::fieldFuncts;
void MathExpr::init() {
initLayerFuncts();
initFieldFuncts();
}
void MathExpr::initLayerFuncts() {
layerFuncts.resize(Op::EOOE);
layerFuncts[static_cast<unsigned long>(Op::addition)] = [](std::vector<MathExpr::CharType> &string, NumType &equal, std::vector<NumType> & otherArgs) -> void {
string.insert(string.end(), {' ', opToChar(Op::addition), ' '});
equal += otherArgs[0];
std::vector<MathExpr::CharType> digits = intToDigit(otherArgs[0]);
for(int i = 0; i < digits.size(); i++ ) {
string.push_back(digits[i]);
}
};
layerFuncts[static_cast<unsigned long>(Op::subtraction)] = [](std::vector<MathExpr::CharType> &string, MathExpr::NumType &equal, std::vector<NumType> & otherArgs) -> void {
string.insert(string.end(), {' ', opToChar(Op::subtraction), ' '});
equal -= otherArgs[0];
std::vector<MathExpr::CharType> digits = intToDigit(otherArgs[0]);
for(int i = 0; i < digits.size(); i++ ) {
string.push_back(digits[i]);
}
};
}
void MathExpr::initFieldFuncts() {
fieldFuncts.resize(Field::EOFE);
fieldFuncts[static_cast<unsigned long>(Field::integers)] = [](std::vector<MathExpr::CharType> &string, NumType &equal, std::vector<MathExpr::Op> &validOps, unsigned char length, unsigned char difficulty, std::mt19937 &rng, std::uniform_int_distribution<MathExpr::OpType> &opGen) -> void {
std::uniform_int_distribution<MathExpr::NumType> numGen(1, static_cast<MathExpr::NumType>(pow(10, difficulty)));
equal = numGen(rng);
std::vector<MathExpr::CharType> digits = intToDigit(equal);
for(int i = 0; i < digits.size(); i++ ) {
string.push_back(digits[i]);
}
for (int i = 0; i < length - 1; i++) {
MathExpr::Op op = validOps[opGen(rng)];
int count = otherArgsCount(op);
std::vector<MathExpr::NumType> otherArgs(count);
for(int j = 0; j < count; j++) {
otherArgs[j] = (numGen(rng));
}
layer(string, equal, op, otherArgs);
}
};
}
char MathExpr::opToChar(OpType ordinal) {
return opToChar(static_cast<Op>(ordinal));
}
char MathExpr::opToChar(Op op) {
switch(op) {
case Op::addition : return '+';
case Op::subtraction : return '-';
default : return '_';
}
}
MathExpr::NumType MathExpr::otherArgsCount(MathExpr::Op op) {
switch(op) {
case Op::addition : return 1;
case Op::subtraction : return 1;
default : return 0;
}
}
std::vector<MathExpr::CharType> MathExpr::intToDigit(MathExpr::NumType num) {
std::vector<MathExpr::CharType> digits;
while(num >= 10) {
digits.insert(digits.begin(),'0' + static_cast<MathExpr::CharType>(num % 10));
num /= 10;
} digits.insert(digits.begin(), '0' + static_cast<MathExpr::CharType>(num));
return digits;
}
bool MathExpr::initBool = false;
MathExpr::MathExpr(std::vector<CharType> exp, MathExpr::NumType equal) {
if(!initBool) init();
this->string = std::vector<CharType>(exp);
this->equal = equal;
}
void MathExpr::print(MathExpr &exp) {
for(int i = 0; i < exp.string.size(); i++) {
std::cout << exp.string[i];
}
}
void MathExpr::layer(std::vector<MathExpr::CharType> &string, MathExpr::NumType &equal, MathExpr::Op op, std::vector<MathExpr::NumType> &otherArgs) {
layerFuncts[op](string, equal, otherArgs);
}
MathExpr MathExpr::generate(std::vector<MathExpr::Op> &validOps, MathExpr::Field field, unsigned char length, unsigned char difficulty) {
std::vector<MathExpr::CharType> string;
std::random_device rd;
std::mt19937 rng(rd());
std::uniform_int_distribution<MathExpr::OpType> opGen(0, static_cast<MathExpr::OpType>(validOps.size() - 1));
MathExpr::NumType equal;
fieldFuncts[field](string, equal, validOps, length, difficulty, rng, opGen);
return MathExpr::MathExpr(string, equal);
}
here is the corresponding .h file
//
// Created by Anthony Monterrosa on 4/17/18.
//
// EO_E -> "end of _ enum".
#ifndef MATHTESTGENERATOR_MATHEXPR_H
#define MATHTESTGENERATOR_MATHEXPR_H
#include <functional>
#include <random>
#include <vector>
class MathExpr {
public:
using FieldType = unsigned char;
using OpType = unsigned char;
using NumType = short int;
using CharType = char;
enum Field : FieldType {
integers,
EOFE // rational, real, complex.
};
enum Op : OpType {
addition,
subtraction,
EOOE // multiplication, division, absolute value, radical
};
explicit MathExpr(std::vector<CharType>, NumType);
std::vector<CharType> string;
NumType equal;
static void print(MathExpr &);
static MathExpr generate(std::vector<Op> &, Field = Field::integers, unsigned char length = 2, unsigned char difficulty = 1);
//protected:
static void init();
static bool initBool;
static void layer(std::vector<MathExpr::CharType> &, NumType &, Op, std::vector<NumType> &);
static NumType otherArgsCount(Op);
static std::vector<CharType> intToDigit(NumType);
static char opToChar(OpType);
static char opToChar(Op);
static std::vector<std::function<void(std::vector<MathExpr::CharType> &, NumType &, std::vector<NumType> &)>> layerFuncts;
static void initLayerFuncts();
static std::vector<std::function<void(std::vector<MathExpr::CharType> &, NumType &, std::vector<MathExpr::Op> &, unsigned char, unsigned char, std::mt19937 &, std::uniform_int_distribution<MathExpr::OpType> &)>> fieldFuncts;
static void initFieldFuncts();
};
#endif //MATHTESTGENERATOR_MATHEXPR_H
My gut says the error has to do with the "string" vector, but I'm unsure of how to tell. I would appreciate insight into the problem.

Pure virtual function error

I receive this error:
In function 'bool detect_feedback(AudioEffect*)':
54:30: error: cannot convert 'std::shared_ptr<AudioEffect>' to 'AudioEffect*' in assignment
55:16: error: cannot convert 'std::shared_ptr<AudioEffect>' to 'AudioEffect*' in assignment
55:40: error: cannot convert 'std::shared_ptr<AudioEffect>' to 'AudioEffect*' in assignment
The code is as follows:
#include<stdlib.h>
#include<iostream>
#include<memory>`
//BASE CLASS
// audio and have a subsequent effect (next).
struct AudioEffect
{
virtual ~AudioEffect() = default;
virtual void process(float* buf, size_t num) = 0;
std::shared_ptr<AudioEffect> next;
};
//DERIVING MULTIPLE AUDIO-EFFECTS
//Noise Gate
struct NoiseGate: public AudioEffect
{
float threshold;
void process(float *buf, size_t num)
{
if (*buf > threshold)
*buf = threshold;
}
};
//Gain Boost
struct GainBoost: public AudioEffect
{
float signal;
void process(float *buf, size_t num)
{
*buf = *buf + signal;
}
};
//Compressor
struct Compressor: public AudioEffect
{
float offset;
void process(float *buf, size_t num)
{
*buf = *buf - offset;
}
};
//Function
// Implement a function that checks if there is a feedback loop
// in the effects chain.
//... detect_feedback(...)
//{
//}
bool detect_feedback (AudioEffect *ae)
{
AudioEffect *p, *q;
for (p = ae;p != NULL; p = p->next)
for (q = p->next; q != NULL; q = q->next)
if (typeid(*p) == typeid(*q))
return true;
return false;
}
//MAIN
int main(int argc, char *argv[])
{
return 0;
}
You can not assign a shared_ptr to a raw pointer. You need to use the .get() method to obtain a raw pointer.
(p->next).get()