Skip to content

Commit

Permalink
Added Reader and Writer
Browse files Browse the repository at this point in the history
Generic byte array I/O. These will replace much of net_msg.c and
will be available in the public API for the plugins. Currently the
plugins are using various hacks to write network messages.
  • Loading branch information
skyjake committed Aug 13, 2011
1 parent 5d73ae2 commit 5be2f3b
Show file tree
Hide file tree
Showing 4 changed files with 563 additions and 0 deletions.
101 changes: 101 additions & 0 deletions doomsday/engine/api/reader.h
@@ -0,0 +1,101 @@
/**\file
*\section License
* License: GPL
* Online License Link: http://www.gnu.org/licenses/gpl.html
*
*\author Copyright © 2011 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/

#ifndef __DOOMSDAY_READER_H__
#define __DOOMSDAY_READER_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "dd_types.h"

struct reader_s; // The reader instance (opaque).
typedef struct reader_s Reader;

/**
* Constructs a new reader. The reader will use the engine's netBuffer
* as the reading buffer. The reader has to be destroyed with Reader_Destruct()
* after it is not needed any more.
*/
Reader* Reader_New(void);

/**
* Initializes the reader. The reader will use @a buffer as the reading buffer.
* The buffer is expected to use network byte order. The reader has to be destroyed
* with Reader_Destruct() after it is not needed any more.
*
* @param buffer Buffer to use for reading.
* @param len Length of the buffer.
*/
Reader* Reader_NewWithBuffer(const byte* buffer, size_t len);

/**
* Destroys the reader.
*/
void Reader_Destruct(Reader* reader);

/**
* Returns the current position of the reader.
*/
size_t Reader_Pos(const Reader* reader);

/**
* Returns the size of the reading buffer.
*/
size_t Reader_Size(const Reader* reader);

/**
* Sets the position of the reading cursor in the buffer.
*
* @param reader Reader.
* @param newPos New position.
*/
void Reader_SetPos(Reader* reader, size_t newPos);

int8_t Reader_ReadChar(Reader* reader);
byte Reader_ReadByte(Reader* reader);
int16_t Reader_ReadInt16(Reader* reader);
uint16_t Reader_ReadUInt16(Reader* reader);
int32_t Reader_ReadInt32(Reader* reader);
uint32_t Reader_ReadUInt32(Reader* reader);
float Reader_ReadFloat(Reader* reader);

/**
* Reads @a len bytes into @a buffer.
*/
void Reader_Read(Reader* reader, void* buffer, size_t len);

/**
* Only 15 bits can be used for the number because the high bit of the
* lower byte is used to determine whether the upper byte follows or not.
*/
uint16_t Reader_ReadPackedUInt16(Reader* reader);

uint32_t Reader_ReadPackedUInt32(Reader* reader);

#ifdef __cplusplus
} // extern "C"
#endif

#endif // __DOOMSDAY_READER_H__
95 changes: 95 additions & 0 deletions doomsday/engine/api/writer.h
@@ -0,0 +1,95 @@
/**\file
*\section License
* License: GPL
* Online License Link: http://www.gnu.org/licenses/gpl.html
*
*\author Copyright © 2011 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/

#ifndef __DOOMSDAY_WRITER_H__
#define __DOOMSDAY_WRITER_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "dd_types.h"

struct writer_s; // The writer instance (opaque).
typedef struct writer_s Writer;

/**
* Constructs a new writer. The writer will use the engine's netBuffer
* as the writing buffer. The writer has to be destroyed with Writer_Destruct()
* after it is not needed any more.
*/
Writer* Writer_New(void);

/**
* Initializes the writer. The writer will use @a buffer as the writing buffer.
* The buffer will use network byte order. The writer has to be destroyed
* with Writer_Destruct() after it is not needed any more.
*
* @param buffer Buffer to use for reading.
* @param len Length of the buffer.
*/
Writer* Writer_NewWithBuffer(byte* buffer, size_t len);

/**
* Destroys the writer.
*/
void Writer_Destruct(Writer* writer);

size_t Writer_Pos(const Writer* writer);

size_t Writer_Size(const Writer* writer);

/**
* Sets the position of the writing cursor in the buffer.
*
* @param writer Writer.
* @param newPos New position.
*/
void Writer_SetPos(Writer* writer, size_t newPos);

void Writer_WriteChar(Writer* writer, char v);
void Writer_WriteByte(Writer* writer, byte v);
void Writer_WriteInt16(Writer* writer, int16_t v);
void Writer_WriteUInt16(Writer* writer, uint16_t v);
void Writer_WriteInt32(Writer* writer, int32_t v);
void Writer_WriteUInt16(Writer* writer, uint16_t v);
void Writer_WriteFloat(Writer* writer, float v);

