/*
Copyright 2005 Chad Yoshikawa
http://www.ececs.uc.edu/~yoshikco
yoshikco@ececs.uc.edu
This, and other source files, were derived from two GPL'd sources:
"An Almost Complete Namespace Extension Sample"
http://www.codeproject.com/shell/NamespaceExtImpl.asp
Copyright 2005 Pascal Hurni
AdfView
http://www.viksoe.dk/code/adfview.htm
Written by Bjarke Viksoe
Copyright (c) 2001-2002 Bjarke Viksoe.
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
*/
#pragma once
#include <Winsock2.h>
#include <string>
/// This is a set of helper functions that enable us to send/receive data types over-the-wire
class IOLibrary {
public:
/// Write a buffer to a socket
/// @param mySocket the socket to write to
/// @param buf the buffer to write
/// @param length the number of bytes to write
static void WriteBuffer(SOCKET mySocket, char* buf, int length) {
int num_written = 0;
int ret_value;
//char BUFFER[1024];
while (num_written < length) {
ret_value = send(mySocket,buf+num_written,length-num_written,NULL);
if (ret_value == SOCKET_ERROR) {
// error
CGalaxyUtils::TraceTime("Error when writing to socket");
}
num_written+=ret_value;
} // END WHILE
} // END WRITEBUFFER
/// Read a buffer from a socket
/// @param mySocket the socket to read from
/// @param buf the buffer to read into
/// @param length the number of bytes to read
static void ReadBuffer(SOCKET mySocket, char* buf, int length) {
int num_read = 0;
while (num_read < length) {
num_read+= recv(mySocket,buf+num_read,length-num_read,NULL);
}
}
/// A templated method to convert a primitive type to an array of bytes
/// @param arg the object to convert
/// @return a buffer of bytes representing the primivive type, to be freed by the caller
template <class T>
static char* ConvertToByteArray(T arg) {
char * ret = new char[sizeof(T)];
for (int i=0;i<sizeof(arg); i++) {
int offset = i*8;
ret[i] = (arg& (0xff << offset)) >> offset;
} // end for
return (ret);
} // end ConvertToByteArray
/// A templated method to convert an array of bytes back to a primitive type
/// @param buf the buffer to convert
/// @return the primitive type, reconstituted.
template <class T>
static T ConvertBytesTo(byte *buf) {
T ret = 0x0;
for (int i=0;i<sizeof(T); i++) {
int offset = i*8;
ret |= buf[i] << offset;
} // end for
return (ret);
}
/// Convert a bunch of bytes to a wide string
/// @param buf the pointer to the byte buffer
/// @param num_bytes the number of bytes (not characters)
/// @return the new wide string
static std::wstring ConvertBytesToString(byte* buf, int num_bytes) {
std::wstring ret;
ret.reserve(num_bytes/sizeof(wchar_t));
wchar_t c;
for (unsigned int i=0;i<num_bytes/sizeof(wchar_t);i++) {
c = buf[i*2] | buf[i*2+1] << 8;
ret +=c;
}
return (ret);
} // end ConvertToByteArray
/// A templated method to write a primitive value to the socket
/// @param mySocket the socket to write to
/// @param arg the value to write
template <class T>
static void Write(SOCKET mySocket,T arg) {
char* buf= ConvertToByteArray<T>(arg);
WriteBuffer(mySocket,buf,sizeof(arg));
delete[] buf;
}
/// Write a unicode string to a socket
/// @param mySocket the socket
/// @param str the string to write
static void WriteString(SOCKET mySocket,std::wstring str) {
int num_bytes = (int)(str.length()*sizeof(wchar_t));
IOLibrary::Write<int>(mySocket,num_bytes);
IOLibrary::WriteBuffer(mySocket, (char*)(str.c_str()),num_bytes);
}
/// Templated method to read a primitive type from a socket
/// @param mySocket the socket
/// @return the primitive type
template <class T>
static T Read(SOCKET mySocket) {
byte buf[sizeof(T)];
ReadBuffer(mySocket,(char*)buf,sizeof(T));
T ret = ConvertBytesTo<T>(buf);
return (ret);
}
/// Read a string from a socket
/// @param mySocket the socket
/// @return the unicode string
static std::wstring ReadString(SOCKET mySocket) {
int num_bytes = Read<int>(mySocket);
byte *buf = new byte[num_bytes];
ReadBuffer(mySocket,(char*)buf,num_bytes);
std::wstring ret = ConvertBytesToString(buf,num_bytes);
delete[] buf;
return (ret);
}
};