MKV file cluster size which is encoded? - c++

Element IDs (also called EBML IDs), beginning with the ID itself, followed by the Data Size.
Data size, in octets, is also coded with an UTF-8 like system.
How can I decode the data size in decimal

You can find the below simple sample code in
https://github.com/wangf1978/DumpTS/blob/master/Matroska.h
static uint64_t UnpackUnsignedIntVal(CBitstream&bs, uint8_t max_octs = 8, bool unPackVal=true, uint8_t* pcbValLen=nullptr)
{
uint8_t nLeadingZeros = 0;
uint64_t u64Val = bs.GetByte();
for (uint8_t i = 0; i < max_octs; i++)
if ((u64Val&(1ULL << (7 - i))) == 0)
nLeadingZeros++;
else
break;
if (nLeadingZeros >= max_octs) // Unexpected
return UINT64_MAX;
if (unPackVal)
u64Val &= ~(1 << (7 - nLeadingZeros));
for (uint8_t i = 0; i<nLeadingZeros; i++)
u64Val = (((uint64_t)u64Val) << 8) | (uint8_t)bs.GetBits(8);
if (pcbValLen != nullptr)
*pcbValLen = nLeadingZeros + 1;
return u64Val;
}
virtual int Unpack(CBitstream& bs)
{
// Read the element ID
uint64_t u64Val = UnpackUnsignedIntVal(bs, 4, false);
if (u64Val == UINT64_MAX)
return -1;
ID = (uint32_t)u64Val;
if ((u64Val = UnpackUnsignedIntVal(bs)) == UINT64_MAX)
return -1;
Size = u64Val;
//printf("ID: 0X%X, Size: %lld(0X%llX)\n", ID, Size, Size);
return 0;
}

Related

Reading Files/Folders from disk with FAT12 in Own OS

I am developing an OS, I am trying to Implement FAT12 Filesystem from an Other's OS Source Code, Finally, I can Mount a FAT12 Formatted disk and Get its FAT12 Information.
It can Read DriveName ( When 'Location = 0' ).
But When I am trying to List Directories from disk, It is not Working!
Here, This is My Code to Get Directories,
void FAT12_PrintDirectories(uint32_t Location, uint32_t numEntries, uint8_t DriveNum)
{
uint8_t read[((numEntries*32)/4096)+1];
AHCI::Port* port = AHCI::GlobalAHCI->ports[0];
port->Configure();
port->buffer = (uint8_t*)GlobalAllocator.RequestPage();
memset(port->buffer, 0, ((numEntries*32)/4096)+1);
port->Read(Location /* If I write here '0' Instead of Location, then Output is Image2 */, Location+((numEntries*32)/4096)+1, port->buffer);
for (int n = 0; n < sizeof(port->buffer); n++)
{
GlobalRenderer->PutChar(port->buffer[n]);
read[n] = port->buffer[n];
}
char drivename[12];
memset(&drivename, 0, 12);
memcpy(drivename, read, 8);
if(read[9] != ' ')
{
drivename[8] = '.';
memcpy(drivename + 9, read + 8, 3);
}
drivename[11] = 0;
// Print test read
GlobalRenderer->Next();
for (int n = 0; n < sizeof(read); n++)
{
GlobalRenderer->Print("=");
GlobalRenderer->Print(to_string((uint64_t)read[n]));
}
GlobalRenderer->Next();
GlobalRenderer->Print("Listing Dirs!");
GlobalRenderer->Next();
GlobalRenderer->Print("DriveName : ");
GlobalRenderer->Print(drivename);
GlobalRenderer->Next();
uint8_t *reads = read;
GlobalRenderer->Print("Dirs : ");
GlobalRenderer->Next();
for (unsigned int i = 0; i < numEntries; i++)
{
if(!reads[11] & 0x08 || reads[11] & 0x02 || reads[0] == 0 || reads[0] == 0xE5)
{
// Print FileName
for (uint8_t j = 0; j < 11; j++)
{
if(j == 8 && reads[j] != ' ')
{
GlobalRenderer->Print(".");
}
if(reads[j] != 0x20)
{
GlobalRenderer->Print(to_string((uint64_t)reads[j]));
}
if(reads[11] & 0x10 && j == 10)
{
GlobalRenderer->Print("/");
}
uint32_t nextCluster = (reads[27] << 8) | reads[26];
uint32_t size = *(uint32_t *)&reads[28];
}
reads += 32;
}
GlobalRenderer->Print("-");
}
}
Here It is my Calling Code for that function FAT12_PrintDirectories(dirOff, 32, 0);
This time dirOff = 2097153
Output :
After 'Dirs' text - Image1
Image2
Location = ((FAT12_MOUNT *)getDiskMount(numActiveMounts).mount)->RootDirectoryOffset*512+1;

