My own application malfunctioning C++ - c++

I can not get my c++ application to work properly, i will paste my simple memory class and a test app here.
Right now i get an access violation and no output when i run it in the console. I use Visual Studio 2015.
I seem to haave problems with my car class, not sure what could be wrong. And i ge some error message if i try to debug. I have no idea how to fix it...
#define WIN32_LEAN_AND_MEAN
enum memtype {typechar = 1, typeint};
class Mem
{
public:
Mem(int size);
void * alloc(memtype t);
void * ptr();
void release();
~Mem();
private:
int sizebytes;
void * p;
};
#include <new.h>
#include "Mem.h"
Mem::Mem(int size)
{
sizebytes = size;
}
void * Mem::alloc(memtype t)
{
if (t==typechar)
{
p = (char *)new char(sizebytes);
return p;
}
}
void * Mem::ptr()
{
return p;
}
void Mem::release()
{
if(p)
delete p;
}
Mem::~Mem()
{
if(p)
delete p;
}
#include "Mem.h"
#include <stdio.h>
int check(void * p)
{
int retval = 0;
if (p == NULL)
{
printf("Memory Fail: NULL pointer...\n");
retval = 0;
}
else
retval = 1;
return retval;
}
class Car
{
public:
Car::Car()
{
Car::name = 0;
Car::brand = 0;
Car::type = 0;
}
int Car::alloc(char *inname, char *inbrand, char *intype)
{
Car::name = new Mem(sizeof(*inname));
if (!check(Car::name->alloc(typechar)))
return 0;
printf("%s", sizeof(*inname));
Car::brand = new Mem(sizeof(*inbrand));
if (!check(Car::brand->alloc(typechar)))
return 0;
printf("%s", sizeof(*inbrand));
Car::type = new Mem(sizeof(*intype));
if (!check(Car::type->alloc(typechar)))
return 0;
printf("%s", sizeof(*intype));
/*sprintf?*/
sprintf_s((char *)Car::name->ptr(), sizeof(*inname), "%s", inname);
sprintf_s((char *)Car::brand->ptr(), sizeof(*inbrand), "%s", inbrand);
sprintf_s((char *)Car::type->ptr(), sizeof(*intype), "%s", intype);
return 1;
}
char * Car::getName()
{
if(Car::name!=0)
return (char *)Car::name->ptr();
}
char * Car::getBrand()
{
if(Car::brand!=0)
return (char *)Car::brand->ptr();
}
char * Car::getType()
{
if(Car::type!=0)
return (char *)Car::type->ptr();
}
Car::~Car()
{
if (Car::name != 0)
delete Car::name;
if (Car::brand != 0)
delete Car::brand;
if (Car::type != 0)
delete Car::type;
}
private:
Mem *name, *brand, *type;
};
void store()
{
}
int main()
{
Mem cartype1(sizeof("Sedan"));
cartype1.alloc(typechar);
check(cartype1.ptr());
Mem cartype2(sizeof("Van"));
cartype2.alloc(typechar);
check(cartype2.ptr());
Mem cartype3(sizeof("Pickup"));
cartype3.alloc(typechar);
check(cartype3.ptr());
sprintf((char *)cartype1.ptr(), "%s", "Sedan");
sprintf((char *)cartype2.ptr(), "%s", "Van");
sprintf((char *)cartype3.ptr(), "%s", "Pickup");
Mem carname(sizeof("Supah Car"));
carname.alloc(typechar);
check(carname.ptr());
Mem carbrand(sizeof("Supah"));
carbrand.alloc(typechar);
check(carbrand.ptr());
sprintf((char *)carname.ptr(), "%s", "Supah Car");
sprintf((char *)carbrand.ptr(), "%s", "Supah");
Car test;
test.alloc((char *)carname.ptr(), (char *)carbrand.ptr(), (char *)cartype1.ptr());
printf("%s is of brand %s and type %s\n", test.getName(), test.getBrand(), test.getType());
char * nullptrtest = NULL;
printf_s("%d", &test);
printf_s("sizeof int %d\n", sizeof(int));
printf_s("Test %s\n", carname.ptr());
return 1;
}