/**
* Writes @a len bytes from @a buffer.
*/
void Writer_Write(Writer* writer, const void* buffer, size_t len);

/**
* Only 15 bits can be used for the number because the high bit of the
* lower byte is used to determine whether the upper byte follows or not.
*/
void Writer_WritePackedUInt16(Writer* writer, uint16_t v);

void Writer_WritePackedUInt32(Writer* writer, uint32_t v);

#ifdef __cplusplus
} // extern "C"
#endif

#endif // __DOOMSDAY_WRITER_H__
185 changes: 185 additions & 0 deletions doomsday/engine/portable/src/reader.c
@@ -0,0 +1,185 @@
/**\file
*\section License
* License: GPL
* Online License Link: http://www.gnu.org/licenses/gpl.html
*
*\author Copyright © 2011 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/

#include "de_misc.h"
#include "de_console.h"
#include "net_buf.h"
#include "reader.h"

struct reader_s
{
const byte* data; // The data buffer.
size_t size; // Size of the data buffer.
size_t pos; // Current position in the buffer.
};

static boolean Reader_Check(const Reader* reader, size_t len)
{
if(!reader || !reader->data) return false;
if(reader->pos > reader->size - len)
{
Con_Error("Reader_Check: Position %lu[+%lu] out of bounds, size=%lu.\n",
(unsigned long) reader->pos,
(unsigned long) len,
(unsigned long) reader->size);
}
return true;
}

Reader* Reader_New(void)
{
Reader* rd = M_Calloc(sizeof(Reader));
rd->size = netBuffer.length;
rd->data = (const byte*) netBuffer.msg.data;
return rd;
}

Reader* Reader_NewWithBuffer(const byte* buffer, size_t len)
{
Reader* rd = M_Calloc(sizeof(Reader));
rd->size = len;
rd->data = buffer;
return rd;
}

void Reader_Destruct(Reader* reader)
{
M_Free(reader);
}

size_t Reader_Pos(const Reader* reader)
{
if(!reader) return 0;
return reader->pos;
}

size_t Reader_Size(const Reader* reader)
{
if(!reader) return 0;
return reader->size;
}

void Reader_SetPos(Reader* reader, size_t newPos)
{
if(!reader) return;
reader->pos = newPos;
Reader_Check(reader, 0);
}

int8_t Reader_ReadChar(Reader* reader)
{
if(!Reader_Check(reader, 1)) return 0;
return ((int8_t*)reader->data)[reader->pos++];
}

byte Reader_ReadByte(Reader* reader)
{
if(!Reader_Check(reader, 1)) return 0;
return reader->data[reader->pos++];
}

int16_t Reader_ReadInt16(Reader* reader)
{
int16_t result = 0;
if(Reader_Check(reader, 2))
{
result = SHORT( *(int16_t*) &reader->data[reader->pos] );
reader->pos += 2;
}
return result;
}

uint16_t Reader_ReadUInt16(Reader* reader)
{
uint16_t result = 0;
if(Reader_Check(reader, 2))
{
result = USHORT( *(uint16_t*) &reader->data[reader->pos] );
reader->pos += 2;
}
return result;
}

int32_t Reader_ReadInt32(Reader* reader)
{
int32_t result = 0;
if(Reader_Check(reader, 4))
{
result = LONG( *(int32_t*) &reader->data[reader->pos] );
reader->pos += 4;
}
return result;
}

uint32_t Reader_ReadUInt32(Reader* reader)
{
uint32_t result = 0;
if(Reader_Check(reader, 4))
{
result = ULONG( *(uint32_t*) &reader->data[reader->pos] );
reader->pos += 4;
}
return result;
}

float Reader_ReadFloat(Reader* reader)
{
uint32_t v = Reader_ReadUInt32(reader);
return *(float*) &v;
}

void Reader_Read(Reader* reader, void* buffer, size_t len)
{
if(Reader_Check(reader, len))
{
memcpy(buffer, reader->data + reader->pos, len);
reader->pos += len;
}
}

uint16_t Reader_ReadPackedUInt16(Reader* reader)
{
ushort pack = Reader_ReadByte(reader);
if(pack & 0x80)
{
pack &= ~0x80;
pack |= Reader_ReadByte(reader) << 7;
}
return pack;
}

uint32_t Reader_ReadPackedUInt32(Reader* reader)
{
byte pack = 0;
int pos = 0;
uint value = 0;

while(Reader_Check(reader, 1))
{
pack = Reader_ReadByte(reader);
value |= ((pack & 0x7f) << pos);
pos += 7;
} while(pack & 0x80);

return value;
}

0 comments on commit 5be2f3b

Please sign in to comment.