aboutsummaryrefslogtreecommitdiff
path: root/c++-qt/src/gatsstream.cpp
blob: 920b2d69f3dbe786967f9352d0ae71c519b5bf7c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include "gats-qt/gatsstream.h"
#include "gats-qt/object.h"

#ifdef WIN32
#include <winsock2.h>
#else
#include <arpa/inet.h>
#endif

#include <QBuffer>

Gats::GatsStream::GatsStream( QIODevice &rStream ) :
	rStream( rStream )
{
}

Gats::GatsStream::~GatsStream()
{
}

Gats::Object *Gats::GatsStream::readObject()
{
	char buf[1500];

	do
	{
		if( qbRead.size() < 5 )
		{
			int iRead = rStream.read( buf, 5-qbRead.size() );
			qbRead.append( buf, iRead );

			if( qbRead.size() < 5 )
				return NULL;
		}
	} while( !skipReadNulls() );

	uint8_t uVer;
	uVer = qbRead[0];
	
	int32_t iSize;
	memcpy( &iSize, qbRead.constData()+1, 4 );
	iSize = ntohl( iSize );
	while( qbRead.size() < iSize )
	{
		int32_t iRead = iSize - qbRead.size();
		if( iRead > 1500 )
			iRead = 1500;
		int32_t iReal = rStream.read( buf, iRead );
		qbRead.append( buf, iReal );
		if( iReal < iRead )
		{
			return NULL;
		}
	}

	if( qbRead.size() < iSize )
	{
		return NULL;
	}

	QBuffer rTmp( &qbRead );
	rTmp.open( QIODevice::ReadOnly );
	rTmp.seek( 5 );
	Gats::Object *pObj = Gats::Object::read( rTmp );
	qbRead.clear();

	emit objectRead( pObj );

	return pObj;
}

void Gats::GatsStream::readAllObjects()
{
	while( readObject() ) { }
}

void Gats::GatsStream::writeObject( Gats::Object *pObject )
{
	QIODevice *pTmp;
	if( rStream.isSequential() )
	{
		pTmp = new QBuffer();
		pTmp->open( QIODevice::WriteOnly );
	}
	else
	{
		pTmp = &rStream;
	}

	uint8_t uBuf = 1;
	uint32_t iSize = 0;
	pTmp->write( (const char *)&uBuf, 1 );
	uint64_t iSizePos = pTmp->pos();
	pTmp->write( (const char *)&iSize, 4 );
	pObject->write( *pTmp );
	iSize = htonl( pTmp->pos() );
	uint64_t iEndPos = pTmp->pos();
	pTmp->seek( iSizePos );
	pTmp->write( (const char *)&iSize, 4 );

	if( rStream.isSequential() )
	{
		pTmp->close();
		rStream.write( ((QBuffer *)pTmp)->data() );
		delete pTmp;
	}
	else
	{
		pTmp->seek( iSizePos );
	}
}

bool Gats::GatsStream::skipReadNulls()
{
	bool bHaveSeeked = false;
	for(;;)
	{
		if( qbRead.size() == 0 )
			return false;
		if( qbRead.at(0) != 0 )
			return !bHaveSeeked; //true;
		else
		{
			qbRead.remove( 0, 1 );
			bHaveSeeked = true;
		}
	}
}