int Car::alloc(char *inname, char *inbrand, char *intype)
{
Car::name = new Mem(sizeof(*inname));
sizeof *inname will give you sizeof(char) == 1
So your name member has allocated array of 1 char exactly.
You later write to this array a lot more. As a result your heap is corrupted.
I do not know why you want to play with emulating memory allocation instead of using std::string - but you need to allocate at least strlen(inname)+1 bytes to store inname

Related

Firebird database UDF for encrypt/decrypt not freeing memory

I'm testing a UDF external function in Firebird 3 database, I made a C++ DLL which performs a simple XOR to a given string using a given key.
This is the code:
#include <windows.h>
#include <iostream>
#include <string>
#include <stdio.h>
#include <vector>
#include <math.h>
#include "../FirebirdLib/src/include/ibase.h"
#include "ib_util.h"
using namespace std;
//------------------------------------------------------------------------------------
typedef void (__stdcall * FCallback)(const char * message);
FCallback g_messageCallback = 0;
FCallback g_errorCallback = 0;
//------------------------------------------------------------------------------------
#define ON_MESSAGE(mess) { if(g_messageCallback) g_messageCallback(mess); }
#define ON_ERROR(mess) { if(g_errorCallback) g_errorCallback(mess); }
//------------------------------------------------------------------------------------
extern "C" __declspec(dllexport) void RegisterCallbacks(FCallback messageCallback, FCallback errorCallback)
{
g_messageCallback = messageCallback;
g_errorCallback = errorCallback;
}
//------------------------------------------------------------------------------------
class EncryptionUDF
{
public:
EncryptionUDF()
{
//ON_MESSAGE("--EncryptionUDF created--")
}
~EncryptionUDF()
{
//ON_MESSAGE("--EncryptionUDF destroyed--")
}
char* XORCipher(const char* data, const char* key, int dataLen, int keyLen) {
char* output = (char*)ib_util_malloc(2000 + 1L);
output[dataLen] = '\0';
for (int i = 0; i < dataLen; ++i) {
if (data[i] != key[i % keyLen])
output[i] = data[i] ^ key[i % keyLen];
else
output[i] = data[i];
}
return output;
}
char * Encrypt(const char * str, const char * key) {
int dataLen = strlen(str);
int keyLen = strlen(key);
char* output = (char*)ib_util_malloc(2000 + 1L);
output[dataLen] = '\0';
try {
if ((str == NULL) || (str[0] == '\0')) {
return NULL;
}
else {
try {
if ((key != NULL) && (key[0] == '\0')) {
strncpy(output, str, dataLen);
}
else if (key != NULL) {
output = XORCipher(str, key, dataLen, keyLen);
}
else strncpy(output, str, dataLen);
}
catch (...) { strncpy(output, str, dataLen); }
return output;
}
}
catch (...) { strncpy(output, str, dataLen); }
return output;
}
char * Decrypt(const char * str, const char * key) {
int dataLen = strlen(str);
int keyLen = strlen(key);
char* output = (char*)ib_util_malloc(2000 + 1L);
output[dataLen] = '\0';
try {
if ((str == NULL) || (str[0] == '\0')) {
return NULL;
}
else {
try {
if ((key != NULL) && (key[0] == '\0')) {
strncpy(output, str, dataLen);
}
else if (key != NULL) {
output = XORCipher(str, key, dataLen, keyLen);
}
else strncpy(output, str, dataLen);
}
catch (...) { strncpy(output, str, dataLen); }
return output;
}
}
catch (...) { strncpy(output, str, dataLen); }
return output;
}
};
//------------------------------------------------------------------------------------
extern "C" __declspec(dllexport) char * EncryptUDF_DesEncrypt(const char *str, const char *key)
{
try
{
EncryptionUDF self = EncryptionUDF();
return self.Encrypt(str, key);
}
catch (std::exception & ex)
{
ON_ERROR(ex.what());
}
catch (...)
{
ON_ERROR("Unknown error");
}
return 0;
}
//------------------------------------------------------------------------------------
extern "C" __declspec(dllexport) char * EncryptUDF_DesDecrypt(const char *str, const char *key)
{
try
{
EncryptionUDF self = EncryptionUDF();
return self.Decrypt(str, key);
}
catch (std::exception & ex)
{
ON_ERROR(ex.what());
}
catch (...)
{
ON_ERROR("Unknown error");
}
return 0;
}
//------------------------------------------------------------------------------------
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
//------------------------------------------------------------------------------------
The UDF is defined in database as:
DECLARE EXTERNAL FUNCTION X_DECRYPT
CSTRING(2000),
CSTRING(64)
RETURNS CSTRING(2000) FREE_IT
ENTRY_POINT 'EncryptUDF_DesDecrypt' MODULE_NAME 'EncryptUDF';
DECLARE EXTERNAL FUNCTION X_ENCRYPT
CSTRING(2000),
CSTRING(64)
RETURNS CSTRING(2000) FREE_IT
ENTRY_POINT 'EncryptUDF_DesEncrypt' MODULE_NAME 'EncryptUDF';
When using this UDF in SQL select commands, the ram used by firebird server tends to increase continously. When using embedded the RAM goes up quickly, when in server mode, the RAM is increasing but slowly and somehow more controlled.
Please help to understand where the error is.
After some investigation, I decided to change the parts on code where the string is copied using:
strncpy(output, str, dataLen);
with:
strncpy_s(output, dataLen, str, dataLen);
and after this change, the memory has been in normal levels, either in embedded firebird or in server mode.
It seems that was a memory leak in releasing or managing those string copies.

Segmentation fault on loading structure from file in C

I was playing with C/'s fopen() and putc() functions and wanted to implement serialization/deserialization of a structure. However, here some "Segmentation fault" error occurs. I investigated similar questions and found, that it happens when I am trying to access some memory that doesn't belong to me.
What should I fix in my code to make it work properly?
struct Account {
string holder_name;
string holder_password;
double current_sum;
};
int save_to_file(Account * account);
Account * load_from_file(string holder_name);
int main(){
Account account = { "BEN", "password", 200.0 };
save_to_file(&account);
load_from_file("BEN");
return 0;
}
int save_to_file(Account * account){
const char * cstr = account->holder_name.c_str();
int size = sizeof(struct Account);
FILE * fp = fopen(cstr, "wb");
char * c;
c = (char *) account;
for(int i=0; i < size; i++)
{
putc(*c++, fp);
}
return fclose(fp);
}
Account * load_from_file(string holder_name)
{
FILE * fp;
char *c;
int i;
int size = sizeof(struct Account);
struct Account * ptr = (struct Account *) malloc(sizeof(struct Account));
if ((fp = fopen(holder_name.c_str(), "rb")) == NULL)
{
perror("Error occured while opening file");
return NULL;
}
c = (char *)ptr;
while ((i = getc(fp))!=EOF)
{
*c = i;
c++;
}
fclose(fp);
return ptr;
}
The string type doesn't belongs to C language, it's a object that comes from C++.
Since it may be implemented with pointers inside the object, you can't simply write their binary values to a file : the pointed memory won't be allocated when you'll read the file later.
A simple rule is that writing a pointer value to a file is a probably a mistake.
For your code to work, simply replace the string type with a char []. Here is the code with this only modification :
#include <stdlib.h>
#include <stdio.h>
struct Account {
char holder_name[100];
char holder_password[100];
double current_sum;
};
int save_to_file(struct Account * account);
struct Account * load_from_file(char *holder_name);
int main(){
struct Account account = { "BEN", "password", 200.0 };
save_to_file(&account);
load_from_file("BEN");
return 0;
}
int save_to_file(struct Account * account){
const char * cstr = account->holder_name;
int size = sizeof(struct Account);
FILE * fp = fopen(cstr, "wb");
char * c;
c = (char *) account;
for(int i=0; i < size; i++)
{
putc(*c++, fp);
}
return fclose(fp);
}
struct Account * load_from_file(char *holder_name)
{
FILE * fp;
char *c;
int i;
int size = sizeof(struct Account);
struct Account * ptr = (struct Account *) malloc(sizeof(struct Account));
if ((fp = fopen(holder_name, "rb")) == NULL)
{
perror("Error occured while opening file");
return NULL;
}
c = (char *)ptr;
while ((i = getc(fp))!=EOF)
{
*c = i;
c++;
}
fclose(fp);
return ptr;
}

How to asynchronously read/write in C++?

How do you copy one stream to another using dedicated read/write threads in C++?
Let's say I have these methods (not real, but to illustrate the point) to read/write data from. These read/write functions could represent anything (network/file/USB/serial/etc).
// returns the number of bytes read
void read(char* buffer, int bufferSize, int* bytesRead);
// returns the number of bytes written
void write(char* buffer, int bufferSize, int* bytesWritten);
The solution should also be portable.
NOTE: I am aware that Windows has a FILE_FLAG_OVERLAPPED feature, but this assumes that the read/write is file IO. Remember, these read/write methods could represent anything.
Here is the solution I came up with.
Header
#pragma once
#include <stdlib.h>
#include <queue>
#include <mutex>
#include <thread>
#include <chrono>
#include <list>
#include <thread>
#define ASYNC_COPY_READ_WRITE_SUCCESS 0
struct BufferBlock;
struct ReadStream
{
// read a stream to a buffer.
// return non-zero if error occured
virtual int read(char* buffer, int bufferSize, int* bytesRead) = 0;
};
struct WriteStream
{
// write a buffer to a stream.
// return non-zero if error occured
virtual int write(char* buffer, int bufferSize, int* bytesWritten) = 0;
};
class BufferBlockManager
{
public:
BufferBlockManager(int numberOfBlocks, int bufferSize);
~BufferBlockManager();
void enqueueBlockForRead(BufferBlock* block);
void dequeueBlockForRead(BufferBlock** block);
void enqueueBlockForWrite(BufferBlock* block);
void dequeueBlockForWrite(BufferBlock** block);
void resetState();
private:
std::list<BufferBlock*> blocks;
std::queue<BufferBlock*> blocksPendingRead;
std::queue<BufferBlock*> blocksPendingWrite;
std::mutex queueLock;
std::chrono::milliseconds dequeueSleepTime;
};
void AsyncCopyStream(BufferBlockManager* bufferBlockManager, ReadStream* readStream, WriteStream* writeStream, int* readResult, int* writeResult);
CPP
#include "AsyncReadWrite.h"
struct BufferBlock
{
BufferBlock(int bufferSize) : buffer(NULL)
{
this->bufferSize = bufferSize;
this->buffer = new char[bufferSize];
this->actualSize = 0;
this->isLastBlock = false;
}
~BufferBlock()
{
this->bufferSize = 0;
free(this->buffer);
this->buffer = NULL;
this->actualSize = 0;
}
char* buffer;
int bufferSize;
int actualSize;
bool isLastBlock;
};
BufferBlockManager::BufferBlockManager(int numberOfBlocks, int bufferSize)
{
dequeueSleepTime = std::chrono::milliseconds(100);
for (int x = 0; x < numberOfBlocks; x++)
{
BufferBlock* block = new BufferBlock(bufferSize);
blocks.push_front(block);
blocksPendingRead.push(block);
}
}
BufferBlockManager::~BufferBlockManager()
{
for (std::list<BufferBlock*>::const_iterator iterator = blocks.begin(), end = blocks.end(); iterator != end; ++iterator) {
delete (*iterator);
}
}
void BufferBlockManager::enqueueBlockForRead(BufferBlock* block)
{
queueLock.lock();
block->actualSize = 0;
block->isLastBlock = false;
blocksPendingRead.push(block);
queueLock.unlock();
}
void BufferBlockManager::dequeueBlockForRead(BufferBlock** block)
{
WAITFOR:
while (blocksPendingRead.size() == 0)
std::this_thread::sleep_for(dequeueSleepTime);
queueLock.lock();
if (blocksPendingRead.size() == 0)
{
queueLock.unlock();
goto WAITFOR;
}
*block = blocksPendingRead.front();
blocksPendingRead.pop();
queueLock.unlock();
}
void BufferBlockManager::enqueueBlockForWrite(BufferBlock* block)
{
queueLock.lock();
blocksPendingWrite.push(block);
queueLock.unlock();
}
void BufferBlockManager::dequeueBlockForWrite(BufferBlock** block)
{
WAITFOR:
while (blocksPendingWrite.size() == 0)
std::this_thread::sleep_for(dequeueSleepTime);
queueLock.lock();
if (blocksPendingWrite.size() == 0)
{
queueLock.unlock();
goto WAITFOR;
}
*block = blocksPendingWrite.front();
blocksPendingWrite.pop();
queueLock.unlock();
}
void BufferBlockManager::resetState()
{
queueLock.lock();
blocksPendingRead = std::queue<BufferBlock*>();
blocksPendingWrite = std::queue<BufferBlock*>();
for (std::list<BufferBlock*>::const_iterator iterator = blocks.begin(), end = blocks.end(); iterator != end; ++iterator) {
(*iterator)->actualSize = 0;
}
queueLock.unlock();
}
struct AsyncCopyContext
{
AsyncCopyContext(BufferBlockManager* bufferBlockManager, ReadStream* readStream, WriteStream* writeStream)
{
this->bufferBlockManager = bufferBlockManager;
this->readStream = readStream;
this->writeStream = writeStream;
this->readResult = ASYNC_COPY_READ_WRITE_SUCCESS;
this->writeResult = ASYNC_COPY_READ_WRITE_SUCCESS;
}
BufferBlockManager* bufferBlockManager;
ReadStream* readStream;
WriteStream* writeStream;
int readResult;
int writeResult;
};
void ReadStreamThread(AsyncCopyContext* asyncContext)
{
int bytesRead = 0;
BufferBlock* readBuffer = NULL;
int readResult = ASYNC_COPY_READ_WRITE_SUCCESS;
while (
// as long there hasn't been any write errors
asyncContext->writeResult == ASYNC_COPY_READ_WRITE_SUCCESS
// and we haven't had an error reading yet
&& readResult == ASYNC_COPY_READ_WRITE_SUCCESS)
{
// let's deque a block to read to!
asyncContext->bufferBlockManager->dequeueBlockForRead(&readBuffer);
readResult = asyncContext->readStream->read(readBuffer->buffer, readBuffer->bufferSize, &bytesRead);
readBuffer->actualSize = bytesRead;
readBuffer->isLastBlock = bytesRead == 0;
if (readResult == ASYNC_COPY_READ_WRITE_SUCCESS)
{
// this was a valid read, go ahead and queue it for writing
asyncContext->bufferBlockManager->enqueueBlockForWrite(readBuffer);
}
else
{
// an error occured reading
asyncContext->readResult = readResult;
// since an error occured, lets queue an block to write indicatiting we are done and there are no more bytes to read
readBuffer->isLastBlock = true;
readBuffer->actualSize = 0;
asyncContext->bufferBlockManager->enqueueBlockForWrite(readBuffer);
}
if (readBuffer->isLastBlock) return;
}
}
void WriteStreamThread(AsyncCopyContext* asyncContext)
{
int bytesWritten = 0;
BufferBlock* writeBuffer = NULL;
int writeResult = ASYNC_COPY_READ_WRITE_SUCCESS;
bool isLastWriteBlock = false;
while (
// as long as there are no errors during reading
asyncContext->readResult == ASYNC_COPY_READ_WRITE_SUCCESS
// and we haven't had an error writing yet
&& writeResult == ASYNC_COPY_READ_WRITE_SUCCESS)
{
// lets dequeue a block for writing!
asyncContext->bufferBlockManager->dequeueBlockForWrite(&writeBuffer);
isLastWriteBlock = writeBuffer->isLastBlock;
if (writeBuffer->actualSize > 0)
writeResult = asyncContext->writeStream->write(writeBuffer->buffer, writeBuffer->actualSize, &bytesWritten);
if (writeResult == ASYNC_COPY_READ_WRITE_SUCCESS)
{
asyncContext->bufferBlockManager->enqueueBlockForRead(writeBuffer);
if (isLastWriteBlock) return;
}
else
{
asyncContext->writeResult = writeResult;
asyncContext->bufferBlockManager->enqueueBlockForRead(writeBuffer);
return;
}
}
}
void AsyncCopyStream(BufferBlockManager* bufferBlockManager, ReadStream* readStream, WriteStream* writeStream, int* readResult, int* writeResult)
{
AsyncCopyContext asyncContext(bufferBlockManager, readStream, writeStream);
std::thread readThread(ReadStreamThread, &asyncContext);
std::thread writeThread(WriteStreamThread, &asyncContext);
readThread.join();
writeThread.join();
*readResult = asyncContext.readResult;
*writeResult = asyncContext.writeResult;
}
Usage
#include <stdio.h>
#include <tchar.h>
#include "AsyncReadWrite.h"
struct ReadTestStream : ReadStream
{
int readCount = 0;
int read(char* buffer, int bufferSize, int* bytesRead)
{
printf("Starting read...\n");
memset(buffer, bufferSize, 0);
if (readCount == 10)
{
*bytesRead = 0;
return 0;
}
// pretend this function takes a while!
std::this_thread::sleep_for(std::chrono::milliseconds(100));
char buff[100];
sprintf_s(buff, "This is read number %d\n", readCount);
strcpy_s(buffer, sizeof(buff), buff);
*bytesRead = strlen(buffer);
readCount++;
printf("Finished read...\n");
return 0;
}
};
struct WriteTestStream : WriteStream
{
int write(char* buffer, int bufferSize, int* bytesWritten)
{
printf("Starting write...\n");
// pretend this function takes a while!
std::this_thread::sleep_for(std::chrono::milliseconds(500));
printf(buffer);
printf("Finished write...\n");
return 0;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
BufferBlockManager bufferBlockManager(5, 4096);
ReadTestStream readStream;
WriteTestStream writeStream;
int readResult = 0;
int writeResult = 0;
printf("Starting copy...\n");
AsyncCopyStream(&bufferBlockManager, &readStream, &writeStream, &readResult, &writeResult);
printf("Finished copy... readResult=%d writeResult=%d \n", readResult, writeResult);
getchar();
return 0;
}
EDIT: I put my solution into a GitHub repository here. If you wish to use this code, refer to the repository since it may be more updated than this answer.
Typically, you would just have one thread for each direction that alternates between reads and writes.

Color switching of an image using C++ code

Since i am quiet new to C++ and Image processing i have a problem modifying and adding a function to the code.
The requirement is only to switch between the RGB colors.
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "ctype.h"
#include "math.h"
class myImageData
{
private:
int mW;
int mH;
int mCH;
double * mData;
void SkipComments(FILE *fp)
{
int ch;
char line[100];
while ((ch = fgetc(fp)) != EOF && isspace(ch))
;
if (ch == '#')
{
fgets(line, sizeof(line), fp);
SkipComments(fp);
}
else
{
fseek(fp, -1, SEEK_CUR);
}
}
public:
myImageData(void)
{
this->mData = NULL;
}
~myImageData()
{
if (this->mData != NULL)
{
delete[] this->mData;
}
}
void init(int W, int H, int CH)
{
this->mW = W;
this->mH = H;
this->mCH = CH;
if (this->mData != NULL)
delete[] this->mData;
this->mData = new double[(this->mW)*(this->mH)*(this->mCH)];
}
int getWidth(void)
{
return this->mW;
}
int getHeight(void)
{
return this->mH;
}
int getCH(void)
{
return this->mCH;
}
double * getDataPtr(void)
{
return this->mData;
}
double get(int x, int y)
{
return this->mData[y*(this->mW) + x];
}
double get(int x, int y, int CH)
{
return this->mData[this->mCH * (y*(this->mW) + x) + CH];
}
void set(int x, int y, double value)
{
this->mData[y*(this->mW) + x] = value;
}
void set(int x, int y, int CH, double value)
{
this->mData[this->mCH *(y*(this->mW) + x) + CH] = value;
}
void read(const char *filename);
void save(const char *filename);
};
void myImageData::read(const char *filename)
{
FILE *file = fopen(filename, "r");
if (file == NULL){
printf("Cannot open %s\n", filename);
exit(1); //abnormal termination
}
printf("Read an image from: %s\n", filename);
// read ppm/pgm header
char buf[256];
char filetype[256];
int W, H, Range, CH;
fgets(buf, sizeof(buf), file);
sscanf(buf, "%s", filetype);
SkipComments(file);
fgets(buf, sizeof(buf), file);
sscanf(buf, "%d%d", &W, &H);
SkipComments(file);
fgets(buf, sizeof(buf), file);
sscanf(buf, "%d", &Range);
//printf("Header: %s, %d, %d, %d\n", filetype, W, H, Range);
SkipComments(file);
if (strcmp(filetype, "P5") == 0)
{
CH = 1;
}
else if (strcmp(filetype, "P6") == 0)
{
CH = 3;
}
else
{
printf("Unknown image type\n");
exit(1); //abnormal termination
}
if (Range != 255){
printf("Invalid data\n");
exit(1); //abnormal termination
}
// create myImageData class
init(W, H, CH);
// read ppm data
int datalength = this->mW * this->mH * this->mCH;
unsigned char * temp = new unsigned char[datalength];
fread(temp, sizeof(unsigned char), datalength, file);
double * ptr1 = this->mData;
unsigned char *ptr2 = temp;
for (int i = 0; i < datalength; i++){
*ptr1 = (double)*ptr2;
ptr1++;
ptr2++;
}
delete[] temp;
fclose(file);
}
void myImageData::save(const char *filename){
char filenamefull[256];
if (this->mCH == 1){
sprintf(filenamefull, "%s.pgm", filename);
}
else{
sprintf(filenamefull, "%s.ppm", filename);
}
FILE *file = fopen(filenamefull, "w");
printf("Write an image to: %s \n", filenamefull);
if (this->mCH == 1){
fprintf(file, "P5\n");
}
else{
fprintf(file, "P6\n");
}
fprintf(file, "%d %d\n", this->mW, this->mH);
fprintf(file, "255\n");
int datalength = this->mW * this->mH * this->mCH;
unsigned char * temp = new unsigned char[datalength];
double * ptr1 = this->mData;
unsigned char * ptr2 = temp;
for (int i = 0; i < datalength; i++){
double value = *ptr1;
value = round(value);
if (value > 255) value = 255;
if (value < 0) value = 0;
*ptr2 = (unsigned char)value;
ptr1++;
ptr2++;
}
fwrite(temp, sizeof(unsigned char), datalength, file);
delete[] temp;
fprintf(file, "Â¥n");
fclose(file);
}
The errors i am having:
error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup
error LNK1120: 1 unresolved externals
Firstly, you have no main function. No surprise that your code doesn't work.. all you have is a class to load, save and manipulate PPM image files.
You appear to me using Visual Studio, so you'll need a function that looks like this:
int _tmain(int argc, _TCHAR* argv[])
{
myImageData image;
image.read("atestfile.ppm");
// do some stuff to your image
image.write("outputfile.ppm");
}
I'm assuming you have a test image in PPM format you can use here, of course.
Now this is madness:
double * ptr1 = this->mData;
unsigned char * ptr2 = temp;
for (int i = 0; i < datalength; i++){
double value = *ptr1;
value = round(value);
if (value > 255) value = 255;
if (value < 0) value = 0;
*ptr2 = (unsigned char)value;
ptr1++;
ptr2++;
}
You've read from an unsigned char, so there's no point stuffing it into a double, and there's definitely no point in checking if the value lies outside of 0 to 255. Why are you storing things in doubles? It makes no sense! Even if you did do something that needed a full double-precision floating point value per channel, you throw it all away in the output when you clamp everything to 0-255 again:
for (int i = 0; i < datalength; i++){
double value = *ptr1;
value = round(value);
if (value > 255) value = 255;
if (value < 0) value = 0;
*ptr2 = (unsigned char)value;
ptr1++;
ptr2++;
}
Also, this is basically C dressed up in a thin C++ veneer. That's okay, everyone has to start somewhere. But instead of using new to create an array, you can do this:
// read ppm data
int datalength = this->mW * this->mH * this->mCH;
// using a std::vector here means that the allocated memory will be freed
// automatically, even in the result of an error occurring.
std::vector<unsigned char> temp(datalength);
fread(&temp[0], sizeof(unsigned char), datalength, file);
I'd also consider using iostream classes such as fstream instead of fread and fopen and so on. But this is not really the place to get into those kinds of details.
Anyway, What to do with your image once it is loaded? You've got dead easy helper functions to read and write pixel values, which will let you do pretty much anything you want. Here's a simple example, swapping the R and B channels. You might get something better when you actually tell us what you wanted.
void swapRB(myImageData& image)
{
assert(image.getCH() == 3);
for (int x = 0; x < image.getWidth())
{
for (int y = 0; x < image.getHeight())
{
double R = image.get(x, y, 0);
double G = image.get(x, y, 1);
double B = image.get(x, y, 2);
image.set(x, y, 0, B);
image.set(x, y, 2, R);
}
}
}

Base64 Encript/Decript (C++ Builder XE)

I'm need encrypt a content of strings in C++ Builder XE and found this code on the internet:
AnsiString Base64Encode(AnsiString slToEnc)
{
//The Base64 Table
const char Base64Table[64]=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char * buftoenc = slToEnc.c_str();
int bufsize = slToEnc.Length() + 1;
char * encbuf = new char[slToEnc.Length() * 5];
encbuf[0] = '\0'; int ilStrLen = -1;
int i=0; int b64byte[5];
unsigned char *buftemp;
AnsiString slRetVal = EmptyStr;
buftemp=(unsigned char *)malloc(bufsize+2);
strcpy(buftemp,buftoenc);
if (fmod(bufsize,3)==1)
{
buftemp[bufsize]='\0';
buftemp[bufsize+1]='\0';
}
if (fmod(bufsize,3)==2)buftemp[bufsize]='\0';
while (i<bufsize)
{
b64byte[0]=buftemp[i]>>2;
b64byte[1]=((buftemp[i]&3)<<4)|(buftemp[i+1]>>4);
b64byte[2]=((buftemp[i+1]&0x0F)<<2)|(buftemp[i+2]>>6);
b64byte[3]=buftemp[i+2]&0x3F;
encbuf[i+(i/3)]=Base64Table[b64byte[0]];
encbuf[i+(i/3)+1]=Base64Table[b64byte[1]];
encbuf[i+(i/3)+2]=Base64Table[b64byte[2]];
encbuf[i+(i/3)+3]=Base64Table[b64byte[3]];
i+=3;
}
free(buftemp);
if (fmod(bufsize,3)==0) ilStrLen = bufsize*8/6;
else if (fmod(bufsize,3)==1) ilStrLen = ((bufsize+2)*8/6)-2;
else if (fmod(bufsize,3)==2) ilStrLen = ((bufsize+1)*8/6)-1;
else ilStrLen = -1;
if(ilStrLen> 0) slRetVal = AnsiString(encbuf).SubString(1, ilStrLen);
if(encbuf != NULL) { delete encbuf; encbuf = NULL; }
return slRetVal;
}
// Calling function in a button component =>
Base64Encode(Memo1->Text);
But it generates a small erro on compilation making reference to ambiguity between the function std::fmod(double, double) being in this source code and the same function of math.h library.
Some suggestion?
In order to resolve the ambiguity you need to specify the namespace for the fmod function. Just change the line:
if (fmod(bufsize,3)==1)
to:
if (std::fmod(bufsize,3)==1)
and it should compile for you.
You can use http://docwiki.embarcadero.com/Libraries/Rio/en/System.NetEncoding.TBase64Encoding
TBase64Encoding* enc = new TBase64Encoding();
UnicodeString decoded = enc->Decode(encoded);
delete enc;
TBase64Encoding* enc = new TBase64Encoding();
UnicodeString encoded = enc->Encode(whatever);
delete enc;
My version is a simple fast encoder (decoder) of base64 for C++ Builder.
//---------------------------------------------------------------------------
UnicodeString __fastcall TExample::Base64Encode(void *data,int length)
{
if (length<=0) return L"";
static const char set[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
unsigned char *in=(unsigned char*)data;
char *pos,*out=pos=new char[((length-1)/3+1)<<2];
while ((length-=3)>=0)
{
pos[0]=set[in[0]>>2];
pos[1]=set[((in[0]&0x03)<<4)|(in[1]>>4)];
pos[2]=set[((in[1]&0x0F)<<2)|(in[2]>>6)];
pos[3]=set[in[2]&0x3F];
pos+=4;
in+=3;
};
if ((length&2)!=0)
{
pos[0]=set[in[0]>>2];
if ((length&1)!=0)
{
pos[1]=set[((in[0]&0x03)<<4)|(in[1]>>4)];
pos[2]=set[(in[1]&0x0F)<<2];
}
else
{
pos[1]=set[(in[0]&0x03)<<4];
pos[2]='=';
};
pos[3]='=';
pos+=4;
};
UnicodeString code=UnicodeString(out,pos-out);
delete[] out;
return code;
};
//---------------------------------------------------------------------------
int __fastcall TExample::Base64Decode(const UnicodeString &code,unsigned char **data)
{
int length;
if (((length=code.Length())==0)||((length&3)!=0)) return 0;
wchar_t *str=code.c_str();
unsigned char *pos,*out=pos=new unsigned char[(length>>2)*3];
while (*str!=0)
{
length=-1;
int shift=18,bits=0;
do
{
wchar_t s=str[++length];
if ((s>=L'A')&&(s<=L'Z')) bits|=(s-L'A')<<shift;
else if ((s>=L'a')&&(s<=L'z')) bits|=(s-(L'a'-26))<<shift;
else if (((s>=L'0')&&(s<=L'9'))) bits|=(s-(L'0'-52))<<shift;
else if (s==L'+') bits|=62<<shift;
else if (s==L'/') bits|=63<<shift;
else if (s==L'=')
{
length--;
break;
}
else
{
delete[] out;
return 0;
};
}
while ((shift-=6)>=0);
pos[0]=bits>>16;
pos[1]=bits>>8;
pos[2]=bits;
pos+=length;
str+=4;
};
*data=out;
return pos-out;
};
//---------------------------------------------------------------------------