Facing issues trying to decode base64 image

I have a JPEG image, which is represented as a base64 encoded string. I want to save it as a decoded byte array using the Win32 API WriteFile() function.
Because I will use WriteFile(), I need a C string, and I need to know its length, strlen() is bad, because, as I understand, it counts to \0 which could not be the exact end of file. So, I need a function that decodes base64 and returns a char* and outputs the exact byte count.
I have read this answer, and chose code from here (some stuff changed, I marked it):
static const unsigned char base64_table[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
unsigned char * base64_decode(const unsigned char *src, size_t len,
size_t *out_len)
{
unsigned char dtable[256], *out, *pos, block[4], tmp;
size_t i, count, olen;
int pad = 0;
memset(dtable, 0x80, 256); // CHANGED
for (i = 0; i < sizeof(base64_table) - 1; i++)
dtable[base64_table[i]] = (unsigned char) i;
dtable['='] = 0;
count = 0;
for (i = 0; i < len; i++) {
if (dtable[src[i]] != 0x80)
count++;
}
if (count == 0 || count % 4)
return NULL;
olen = count / 4 * 3;
pos = out = new unsigned char[olen]; // CHANGED
if (out == NULL)
return NULL;
count = 0;
for (i = 0; i < len; i++) {
tmp = dtable[src[i]];
if (tmp == 0x80)
continue;
if (src[i] == '=')
pad++;
block[count] = tmp;
count++;
if (count == 4) {
*pos++ = (block[0] << 2) | (block[1] >> 4);
*pos++ = (block[1] << 4) | (block[2] >> 2);
*pos++ = (block[2] << 6) | block[3];
count = 0;
if (pad) {
if (pad == 1)
pos--;
else if (pad == 2)
pos -= 2;
else {
/* Invalid padding */
free(out); // CHANGED
return NULL;
}
break;
}
}
}
*out_len = pos - out;
return out;
}
Usage
unsigned char base[]="data:image/jpeg;base64,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";
unsigned char *g = base64_decode(base, 2568, &re); // length is appearing when you hover mouse on char[] in Visual Studio
// after call re equals 1921
HANDLE f2 = CreateFile(L"img.jpeg", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD wr2;
WriteFile(f2, g, re, &wr2, 0);
CloseHandle(f2);
The file I am getting is not viewable, the Photos app says it is corrupted. The main problem - it weights 1.87 kb, but should be 2.31 (I download this image from a browser).
What am I doing wrong?
As #IngoLeonhardt pointed out, I should not pass the data:image/jpeg;base64, part to the function. Now it works.

if statement doesn't work on Nucleo64 but it does on Maple mini

I have a code that works on Maple Mini but I have to change hardware to Nucleo F030r8 because it has more ADC's and it totally sucks.
In the modbus_update() function there is a check of the size of inputBuffer and the following code should run only if the value of this variable is bigger than 0.
if (inputBuffer > 0 && micros() - microsFlag >= T3_5) {
...
}
But it runs even if value of inputBuffer is exactly 0. The strange thing is that this code (with different serial ports opening method) runs perfectly on Maple Mini. Does anyone have any idea what can be be the problem?
Here is the whole code:
#define BAUDRATE 19200
#define RE_PIN PC12
#define TE_PIN PF4
#define LED_PIN LED_BUILTIN
#define SLAVE_ID 1
#define BUFFER_SIZE 256 // max frame size
#define READ_INTERNAL_REGISTERS 4 // function code
#define MIN_REGISTER_ADDRESS 30001
#define MAX_REGISTER_ADDRESS 30020
#define MAX_SENSORS_PER_ROW 10
#define SENSORS_PER_ROW 7
#define MAX_ROWS 2
#define ROWS 1
#define DEBUG true
#define INVALID_VALUE 0x7FFF
const byte INPUTS[] = {PA0, PA1, PA4, PB0, PC1, PC0};
unsigned char frame[BUFFER_SIZE];
unsigned char functionCode;
unsigned int T1;
unsigned int T1_5; // inter character time out
unsigned int T3_5; // frame delay
unsigned long millisFlag = 0;
unsigned long microsFlag = 0;
unsigned char inputBuffer = 0;
int dlyCounter = 0;
int16_t sensorVals[MAX_SENSORS_PER_ROW * MAX_ROWS];
/*
HardwareSerial *modbus = &Serial;
HardwareSerial Serial1(PA10, PA9);
HardwareSerial *debug = &Serial1;
*/
HardwareSerial debug(PA10, PA9);
void setup() {
pinMode(LED_PIN, OUTPUT);
for (int i = 0; i < SENSORS_PER_ROW; i++) {
pinMode(INPUTS[i], INPUT_PULLUP);
}
debug.begin(BAUDRATE, SERIAL_8E1);
modbus_configure(BAUDRATE, 0); // baud rate, low latency
microsFlag = micros();
}
void loop() {
readSensorVals(100);
modbus_update();
}
unsigned int modbus_update() {
unsigned char overflow = 0;
while (Serial.available()) {
if (overflow) {
Serial.read(); // empty the input buffer
} else {
if (inputBuffer == BUFFER_SIZE) {
overflow = 1;
} else {
frame[inputBuffer] = Serial.read();
inputBuffer++;
}
}
microsFlag = micros();
}
// If an overflow occurred return to the main sketch
// without responding to the request i.e. force a timeout
if (overflow) {
debug.println("Error: input buffer overflow");
return 0;
}
// if inter frame delay occurred, check the incoming package
if (inputBuffer > 0 && micros() - microsFlag >= T3_5) {
debug.println("\nIncoming frame:");
for (int i = 0; i < inputBuffer; i++) {
debug.print(frame[i], HEX);
debug.print(" ");
}
debug.println();
// check CRC
unsigned int crc = ((frame[inputBuffer - 2] << 8) | frame[inputBuffer - 1]); // combine the crc Low & High bytes
if (calculateCRC(frame, inputBuffer - 2) != crc) {
debug.println("Error: checksum failed");
inputBuffer = 0;
return 0;
}
debug.println("CRC OK");
// check ID
unsigned char id = frame[0];
if (id > 242) {
debug.println("Error: Invalid ID");
inputBuffer = 0;
return 0;
}
// check if it's a broadcast message
if (id == 0) {
debug.println("Broadcast message");
inputBuffer = 0;
return 0;
}
if (id != SLAVE_ID) {
debug.println("Not my ID");
inputBuffer = 0;
return 0;
}
debug.println("ID OK");
// check function code
functionCode = frame[1];
if (functionCode != READ_INTERNAL_REGISTERS) {
debug.println("Exception: illegal function");
exceptionResponse(1);
inputBuffer = 0;
return 0;
}
debug.println("Function code OK");
// check frame size (function 4 frame MUST be 8 bytes long)
if (inputBuffer != 8) {
// some workaround here:
//if (inputBuffer != 8 || !(inputBuffer == 9 && frame[inputBuffer] == 0)) {
debug.println("Error: inaccurate frame length");
inputBuffer = 0;
return 0;
}
debug.println("Frame size OK");
// check data address range
unsigned int noOfRegisters = ((frame[4] << 8) | frame[5]); // combine the number of register bytes
if (noOfRegisters > 125) {
debug.println("Exception: illegal data address");
exceptionResponse(2);
inputBuffer = 0;
return 0;
}
unsigned int firstRegAddress = ((frame[2] << 8) | frame[3]); // combine the starting address bytes
debug.print("First address: ");
debug.println(firstRegAddress);
unsigned int lastRegAddress = firstRegAddress + noOfRegisters - 1;
debug.print("Last address: ");
debug.println(lastRegAddress);
unsigned char noOfBytes = noOfRegisters * 2;
unsigned char responseFrameSize = 5 + noOfBytes; // ID, functionCode, noOfBytes, (dataLo + dataHi) * number of registers, crcLo, crcHi
unsigned char responseFrame[responseFrameSize];
responseFrame[0] = SLAVE_ID;
responseFrame[1] = 0x04;
responseFrame[2] = noOfBytes;
unsigned char address = 3; // PDU starts at the 4th byte
for (int index = (int)(firstRegAddress - MIN_REGISTER_ADDRESS); index <= (int)(lastRegAddress - MIN_REGISTER_ADDRESS); index++) {
int16_t temp = (index >= 0 && index < MAX_ROWS * MAX_SENSORS_PER_ROW) ? sensorVals[index] : INVALID_VALUE;
responseFrame[address] = temp >> 8; // split the register into 2 bytes
address++;
responseFrame[address] = temp & 0xFF;
address++;
}
unsigned int crc16 = calculateCRC(responseFrame, responseFrameSize - 2);
responseFrame[responseFrameSize - 2] = crc16 >> 8; // split crc into 2 bytes
responseFrame[responseFrameSize - 1] = crc16 & 0xFF;
debug.println("Frame to send:");
for (int i = 0; i < responseFrameSize; i++) {
debug.print(responseFrame[i], HEX);
debug.print(" ");
}
debug.println();
sendPacket(responseFrame, responseFrameSize);
inputBuffer = 0;
while (Serial.available()) { // empty input buffer
Serial.read();
}
}
}
void modbus_configure(long baud, unsigned char _lowLatency) {
Serial.begin(baud, SERIAL_8E1);
pinMode(TE_PIN, OUTPUT);
pinMode(RE_PIN, OUTPUT);
rxEnable(); // pin 0 & pin 1 are reserved for RX/TX. To disable set TE and RE pin < 2
if (baud == 1000000 && _lowLatency) {
T1 = 1;
T1_5 = 1;
T3_5 = 10;
} else if (baud >= 115200 && _lowLatency) {
T1 = 50;
T1_5 = 75;
T3_5 = 175;
} else if (baud > 19200) {
T1 = 500;
T1_5 = 750;
T3_5 = 1750;
} else {
T1 = 10000000 / baud;
T1_5 = 15000000 / baud; // 1T * 1.5 = T1.5
T3_5 = 35000000 / baud; // 1T * 3.5 = T3.5
}
}
void exceptionResponse(unsigned char exception) {
unsigned char responseFrameSize = 5;
unsigned char responseFrame[responseFrameSize];
responseFrame[0] = SLAVE_ID;
responseFrame[1] = (functionCode | 0x80); // set the MSB bit high, informs the master of an exception
responseFrame[2] = exception;
unsigned int crc16 = calculateCRC(responseFrame, 3); // ID, functionCode + 0x80, exception code == 3 bytes
responseFrame[3] = crc16 >> 8;
responseFrame[4] = crc16 & 0xFF;
sendPacket(responseFrame, responseFrameSize); // exception response is always 5 bytes (ID, functionCode + 0x80, exception code, 2 bytes crc)
}
unsigned int calculateCRC(unsigned char f[], byte bufferSize) {
unsigned int temp, temp2, flag;
temp = 0xFFFF;
for (unsigned char i = 0; i < bufferSize; i++) {
temp = temp ^ f[i];
for (unsigned char j = 1; j <= 8; j++) {
flag = temp & 0x0001;
temp >>= 1;
if (flag)
temp ^= 0xA001;
}
}
// Reverse byte order.
temp2 = temp >> 8;
temp = (temp << 8) | temp2;
temp &= 0xFFFF;
return temp; // the returned value is already swapped - crcLo byte is first & crcHi byte is last
}
void rxEnable() {
if (TE_PIN > 1 && RE_PIN > 1) {
digitalWrite(TE_PIN, LOW);
digitalWrite(RE_PIN, LOW);
digitalWrite(LED_PIN, LOW);
}
}
void txEnable() {
if (TE_PIN > 1 && RE_PIN > 1) {
digitalWrite(TE_PIN, HIGH);
digitalWrite(RE_PIN, HIGH);
digitalWrite(LED_PIN, HIGH);
}
}
void sendPacket(unsigned char f[], unsigned char bufferSize) {
txEnable();
delayMicroseconds(T3_5);
for (unsigned char i = 0; i < bufferSize; i++) {
Serial.write(f[i]);
}
Serial.flush();
delayMicroseconds(T3_5); // allow frame delay to indicate end of transmission
rxEnable();
}
// #param dly delay between sensor readings in milliseconds
void readSensorVals(int dly) {
if (millis() != millisFlag) {
dlyCounter++;
millisFlag = millis();
}
if (dlyCounter >= dly) { // read sensor values
for (int i = 0; i < MAX_ROWS; i++) {
for (int j = 0; j < MAX_SENSORS_PER_ROW; j++) {
int actualIndex = i * MAX_SENSORS_PER_ROW + j;
if (i < ROWS && j < SENSORS_PER_ROW) {
sensorVals[actualIndex] = random(20, 30);
//sensorVals[actualIndex] = (4096 - analogRead(INPUTS[j])) / 20 - 133;
} else {
sensorVals[actualIndex] = INVALID_VALUE;
}
}
}
dlyCounter = 0;
}
}

Websocket Poco can't receive big data

I downloaded and built Poco project from Poco and run WebsocketServer project in poco-1.7.6\Net\samples\WebSocketServer.
When I worked with small data that is smaller 128 KB (131072 bytes), it work perfectly. But if I work with bigger data (I need to send 20 MB), my data will be cut so server don't receive data enough.
Here is code that I copy in project:
WebSocket ws(request, response);
char *buffer = new char[1000000]; // It just receive 131072 bytes
int flags;
int n;
do
{
n = ws.receiveFrame(buffer, sizeof(buffer), flags);
ws.sendFrame(buffer, tmp.length(), flags);
} while (n > 0 || (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE);
delete[] buffer;
Deframe code:
int WebSocketImpl::receiveBytes(void* buffer, int length, int)
{
char header[MAX_HEADER_LENGTH];
int n = receiveNBytes(header, 2);
if (n <= 0)
{
_frameFlags = 0;
return n;
}
poco_assert (n == 2);
Poco::UInt8 lengthByte = static_cast<Poco::UInt8>(header[1]);
int maskOffset = 0;
if (lengthByte & FRAME_FLAG_MASK) maskOffset += 4;
lengthByte &= 0x7f;
if (lengthByte > 0 || maskOffset > 0)
{
if (lengthByte + 2 + maskOffset < MAX_HEADER_LENGTH)
{
n = receiveNBytes(header + 2, lengthByte + maskOffset);
}
else
{
n = receiveNBytes(header + 2, MAX_HEADER_LENGTH - 2);
}
if (n <= 0) throw WebSocketException("Incomplete header received", WebSocket::WS_ERR_INCOMPLETE_FRAME);
n += 2;
}
Poco::MemoryInputStream istr(header, n);
Poco::BinaryReader reader(istr, Poco::BinaryReader::NETWORK_BYTE_ORDER);
Poco::UInt8 flags;
char mask[4];
reader >> flags >> lengthByte;
_frameFlags = flags;
int payloadLength = 0;
int payloadOffset = 2;
if ((lengthByte & 0x7f) == 127)
{
Poco::UInt64 l;
reader >> l;
if (l > length) throw WebSocketException(Poco::format("Insufficient buffer for payload size %Lu", l), WebSocket::WS_ERR_PAYLOAD_TOO_BIG);
payloadLength = static_cast<int>(l);
payloadOffset += 8;
}
else if ((lengthByte & 0x7f) == 126)
{
Poco::UInt16 l;
//lenBuffer = l;
if (l > length) throw WebSocketException(Poco::format("Insufficient buffer for payload size %hu", l), WebSocket::WS_ERR_PAYLOAD_TOO_BIG);
payloadLength = static_cast<int>(l);
payloadOffset += 2;
}
else
{
Poco::UInt8 l = lengthByte & 0x7f;
if (l > length) throw WebSocketException(Poco::format("Insufficient buffer for payload size %u", unsigned(l)), WebSocket::WS_ERR_PAYLOAD_TOO_BIG);
payloadLength = static_cast<int>(l);
}
if (lengthByte & FRAME_FLAG_MASK)
{
reader.readRaw(mask, 4);
payloadOffset += 4;
}
int received = 0;
if (payloadOffset < n)
{
std::memcpy(buffer, header + payloadOffset, n - payloadOffset);
received = n - payloadOffset;
}
if (received < payloadLength)
{
n = receiveNBytes(reinterpret_cast<char*>(buffer) + received, payloadLength - received);
if (n <= 0) throw WebSocketException("Incomplete frame received", WebSocket::WS_ERR_INCOMPLETE_FRAME);
received += n;
}
if (lengthByte & FRAME_FLAG_MASK)
{
char* p = reinterpret_cast<char*>(buffer);
for (int i = 0; i < received; i++)
{
p[i] ^= mask[i % 4];
}
}
return received;
}
Can anyone help me, please!
P/s: Sorry about my English
UPDATE: I just got this problem in Chrome. It work fine with Firefox and Edge
Setting setChunkedTransferEncoding should make it work.
In the code before the response is sent set:
response.setChunkedTransferEncoding(true);

Reading 12 Bit input c++

I'm trying to write a small program that can read and write 12 bit. The Input shouldn't have any issues but I'll include it so you understand the problem better. The input should be created as sample.lzw by the OFStream12Bits.cpp/main.cpp included below and the output should be reading the sample.lzw back from the write functions. I'm having problems with the output and getting code mismatch in the main when reading the code. I think the issues is from the operator>> and the readBit functions not sure exactly though.
Thank you very much for any help, I've been stuck on this for awhile!
The instructions for the readbit are as follows...
//basic readBit
//read12Bits(): 12Bit =
//declare Result : 12Bit = 0;
//for i = 1 to 12
//do
//declare lBit : Bit = get bit from input
//if(lBit == 1)
//then Result = (1 << (i-1)) + Result; //set bit at index i
//od
//return result
The part I don't understand is I need to return *this but there is no + operator so I can't use result to set the bit at index i. at the moment I have the code like this.
IFStream12Bits& IFStream12Bits::operator>>(int& a12BitValue)
{
//int Result = a12BitValue;
//a12BitValue = ((a12BitValue & 0x0fff) << 1);
a12BitValue = a12BitValue & 0x0fff;
for (int i = 0; i < 12; i++)
{
int bit = readBit();
if (bit == 1)
{
a12BitValue = (1 << (i - 1)) + a12BitValue; //set bit at index i
}
}
return *this;
}
Also The instructions for the readBit are as follows...
//implements mapping process. returns 0 or 1 depending on value of fBuffer[fByteIndex] & (1 << (fBitIndex - 1))
//see how it works with experiments
//at start check if (fByteCount == 0){reload();} then use reload() called as buffer does not contain any data before calling reload
//next fetch the bit store and then advance fByteIndex and fBitIndex
//if fBitIndex(highest to lowest) reaches 0 you need to switch to the next byte in the buffer. and also decrment fByteCount
//then finally return result
And the code is
int IFStream12Bits::readBit()
{
if (fByteCount == 0){ reload(); }
//int bit = fBuffer[fByteIndex] & (1 << (fBitIndex - 1));
int bit = fBuffer[fByteIndex] & (1 << (fBitIndex - 1));
int result = 0;
cout << "bit: " << bit << endl;
//added this just cause
if (bit == 0)
{
result = 0;
}
else
{
result = 1;
}
//additional logic required?
fByteIndex++;
fBitIndex--;
//switch to next byte in the buffer
if (fBitIndex == 0)
{
fByteCount--;
fBitIndex = 8;
fByteIndex = 0;
}
return result;
}
Here are the full .cpp files if you need to understand what is happening...
IFStream12Bits.cpp
#include "IFStream12Bits.h"
#include <iostream>
using namespace std;
//default constructor
IFStream12Bits::IFStream12Bits()
{
init();
}
//takes aFIleName
IFStream12Bits::IFStream12Bits(const char* aFileName)
{
init();
open(aFileName);
}
//deconstructor
IFStream12Bits::~IFStream12Bits()
{
close();
}
//initialize the integer member variables with sensible values
//:fBuffer(), fByteCount(0), fByteIndex(0), fBitIndex(8)
//fBitIndex(highToLow)
void IFStream12Bits::init()
{
for (int i = 0; i < 32; i++)
{
fBuffer[i] = 0;
}
fByteCount = 0;
fByteIndex = 0;
fBitIndex = 8;
}
//fills input buffer fBuffer with the next 32 bytes and sets fByteCount to number of bytes read
void IFStream12Bits::reload()
{
//fills fBuffer with 32 bytes
fIStream.read((char*)fBuffer, 32);
//fIStream.read((char*)fBuffer, fByteIndex + (fBitIndex % 8 ? 1 : 0));
//sets fByteCount to number of bytes read
fByteCount = fIStream.gcount();
}
//implements mapping process. returns 0 or 1 depending on value of fBuffer[fByteIndex] & (1 << (fBitIndex - 1))
//see how it works with experiments
//at start check if (fByteCount == 0){reload();} then use reload() called as buffer does not contain any data before calling reload
//next fetch the bit store and then advance fByteIndex and fBitIndex
//if fBitIndex(highest to lowest) reaches 0 you need to switch to the next byte in the buffer. and also decrment fByteCount
//then finally return result
int IFStream12Bits::readBit()
{
if (fByteCount == 0){ reload(); }
//int bit = fBuffer[fByteIndex] & (1 << (fBitIndex - 1));
int bit = fBuffer[fByteIndex] & (1 << (fBitIndex - 1));
int result = 0;
cout << "bit: " << bit << endl;
if (bit == 0)
{
result = 0;
}
else
{
result = 1;
}
//additional logic required?
fByteIndex++;
fBitIndex--;
//switch to next byte in the buffer
if (fBitIndex == 0)
{
fByteCount--;
fBitIndex = 8;
fByteIndex = 0;
}
return result;
}
void IFStream12Bits::open(const char* aFileName)
{
fIStream.open(aFileName, std::fstream::binary);
}
void IFStream12Bits::close()
{
fIStream.close();
}
bool IFStream12Bits::fail()
{
return fIStream.fail();
}
//true if no bytes left in input stream (fByteCount == 0)(should be zero if never read anythign from fIStream)
bool IFStream12Bits::eof()
{
return fByteCount == 0;
}
//read 12Bit codes from the bit input stream implements the read12Bits algorithm as shown in the tutorial
//basic readBit
//read12Bits(): 12Bit =
//declare Result : 12Bit = 0;
//for i = 1 to 12
//do
//declare lBit : Bit = get bit from input
//if(lBit == 1)
//then Result = (1 << (i-1)) + Result; //set bit at index i
//od
//return result
// multiply values by 2 to shift left???????????
IFStream12Bits& IFStream12Bits::operator>>(int& a12BitValue)
{
//int Result = a12BitValue;
//a12BitValue = ((a12BitValue & 0x0fff) << 1);
a12BitValue = a12BitValue & 0x0fff;
for (int i = 0; i < 12; i++)
{
int bit = readBit();
if (bit == 1)
{
a12BitValue = (1 << (i - 1)) + a12BitValue; //set bit at index i
}
}
return *this;
}
OFStream12Bits.cpp
#include "OFStream12Bits.h"
OFStream12Bits::OFStream12Bits()
{
init();
}
OFStream12Bits::OFStream12Bits(const char* aFileName)
{
init();
open(aFileName);
}
OFStream12Bits::~OFStream12Bits()
{
close();
}
void OFStream12Bits::init()
{
for (int i = 0; i < 32; i++)
{
fBuffer[i] = 0;
}
fByteIndex = 0;
fBitIndex = 8;
}
void OFStream12Bits::writeBit0()
{
fBitIndex--;
finishWriteBit();
}
void OFStream12Bits::writeBit1()
{
fBuffer[fByteIndex] += 1 << (fBitIndex - 1);
fBitIndex--;
finishWriteBit();
}
void OFStream12Bits::finishWriteBit()
{
if (fBitIndex == 0)
{
if (fByteIndex == 31)
{
fByteIndex++;
//write full buffer to stream
flush();
}
else
{
fByteIndex++;
fBitIndex = 8;
}
}
}
void OFStream12Bits::open(const char* aFileName)
{
fOStream.open(aFileName, std::ofstream::binary);
}
bool OFStream12Bits::fail()
{
return fOStream.fail();
}
void OFStream12Bits::close()
{
flush();
fOStream.close();
}
void OFStream12Bits::flush()
{
// do we need to add last byte?
fOStream.write((char*)fBuffer, fByteIndex + (fBitIndex % 8 ? 1 : 0));
init();
}
OFStream12Bits& OFStream12Bits::operator<<(int a12BitValue)
{
a12BitValue = a12BitValue & 0x0fff; // mask 12 lower bits
for (int i = 0; i < 12; i++) //write 12 bits
{
if (a12BitValue & 0x01) // the current lowest bit is set
{
writeBit1();
}
else
{
writeBit0();
}
a12BitValue >>= 1; // code = code / 2 --shifting value accross
}
return *this;
}
main.cpp
#include "OFStream12Bits.h"
#include "IFStream12Bits.h"
#include <iostream>
using namespace std;
void write4096()
{
cout << "Write 4096 codes" << endl;
OFStream12Bits lWriter("sample.lzw");
if (lWriter.fail())
{
cerr << "Error: unable to open output file" << endl;
exit(1);
}
for (int i = 4096; i >= 0; i--)
{
lWriter << i;
}
}
void read4096()
{
cout << "Read 4096 codes" << endl;
IFStream12Bits lInput("sample.lzw");
if (lInput.fail())
{
cerr << "Error: unable to open input file!" << endl;
exit(2);
}
for (int i = 4095; i >= 0; i--)
{
int l12BitValue;
lInput >> l12BitValue;
if (l12BitValue != i)
{
cerr << "Error: Code mismatch: " << l12BitValue << " != " << i << endl;
exit(3);
}
}
if (!lInput.eof())
{
cerr << "Error: Input stream not exhausted" << endl;
}
}
int main()
{
write4096();
read4096();
cout << "SUCCESS" << endl;
return 0;
}
Your input code is starting with the previous value. You should start with 0, because you're not clearing bits that aren't set.
IFStream12Bits& IFStream12Bits::operator>>(int& a12BitValue)
{
a12BitValue = 0;
for (int i = 0; i < 12; i++)
{
int bit = readBit();
if (bit == 1)
{
a12BitValue = (1 << (i - 1)) + a12BitValue; //set bit at index i
}
}
return *this;
}
Also, + will work here, but it's clearer to use bitwise operations when dealing with bits. Additionally, I think your shift is off. I would write the set bit line like this:
a12BitValue |= 1 << i;
If you think about it, when i is 0, you want to set the first bit (which is 1 or 1 << 0.) When i is 1, you want the next bit, and so on. So you should not need to subtract one.
I'm not sure that's the only problem, but you might try testing each class independently with unit tests. For example, start with a raw byte buffer, like {0x89, 0xAB, 0xCD, 0xEF, 0x01}, and then read three sets of 12 bits off. Verify they are correct. Then create an empty buffer, and write specific bits to it, and check that the bytes are correct.
By testing the algorithms independently, and with very strict input/output, you'll find it much easier to determine the flaw.