Initial Comit
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
common/build/**
|
||||
listener/build/**
|
||||
26
common/.vscode/c_cpp_properties.json
vendored
Normal file
26
common/.vscode/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**",
|
||||
"/home/pi/Boneyard"
|
||||
],
|
||||
"defines": [],
|
||||
"cStandard": "c17",
|
||||
"cppStandard": "gnu++17",
|
||||
"intelliSenseMode": "linux-gcc-arm64"
|
||||
},
|
||||
{
|
||||
"name": "ARM64",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**"
|
||||
],
|
||||
"defines": [],
|
||||
"cStandard": "c17",
|
||||
"cppStandard": "gnu++17",
|
||||
"intelliSenseMode": "linux-gcc-arm64"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
3
common/.vscode/settings.json
vendored
Normal file
3
common/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
|
||||
}
|
||||
6
common/CMakeLists.txt
Normal file
6
common/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.10.0)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/home/pi/Boneyard")
|
||||
project(common VERSION 0.1.0 LANGUAGES C CXX)
|
||||
|
||||
add_library(common string.cpp fileio.cpp intel.cpp mmap.cpp)
|
||||
|
||||
129
common/array.hpp
Executable file
129
common/array.hpp
Executable file
@@ -0,0 +1,129 @@
|
||||
#ifndef _COMMON_ARRAY_HPP_
|
||||
#define _COMMON_ARRAY_HPP_
|
||||
#ifndef _COMMON_WINDOWS_HPP_
|
||||
#include <common/windows.hpp>
|
||||
#endif
|
||||
#ifndef _COMMON_EXCEPTION_HPP_
|
||||
#include <common/except.hpp>
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
class Array
|
||||
{
|
||||
public:
|
||||
Array(void);
|
||||
Array(const Array<T> &someArray);
|
||||
virtual ~Array();
|
||||
T &operator[](DWORD index);
|
||||
T &elementAt(DWORD index);
|
||||
Array<T> &operator=(const Array<T> &someArray);
|
||||
bool operator==(const Array<T> &someArray)const;
|
||||
DWORD size(void)const;
|
||||
void size(DWORD size);
|
||||
DWORD sizeBytes(void)const;
|
||||
private:
|
||||
void destroy(void);
|
||||
void create(DWORD elements);
|
||||
|
||||
T *mpArray;
|
||||
DWORD mElements;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
Array<T>::Array(void)
|
||||
: mpArray(0), mElements(0)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
Array<T>::Array(const Array<T> &someArray)
|
||||
: mpArray(0), mElements(0)
|
||||
{
|
||||
*this=someArray;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
Array<T>::~Array()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
T &Array<T>::operator[](DWORD index)
|
||||
{
|
||||
if(index>mElements)throw ArrayIndexOutOfBoundsException();
|
||||
return mpArray[index];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
Array<T> &Array<T>::operator=(const Array<T> &someArray)
|
||||
{
|
||||
destroy();
|
||||
if(!someArray.size())return *this;
|
||||
size(someArray.size());
|
||||
for(unsigned index=0;index<size();index++)operator[](index)=((Array<T>&)someArray)[index];
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
bool Array<T>::operator==(const Array<T> &someArray)const
|
||||
{
|
||||
if(!someArray.size()||(size()!=someArray.size()))return FALSE;
|
||||
for(int index=0;index<(int)size();index++)if(!(((Array<T>&)*this).operator[](index)==((Array<T>&)someArray)[index]))return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
DWORD Array<T>::sizeBytes(void)const
|
||||
{
|
||||
return mElements*sizeof(T);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
DWORD Array<T>::size(void)const
|
||||
{
|
||||
return mElements;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void Array<T>::size(DWORD size)
|
||||
{
|
||||
create(size);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
void Array<T>::destroy(void)
|
||||
{
|
||||
if(!mpArray)return;
|
||||
delete[] mpArray;
|
||||
mpArray=0;
|
||||
mElements=0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
void Array<T>::create(DWORD elements)
|
||||
{
|
||||
destroy();
|
||||
if(!elements)return;
|
||||
mpArray=new T[elements];
|
||||
if(0==mpArray)throw(NullError());
|
||||
mElements=elements;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
T &Array<T>::elementAt(DWORD index)
|
||||
{
|
||||
if(index>mElements)throw ArrayIndexOutOfBoundsException();
|
||||
return mpArray[index];
|
||||
}
|
||||
#endif
|
||||
173
common/block.hpp
Executable file
173
common/block.hpp
Executable file
@@ -0,0 +1,173 @@
|
||||
#ifndef _COMMON_BLOCK_HPP_
|
||||
#define _COMMON_BLOCK_HPP_
|
||||
#ifndef _COMMON_EXCEPTION_HPP_
|
||||
#include <common/except.hpp>
|
||||
#endif
|
||||
#ifndef _COMMON_WINDOWS_HPP_
|
||||
#include <common/windows.hpp>
|
||||
#endif
|
||||
#ifndef _COMMON_ARRAY_HPP_
|
||||
#include <common/array.hpp>
|
||||
#endif
|
||||
#ifndef _MSC_VER
|
||||
#ifdef _EXPAND_BLOCK_TEMPLATES_
|
||||
#pragma option -Jgd
|
||||
#endif
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
class Block;
|
||||
|
||||
template <class T>
|
||||
class Container
|
||||
{
|
||||
friend class Block<T>;
|
||||
public:
|
||||
Container<T> *next();
|
||||
void next(Container<T> *nextItem);
|
||||
Container<T> *prev();
|
||||
void prev(Container<T> *prevItem);
|
||||
private:
|
||||
Container *mNext;
|
||||
Container *mPrev;
|
||||
T *mItem;
|
||||
Container(void);
|
||||
virtual ~Container();
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class Block
|
||||
{
|
||||
public:
|
||||
class BlockBoundary{};
|
||||
typedef LONG Index;
|
||||
Block(void);
|
||||
Block(const Block<T> &someBlock);
|
||||
virtual ~Block(void);
|
||||
LONG size(void)const;
|
||||
void insert(const T& item);
|
||||
void insert(const T *item);
|
||||
bool insertAfter(Index itemIndex,const T *item);
|
||||
void insert(Block<T> &newBlock);
|
||||
void remove(void);
|
||||
void remove(const T *item);
|
||||
void remove(Block<T> &removeBlock);
|
||||
void remove(Index itemIndex);
|
||||
void toArray(Array<T> &array);
|
||||
Block<T> &operator=(const Block<T> &someBlock);
|
||||
WORD operator==(const Block<T> &someBlock)const;
|
||||
T &operator[](LONG itemIndex);
|
||||
Block<T> &operator+=(const Block<T> &someBlock);
|
||||
private:
|
||||
T &find(LONG itemIndex);
|
||||
LONG mSize;
|
||||
LONG mLastIndexReferenced;
|
||||
Container<T> *mLastObjectReferenced;
|
||||
Container<T> *mLastObjectInserted;
|
||||
Container<T> *mContainer;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
Block<T>::Block(void)
|
||||
: mContainer(0), mSize(0), mLastIndexReferenced(-1),
|
||||
mLastObjectReferenced(0), mLastObjectInserted(0)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
Block<T>::Block(const Block<T> &someBlock)
|
||||
: mContainer(0), mSize(0), mLastIndexReferenced(-1),
|
||||
mLastObjectReferenced(0), mLastObjectInserted(0)
|
||||
{
|
||||
*this=someBlock;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
Block<T>::~Block()
|
||||
{
|
||||
remove();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
LONG Block<T>::size(void)const
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
T & Block<T>::operator [](LONG itemIndex)
|
||||
{
|
||||
if(itemIndex>=mSize)throw(BoundaryError());
|
||||
if(!mContainer)return *((T*)0);
|
||||
else if(itemIndex==mLastIndexReferenced&&-1!=mLastIndexReferenced&&mLastObjectReferenced)return *mLastObjectReferenced->mItem;
|
||||
else if(itemIndex==mLastIndexReferenced+1&&-1!=mLastIndexReferenced)
|
||||
{
|
||||
mLastIndexReferenced++;
|
||||
mLastObjectReferenced=mLastObjectReferenced->next();
|
||||
return *mLastObjectReferenced->mItem;
|
||||
}
|
||||
return find(itemIndex);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
void Block<T>::toArray(Array<T> &array)
|
||||
{
|
||||
array.size(size());
|
||||
for(int index=0;index<size();index++)
|
||||
array[index]=operator[](index);
|
||||
}
|
||||
|
||||
// Container class methods
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
Container<T>::Container()
|
||||
: mNext(0), mPrev(0), mItem(0)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
Container<T>::~Container()
|
||||
{
|
||||
if(mItem)delete mItem;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
Container<T> *Container<T>::next(void)
|
||||
{
|
||||
return mNext;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
void Container<T>::next(Container<T> *nextItem)
|
||||
{
|
||||
mNext=nextItem;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
Container<T> *Container<T>::prev(void)
|
||||
{
|
||||
return mPrev;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
void Container<T>::prev(Container<T> *prevItem)
|
||||
{
|
||||
mPrev=prevItem;
|
||||
}
|
||||
#if defined(_MSC_VER)
|
||||
#include <common/block.tpp>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
185
common/block.tpp
Executable file
185
common/block.tpp
Executable file
@@ -0,0 +1,185 @@
|
||||
#ifndef _COMMON_BLOCK_TPP_
|
||||
#define _COMMON_BLOCK_TPP_
|
||||
|
||||
template <class T>
|
||||
void Block<T>::remove(void)
|
||||
{
|
||||
if(!mContainer)return;
|
||||
Container<T> *Cursor=mContainer;
|
||||
Container<T> *Thumb;
|
||||
while(Cursor)
|
||||
{
|
||||
Thumb=Cursor;
|
||||
Cursor=Cursor->next();
|
||||
::delete Thumb;
|
||||
}
|
||||
mContainer=0;
|
||||
mLastIndexReferenced=-1L;
|
||||
mLastObjectReferenced=0;
|
||||
mLastObjectInserted=0;
|
||||
mSize=0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T &Block<T>::find(LONG itemIndex)
|
||||
{
|
||||
Container<T> *lpCursor=mContainer;
|
||||
Index i=0;
|
||||
for(i=0;i<mSize&&i<itemIndex;i++)lpCursor=lpCursor->next();
|
||||
if(i==itemIndex)
|
||||
{
|
||||
mLastIndexReferenced=i;
|
||||
mLastObjectReferenced=lpCursor;
|
||||
return *lpCursor->mItem;
|
||||
}
|
||||
return *((T*)0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
Block<T> &Block<T>::operator+=(const Block<T> &someBlock)
|
||||
{
|
||||
size_t blockSize(someBlock.size());
|
||||
|
||||
if(!blockSize)return *this;
|
||||
for(int itemIndex=0;itemIndex<blockSize;itemIndex++)insert(&((Block<T>&)someBlock)[itemIndex]);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool Block<T>::insertAfter(Index itemIndex,const T *item)
|
||||
{
|
||||
if(itemIndex>=mSize)return false;
|
||||
mLastObjectInserted->next(::new Container<T>);
|
||||
mLastObjectInserted->next()->prev(mLastObjectInserted);
|
||||
mLastObjectInserted=mLastObjectInserted->next();
|
||||
mLastObjectInserted->mItem=::new T();
|
||||
mSize++;
|
||||
for(int index=mSize-1;index>itemIndex+1;index--)
|
||||
{
|
||||
operator[](index)=operator[](index-1);
|
||||
}
|
||||
operator[](itemIndex+1)=*item;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void Block<T>::insert(Block<T> &newBlock)
|
||||
{
|
||||
LONG size(newBlock.size());
|
||||
for(Index i=0;i<size;i++)insert(&newBlock[i]);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void Block<T>::insert(const T& item)
|
||||
{
|
||||
insert(&item);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void Block<T>::insert(const T *item)
|
||||
{
|
||||
if(!mContainer)
|
||||
{
|
||||
mContainer=::new Container<T>;
|
||||
mContainer->mItem=::new T(*item);
|
||||
mLastObjectInserted=mContainer;
|
||||
mSize++;
|
||||
}
|
||||
else
|
||||
{
|
||||
mLastObjectInserted->next(::new Container<T>);
|
||||
mLastObjectInserted->next()->prev(mLastObjectInserted);
|
||||
mLastObjectInserted=mLastObjectInserted->next();
|
||||
mLastObjectInserted->mItem=::new T(*item);
|
||||
mSize++;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void Block<T>::remove(Block<T> &removeBlock)
|
||||
{
|
||||
LONG size(removeBlock.size());
|
||||
|
||||
if(!size)return;
|
||||
for(long itemIndex=size-1;itemIndex>=0;itemIndex--)remove(&removeBlock[itemIndex]);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void Block<T>::remove(const T *item)
|
||||
{
|
||||
Container<T> *lpThumb=mContainer;
|
||||
|
||||
if(!lpThumb)return;
|
||||
if(*item==*(mLastObjectInserted->mItem))lpThumb=mLastObjectInserted;
|
||||
else while(lpThumb){if(*item==*(lpThumb->mItem))break;lpThumb=lpThumb->next();}
|
||||
if(!lpThumb)return;
|
||||
if(lpThumb==mContainer)
|
||||
{
|
||||
if(lpThumb->next()){mContainer=lpThumb->next();mContainer->prev(0);}
|
||||
else {mContainer=0;mLastObjectInserted=0;}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(lpThumb->next()){lpThumb->prev()->next(lpThumb->next());lpThumb->next()->prev(lpThumb->prev());}
|
||||
else {lpThumb->prev()->next(0);mLastObjectInserted=lpThumb->prev();}
|
||||
}
|
||||
::delete lpThumb;
|
||||
mSize--;
|
||||
mLastIndexReferenced=-1;
|
||||
mLastObjectReferenced=0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void Block<T>::remove(LONG itemIndex)
|
||||
{
|
||||
Container<T> *lpThumb=mContainer;
|
||||
|
||||
if(!lpThumb||itemIndex>=mSize)return;
|
||||
if(itemIndex==mSize-1)lpThumb=mLastObjectInserted;
|
||||
else
|
||||
{
|
||||
for(Index i=0;i<itemIndex&&lpThumb;i++)
|
||||
{
|
||||
if(itemIndex==i)break;
|
||||
lpThumb=lpThumb->next();
|
||||
}
|
||||
if(!lpThumb)return;
|
||||
}
|
||||
if(lpThumb==mContainer)
|
||||
{
|
||||
if(lpThumb->next()){mContainer=lpThumb->next();mContainer->prev(0);}
|
||||
else {mContainer=0;mLastObjectInserted=0;}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(lpThumb->next()){lpThumb->prev()->next(lpThumb->next());lpThumb->next()->prev(lpThumb->prev());}
|
||||
else {lpThumb->prev()->next(0);mLastObjectInserted=lpThumb->prev();}
|
||||
}
|
||||
::delete lpThumb;
|
||||
mSize--;
|
||||
mLastIndexReferenced=-1;
|
||||
mLastObjectReferenced=0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
Block<T> &Block<T>::operator=(const Block<T> &someBlock)
|
||||
{
|
||||
LONG itemCount(someBlock.size());
|
||||
|
||||
remove();
|
||||
if(!itemCount)return *this;
|
||||
for(LONG itemIndex=0;itemIndex<itemCount;itemIndex++)insert(&(((Block<T>&)someBlock)[itemIndex]));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
WORD Block<T>::operator==(const Block<T> &someBlock)const
|
||||
{
|
||||
LONG itemCount(size());
|
||||
|
||||
if(itemCount!=someBlock.size())return FALSE;
|
||||
for(LONG itemIndex=0;itemIndex<itemCount;itemIndex++)
|
||||
if(!(((Block<T>&)*this).operator[](itemIndex)==((Block<T>&)someBlock)[itemIndex]))return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
50
common/except.hpp
Executable file
50
common/except.hpp
Executable file
@@ -0,0 +1,50 @@
|
||||
#ifndef _COMMON_EXCEPTION_HPP_
|
||||
#define _COMMON_EXCEPTION_HPP_
|
||||
#ifndef _COMMON_STRING_HPP_
|
||||
#include <common/string.hpp>
|
||||
#endif
|
||||
|
||||
class Exception
|
||||
{
|
||||
public:
|
||||
Exception(){mReason="";}
|
||||
Exception(const String &reason){mReason=reason;}
|
||||
virtual ~Exception(){;}
|
||||
virtual String toString(){return mReason;}
|
||||
const String &getReason(void)const{return mReason;};
|
||||
private:
|
||||
String mReason;
|
||||
};
|
||||
|
||||
class BoundaryError : public Exception
|
||||
{
|
||||
public :
|
||||
String toString(){return "BoundaryError";}
|
||||
};
|
||||
|
||||
class NullError : public Exception
|
||||
{
|
||||
public :
|
||||
String toString(){return "NullError";}
|
||||
};
|
||||
|
||||
class ArrayIndexOutOfBoundsException : public Exception
|
||||
{
|
||||
public :
|
||||
String toString(){return "ArrayIndexOutOfBounds";}
|
||||
};
|
||||
|
||||
class LibraryNotFoundException : public Exception
|
||||
{
|
||||
public:
|
||||
LibraryNotFoundException(const String &reason="LibraryNotFoundException"):Exception(reason){;}
|
||||
String toString(){return getReason();}
|
||||
};
|
||||
|
||||
class InvalidStateException : public Exception
|
||||
{
|
||||
public:
|
||||
InvalidStateException(const String &reason="InvalidStateException"):Exception(reason){;}
|
||||
String toString(){return getReason();}
|
||||
};
|
||||
#endif
|
||||
239
common/fileio.cpp
Executable file
239
common/fileio.cpp
Executable file
@@ -0,0 +1,239 @@
|
||||
#include <common/fileio.hpp>
|
||||
#include <common/pointer.hpp>
|
||||
|
||||
FileIO::FileIO(void)
|
||||
: mlpFilePointer(0), mByteOrder(LittleEndian)
|
||||
{
|
||||
}
|
||||
|
||||
FileIO::FileIO(String pathFileName,ByteOrder byteOrder,Mode openMode,CreationFlags creationFlags)
|
||||
: mlpFilePointer(0) , mByteOrder(byteOrder)
|
||||
{
|
||||
open(pathFileName,byteOrder,openMode,creationFlags);
|
||||
}
|
||||
|
||||
FileIO::~FileIO()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
bool FileIO::close(void)
|
||||
{
|
||||
if(!mlpFilePointer)return false;
|
||||
::fclose(mlpFilePointer);
|
||||
mlpFilePointer=0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileIO::open(String pathFileName,ByteOrder byteOrder,Mode openMode,CreationFlags creationFlags)
|
||||
{
|
||||
close();
|
||||
if(pathFileName.isNull())return false;
|
||||
mByteOrder=byteOrder;
|
||||
if(ReadOnly==openMode)
|
||||
{
|
||||
mlpFilePointer=::fopen(pathFileName,"rb");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(CreateAlways==creationFlags)mlpFilePointer=::fopen(pathFileName,"w+b");
|
||||
else if(Create==creationFlags)mlpFilePointer=::fopen(pathFileName,"a+b");
|
||||
else mlpFilePointer=::fopen(pathFileName,"r+b");
|
||||
}
|
||||
if(!mlpFilePointer)return false;
|
||||
setBufferLength(BufferLength);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileIO::setBufferLength(DWORD length)
|
||||
{
|
||||
if(!isOkay())return false;
|
||||
return !::setvbuf(mlpFilePointer, 0, _IOFBF, length);
|
||||
}
|
||||
|
||||
bool FileIO::peek(BYTE &value)
|
||||
{
|
||||
if(!isOkay())return false;
|
||||
read(value);
|
||||
seek(tell()-1,SeekCurrent);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileIO::read(WORD &value)
|
||||
{
|
||||
BYTE byteValue;
|
||||
|
||||
if(!isOkay())return false;
|
||||
if(!read(byteValue))return false;
|
||||
value=byteValue;
|
||||
if(!read(byteValue))return false;
|
||||
value|=((WORD)byteValue)<<8;
|
||||
if(BigEndian==mByteOrder)value=Intel::intelData(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileIO::read(DWORD &value)
|
||||
{
|
||||
WORD wordValue;
|
||||
|
||||
if(!isOkay())return false;
|
||||
if(!read(wordValue))return false;
|
||||
value=wordValue;
|
||||
if(!read(wordValue))return false;
|
||||
value|=((DWORD)wordValue)<<16;
|
||||
if(BigEndian==mByteOrder)value=Intel::intelData(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t FileIO::read(char *lpBuffer,DWORD lengthData)
|
||||
{
|
||||
BYTE byteValue(0);
|
||||
|
||||
if(!isOkay()||!lpBuffer)return false;
|
||||
size_t result = ::fread(lpBuffer,1,lengthData,mlpFilePointer);
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t FileIO::read(char *lpBuffer,DWORD lengthData,int stopChar)
|
||||
{
|
||||
BYTE tempChar;
|
||||
int bytesRead;
|
||||
|
||||
if(!isOkay()||!lpBuffer||!lengthData)return false;
|
||||
for(bytesRead=0;bytesRead<lengthData-1;bytesRead++)
|
||||
{
|
||||
if(!read(tempChar))return false;
|
||||
if(tempChar==stopChar)break;
|
||||
*(lpBuffer++)=tempChar;
|
||||
}
|
||||
*(lpBuffer)=0;
|
||||
if(!bytesRead)return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileIO::write(char *lpBuffer,DWORD lengthData)
|
||||
{
|
||||
if(!isOkay()||!lpBuffer||!lengthData)return false;
|
||||
if(1!=::fwrite(lpBuffer,1,lengthData,mlpFilePointer))return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOL FileIO::readLine(String &lineString)
|
||||
{
|
||||
BYTE charByte;
|
||||
BYTE *ptrLine;
|
||||
DWORD bytesRead(0);
|
||||
DWORD actualBytesRead(0);
|
||||
BOOL returnCode(false);
|
||||
|
||||
lineString.reserve(adaptiveBlockLength,false);
|
||||
ptrLine=(BYTE*)(char*)lineString;
|
||||
while(TRUE)
|
||||
{
|
||||
if(eof())break;
|
||||
if(!read(charByte))break;
|
||||
actualBytesRead++;
|
||||
if(bytesRead>=adaptiveBlockLength-1)
|
||||
{
|
||||
*ptrLine=0;
|
||||
String tmpString(lineString);
|
||||
int nextIndex(ptrLine-(BYTE*)(char*)lineString);
|
||||
lineString.reserve(adaptiveBlockLength+BlockIncrement,false);
|
||||
::memcpy((char*)lineString,(char*)tmpString,adaptiveBlockLength);
|
||||
adaptiveBlockLength+=BlockIncrement;
|
||||
ptrLine=(BYTE*)(char*)lineString+nextIndex;
|
||||
}
|
||||
if(CarriageReturn==charByte)
|
||||
{
|
||||
if(!read(charByte))break;
|
||||
if(LineFeed==charByte)
|
||||
{
|
||||
*ptrLine=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(LineFeed==charByte)
|
||||
{
|
||||
*ptrLine++=0;
|
||||
break;
|
||||
}
|
||||
else if(NullChar==charByte)
|
||||
{
|
||||
*ptrLine++=0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptrLine++=charByte;
|
||||
bytesRead++;
|
||||
}
|
||||
}
|
||||
return actualBytesRead>0;
|
||||
}
|
||||
|
||||
bool FileIO::write(WORD value)
|
||||
{
|
||||
BYTE byteValue;
|
||||
|
||||
if(!isOkay())return false;
|
||||
if(BigEndian==mByteOrder)value=Intel::intelData(value);
|
||||
byteValue=(BYTE)(value&0x00FF);
|
||||
if(!write(byteValue))return false;
|
||||
byteValue=(BYTE)(value>>8);
|
||||
if(!write(byteValue))return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileIO::write(DWORD value)
|
||||
{
|
||||
WORD wordValue;
|
||||
|
||||
if(!isOkay())return false;
|
||||
if(BigEndian==mByteOrder)
|
||||
{
|
||||
WORD hiWord(HIWORD(value));
|
||||
WORD loWord(LOWORD(value));
|
||||
|
||||
value=((DWORD)Intel::intelData(loWord))<<16;
|
||||
value|=Intel::intelData(hiWord);
|
||||
if(!write((char*)&value,sizeof(value)))return false;
|
||||
return true;
|
||||
}
|
||||
wordValue=(WORD)(value&0xFFFF);
|
||||
if(!write(wordValue))return false;
|
||||
wordValue=(WORD)(value>>16);
|
||||
if(!write(wordValue))return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileIO::writeLine(const String &strLine)
|
||||
{
|
||||
if(!isOkay()||strLine.isNull())return false;
|
||||
if(!write((char*)(String&)strLine,strLine.length()))return false;
|
||||
return write((char*)"\r\n",2);
|
||||
}
|
||||
|
||||
bool FileIO::rewind(void)
|
||||
{
|
||||
if(!isOkay())return false;
|
||||
return (!::fseek(mlpFilePointer,0,SEEK_SET));
|
||||
}
|
||||
|
||||
FileIO &FileIO::operator++(void)
|
||||
{
|
||||
seek(1L,SeekCurrent);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileIO &FileIO::operator--(void)
|
||||
{
|
||||
seek(-1L,SeekCurrent);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool FileIO::seek(LONG seekOffset,SeekFrom seekFrom)
|
||||
{
|
||||
if(!isOkay())return false;
|
||||
return 0==::fseek(mlpFilePointer,seekOffset,seekFrom)?true:false;
|
||||
}
|
||||
|
||||
128
common/fileio.hpp
Executable file
128
common/fileio.hpp
Executable file
@@ -0,0 +1,128 @@
|
||||
#ifndef _COMMON_FILEIO_HPP_
|
||||
#define _COMMON_FILEIO_HPP_
|
||||
#ifndef _COMMON_WINDOWS_HPP_
|
||||
#include <common/windows.hpp>
|
||||
#endif
|
||||
#ifndef _COMMON_STRING_HPP_
|
||||
#include <common/string.hpp>
|
||||
#endif
|
||||
#ifndef _COMMON_STDIO_HPP_
|
||||
#include <common/stdio.hpp>
|
||||
#endif
|
||||
#ifndef _COMMON_INTEL_HPP_
|
||||
#include <common/intel.hpp>
|
||||
#endif
|
||||
|
||||
#pragma warning( disable : 26812)
|
||||
|
||||
// Optimized for fast reading of files.
|
||||
|
||||
class FileIO
|
||||
{
|
||||
public:
|
||||
enum Mode{ReadOnly,ReadWrite};
|
||||
enum ByteOrder{BigEndian,LittleEndian};
|
||||
enum SeekFrom{SeekCurrent=SEEK_CUR,SeekEnd=SEEK_END,SeekBeginning=SEEK_SET};
|
||||
enum CreationFlags{Create,CreateAlways,None};
|
||||
FileIO(void);
|
||||
FileIO(String pathFileName,ByteOrder byteOrder=LittleEndian,Mode openMode=ReadOnly,CreationFlags creationFlags=None);
|
||||
virtual ~FileIO();
|
||||
bool open(String pathFileName,ByteOrder byteOrder=LittleEndian,Mode openMode=ReadOnly,CreationFlags creationFlags=None);
|
||||
bool close(void);
|
||||
bool rewind(void);
|
||||
bool peek(BYTE &value);
|
||||
bool read(BYTE &value);
|
||||
bool read(WORD &value);
|
||||
bool read(DWORD &value);
|
||||
size_t read(char *lpBuffer,DWORD lengthData);
|
||||
size_t read(BYTE *lpBuffer,DWORD lengthData);
|
||||
size_t read(char *lpBuffer,DWORD lengthData,int stopChar);
|
||||
bool eof(void)const;
|
||||
bool setBufferLength(DWORD length);
|
||||
bool write(BYTE value);
|
||||
bool write(WORD value);
|
||||
bool write(DWORD value);
|
||||
bool write(char *lpBuffer,DWORD lengthData);
|
||||
FileIO &operator++(void);
|
||||
FileIO &operator--(void);
|
||||
bool seek(LONG seekOffset,SeekFrom seekFrom);
|
||||
BOOL readLine(String &lineString);
|
||||
bool writeLine(const String &strLine);
|
||||
bool isOkay(void)const;
|
||||
DWORD tell(void)const;
|
||||
ByteOrder getByteOrder(void)const;
|
||||
void setByteOrder(ByteOrder byteOrder);
|
||||
DWORD size(void);
|
||||
private:
|
||||
enum {CarriageReturn=0x0D,LineFeed=0x0A,NullChar=0x00};
|
||||
enum {BufferLength=65536}; // This is for the file stream
|
||||
enum {InitialBlockLength=65536,BlockIncrement=65536}; // This is for readLine
|
||||
FILE *mlpFilePointer;
|
||||
ByteOrder mByteOrder;
|
||||
DWORD adaptiveBlockLength=InitialBlockLength; // This is for readLine
|
||||
};
|
||||
|
||||
inline
|
||||
bool FileIO::isOkay(void)const
|
||||
{
|
||||
return (mlpFilePointer?true:false);
|
||||
}
|
||||
|
||||
inline
|
||||
DWORD FileIO::tell(void)const
|
||||
{
|
||||
if(!isOkay())return false;
|
||||
return ::ftell(mlpFilePointer);
|
||||
}
|
||||
|
||||
inline
|
||||
bool FileIO::eof(void)const
|
||||
{
|
||||
if(!isOkay())return true;
|
||||
return ::feof(mlpFilePointer);
|
||||
}
|
||||
|
||||
inline
|
||||
bool FileIO::read(BYTE &value)
|
||||
{
|
||||
if(!isOkay())return false;
|
||||
return (sizeof(value)==::fread(&value,1,1,mlpFilePointer)?true:false);
|
||||
}
|
||||
|
||||
inline
|
||||
size_t FileIO::read(BYTE *lpBuffer,DWORD lengthData)
|
||||
{
|
||||
return read((char*)lpBuffer,lengthData);
|
||||
}
|
||||
|
||||
inline
|
||||
bool FileIO::write(BYTE value)
|
||||
{
|
||||
if(!isOkay())return false;
|
||||
if(1!=::fwrite(&value,1,1,mlpFilePointer))return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline
|
||||
FileIO::ByteOrder FileIO::getByteOrder(void)const
|
||||
{
|
||||
return mByteOrder;
|
||||
}
|
||||
|
||||
inline
|
||||
void FileIO::setByteOrder(ByteOrder byteOrder)
|
||||
{
|
||||
mByteOrder=byteOrder;
|
||||
}
|
||||
|
||||
inline
|
||||
DWORD FileIO::size(void)
|
||||
{
|
||||
DWORD currentPosition = tell();
|
||||
seek(0,FileIO::SeekFrom::SeekEnd);
|
||||
DWORD lastPosition = tell();
|
||||
seek(currentPosition, FileIO::SeekFrom::SeekBeginning);
|
||||
return lastPosition-currentPosition;
|
||||
}
|
||||
|
||||
#endif
|
||||
21
common/intel.cpp
Executable file
21
common/intel.cpp
Executable file
@@ -0,0 +1,21 @@
|
||||
#include <common/intel.hpp>
|
||||
|
||||
WORD Intel::intelData(WORD someData)
|
||||
{
|
||||
WORD tempData(someData);
|
||||
|
||||
someData>>=8;
|
||||
someData+=tempData<<8;
|
||||
return someData;
|
||||
}
|
||||
|
||||
DWORD Intel::intelData(DWORD someData)
|
||||
{
|
||||
WORD tempDataHi(HIWORD(someData));
|
||||
WORD tempDataLo(LOWORD(someData));
|
||||
|
||||
someData=tempDataLo;
|
||||
someData<<=16;
|
||||
someData|=tempDataHi;
|
||||
return someData;
|
||||
}
|
||||
26
common/intel.hpp
Executable file
26
common/intel.hpp
Executable file
@@ -0,0 +1,26 @@
|
||||
#ifndef _COMMON_INTEL_HPP_
|
||||
#define _COMMON_INTEL_HPP_
|
||||
#ifndef _COMMON_WINDOWS_HPP_
|
||||
#include <common/windows.hpp>
|
||||
#endif
|
||||
|
||||
class Intel
|
||||
{
|
||||
public:
|
||||
Intel(void);
|
||||
virtual ~Intel();
|
||||
static WORD intelData(WORD someData);
|
||||
static DWORD intelData(DWORD someData);
|
||||
private:
|
||||
};
|
||||
|
||||
inline
|
||||
Intel::Intel(void)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Intel::~Intel()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
74
common/mmap.cpp
Normal file
74
common/mmap.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
#include <common/mmap.hpp>
|
||||
#include <common/except.hpp>
|
||||
|
||||
bool MemoryMappedFile::open(const String& pathFileName,CreationFlags creationFlags)
|
||||
{
|
||||
if(isOkay())
|
||||
{
|
||||
close();
|
||||
}
|
||||
mFD=::open(pathFileName,getFileAccessFromFlags(creationFlags));
|
||||
mCreationFlags= creationFlags;
|
||||
if(!isOkay())return false;
|
||||
struct stat sb;
|
||||
if(-1==::fstat(mFD,&sb))
|
||||
{
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
mFileLength = sb.st_size;
|
||||
if(!createMemoryMap())
|
||||
{
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MemoryMappedFile::createMemoryMap(void)
|
||||
{
|
||||
void *pAddress = ::mmap(NULL,mFileLength,getMemoryMapAccessFromFlags(mCreationFlags),mCreationFlags == CreationFlags::ReadOnly?MAP_PRIVATE:MAP_SHARED,mFD,0);
|
||||
if(MAP_FAILED == pAddress)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
mlpMappedDataBase = (char *)pAddress;
|
||||
mIndex=0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void MemoryMappedFile::close()
|
||||
{
|
||||
if(!isOkay())return;
|
||||
::munmap((void*)mlpMappedDataBase, mFileLength);
|
||||
::close(mFD);
|
||||
mFD=-1;
|
||||
mFileLength=-1;
|
||||
}
|
||||
|
||||
int MemoryMappedFile::getFileAccessFromFlags(CreationFlags creationFlags)const
|
||||
{
|
||||
switch(creationFlags)
|
||||
{
|
||||
case ReadOnly :
|
||||
return O_RDONLY | S_IRUSR ;
|
||||
case ReadWrite :
|
||||
return O_RDWR | O_CREAT, S_IRUSR | S_IWUSR;
|
||||
default :
|
||||
throw new Exception("Undefined creation flag");
|
||||
}
|
||||
}
|
||||
|
||||
int MemoryMappedFile::getMemoryMapAccessFromFlags(CreationFlags creationFlags)const
|
||||
{
|
||||
switch(creationFlags)
|
||||
{
|
||||
case ReadOnly :
|
||||
return PROT_READ;
|
||||
case ReadWrite :
|
||||
return PROT_READ | PROT_WRITE;
|
||||
default :
|
||||
throw new Exception("Undefined creation flag");
|
||||
}
|
||||
}
|
||||
|
||||
96
common/mmap.hpp
Normal file
96
common/mmap.hpp
Normal file
@@ -0,0 +1,96 @@
|
||||
#ifndef _COMMON_MMAP_HPP_
|
||||
#define _COMMON_MMAP_HPP_
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
#include <sys/mman.h>
|
||||
#include <common/string.hpp>
|
||||
|
||||
class MemoryMappedFile
|
||||
{
|
||||
public:
|
||||
enum CreationFlags{ReadOnly,ReadWrite};
|
||||
MemoryMappedFile(const String& pathFileName,CreationFlags creationFlags);
|
||||
virtual ~MemoryMappedFile();
|
||||
bool open(const String& pathFileName,CreationFlags creationFlags);
|
||||
bool readLine(String &strLine);
|
||||
char readChar(void);
|
||||
bool eof(void);
|
||||
char peekChar(void);
|
||||
void close(void);
|
||||
bool isOkay(void);
|
||||
off_t tell(void);
|
||||
private:
|
||||
enum {CarriageReturn=0x0D,LineFeed=0x0A,NullChar=0x00};
|
||||
enum {BlockSize=65536};
|
||||
bool createMemoryMap(void);
|
||||
int getFileAccessFromFlags(CreationFlags creationFlags)const;
|
||||
int getMemoryMapAccessFromFlags(CreationFlags creationFlags)const;
|
||||
|
||||
int mFD = -1;
|
||||
unsigned long mIndex;
|
||||
off_t mFileLength = -1;
|
||||
char *mlpMappedDataBase = 0;
|
||||
CreationFlags mCreationFlags;
|
||||
};
|
||||
|
||||
/// @brief
|
||||
/// @param pathFileName
|
||||
/// @param access
|
||||
inline
|
||||
MemoryMappedFile::MemoryMappedFile(const String& pathFileName,CreationFlags creationFlags)
|
||||
{
|
||||
open(pathFileName, creationFlags);
|
||||
}
|
||||
|
||||
inline
|
||||
MemoryMappedFile::~MemoryMappedFile()
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
char MemoryMappedFile::readChar()
|
||||
{
|
||||
return mlpMappedDataBase[mIndex++];
|
||||
}
|
||||
|
||||
inline
|
||||
bool MemoryMappedFile::eof()
|
||||
{
|
||||
return mIndex<mFileLength?false:true;
|
||||
}
|
||||
|
||||
inline
|
||||
char MemoryMappedFile::peekChar()
|
||||
{
|
||||
return mlpMappedDataBase[mIndex];
|
||||
}
|
||||
|
||||
inline
|
||||
off_t MemoryMappedFile::tell(void)
|
||||
{
|
||||
return mIndex;
|
||||
}
|
||||
|
||||
inline
|
||||
bool MemoryMappedFile::readLine(String &strLine)
|
||||
{
|
||||
off_t beginPosition = mIndex;
|
||||
while(mIndex<mFileLength && !(LineFeed==mlpMappedDataBase[mIndex++]));
|
||||
off_t currentPosition = mIndex;
|
||||
if(beginPosition==currentPosition)return false;
|
||||
off_t length = (currentPosition - beginPosition) -1;
|
||||
strLine.reserve(length<<1,0);
|
||||
::memcpy((char*)strLine,mlpMappedDataBase+beginPosition,length);
|
||||
*((char*)strLine+length)=0;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline
|
||||
bool MemoryMappedFile::isOkay(void)
|
||||
{
|
||||
return -1==mFD?false:true;
|
||||
}
|
||||
|
||||
#endif
|
||||
159
common/pointer.hpp
Executable file
159
common/pointer.hpp
Executable file
@@ -0,0 +1,159 @@
|
||||
#ifndef _COMMON_SMARTPOINTER_HPP_
|
||||
#define _COMMON_SMARTPOINTER_HPP_
|
||||
#ifndef _COMMON_WINDOWS_HPP_
|
||||
#include <common/windows.hpp>
|
||||
#endif
|
||||
|
||||
class PointerDisposition
|
||||
{
|
||||
public:
|
||||
enum Disposition{Assume,Delete};
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class SmartPointer
|
||||
{
|
||||
public:
|
||||
SmartPointer(void);
|
||||
SmartPointer(T FAR *lpSmartPointer,PointerDisposition::Disposition disposition=PointerDisposition::Assume);
|
||||
SmartPointer(const SmartPointer<T> &someSmartPointer);
|
||||
virtual ~SmartPointer();
|
||||
T FAR *operator->(void);
|
||||
operator T FAR *(void);
|
||||
operator LPARAM(void);
|
||||
SmartPointer<T> &operator=(const SmartPointer<T> &someSmartPointer);
|
||||
SmartPointer<T> &operator=(T FAR *lpSmartPointer);
|
||||
WORD operator==(const SmartPointer<T> &someSmartPointer)const;
|
||||
void disposition(PointerDisposition::Disposition disposition);
|
||||
PointerDisposition::Disposition disposition(void)const;
|
||||
void destroy(void);
|
||||
bool isOkay(void)const;
|
||||
bool isNull(void)const;
|
||||
protected:
|
||||
T **ppt(void);
|
||||
private:
|
||||
T FAR *mlpSmartPointer;
|
||||
PointerDisposition::Disposition mDisposition;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
SmartPointer<T>::SmartPointer(void)
|
||||
: mlpSmartPointer(0), mDisposition(PointerDisposition::Assume)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
SmartPointer<T>::SmartPointer(T FAR *lpSmartPointer,PointerDisposition::Disposition disposition)
|
||||
: mlpSmartPointer(lpSmartPointer), mDisposition(disposition)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
SmartPointer<T>::SmartPointer(const SmartPointer<T> &someSmartPointer)
|
||||
: mlpSmartPointer(0), mDisposition(PointerDisposition::Assume)
|
||||
{
|
||||
*this=someSmartPointer;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
SmartPointer<T>::~SmartPointer()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
SmartPointer<T>::operator T FAR *(void)
|
||||
{
|
||||
return mlpSmartPointer;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
T **SmartPointer<T>::ppt(void)
|
||||
{
|
||||
return &mlpSmartPointer;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
SmartPointer<T>::operator LPARAM(void)
|
||||
{
|
||||
return (LPARAM)mlpSmartPointer;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
T FAR *SmartPointer<T>::operator->(void)
|
||||
{
|
||||
return mlpSmartPointer;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
SmartPointer<T> &SmartPointer<T>::operator=(const SmartPointer<T> &someSmartPointer)
|
||||
{
|
||||
destroy();
|
||||
mlpSmartPointer=someSmartPointer.mlpSmartPointer;
|
||||
mDisposition=PointerDisposition::Assume;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
SmartPointer<T> &SmartPointer<T>::operator=(T FAR *lpSmartPointer)
|
||||
{
|
||||
destroy();
|
||||
mlpSmartPointer=lpSmartPointer;
|
||||
mDisposition=PointerDisposition::Assume;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
WORD SmartPointer<T>::operator==(const SmartPointer<T> &someSmartPointer)const
|
||||
{
|
||||
return *mlpSmartPointer==*someSmartPointer.mlpSmartPointer;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
void SmartPointer<T>::destroy(void)
|
||||
{
|
||||
if(!mlpSmartPointer)return;
|
||||
if(PointerDisposition::Assume==mDisposition)mlpSmartPointer=0;
|
||||
else {::delete mlpSmartPointer;mlpSmartPointer=0;}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
void SmartPointer<T>::disposition(PointerDisposition::Disposition disposition)
|
||||
{
|
||||
mDisposition=disposition;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
PointerDisposition::Disposition SmartPointer<T>::disposition(void)const
|
||||
{
|
||||
return mDisposition;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
bool SmartPointer<T>::isNull(void)const
|
||||
{
|
||||
return (mlpSmartPointer?FALSE:TRUE);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline
|
||||
bool SmartPointer<T>::isOkay(void)const
|
||||
{
|
||||
return !isNull();
|
||||
}
|
||||
#endif
|
||||
46
common/profiler.hpp
Normal file
46
common/profiler.hpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef _COMMON_PROFILER_HPP_
|
||||
#define _COMMON_PROFILER_HPP_
|
||||
#include <chrono>
|
||||
|
||||
class Profiler
|
||||
{
|
||||
public:
|
||||
Profiler();
|
||||
virtual ~Profiler();
|
||||
void start(void);
|
||||
long end(void);
|
||||
long elapsed(void);
|
||||
private:
|
||||
std::chrono::_V2::system_clock::time_point start_time = std::chrono::high_resolution_clock::now();
|
||||
};
|
||||
|
||||
inline
|
||||
Profiler::Profiler()
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Profiler::~Profiler()
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
void Profiler::start(void)
|
||||
{
|
||||
start_time = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
inline
|
||||
long Profiler::end(void)
|
||||
{
|
||||
std::chrono::_V2::system_clock::time_point end_time = std::chrono::high_resolution_clock::now();
|
||||
long elapsed_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count();
|
||||
return elapsed_time_ms;
|
||||
}
|
||||
|
||||
inline
|
||||
long Profiler::elapsed(void)
|
||||
{
|
||||
return end();
|
||||
}
|
||||
#endif
|
||||
4
common/stdio.hpp
Executable file
4
common/stdio.hpp
Executable file
@@ -0,0 +1,4 @@
|
||||
#ifndef _COMMON_STDIO_HPP_
|
||||
#define _COMMON_STDIO_HPP_
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
4
common/stdlib.hpp
Executable file
4
common/stdlib.hpp
Executable file
@@ -0,0 +1,4 @@
|
||||
#ifndef _COMMON_STDLIB_HPP_
|
||||
#define _COMMON_STDLIB_HPP_
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
705
common/string.cpp
Executable file
705
common/string.cpp
Executable file
@@ -0,0 +1,705 @@
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <common/string.hpp>
|
||||
#include <common/block.hpp>
|
||||
#include <common/array.hpp>
|
||||
|
||||
String::String(const char *npStr)
|
||||
: mnpStr(0), mLengthBytes(0)
|
||||
{
|
||||
DWORD stringLength;
|
||||
|
||||
if(!npStr)return;
|
||||
try{stringLength=::strlen(npStr);}
|
||||
catch(...){{stringLength=0;}}
|
||||
if(!stringLength)return;
|
||||
stringLength++;
|
||||
reserve(stringLength,FALSE);
|
||||
::strcpy(mnpStr,npStr);
|
||||
}
|
||||
|
||||
String::String(const wchar_t* npWideString, int length)
|
||||
: mnpStr(0), mLengthBytes(0)
|
||||
{
|
||||
if (!npWideString || 0 == length)return;
|
||||
reserve(length);
|
||||
for (wchar_t index = 0;index < length;index++)
|
||||
{
|
||||
char character = (char)((npWideString[index]<<8)>>8);
|
||||
operator[](index) = character;
|
||||
}
|
||||
}
|
||||
|
||||
String::String(const String &newString)
|
||||
: mnpStr(0), mLengthBytes(0)
|
||||
{
|
||||
DWORD stringLength;
|
||||
|
||||
if(!newString.mnpStr)return;
|
||||
if(!(stringLength=newString.length()))return;
|
||||
stringLength++;
|
||||
reserve(stringLength,FALSE);
|
||||
::strcpy(mnpStr,newString.mnpStr);
|
||||
}
|
||||
|
||||
String &String::operator=(const String &someString)
|
||||
{
|
||||
int stringLength;
|
||||
|
||||
if(this==&someString)return *this;
|
||||
if(someString.isNull()){removeData();return *this;}
|
||||
if(!(stringLength=::strlen(someString.mnpStr)))return *this;
|
||||
stringLength++;
|
||||
if(lengthBytes()>=stringLength)::strcpy(mnpStr,someString.mnpStr);
|
||||
else {reserve(stringLength,FALSE);::strcpy(mnpStr,someString.mnpStr);}
|
||||
return *this;
|
||||
}
|
||||
|
||||
int String::operator=(const char *someCharStar)
|
||||
{
|
||||
int stringLength;
|
||||
|
||||
if(!someCharStar)return 0;
|
||||
if(!(stringLength=::strlen(someCharStar)))return 0;
|
||||
stringLength++;
|
||||
if(lengthBytes()>=stringLength)::strcpy(mnpStr,someCharStar);
|
||||
else {reserve(stringLength,FALSE);::strcpy(mnpStr,someCharStar);}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void String::operator+=(char someChar)
|
||||
{
|
||||
DWORD strLength(length());
|
||||
if(strLength+2>mLengthBytes)
|
||||
{
|
||||
String tmpString(someChar);
|
||||
*this+=tmpString;
|
||||
return;
|
||||
}
|
||||
*(mnpStr+strLength)=someChar;
|
||||
*(mnpStr+strLength+1)=0;
|
||||
}
|
||||
|
||||
int String::operator+=(const String &someString)
|
||||
{
|
||||
char *lpString;
|
||||
DWORD currLength;
|
||||
DWORD stringLength;
|
||||
|
||||
if(!someString.mnpStr)return 0;
|
||||
stringLength=someString.length();
|
||||
stringLength++;
|
||||
if(!mnpStr)
|
||||
{
|
||||
reserve(stringLength,FALSE);
|
||||
::strcpy(mnpStr,someString.mnpStr);
|
||||
return 1;
|
||||
}
|
||||
currLength=::strlen(mnpStr);
|
||||
if(lengthBytes()-currLength>=stringLength)
|
||||
{
|
||||
::strcat(mnpStr,someString.mnpStr);
|
||||
return 1;
|
||||
}
|
||||
lpString=mnpStr;
|
||||
mnpStr=::new char[currLength+stringLength+MaxString];
|
||||
mLengthBytes=currLength+stringLength+MaxString;
|
||||
::strcpy(mnpStr,lpString);
|
||||
::strcpy(mnpStr+currLength,someString.mnpStr);
|
||||
::delete[] lpString;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int String::operator+=(const char *someStr)
|
||||
{
|
||||
char *lpString;
|
||||
DWORD currLength;
|
||||
DWORD stringLength;
|
||||
|
||||
if(!someStr)return 0;
|
||||
stringLength=::strlen(someStr);
|
||||
stringLength++;
|
||||
if(!mnpStr)
|
||||
{
|
||||
reserve(stringLength,FALSE);
|
||||
::strcpy(mnpStr,someStr);
|
||||
return 1;
|
||||
}
|
||||
currLength=::strlen(mnpStr);
|
||||
if(lengthBytes()-currLength>=stringLength)
|
||||
{
|
||||
::strcat(mnpStr,someStr);
|
||||
return 1;
|
||||
}
|
||||
lpString=mnpStr;
|
||||
mnpStr=::new char[currLength+stringLength+MaxString];
|
||||
mLengthBytes=currLength+stringLength+MaxString;
|
||||
::strcpy(mnpStr,lpString);
|
||||
::strcpy(mnpStr+currLength,someStr);
|
||||
::delete[] lpString;
|
||||
return 1;
|
||||
}
|
||||
|
||||
String String::operator+(const String &someString)const
|
||||
{
|
||||
String tmpString(*this);
|
||||
tmpString+=someString;
|
||||
return tmpString;
|
||||
}
|
||||
|
||||
int String::token(const char *tokenString)
|
||||
{
|
||||
if(!tokenString||!mnpStr)return 0;
|
||||
if(::strtok(mnpStr,tokenString))return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
long String::strchr(char someChar)const
|
||||
{
|
||||
long pos;
|
||||
if(!mnpStr)return -1;
|
||||
pos=(long)::strchr(mnpStr,someChar);
|
||||
if(!pos)return -1;
|
||||
return pos-(long)mnpStr;
|
||||
}
|
||||
|
||||
long String::strpos(const char *string)const
|
||||
{
|
||||
long stringPosition;
|
||||
if(!mnpStr)return -1;
|
||||
stringPosition=(long)::strstr(mnpStr,string);
|
||||
if(!stringPosition)return -1;
|
||||
return stringPosition-(long)mnpStr;
|
||||
}
|
||||
|
||||
int String::strncmp(const char *string)const
|
||||
{
|
||||
int srcLength;
|
||||
int dstLength;
|
||||
|
||||
if(!mnpStr)return -1;
|
||||
srcLength=::strlen(string);
|
||||
dstLength=::strlen(mnpStr);
|
||||
return ::strncmp(mnpStr,string,srcLength<dstLength?srcLength:dstLength);
|
||||
}
|
||||
|
||||
void String::upper(void)
|
||||
{
|
||||
char *string=mnpStr;
|
||||
|
||||
if(!mnpStr)return;
|
||||
while(*string)
|
||||
{
|
||||
*string=::toupper(*string);
|
||||
string++;
|
||||
}
|
||||
}
|
||||
|
||||
void String::lower(void)
|
||||
{
|
||||
char *string=mnpStr;
|
||||
|
||||
if(!mnpStr)return;
|
||||
while(*string)
|
||||
{
|
||||
*string=::tolower(*string);
|
||||
string++;
|
||||
}
|
||||
}
|
||||
|
||||
String String::betweenString(char beginToken,char endToken)const
|
||||
{
|
||||
char nullString[MaxString]={0};
|
||||
short stringLength;
|
||||
char *lpBegin;
|
||||
char *lpEnd;
|
||||
|
||||
if(!mnpStr)return String(nullString);
|
||||
stringLength=length();
|
||||
if(1>=stringLength)return String(nullString);
|
||||
if(beginToken)
|
||||
{
|
||||
if(0==(lpBegin=::strchr(mnpStr,beginToken)))return String(nullString);
|
||||
if(++lpBegin-mnpStr>=stringLength)return String(nullString);
|
||||
}
|
||||
else lpBegin=mnpStr;
|
||||
if(0==(lpEnd=::strchr(lpBegin,endToken)))return *this;
|
||||
if(lpBegin==lpEnd)return String(nullString);
|
||||
if(sizeof(nullString)<=(lpEnd-lpBegin)+1)
|
||||
{
|
||||
String nullString;
|
||||
nullString.reserve((lpEnd-lpBegin)+1,FALSE);
|
||||
::memcpy(nullString,lpBegin,lpEnd-lpBegin);
|
||||
*((char*)nullString+(lpEnd-lpBegin))=0;
|
||||
return nullString;
|
||||
}
|
||||
::memcpy(nullString,lpBegin,lpEnd-lpBegin);
|
||||
*(nullString+(lpEnd-lpBegin))=0;
|
||||
return String(nullString);
|
||||
}
|
||||
|
||||
Block<String> String::split(char delimeter)const
|
||||
{
|
||||
Block<String> stringList = Block<String>();
|
||||
String strDelimeter = String(delimeter);
|
||||
String runningString = String(*this);
|
||||
|
||||
int position = runningString.strpos(strDelimeter);
|
||||
while (-1 != position)
|
||||
{
|
||||
stringList.insert(new String(runningString.substr(0, position - 1)));
|
||||
runningString = runningString.substr(position + 1);
|
||||
position = runningString.strpos(strDelimeter);
|
||||
}
|
||||
if (runningString.length())stringList.insert(new String(runningString));
|
||||
return stringList;
|
||||
}
|
||||
|
||||
WORD String::makeBlock(Block<String> &receiveStrings,const String &tokenString)const
|
||||
{
|
||||
String stringData(*this);
|
||||
String workString;
|
||||
LONG stringPos;
|
||||
LONG lengthToken;
|
||||
|
||||
receiveStrings.remove();
|
||||
if(!(lengthToken=tokenString.length()))return FALSE;
|
||||
if(stringData.isNull())return FALSE;
|
||||
while(TRUE)
|
||||
{
|
||||
if(-1==(stringPos=stringData.strpos(tokenString)))
|
||||
{
|
||||
if(!stringData.isNull())receiveStrings.insert(&stringData);
|
||||
return receiveStrings.size();
|
||||
}
|
||||
else if(stringData.length()!=stringPos+lengthToken)
|
||||
{
|
||||
if(stringPos)
|
||||
{
|
||||
workString=stringData.substr(0,stringPos-lengthToken);
|
||||
receiveStrings.insert(&workString);
|
||||
}
|
||||
stringData=stringData.substr(stringPos+lengthToken,stringData.length());
|
||||
}
|
||||
else stringData.removeTokens(tokenString);
|
||||
}
|
||||
}
|
||||
|
||||
String String::extractDigits(void)const
|
||||
{
|
||||
String tempString;
|
||||
String nullString;
|
||||
char *lpClampOne;
|
||||
char *lpClampTwo;
|
||||
|
||||
if(!mnpStr)return nullString;
|
||||
tempString=mnpStr;
|
||||
lpClampOne=(char*)tempString;
|
||||
while(*lpClampOne&&!isdigit(*lpClampOne))lpClampOne++;
|
||||
if(!*lpClampOne)return nullString;
|
||||
lpClampTwo=lpClampOne;
|
||||
while(*lpClampTwo&&isdigit(*lpClampTwo))lpClampTwo++;
|
||||
*lpClampTwo=0;
|
||||
return lpClampOne;
|
||||
}
|
||||
|
||||
String String::extractAlpha(void)const
|
||||
{
|
||||
String tempString;
|
||||
String nullString;
|
||||
char *lpClampOne;
|
||||
char *lpClampTwo;
|
||||
|
||||
if(!mnpStr)return nullString;
|
||||
tempString=mnpStr;
|
||||
lpClampOne=(char*)tempString;
|
||||
while(*lpClampOne&&!isalpha(*lpClampOne))lpClampOne++;
|
||||
if(!*lpClampOne)return nullString;
|
||||
lpClampTwo=lpClampOne;
|
||||
while(*lpClampTwo&&isalpha(*lpClampTwo))lpClampTwo++;
|
||||
*lpClampTwo=0;
|
||||
return lpClampOne;
|
||||
}
|
||||
|
||||
int String::hex(void)const
|
||||
{
|
||||
String workString(*this);
|
||||
DWORD stringLength;
|
||||
DWORD multiplier(0x01);
|
||||
DWORD value(0L);
|
||||
char *ptrString;
|
||||
|
||||
if(workString.isNull())return FALSE;
|
||||
if(workString.strstr(" "))workString.removeTokens(" ");
|
||||
if(!(stringLength=workString.length()))return FALSE;
|
||||
workString.upper();
|
||||
if(0!=(ptrString=(char*)workString.strstr("0X")))
|
||||
{
|
||||
ptrString+=2;
|
||||
stringLength=::strlen(ptrString);
|
||||
ptrString+=(stringLength-1);
|
||||
}
|
||||
else if('H'==*((char*)workString+(stringLength-1)))
|
||||
{
|
||||
stringLength--;
|
||||
ptrString=(char*)workString+(stringLength-1);
|
||||
}
|
||||
else ptrString=(char*)workString+(stringLength-1);
|
||||
for(LONG stringIndex=stringLength-1;stringIndex>=0;stringIndex--)
|
||||
{
|
||||
switch(*(ptrString--))
|
||||
{
|
||||
case '0' : break;
|
||||
case '1' : {value+=multiplier;break;}
|
||||
case '2' : {value+=multiplier*2;break;}
|
||||
case '3' : {value+=multiplier*3;break;}
|
||||
case '4' : {value+=multiplier*4;break;}
|
||||
case '5' : {value+=multiplier*5;break;}
|
||||
case '6' : {value+=multiplier*6;break;}
|
||||
case '7' : {value+=multiplier*7;break;}
|
||||
case '8' : {value+=multiplier*8;break;}
|
||||
case '9' : {value+=multiplier*9;break;}
|
||||
case 'A' : {value+=multiplier*10;break;}
|
||||
case 'B' : {value+=multiplier*11;break;}
|
||||
case 'C' : {value+=multiplier*12;break;}
|
||||
case 'D' : {value+=multiplier*13;break;}
|
||||
case 'E' : {value+=multiplier*14;break;}
|
||||
case 'F' : {value+=multiplier*15;break;}
|
||||
case '-' : {value*=-1;break;}
|
||||
default : return value;
|
||||
}
|
||||
multiplier*=16;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void String::spaceTerm(void)
|
||||
{
|
||||
size_t strLen;
|
||||
|
||||
if(isNull()||(0==(strLen=length())))return;
|
||||
for(short index=0;index<strLen;index++)if(Blank==*(mnpStr+index)){*(mnpStr+index)=0;return;}
|
||||
}
|
||||
|
||||
BOOL String::endsWidth(char ch)const
|
||||
{
|
||||
int strLength = length();
|
||||
if(isNull()||strLength)return FALSE;
|
||||
return ch == charAt(strLength-1);
|
||||
}
|
||||
|
||||
String& String::trim(void)
|
||||
{
|
||||
String str = trimRight();
|
||||
str=trimLeft();
|
||||
*this = str;
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::trimRight(void)
|
||||
{
|
||||
size_t strLen;
|
||||
|
||||
if(isNull()||(0==(strLen=length())))return *this;
|
||||
for(short index=strLen-1;index>=0;index--)
|
||||
{
|
||||
char ch = mnpStr[index];
|
||||
if (Blank == ch || CarriageReturn==ch || LineFeed==ch)mnpStr[index] = 0;
|
||||
else break;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::trimLeft(void)
|
||||
{
|
||||
size_t strLen;
|
||||
|
||||
if(isNull()||(0==(strLen=length())))return *this;
|
||||
short index=0;
|
||||
for (index = 0;index < strLen;index++)
|
||||
{
|
||||
char ch = mnpStr[index];
|
||||
if (Blank != ch && CarriageReturn != ch && LineFeed != ch)break;
|
||||
}
|
||||
if(!index)return *this;
|
||||
*this=substr(index);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void String::removeTokens(String someTokens)
|
||||
{
|
||||
int length(this->length());
|
||||
int tokens(someTokens.length());
|
||||
String tempString;
|
||||
|
||||
if(!length||!tokens)return;
|
||||
for(int token=0;token<tokens;token++)
|
||||
for (int pos = 0;pos < length;pos++)
|
||||
{
|
||||
if (*(mnpStr + pos) == *(someTokens.mnpStr + token))*(mnpStr + pos) = 0;
|
||||
}
|
||||
for(int pos=0;pos<length;pos++)
|
||||
if((mnpStr+pos))tempString+=*(mnpStr+pos);
|
||||
*this=tempString;
|
||||
}
|
||||
|
||||
void String::replaceToken(BYTE tokenFind,BYTE tokenReplace)
|
||||
{
|
||||
int length(this->length());
|
||||
String tempString;
|
||||
|
||||
if(!length)return;
|
||||
int pos=0;
|
||||
for(pos=0;pos<length;pos++)if(*(mnpStr+pos)==tokenFind)*(mnpStr+pos)=tokenReplace;
|
||||
for(pos=0;pos<length;pos++){if((mnpStr+pos))tempString+=*(mnpStr+pos);}
|
||||
*this=tempString;
|
||||
}
|
||||
|
||||
void String::length(short newLength)
|
||||
{
|
||||
short currLength(length());
|
||||
|
||||
if(currLength==newLength)return;
|
||||
if(currLength>newLength)
|
||||
{
|
||||
String tempString;
|
||||
tempString.reserve(newLength+1);
|
||||
::memcpy(tempString,*this,newLength);
|
||||
*this=tempString;
|
||||
}
|
||||
else while(length()<newLength)*this+=" ";
|
||||
}
|
||||
|
||||
void String::convert(double doubleValue,const char *formatString)
|
||||
{
|
||||
if(!formatString)return;
|
||||
reserve(MaxString);
|
||||
::sprintf(mnpStr,formatString,doubleValue);
|
||||
return;
|
||||
}
|
||||
|
||||
void String::convert(int integerValue,const char *formatString)
|
||||
{
|
||||
if(!formatString)return;
|
||||
reserve(MaxString);
|
||||
::sprintf(mnpStr,formatString,integerValue);
|
||||
return;
|
||||
}
|
||||
|
||||
void String::convert(long longValue,const char *formatString)
|
||||
{
|
||||
if(!formatString)return;
|
||||
reserve(MaxString);
|
||||
::sprintf(mnpStr,formatString,longValue);
|
||||
return;
|
||||
}
|
||||
|
||||
WORD String::remove(WORD removePosition)
|
||||
{
|
||||
WORD stringLength(length());
|
||||
String tempString;
|
||||
|
||||
if(!mnpStr)return FALSE;
|
||||
if(stringLength<=removePosition)return FALSE;
|
||||
if(!removePosition&&1==stringLength){*(mnpStr)='\0';return TRUE;}
|
||||
if(!removePosition){*this=(mnpStr+1);return TRUE;}
|
||||
*(mnpStr+removePosition)=0;
|
||||
tempString=mnpStr;
|
||||
tempString+=String((mnpStr+removePosition+1));
|
||||
*this=tempString;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
String String::substr(WORD startPosition,WORD endPosition)const
|
||||
{
|
||||
WORD stringLength(length());
|
||||
String resultString;
|
||||
|
||||
if(!stringLength)return resultString;
|
||||
if(startPosition>endPosition)return resultString;
|
||||
if(endPosition>stringLength)endPosition=stringLength;
|
||||
resultString.reserve(endPosition-startPosition+2);
|
||||
::memcpy(resultString,mnpStr+startPosition,(endPosition-startPosition)+1);
|
||||
return resultString;
|
||||
}
|
||||
|
||||
WORD String::insert(const String &insertString,WORD insertPosition)
|
||||
{
|
||||
WORD insertLength(insertString.length());
|
||||
|
||||
if(!insertLength)return FALSE;
|
||||
if(!mnpStr)
|
||||
{
|
||||
reserve(insertLength+insertPosition+1);
|
||||
::memset(mnpStr,Blank,insertLength+insertPosition);
|
||||
::memcpy(mnpStr+insertPosition,insertString,insertLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
WORD currentLength(length());
|
||||
String tempString;
|
||||
|
||||
if(insertLength+insertPosition>currentLength)
|
||||
{
|
||||
tempString.reserve(insertLength+insertPosition+currentLength+1);
|
||||
::memset(tempString,Blank,insertLength+insertPosition+currentLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
tempString.reserve(currentLength+insertLength+1);
|
||||
::memset(tempString,Blank,currentLength+insertLength);
|
||||
}
|
||||
::memcpy(tempString,mnpStr,currentLength);
|
||||
if(!(insertPosition>currentLength))shiftRight(tempString,insertPosition,currentLength+insertLength-1,insertLength,currentLength);
|
||||
::memcpy(((char*)tempString)+insertPosition,insertString,insertLength);
|
||||
*this=tempString;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
WORD String::insert(char *lpInsertString,WORD insertPosition)
|
||||
{
|
||||
WORD insertLength;
|
||||
|
||||
if(!lpInsertString||!(insertLength=::strlen(lpInsertString)))return FALSE;
|
||||
if(!mnpStr)
|
||||
{
|
||||
reserve(insertLength+insertPosition+1);
|
||||
::memset(mnpStr,Blank,insertLength+insertPosition);
|
||||
::memcpy(mnpStr+insertPosition,lpInsertString,insertLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
WORD currentLength(length());
|
||||
String tempString;
|
||||
|
||||
if(insertLength+insertPosition>currentLength)
|
||||
{
|
||||
tempString.reserve(insertLength+insertPosition+currentLength+1);
|
||||
::memset(tempString,Blank,insertLength+insertPosition+currentLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
tempString.reserve(currentLength+insertLength+1);
|
||||
::memset(tempString,Blank,currentLength+insertLength);
|
||||
}
|
||||
::memcpy(tempString,mnpStr,currentLength);
|
||||
if(!(insertPosition>currentLength))shiftRight(tempString,insertPosition,currentLength+insertLength-1,insertLength,currentLength);
|
||||
::memcpy(((char*)tempString)+insertPosition,lpInsertString,insertLength);
|
||||
*this=tempString;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void String::shiftRight(String &shiftString,WORD startPos,WORD endPos,WORD insertLength,WORD originalLength)
|
||||
{
|
||||
WORD shiftLength(originalLength-startPos);
|
||||
for(WORD shiftIndex=0;shiftIndex<shiftLength;shiftIndex++,endPos--)
|
||||
*((char*)shiftString+endPos)=*((char*)shiftString+endPos-insertLength);
|
||||
}
|
||||
|
||||
int String::toInt(void)const
|
||||
{
|
||||
if(isNull())return 0;
|
||||
return ::atoi(str());
|
||||
}
|
||||
|
||||
short String::toShort(void)const
|
||||
{
|
||||
if(isNull())return 0;
|
||||
return short(::atoi(str()));
|
||||
}
|
||||
|
||||
unsigned short String::toUShort(void)const
|
||||
{
|
||||
if (isNull())return 0;
|
||||
return (unsigned short)(::atoi(str()));
|
||||
}
|
||||
|
||||
float String::toFloat(void)const
|
||||
{
|
||||
if(isNull())return 0.00;
|
||||
return ::atof(str());
|
||||
}
|
||||
|
||||
double String::toDouble(void)const
|
||||
{
|
||||
if(isNull())return 0.00;
|
||||
return ::atof(str());
|
||||
}
|
||||
|
||||
long String::toLong(void)const
|
||||
{
|
||||
if(isNull())return 0;
|
||||
return ::atol(str());
|
||||
}
|
||||
|
||||
unsigned long String::toULong(void)const
|
||||
{
|
||||
if(isNull())return 0;
|
||||
return (unsigned long)::atol(str());
|
||||
}
|
||||
|
||||
|
||||
String &String::fromInt(int value)
|
||||
{
|
||||
reserve(MaxString);
|
||||
::sprintf(mnpStr,"%d",value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::fromShort(short value)
|
||||
{
|
||||
reserve(MaxString);
|
||||
::sprintf(mnpStr,"%d",value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::fromUShort(unsigned short value)
|
||||
{
|
||||
reserve(MaxString);
|
||||
::sprintf(mnpStr,"%d",value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::fromFloat(float value)
|
||||
{
|
||||
reserve(MaxString);
|
||||
::sprintf(mnpStr,"%9.2lf",value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::fromDouble(double value)
|
||||
{
|
||||
reserve(MaxString);
|
||||
::sprintf(mnpStr,"%9.2lf",value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::fromLong(long value)
|
||||
{
|
||||
reserve(MaxString);
|
||||
::sprintf(mnpStr,"%ld",value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::fromULong(unsigned long value)
|
||||
{
|
||||
reserve(MaxString);
|
||||
::sprintf(mnpStr,"%lu",value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
String &String::fromBool(bool boolValue)
|
||||
{
|
||||
*this=boolValue?"T":"F";
|
||||
return *this;
|
||||
}
|
||||
|
||||
// non-member
|
||||
|
||||
String operator+(const char *str,const String &string)
|
||||
{
|
||||
return String(str)+string;
|
||||
}
|
||||
302
common/string.hpp
Executable file
302
common/string.hpp
Executable file
@@ -0,0 +1,302 @@
|
||||
#ifndef _COMMON_STRING_HPP_
|
||||
#define _COMMON_STRING_HPP_
|
||||
#include <string.h>
|
||||
#ifndef _COMMON_STDLIB_HPP_
|
||||
#include <common/stdlib.hpp>
|
||||
#endif
|
||||
#ifndef _COMMON_WINDOWS_HPP_
|
||||
#include <common/windows.hpp>
|
||||
#endif
|
||||
|
||||
#pragma warning( disable : 6387)
|
||||
|
||||
template <class T>
|
||||
class Block;
|
||||
template <class T>
|
||||
class Array;
|
||||
class istream;
|
||||
class ostream;
|
||||
class String;
|
||||
|
||||
istream &operator>>(istream &stream,String &someString);
|
||||
ostream &operator<<(ostream &stream,const String &someString);
|
||||
|
||||
String operator+(const char *str,const String &string);
|
||||
|
||||
class String
|
||||
{
|
||||
public:
|
||||
enum{MaxString=256};
|
||||
String(void);
|
||||
String(const char *npStr);
|
||||
String(const wchar_t *npWideString,int length);
|
||||
String(const String &newString);
|
||||
String(int resourceStringID);
|
||||
String(char characterItem);
|
||||
virtual ~String();
|
||||
int operator!=(const String &someString)const;
|
||||
int operator!=(const char *someCharStar)const;
|
||||
int operator==(const String &someString)const;
|
||||
int operator==(const char *someCharStar)const;
|
||||
int operator<(const String &someString)const;
|
||||
int operator>(const String &someString)const;
|
||||
String &operator=(const String &someString);
|
||||
int operator=(const char *someCharStar);
|
||||
int operator+=(const String &someString);
|
||||
int operator+=(const char *someStr);
|
||||
void operator+=(char someChar);
|
||||
char &operator[](DWORD itemIndex);
|
||||
char charAt(DWORD itemIndex)const;
|
||||
String &setAt(DWORD itemIndex,char ch);
|
||||
friend istream &operator>>(istream &stream,String &someString);
|
||||
friend ostream &operator<<(ostream &stream,const String &someString);
|
||||
operator char *(void)const;
|
||||
String operator+(const String &someString)const;
|
||||
void reserve(DWORD nBytes,BOOL setZero=TRUE)__attribute__((always_inline));
|
||||
int token(const char *token);
|
||||
int isNull(void)const;
|
||||
void upper(void);
|
||||
void lower(void);
|
||||
int length(void)const;
|
||||
void length(short newLength);
|
||||
DWORD lengthBytes(void)const;
|
||||
void removeTokens(String someTokens);
|
||||
void replaceToken(BYTE tokenFind,BYTE tokenReplace);
|
||||
int hex(void)const;
|
||||
void expand(void);
|
||||
void convert(double doubleValue,const char *formatString);
|
||||
void convert(int integerValue,const char *formatString);
|
||||
void convert(long longValue,const char *formatString);
|
||||
long strstr(const char *string)const;
|
||||
long strpos(const char *string)const;
|
||||
long strchr(char someChar)const;
|
||||
int strncmp(const char *string)const;
|
||||
BOOL endsWidth(char ch)const;
|
||||
String& trim(void);
|
||||
String &trimRight(void);
|
||||
String &trimLeft(void);
|
||||
void spaceTerm(void);
|
||||
String betweenString(char beginToken,char endToken)const;
|
||||
Block<String> split(char delimter)const;
|
||||
String substr(WORD startPosition,WORD endPosition)const;
|
||||
String substr(WORD startPosition)const;
|
||||
String extractDigits(void)const;
|
||||
String extractAlpha(void)const;
|
||||
WORD makeBlock(Block<String> &receiveStrings,const String &tokenString)const;
|
||||
WORD insert(const String &insertString,WORD insertPosition=0);
|
||||
WORD insert(char *lpInsertString,WORD insertPosition=0);
|
||||
WORD remove(WORD removePosition=0);
|
||||
int toInt(void)const;
|
||||
short toShort(void)const;
|
||||
unsigned short toUShort(void)const;
|
||||
float toFloat(void)const;
|
||||
double toDouble(void)const;
|
||||
long toLong(void)const;
|
||||
unsigned long toULong(void)const;
|
||||
String &fromInt(int value);
|
||||
String &fromShort(short value);
|
||||
String &fromUShort(unsigned short value);
|
||||
String &fromFloat(float value);
|
||||
String &fromLong(long value);
|
||||
String &fromULong(unsigned long value);
|
||||
String &fromBool(bool value);
|
||||
String &fromDouble(double value);
|
||||
bool equals(const String &string)const;
|
||||
const char *str(void)const;
|
||||
char *str(void);
|
||||
String quotes(void)const;
|
||||
String reverse(void)const;
|
||||
private:
|
||||
enum{Blank=' ',CarriageReturn=0x0D,LineFeed=0x0A};
|
||||
void shiftRight(String &shiftString,WORD startPos,WORD endPos,WORD insertLength,WORD originalLength);
|
||||
void removeData(void);
|
||||
|
||||
char FAR *mnpStr;
|
||||
DWORD mLengthBytes;
|
||||
};
|
||||
|
||||
inline
|
||||
String::String(void)
|
||||
: mnpStr(0), mLengthBytes(0L)
|
||||
{
|
||||
reserve(MaxString);
|
||||
}
|
||||
|
||||
inline
|
||||
String::String(char characterItem)
|
||||
: mnpStr(0), mLengthBytes(0)
|
||||
{
|
||||
reserve(sizeof(characterItem)+1);
|
||||
*mnpStr=characterItem;
|
||||
}
|
||||
|
||||
inline
|
||||
String::~String()
|
||||
{
|
||||
removeData();
|
||||
}
|
||||
|
||||
inline
|
||||
String::operator char *(void)const
|
||||
{
|
||||
return mnpStr;
|
||||
}
|
||||
|
||||
inline
|
||||
char &String::operator[](DWORD itemIndex)
|
||||
{
|
||||
return *(mnpStr+itemIndex);
|
||||
}
|
||||
|
||||
inline
|
||||
String &String::setAt(DWORD itemIndex,char ch)
|
||||
{
|
||||
*(mnpStr+itemIndex)=ch;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline
|
||||
char String::charAt(DWORD itemIndex)const
|
||||
{
|
||||
return *(mnpStr+itemIndex);
|
||||
}
|
||||
|
||||
inline
|
||||
void String::reserve(DWORD nBytes,BOOL setZero)
|
||||
{
|
||||
if(nBytes>mLengthBytes)
|
||||
{
|
||||
removeData();
|
||||
mnpStr=::new char[nBytes];
|
||||
mLengthBytes=nBytes;
|
||||
}
|
||||
if(setZero)::memset(mnpStr,0,mLengthBytes);
|
||||
}
|
||||
|
||||
inline
|
||||
String String::substr(WORD startPosition)const
|
||||
{
|
||||
return substr(startPosition,length());
|
||||
}
|
||||
|
||||
inline
|
||||
int String::length(void)const
|
||||
{
|
||||
return (mnpStr?::strlen(mnpStr):0);
|
||||
}
|
||||
|
||||
inline
|
||||
void String::removeData(void)
|
||||
{
|
||||
if(!mnpStr)return;
|
||||
::delete[] mnpStr;
|
||||
mnpStr=0;
|
||||
mLengthBytes=0;
|
||||
}
|
||||
|
||||
inline
|
||||
int String::isNull(void)const
|
||||
{
|
||||
if(!mnpStr||!(*mnpStr))return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline
|
||||
DWORD String::lengthBytes(void)const
|
||||
{
|
||||
return mLengthBytes;
|
||||
}
|
||||
|
||||
inline
|
||||
int String::operator==(const String &someString)const
|
||||
{
|
||||
if(!mnpStr&&!someString.mnpStr)return 1;
|
||||
if(!mnpStr||!someString.mnpStr)return 0;
|
||||
return (0==::strcmp(mnpStr,someString.mnpStr));
|
||||
}
|
||||
|
||||
inline
|
||||
int String::operator!=(const String &someString)const
|
||||
{
|
||||
if(!mnpStr&&!someString.mnpStr)return 0;
|
||||
if(!mnpStr||!someString.mnpStr)return 1;
|
||||
return (::strcmp(mnpStr,someString.mnpStr));
|
||||
}
|
||||
|
||||
inline
|
||||
int String::operator!=(const char *someCharStar)const
|
||||
{
|
||||
if(!mnpStr&&!someCharStar)return 0;
|
||||
if(!mnpStr||!someCharStar)return 1;
|
||||
return (::strcmp(mnpStr,someCharStar));
|
||||
}
|
||||
|
||||
inline
|
||||
int String::operator==(const char *someCharStar)const
|
||||
{
|
||||
if(!mnpStr&&!someCharStar)return 1;
|
||||
if(!mnpStr||!someCharStar)return 0;
|
||||
return (0==::strcmp(mnpStr,someCharStar));
|
||||
}
|
||||
|
||||
inline
|
||||
int String::operator<(const String &someString)const
|
||||
{
|
||||
if(isNull()&&someString.isNull())return FALSE;
|
||||
if(isNull())return TRUE;
|
||||
return (::strcmp(mnpStr,someString.mnpStr)<0?TRUE:FALSE);
|
||||
}
|
||||
|
||||
inline
|
||||
int String::operator>(const String &someString)const
|
||||
{
|
||||
if(isNull()&&someString.isNull())return FALSE;
|
||||
if(isNull())return FALSE;
|
||||
return (::strcmp(mnpStr,someString.mnpStr)>0?TRUE:FALSE);
|
||||
}
|
||||
|
||||
inline
|
||||
long String::strstr(const char *string)const
|
||||
{
|
||||
if(!mnpStr)return 0;
|
||||
return (long)::strstr(mnpStr,string);
|
||||
}
|
||||
|
||||
inline
|
||||
bool String::equals(const String &string)const
|
||||
{
|
||||
return *this==string?true:false;
|
||||
}
|
||||
|
||||
inline
|
||||
const char *String::str(void)const
|
||||
{
|
||||
return mnpStr;
|
||||
}
|
||||
|
||||
inline
|
||||
char *String::str(void)
|
||||
{
|
||||
return mnpStr;
|
||||
}
|
||||
|
||||
inline
|
||||
String String::quotes(void)const
|
||||
{
|
||||
return String("\"")+*this+String("\"");
|
||||
}
|
||||
|
||||
inline
|
||||
String String::reverse(void)const
|
||||
{
|
||||
String reverse;
|
||||
for(int index=length()-1;index>=0;index--)
|
||||
{
|
||||
reverse+=charAt(index);
|
||||
}
|
||||
return reverse;
|
||||
}
|
||||
|
||||
typedef String string;
|
||||
|
||||
#endif
|
||||
160
common/utility.hpp
Normal file
160
common/utility.hpp
Normal file
@@ -0,0 +1,160 @@
|
||||
#ifndef _COMMON_UTILITY_HPP_
|
||||
#define _COMMON_UTILITY_HPP_
|
||||
#include <stdio.h>
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
#include <common/string.hpp>
|
||||
|
||||
class Utility
|
||||
{
|
||||
public:
|
||||
static String formatNumber(long number,bool commas=true);
|
||||
static String formatNumber(double number,bool commas=true);
|
||||
static String formatNumber(double number,int places=2);
|
||||
static String formatCurrency(double number,int places=2);
|
||||
static bool fmod(double dividend,double divisor);
|
||||
static bool fmod(double dividend, double divisor,double epsilon);
|
||||
static String bytesTransferredToString(double bytesTransferred);
|
||||
private:
|
||||
static String pad(String theString,char padChar,int toLength);
|
||||
static String addCommas(String& theString);
|
||||
Utility();
|
||||
~Utility();
|
||||
};
|
||||
|
||||
inline
|
||||
Utility::Utility()
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
Utility::~Utility()
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
String Utility::bytesTransferredToString(double bytesTransferred)
|
||||
{
|
||||
double roundedValue = std::round(bytesTransferred * 100.00)/100.00;
|
||||
if(roundedValue >= 1E+15)
|
||||
{
|
||||
return Utility::formatNumber(roundedValue/1E+15,2) + "Pb/s";
|
||||
}
|
||||
else if(roundedValue >= 1000000000000)
|
||||
{
|
||||
return Utility::formatNumber(roundedValue/1000000000000,2) + "Tb/s";
|
||||
}
|
||||
else if(roundedValue >= 1073741824)
|
||||
{
|
||||
return Utility::formatNumber(roundedValue/1073741824,2) + "Gbb/s";
|
||||
}
|
||||
else if(roundedValue >= 1000000)
|
||||
{
|
||||
return Utility::formatNumber(roundedValue/1000000,2) + "Mb/s";
|
||||
}
|
||||
else if(roundedValue >= 1000)
|
||||
{
|
||||
return Utility::formatNumber(roundedValue/1000,2) + "Kb/s";
|
||||
}
|
||||
return Utility::formatNumber(roundedValue,2) + "B/s";
|
||||
}
|
||||
|
||||
inline
|
||||
String Utility::formatNumber(long number,bool commas)
|
||||
{
|
||||
String formattedString;
|
||||
String format="%ld";
|
||||
::sprintf(formattedString.str(),format,number);
|
||||
return addCommas(formattedString);
|
||||
}
|
||||
|
||||
inline
|
||||
String Utility::formatNumber(double number,int places)
|
||||
{
|
||||
String numberString = formatCurrency(number, places);
|
||||
return numberString.substr(1);
|
||||
}
|
||||
|
||||
inline
|
||||
String Utility::formatCurrency(double number,int places)
|
||||
{
|
||||
String formattedString;
|
||||
String format="%.";
|
||||
format+=String().fromInt(places);
|
||||
format+="f";
|
||||
::sprintf(formattedString.str(),format,number);
|
||||
Block<String> items = formattedString.split('.');
|
||||
if(items[0].length()<=3)
|
||||
{
|
||||
if(2==items.size())
|
||||
{
|
||||
return "$"+items[0]+"."+items[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
return "$"+items[0];
|
||||
}
|
||||
}
|
||||
String wholePart = addCommas(items[0]);
|
||||
if(2==items.size())
|
||||
{
|
||||
return "$"+wholePart+"."+items[1];
|
||||
}
|
||||
return "$"+wholePart;
|
||||
}
|
||||
|
||||
inline
|
||||
String Utility::addCommas(String& wholePart)
|
||||
{
|
||||
String placesString;
|
||||
wholePart=wholePart.reverse();
|
||||
for(int index=0;index<wholePart.length();index++)
|
||||
{
|
||||
if(index>0 && 0==(index%3))placesString+=",";
|
||||
placesString+=wholePart.charAt(index);
|
||||
}
|
||||
placesString=placesString.reverse();
|
||||
return placesString;
|
||||
}
|
||||
|
||||
inline
|
||||
String Utility::pad(String theString,char padChar,int toLength)
|
||||
{
|
||||
while(theString.length()<toLength)theString+=padChar;
|
||||
return theString;
|
||||
}
|
||||
|
||||
inline
|
||||
bool Utility::fmod(double dividend, double divisor,double epsilon)
|
||||
{
|
||||
if (divisor == 0.0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Calculate the remainder
|
||||
double remainder = std::fmod(dividend, divisor);
|
||||
|
||||
// Check if the absolute remainder is less than epsilon
|
||||
return std::fabs(remainder) < std::fabs(epsilon);
|
||||
}
|
||||
|
||||
inline
|
||||
bool Utility::fmod(double dividend, double divisor)
|
||||
{
|
||||
if (divisor == 0.0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Define a small epsilon value for floating-point comparisons
|
||||
// Using machine epsilon for double is a common choice.
|
||||
const double epsilon = std::numeric_limits<double>::epsilon() * 100; // Multiplied for a slightly larger tolerance
|
||||
|
||||
// Calculate the remainder
|
||||
double remainder = std::fmod(dividend, divisor);
|
||||
|
||||
// Check if the absolute remainder is less than epsilon
|
||||
return std::fabs(remainder) < epsilon;
|
||||
}
|
||||
#endif
|
||||
72
common/windows.hpp
Executable file
72
common/windows.hpp
Executable file
@@ -0,0 +1,72 @@
|
||||
#ifndef _COMMON_WINDOWS_HPP_
|
||||
#define _COMMON_WINDOWS_HPP_
|
||||
#ifndef _MSC_VER
|
||||
#define _MSC_VER 1200
|
||||
#endif
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOSERVICE
|
||||
#define NOKANJI
|
||||
#define NOCRYPT
|
||||
#define NOMCX
|
||||
#define NOLSTRING
|
||||
#define NODBCS
|
||||
#define NOMETAFILE
|
||||
#define NOPROFILER
|
||||
#define NOLANGUAGE
|
||||
#define NOLOGERROR
|
||||
#define NOMCX
|
||||
#define NOIME
|
||||
#define NOCOMM
|
||||
|
||||
// for backwards compatibility
|
||||
typedef unsigned short USHORT;
|
||||
//typedef unsigned int DWORD;
|
||||
typedef unsigned long DWORD;
|
||||
typedef unsigned short WORD;
|
||||
typedef unsigned char BYTE;
|
||||
typedef bool BOOL;
|
||||
typedef long LONG;
|
||||
typedef unsigned long LPARAM;
|
||||
typedef unsigned long DWORD_PTR;
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define FAR
|
||||
#define NEAR
|
||||
#define MAKEWORD(a, b) ((WORD)(((BYTE)(((DWORD_PTR)(a)) & 0xff)) | ((WORD)((BYTE)(((DWORD_PTR)(b)) & 0xff))) << 8))
|
||||
#define MAKELONG(a, b) ((LONG)(((WORD)(((DWORD_PTR)(a)) & 0xffff)) | ((DWORD)((WORD)(((DWORD_PTR)(b)) & 0xffff))) << 16))
|
||||
#define LOWORD(l) ((WORD)(((DWORD_PTR)(l)) & 0xffff))
|
||||
#define HIWORD(l) ((WORD)((((DWORD_PTR)(l)) >> 16) & 0xffff))
|
||||
|
||||
// The following definitions might be obsolete
|
||||
|
||||
#ifndef DS_3DLOOK
|
||||
#define DS_3DLOOK 0x0004L
|
||||
#endif
|
||||
#ifndef PFD_GENERIC_ACCELERATED
|
||||
#define PFD_GENERIC_ACCELERATED 0x00001000
|
||||
#endif
|
||||
#ifndef PFD_SWAP_LAYER_BUFFERS
|
||||
#define PFD_SWAP_LAYER_BUFFERS 0x00000800
|
||||
#endif
|
||||
#ifndef PFD_DEPTH_DONTCARE
|
||||
#define PFD_DEPTH_DONTCARE 0x20000000
|
||||
#endif
|
||||
#ifndef EN_MSGFILTER
|
||||
#define EN_MSGFILTER 0x0700
|
||||
#endif
|
||||
#ifndef EN_REQUESTRESIZE
|
||||
#define EN_REQUESTRESIZE 0x0701
|
||||
#endif
|
||||
#ifndef EN_SELCHANGE
|
||||
#define EN_SELCHANGE 0x0702
|
||||
#endif
|
||||
#ifndef EN_DROPFILES
|
||||
#define EN_DROPFILES 0x0703
|
||||
#endif
|
||||
#ifndef EN_PROTECTED
|
||||
#define EN_PROTECTED 0x0704
|
||||
#endif
|
||||
#endif
|
||||
#ifndef IMAGE_DIRECTORY_ENTRY_COPYRIGHT
|
||||
#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT IMAGE_DIRECTORY_ENTRY_ARCHITECTURE
|
||||
#endif
|
||||
33
listener/.vscode/launch.json
vendored
Normal file
33
listener/.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "(gdb) Launch",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/build/listener",
|
||||
"args": ["SERVERMODE","55000"],
|
||||
"stopAtEntry": true,
|
||||
"cwd": "${fileDirname}",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
},
|
||||
{
|
||||
"description": "Set Disassembly Flavor to Intel",
|
||||
"text": "-gdb-set disassembly-flavor intel",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
57
listener/.vscode/settings.json
vendored
Normal file
57
listener/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"array": "cpp",
|
||||
"atomic": "cpp",
|
||||
"bit": "cpp",
|
||||
"cctype": "cpp",
|
||||
"chrono": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"compare": "cpp",
|
||||
"complex": "cpp",
|
||||
"concepts": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"deque": "cpp",
|
||||
"string": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"vector": "cpp",
|
||||
"exception": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"functional": "cpp",
|
||||
"iterator": "cpp",
|
||||
"memory": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numeric": "cpp",
|
||||
"random": "cpp",
|
||||
"ratio": "cpp",
|
||||
"string_view": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"new": "cpp",
|
||||
"numbers": "cpp",
|
||||
"ostream": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"semaphore": "cpp",
|
||||
"stop_token": "cpp",
|
||||
"thread": "cpp",
|
||||
"*.tpp": "cpp"
|
||||
}
|
||||
}
|
||||
28
listener/.vscode/tasks.json
vendored
Normal file
28
listener/.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"tasks": [
|
||||
{
|
||||
"type": "cppbuild",
|
||||
"label": "C/C++: g++ build active file",
|
||||
"command": "/usr/bin/g++",
|
||||
"args": [
|
||||
"-fdiagnostics-color=always",
|
||||
"-g",
|
||||
"${file}",
|
||||
"-o",
|
||||
"${fileDirname}/${fileBasenameNoExtension}"
|
||||
],
|
||||
"options": {
|
||||
"cwd": "${fileDirname}"
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$gcc"
|
||||
],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"detail": "Task generated by Debugger."
|
||||
}
|
||||
],
|
||||
"version": "2.0.0"
|
||||
}
|
||||
11
listener/CMakeLists.txt
Normal file
11
listener/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
cmake_minimum_required(VERSION 3.10.0)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/home/pi/Boneyard")
|
||||
project(listener VERSION 0.1.0 LANGUAGES C CXX)
|
||||
|
||||
add_executable(listener main.cpp ClientSocketSender.cpp SocketConnectionReceiver.cpp SocketServer.cpp)
|
||||
|
||||
add_subdirectory(/home/pi/Boneyard/common /home/pi/Boneyard/common/build)
|
||||
target_link_libraries(listener PRIVATE common)
|
||||
|
||||
|
||||
|
||||
118
listener/ClientSocketSender.cpp
Normal file
118
listener/ClientSocketSender.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
#include <listener/ClientSocketSender.hpp>
|
||||
|
||||
ClientSocketSender::ClientSocketSender(String ipAddress, int port)
|
||||
: mIPAddress(ipAddress), mPort(port)
|
||||
{
|
||||
mSocket = ::socket(AF_INET,SOCK_STREAM,0);
|
||||
if(!isOkay())
|
||||
{
|
||||
std::cout << "Unable to initialize socket " << std::endl;
|
||||
return;
|
||||
}
|
||||
mInternalSocketAddress.sin_family = AF_INET;
|
||||
mInternalSocketAddress.sin_port= ::htons(mPort);
|
||||
int result = ::inet_pton(AF_INET, ipAddress.str(), &mInternalSocketAddress.sin_addr);
|
||||
if(result<0)
|
||||
{
|
||||
std::cout << "Unable to convert ipaddress to network address" << std::endl;
|
||||
close();
|
||||
return;
|
||||
}
|
||||
result = ::connect(mSocket, (struct sockaddr*)&mInternalSocketAddress, sizeof(mInternalSocketAddress));
|
||||
if(result<0)
|
||||
{
|
||||
close();
|
||||
std::cout << "Unable to connect to host " << mIPAddress << ":" << mPort << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
ClientSocketSender::~ClientSocketSender()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void ClientSocketSender::close(void)
|
||||
{
|
||||
if(-1!=mSocket)
|
||||
{
|
||||
::close(mSocket);
|
||||
mSocket=-1;
|
||||
}
|
||||
}
|
||||
|
||||
bool ClientSocketSender::sendFile(String &pathFileName)
|
||||
{
|
||||
Profiler profiler;
|
||||
FileIO readFile(pathFileName, FileIO::ByteOrder::LittleEndian, FileIO::Mode::ReadOnly, FileIO::CreationFlags::None);
|
||||
if(!readFile.isOkay())
|
||||
{
|
||||
std::cout << "File open failed " << pathFileName << std::endl;
|
||||
return false;
|
||||
}
|
||||
readFile.setBufferLength(BUFFER_LENGTH);
|
||||
DWORD fileLength = readFile.size();
|
||||
sendPutIndicator(pathFileName, fileLength);
|
||||
Array<char> readBuffer;
|
||||
readBuffer.size(BUFFER_LENGTH);
|
||||
while(true)
|
||||
{
|
||||
size_t bytesRead = readFile.read(&readBuffer[0], readBuffer.size());
|
||||
if(0==bytesRead)
|
||||
{
|
||||
std::cout << "No data was read from the file" << std::endl;
|
||||
break;
|
||||
}
|
||||
sendPacketIndicator(bytesRead);
|
||||
sendPacket(readBuffer, bytesRead);
|
||||
if(bytesRead<readBuffer.size())break;
|
||||
}
|
||||
sendPacketIndicator(0);
|
||||
sendQuit();
|
||||
readFile.close();
|
||||
std::cout << "SendFile done, total took " << profiler.end() << "(ms)" << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientSocketSender::sendPacketIndicator(DWORD bytesToSend)
|
||||
{
|
||||
if(!isOkay())return false;
|
||||
String packetIndicator = "PCKT|";
|
||||
packetIndicator+=String().fromULong(bytesToSend);
|
||||
packetIndicator+="\r\n";
|
||||
::send(mSocket, (char*)packetIndicator, packetIndicator.length(),0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientSocketSender::sendPutIndicator(String fileName,DWORD fileLength)
|
||||
{
|
||||
if(!isOkay())return false;
|
||||
Block<String> parts = fileName.split('/');
|
||||
String pureFileName = parts[parts.size()-1];
|
||||
String putIndicator = "PUT|";
|
||||
putIndicator+=pureFileName;
|
||||
putIndicator+="|";
|
||||
putIndicator+=String().fromULong(fileLength);
|
||||
putIndicator+="\r\n";
|
||||
::send(mSocket, (char*)putIndicator, putIndicator.length(),0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientSocketSender::sendQuit(void)
|
||||
{
|
||||
if(!isOkay())return false;
|
||||
String quitIndicator = "QUIT\r\n";
|
||||
::send(mSocket, (char*)quitIndicator, quitIndicator.length(),0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientSocketSender::sendPacket(Array<char> &buffer,DWORD bytesToSend)
|
||||
{
|
||||
if(!isOkay())return false;
|
||||
::send(mSocket, (char*)&buffer[0], bytesToSend,0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientSocketSender::isOkay(void)
|
||||
{
|
||||
return -1==mSocket?false:true;
|
||||
}
|
||||
37
listener/ClientSocketSender.hpp
Normal file
37
listener/ClientSocketSender.hpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef _LISTENER_CLIENTSOCKETSENDER_HPP_
|
||||
#define _LISTENER_CLIENTSOCKETSENDER_HPP_
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <thread>
|
||||
#include <common/string.hpp>
|
||||
#include <common/profiler.hpp>
|
||||
#include <common/block.hpp>
|
||||
#include <common/fileio.hpp>
|
||||
|
||||
class ClientSocketSender
|
||||
{
|
||||
public:
|
||||
ClientSocketSender(String ipAddress,int port);
|
||||
virtual ~ClientSocketSender();
|
||||
bool sendFile(String &pathFileName);
|
||||
bool isOkay(void);
|
||||
private:
|
||||
// static constexpr int BUFFER_LENGTH=65536;
|
||||
static constexpr int BUFFER_LENGTH=1048576;
|
||||
void close(void);
|
||||
bool sendPacketIndicator(DWORD bytesToSend);
|
||||
bool sendPacket(Array<char> &buffer,DWORD bytesToSend);
|
||||
bool sendPutIndicator(String fileName,DWORD fileLength);
|
||||
bool sendQuit(void);
|
||||
|
||||
struct sockaddr_in mInternalSocketAddress;
|
||||
int mSocket;
|
||||
String mIPAddress;
|
||||
int mPort;
|
||||
};
|
||||
#endif
|
||||
157
listener/SocketConnectionReceiver.cpp
Normal file
157
listener/SocketConnectionReceiver.cpp
Normal file
@@ -0,0 +1,157 @@
|
||||
#include <listener/SocketConnectionReceiver.hpp>
|
||||
#include <common/utility.hpp>
|
||||
|
||||
SocketConnectionReceiver::SocketConnectionReceiver(int socket, sockaddr_in internalSocketAddress)
|
||||
: mSocket(socket), mInternalSocketAddress(internalSocketAddress)
|
||||
{
|
||||
}
|
||||
|
||||
SocketConnectionReceiver::~SocketConnectionReceiver()
|
||||
{
|
||||
}
|
||||
|
||||
void SocketConnectionReceiver::close(void)
|
||||
{
|
||||
if(-1==mSocket)return;
|
||||
std::cout << "Closing connection " << mSocket << std::endl;
|
||||
::close(mSocket);
|
||||
mSocket=-1;
|
||||
}
|
||||
|
||||
void SocketConnectionReceiver::threadFunction(int data)
|
||||
{
|
||||
String line;
|
||||
while(true)
|
||||
{
|
||||
readLine(line);
|
||||
if(0==line.length())
|
||||
{
|
||||
std::cout << "Received an empty command" << std::endl;
|
||||
break;
|
||||
}
|
||||
if(line=="QUIT" || line=="quit")break;
|
||||
Block<String> commands = line.split('|');
|
||||
if(0==commands.size())continue;
|
||||
std::cout << commands[0] << std::endl;
|
||||
commands[0].upper();
|
||||
if(commands[0]=="PUT")
|
||||
{
|
||||
handlePut(commands);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Unrecognized command >" << line << "<" << std::endl;
|
||||
}
|
||||
}
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
/// @brief The client wants to put a file. put {filename} {lengthbytes}
|
||||
/// @param commands [0]=PUT, [1]=filename, [2]=total length
|
||||
/// This will read PCKT {length}.
|
||||
/// The connection will continue reading and writing until it receives PCKT 0
|
||||
/// @return
|
||||
bool SocketConnectionReceiver::handlePut(Block<String> &commands)
|
||||
{
|
||||
Profiler profiler;
|
||||
Array<char> receiveBuffer;
|
||||
Block<String> subCommands;
|
||||
String strLine;
|
||||
String fileName;
|
||||
size_t fileLength;
|
||||
size_t totalBytesRead=0;
|
||||
|
||||
fileName = commands[1];
|
||||
fileLength = commands[commands.size()-1].toLong();
|
||||
std::cout << "PUT" << " " << fileName << " " << fileLength << std::endl;
|
||||
FileIO writeFile(fileName, FileIO::ByteOrder::LittleEndian, FileIO::Mode::ReadWrite,FileIO::CreationFlags::CreateAlways);
|
||||
|
||||
if(!writeFile.isOkay())
|
||||
{
|
||||
std::cout << "Error creating " << fileName << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
while(true)
|
||||
{
|
||||
readLine(strLine);
|
||||
strLine.makeBlock(subCommands, "|");
|
||||
if(subCommands.size()!=2 || !(subCommands[0]=="PCKT"))
|
||||
{
|
||||
std::cout << "Unexpected command sequence" << std::endl;
|
||||
break;
|
||||
}
|
||||
int bufferLength = subCommands[1].toLong();
|
||||
if(0==bufferLength)
|
||||
{
|
||||
std::cout << "Client indicated end of data" << std::endl;
|
||||
break;
|
||||
}
|
||||
receiveBuffer.size(bufferLength);
|
||||
size_t bytes_read = read(receiveBuffer);
|
||||
totalBytesRead+=bytes_read;
|
||||
if(bufferLength!=bytes_read)
|
||||
{
|
||||
std::cout << "Send/Receive size mismatch. The client indicated a data length of " << bufferLength << " but a data length of " << bytes_read << " was received";
|
||||
break;
|
||||
}
|
||||
writeFile.write(&receiveBuffer[0], receiveBuffer.size());
|
||||
|
||||
double percent = ((double)totalBytesRead / (double)fileLength)*100.00;
|
||||
if(Utility::fmod(percent,10.00,0.0078125))
|
||||
{
|
||||
double elapsedTimeSeconds = profiler.elapsed()/1000.00;
|
||||
double bytesPerSecond = totalBytesRead / elapsedTimeSeconds;
|
||||
String strBytesPerSecond = Utility::bytesTransferredToString(bytesPerSecond);
|
||||
std::cout << "Transferred " << totalBytesRead << " of " << fileLength << " " << percent << " percent " << strBytesPerSecond << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
std::cout << "Transfer complete" << std::endl;
|
||||
std::cout << "Received " << totalBytesRead << std::endl;
|
||||
writeFile.close();
|
||||
return totalBytesRead==fileLength;
|
||||
}
|
||||
|
||||
size_t SocketConnectionReceiver::readLine(String &line)
|
||||
{
|
||||
size_t bytes_read = 0;
|
||||
size_t total_bytes = 0;
|
||||
char ch;
|
||||
|
||||
char *lpLineBuffer = (char*)line;
|
||||
while (total_bytes < line.lengthBytes() - 1)
|
||||
{
|
||||
bytes_read = ::recv(mSocket, &ch, 1, 0);
|
||||
if (bytes_read <= 0)
|
||||
{
|
||||
return bytes_read;
|
||||
}
|
||||
if (ch=='\r') // Carriage return
|
||||
{
|
||||
recv(mSocket, &ch, 1, 0); // consume the line feed
|
||||
break;
|
||||
}
|
||||
lpLineBuffer[total_bytes++] = ch;
|
||||
}
|
||||
lpLineBuffer[total_bytes] = '\0';
|
||||
return total_bytes;
|
||||
}
|
||||
|
||||
size_t SocketConnectionReceiver::read(Array<char> &buffer)
|
||||
{
|
||||
size_t bytes_read = 0;
|
||||
size_t bytes_to_read = buffer.size();
|
||||
size_t total_bytes_read =0;
|
||||
|
||||
char *lpLineBuffer = (char*)&buffer[0];
|
||||
while(bytes_to_read>0)
|
||||
{
|
||||
bytes_read = ::recv(mSocket, lpLineBuffer, bytes_to_read, 0);
|
||||
lpLineBuffer+=bytes_read;
|
||||
bytes_to_read -= bytes_read;
|
||||
total_bytes_read += bytes_read;
|
||||
}
|
||||
return total_bytes_read;
|
||||
}
|
||||
35
listener/SocketConnectionReceiver.hpp
Normal file
35
listener/SocketConnectionReceiver.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef _LISTENER_SOCKETCONNECTIONRECEIVER_HPP_
|
||||
#define _LISTENER_SOCKETCONNECTIONRECEIVER_HPP_
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <thread>
|
||||
#include <common/string.hpp>
|
||||
#include <common/profiler.hpp>
|
||||
#include <common/block.hpp>
|
||||
#include <common/fileio.hpp>
|
||||
|
||||
class SocketConnectionReceiver
|
||||
{
|
||||
public:
|
||||
SocketConnectionReceiver(int socket, sockaddr_in inernalSocketAddress);
|
||||
virtual ~SocketConnectionReceiver();
|
||||
void close(void);
|
||||
private:
|
||||
static constexpr size_t BUFFER_LENGTH=65536; // this is the buffer length for the socket
|
||||
void threadFunction(int data);
|
||||
bool handlePut(Block<String> &commands);
|
||||
size_t readLine(String &line);
|
||||
size_t read(Array<char> &buffer);
|
||||
String restoreFileName(Block<String> block,DWORD startIndex,DWORD endIndex);
|
||||
|
||||
friend class SocketServer;
|
||||
char mBuffer[BUFFER_LENGTH] = {0};
|
||||
int mSocket;
|
||||
sockaddr_in mInternalSocketAddress;
|
||||
};
|
||||
#endif
|
||||
85
listener/SocketServer.cpp
Normal file
85
listener/SocketServer.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
#include <listener/SocketServer.hpp>
|
||||
#include <listener/SocketConnectionReceiver.hpp>
|
||||
|
||||
/// @brief This will construct the socket listener. You must then call listen() to listen for connections
|
||||
/// @param port
|
||||
SocketServer::SocketServer(int port)
|
||||
: mListenPort(port), mIsOkay(false), mSocketFileDescriptor(-1)
|
||||
{
|
||||
std::cout << "SocketServer()" << std::endl;
|
||||
int opt=-1;
|
||||
int result;
|
||||
|
||||
// create socket file descriptor
|
||||
mSocketFileDescriptor = ::socket(AF_INET,SOCK_STREAM,0);
|
||||
if(0==mSocketFileDescriptor)return;
|
||||
|
||||
// attach socket to port
|
||||
result = ::setsockopt(mSocketFileDescriptor, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));
|
||||
if(result)
|
||||
{
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
// bind socket to network address and port
|
||||
mInternalSocketAddress.sin_family = AF_INET;
|
||||
mInternalSocketAddress.sin_addr.s_addr=INADDR_ANY;
|
||||
|
||||
|
||||
mInternalSocketAddress.sin_port = htons(mListenPort);
|
||||
result = ::bind(mSocketFileDescriptor,(struct sockaddr*)&mInternalSocketAddress,sizeof(mInternalSocketAddress));
|
||||
if(result)
|
||||
{
|
||||
close();
|
||||
return;
|
||||
}
|
||||
mIsOkay=true;
|
||||
}
|
||||
|
||||
SocketServer::~SocketServer()
|
||||
{
|
||||
std::cout << "~SocketServer()" << std::endl;
|
||||
close();
|
||||
}
|
||||
|
||||
bool SocketServer::isOkay(void)
|
||||
{
|
||||
return mIsOkay;
|
||||
}
|
||||
|
||||
void SocketServer::listen(void)
|
||||
{
|
||||
while(isOkay())
|
||||
{
|
||||
std::cout << "Listening on port " << mListenPort << std::endl;
|
||||
int result = ::listen(mSocketFileDescriptor, MAX_CONNECTIONS);
|
||||
if(result)
|
||||
{
|
||||
std::cout << "Error listening on port " << mListenPort << std::endl;
|
||||
close();
|
||||
return;
|
||||
}
|
||||
struct sockaddr_in internalSocketAddress;
|
||||
socklen_t addressLength = sizeof(internalSocketAddress);
|
||||
|
||||
int socket = ::accept(mSocketFileDescriptor, (struct sockaddr*)&internalSocketAddress, &addressLength);
|
||||
if(result)
|
||||
{
|
||||
std::cout << "Error accepting connection " << mListenPort << std::endl;
|
||||
close();
|
||||
return;
|
||||
}
|
||||
SocketConnectionReceiver socketConnectionReceiver(socket, internalSocketAddress);
|
||||
mExecutionThreads.push_back(std::thread(&SocketConnectionReceiver::threadFunction, &socketConnectionReceiver, 0));
|
||||
}
|
||||
}
|
||||
|
||||
void SocketServer::close(void)
|
||||
{
|
||||
if(-1!=mSocketFileDescriptor)
|
||||
{
|
||||
::close(mSocketFileDescriptor);
|
||||
mSocketFileDescriptor=-1;
|
||||
}
|
||||
}
|
||||
34
listener/SocketServer.hpp
Normal file
34
listener/SocketServer.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef _LISTENER_SOCKETSERVER_HPP_
|
||||
#define _LISTENER_SOCKETSERVER_HPP_
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <common/string.hpp>
|
||||
#include <common/profiler.hpp>
|
||||
#include <common/block.hpp>
|
||||
#include <common/fileio.hpp>
|
||||
|
||||
class SocketServer
|
||||
{
|
||||
public:
|
||||
SocketServer(int port);
|
||||
virtual ~SocketServer();
|
||||
void listen(void);
|
||||
void close(void);
|
||||
bool isOkay(void);
|
||||
private:
|
||||
static constexpr int MAX_CONNECTIONS=10; // The maximum connections to be queued at a time
|
||||
bool mIsOkay;
|
||||
int mListenPort;
|
||||
int mSocketFileDescriptor;
|
||||
struct sockaddr_in mInternalSocketAddress;
|
||||
socklen_t mAddressLength = sizeof(mInternalSocketAddress);
|
||||
std::vector<std::thread> mExecutionThreads;
|
||||
};
|
||||
#endif
|
||||
101
listener/main.cpp
Normal file
101
listener/main.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <common/string.hpp>
|
||||
#include <common/profiler.hpp>
|
||||
#include <common/block.hpp>
|
||||
#include <common/fileio.hpp>
|
||||
#include <common/utility.hpp>
|
||||
#include <listener/SocketServer.hpp>
|
||||
#include <listener/ClientSocketSender.hpp>
|
||||
|
||||
// https://www.man7.org/linux/man-pages/man2/accept.2.html
|
||||
|
||||
void handleServer(Block<String> &commands);
|
||||
void handleClient(Block<String> &commands);
|
||||
|
||||
/// @brief
|
||||
/// @param argc
|
||||
/// @param argv [0] program. [1] SERVERMODE {port} [2] CLIENTMODE {serveripaddress} {serverport} SEND {FileName}
|
||||
/// @return
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Profiler profiler;
|
||||
|
||||
if(argc<2)
|
||||
{
|
||||
std::cout << "listener SERVERMODE {port} | CLIENTMODE {serveripaddress} {serverport} SEND {FileName}" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
Block<String> arguments;
|
||||
for(int index=0;index<argc;index++)
|
||||
{
|
||||
String item(argv[index]);
|
||||
arguments.insert(item);
|
||||
}
|
||||
|
||||
std::cout << argv[1] << std::endl;
|
||||
if(arguments[1]=="SERVERMODE")
|
||||
{
|
||||
handleServer(arguments);
|
||||
}
|
||||
else if(arguments[1]=="CLIENTMODE")
|
||||
{
|
||||
handleClient(arguments);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Unknown command " << arguments[1] << std::endl;
|
||||
}
|
||||
return 0;
|
||||
|
||||
std::cout << "Done, total took " << profiler.end() << "(ms)" << std::endl;
|
||||
}
|
||||
|
||||
/// @brief [0]=program [1]=SERVERMODE [2]={port}
|
||||
/// @param commands
|
||||
void handleServer(Block<String> &commands)
|
||||
{
|
||||
Profiler profiler;
|
||||
|
||||
if(commands.size()!=3)
|
||||
{
|
||||
std::cout << "Missing required parameters" << std::endl;
|
||||
return;
|
||||
}
|
||||
int port = commands[2].toInt();
|
||||
std::cout << commands[1] << ":" << commands[2] << std::endl;
|
||||
SocketServer socketServer(commands[2].toInt());
|
||||
socketServer.listen();
|
||||
std::cout << "Done, total took " << profiler.end() << "(ms)" << std::endl;
|
||||
}
|
||||
|
||||
/// @brief [0]=program, [1]=CLIENTMODE, [2]=serveripaddress, [3]=serverport, [4]=pathfilename
|
||||
/// @param commands
|
||||
void handleClient(Block<String> &commands)
|
||||
{
|
||||
Profiler profiler;
|
||||
if(commands.size()!=5)
|
||||
{
|
||||
std::cout << "Missing required parameters" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
ClientSocketSender clientSocketSender(commands[2],commands[3].toInt());
|
||||
bool returnCode = clientSocketSender.sendFile(commands[4]);
|
||||
if(!returnCode)
|
||||
{
|
||||
std::cout << "The transfer failed." << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Transfer complete" << std::endl;
|
||||
}
|
||||
std::cout << "Done, total took " << profiler.end() << "(ms)" << std::endl;
|
||||
}
|
||||
435
listener/scraps.txt
Normal file
435
listener/scraps.txt
Normal file
@@ -0,0 +1,435 @@
|
||||
// class ClientSocketSender
|
||||
// {
|
||||
// public:
|
||||
// ClientSocketSender(String ipAddress,int port);
|
||||
// virtual ~ClientSocketSender();
|
||||
// bool sendFile(String &pathFileName);
|
||||
// bool isOkay(void);
|
||||
// private:
|
||||
// static constexpr int BUFFER_LENGTH=65536;
|
||||
// void close(void);
|
||||
// bool sendPacketIndicator(long bytesToSend);
|
||||
// bool sendPacket(Array<char> &buffer,long bytesToSend);
|
||||
// bool sendPutIndicator(String fileName,long fileLength);
|
||||
// bool sendQuit(void);
|
||||
|
||||
// struct sockaddr_in mInternalSocketAddress;
|
||||
// int mSocket;
|
||||
// String mIPAddress;
|
||||
// int mPort;
|
||||
// };
|
||||
|
||||
// inline
|
||||
// ClientSocketSender::ClientSocketSender(String ipAddress, int port)
|
||||
// : mIPAddress(ipAddress), mPort(port)
|
||||
// {
|
||||
// mSocket = ::socket(AF_INET,SOCK_STREAM,0);
|
||||
// if(!isOkay())
|
||||
// {
|
||||
// std::cout << "Unable to initialize socket " << std::endl;
|
||||
// return;
|
||||
// }
|
||||
// mInternalSocketAddress.sin_family = AF_INET;
|
||||
// mInternalSocketAddress.sin_port= ::htons(mPort);
|
||||
// int result = ::inet_pton(AF_INET, ipAddress.str(), &mInternalSocketAddress.sin_addr);
|
||||
// if(result<0)
|
||||
// {
|
||||
// std::cout << "Unable to convert ipaddress to network address" << std::endl;
|
||||
// close();
|
||||
// return;
|
||||
// }
|
||||
// result = ::connect(mSocket, (struct sockaddr*)&mInternalSocketAddress, sizeof(mInternalSocketAddress));
|
||||
// if(result<0)
|
||||
// {
|
||||
// close();
|
||||
// std::cout << "Unable to connect to host " << mIPAddress << ":" << mPort << std::endl;
|
||||
// }
|
||||
// }
|
||||
|
||||
// inline
|
||||
// ClientSocketSender::~ClientSocketSender()
|
||||
// {
|
||||
// close();
|
||||
// }
|
||||
|
||||
// inline
|
||||
// void ClientSocketSender::close(void)
|
||||
// {
|
||||
// if(-1!=mSocket)
|
||||
// {
|
||||
// ::close(mSocket);
|
||||
// mSocket=-1;
|
||||
// }
|
||||
// }
|
||||
|
||||
// inline
|
||||
// bool ClientSocketSender::sendFile(String &pathFileName)
|
||||
// {
|
||||
// FileIO readFile(pathFileName, FileIO::ByteOrder::LittleEndian, FileIO::Mode::ReadOnly, FileIO::CreationFlags::None);
|
||||
// if(!readFile.isOkay())
|
||||
// {
|
||||
// std::cout << "File open failed " << pathFileName << std::endl;
|
||||
// return false;
|
||||
// }
|
||||
// readFile.setBufferLength(BUFFER_LENGTH);
|
||||
// DWORD fileLength = readFile.size();
|
||||
// sendPutIndicator(pathFileName, fileLength);
|
||||
// Array<char> readBuffer;
|
||||
// readBuffer.size(BUFFER_LENGTH);
|
||||
// while(true)
|
||||
// {
|
||||
// size_t bytesRead = readFile.read(&readBuffer[0], readBuffer.size());
|
||||
// if(0==bytesRead)
|
||||
// {
|
||||
// std::cout << "No data was read from the file" << std::endl;
|
||||
// break;
|
||||
// }
|
||||
// sendPacketIndicator(bytesRead);
|
||||
// sendPacket(readBuffer, bytesRead);
|
||||
// if(bytesRead<readBuffer.size())break;
|
||||
// }
|
||||
// sendPacketIndicator(0);
|
||||
// sendQuit();
|
||||
// readFile.close();
|
||||
// std::cout << "SendFile complete" << std::endl;
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// bool ClientSocketSender::sendPacketIndicator(long bytesToSend)
|
||||
// {
|
||||
// if(!isOkay())return false;
|
||||
// String packetIndicator = "PCKT|";
|
||||
// packetIndicator+=String().fromInt(bytesToSend);
|
||||
// packetIndicator+="\r\n";
|
||||
// ::send(mSocket, (char*)packetIndicator, packetIndicator.length(),0);
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// bool ClientSocketSender::sendPutIndicator(String fileName,long fileLength)
|
||||
// {
|
||||
// if(!isOkay())return false;
|
||||
// Block<String> parts = fileName.split('/');
|
||||
// String pureFileName = parts[parts.size()-1];
|
||||
// String putIndicator = "PUT|";
|
||||
// putIndicator+=pureFileName;
|
||||
// putIndicator+="|";
|
||||
// putIndicator+=String().fromInt(fileLength);
|
||||
// putIndicator+="\r\n";
|
||||
// ::send(mSocket, (char*)putIndicator, putIndicator.length(),0);
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// inline
|
||||
// bool ClientSocketSender::sendQuit(void)
|
||||
// {
|
||||
// if(!isOkay())return false;
|
||||
// String quitIndicator = "QUIT\r\n";
|
||||
// ::send(mSocket, (char*)quitIndicator, quitIndicator.length(),0);
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// inline
|
||||
// bool ClientSocketSender::sendPacket(Array<char> &buffer,long bytesToSend)
|
||||
// {
|
||||
// if(!isOkay())return false;
|
||||
// ::send(mSocket, (char*)&buffer[0], bytesToSend,0);
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// inline
|
||||
// bool ClientSocketSender::isOkay(void)
|
||||
// {
|
||||
// return -1==mSocket?false:true;
|
||||
// }
|
||||
|
||||
// ***********************************************************************************************************************************************************
|
||||
// ***********************************************************************************************************************************************************
|
||||
// ***********************************************************************************************************************************************************
|
||||
|
||||
// class SocketConnectionReceiver
|
||||
// {
|
||||
// public:
|
||||
// SocketConnectionReceiver(int socket, sockaddr_in inernalSocketAddress);
|
||||
// virtual ~SocketConnectionReceiver();
|
||||
// void close(void);
|
||||
// private:
|
||||
// static constexpr int BUFFER_LENGTH=65536; // this is the buffer length for the socket
|
||||
// void threadFunction(int data);
|
||||
// bool handlePut(Block<String> &commands);
|
||||
// int readLine(String &line);
|
||||
// long read(Array<char> &buffer);
|
||||
// String restoreFileName(Block<String> block,DWORD startIndex,DWORD endIndex);
|
||||
|
||||
// friend class SocketServer;
|
||||
// char mBuffer[BUFFER_LENGTH] = {0};
|
||||
// int mSocket;
|
||||
// sockaddr_in mInternalSocketAddress;
|
||||
// };
|
||||
|
||||
// inline
|
||||
// SocketConnectionReceiver::SocketConnectionReceiver(int socket, sockaddr_in internalSocketAddress)
|
||||
// : mSocket(socket), mInternalSocketAddress(internalSocketAddress)
|
||||
// {
|
||||
// }
|
||||
|
||||
// inline
|
||||
// SocketConnectionReceiver::~SocketConnectionReceiver()
|
||||
// {
|
||||
// }
|
||||
|
||||
// inline
|
||||
// void SocketConnectionReceiver::close(void)
|
||||
// {
|
||||
// if(-1==mSocket)return;
|
||||
// std::cout << "Closing connection " << mSocket << std::endl;
|
||||
// ::close(mSocket);
|
||||
// mSocket=-1;
|
||||
// }
|
||||
|
||||
// inline
|
||||
// void SocketConnectionReceiver::threadFunction(int data)
|
||||
// {
|
||||
// String line;
|
||||
// while(true)
|
||||
// {
|
||||
// readLine(line);
|
||||
// if(0==line.length())
|
||||
// {
|
||||
// std::cout << "Received an empty command" << std::endl;
|
||||
// break;
|
||||
// }
|
||||
// // std::cout << "'" << (char*)line << "'" << std::endl;
|
||||
// if(line=="QUIT" || line=="quit")break;
|
||||
// Block<String> commands = line.split('|');
|
||||
// if(0==commands.size())continue;
|
||||
// std::cout << commands[0] << std::endl;
|
||||
// commands[0].upper();
|
||||
// if(commands[0]=="PUT")
|
||||
// {
|
||||
// handlePut(commands);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// std::cout << "Unrecognized command >" << line << "<" << std::endl;
|
||||
// }
|
||||
// }
|
||||
// close();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// /// @brief The client wants to put a file. put {filename} {lengthbytes}
|
||||
// /// @param commands [0]=PUT, [1]=filename, [2]=total length
|
||||
// /// This will read PCKT {length}.
|
||||
// /// The connection will continue reading and writing until it receives PCKT 0
|
||||
// /// @return
|
||||
// inline
|
||||
// bool SocketConnectionReceiver::handlePut(Block<String> &commands)
|
||||
// {
|
||||
// Array<char> receiveBuffer;
|
||||
// Block<String> subCommands;
|
||||
// String strLine;
|
||||
// String fileName;
|
||||
// long fileLength;
|
||||
// long totalBytesRead=0;
|
||||
|
||||
// fileName = commands[1];
|
||||
// fileLength = commands[commands.size()-1].toLong();
|
||||
// std::cout << "PUT" << " " << fileName << " " << fileLength << std::endl;
|
||||
// FileIO writeFile(fileName, FileIO::ByteOrder::LittleEndian, FileIO::Mode::ReadWrite,FileIO::CreationFlags::CreateAlways);
|
||||
// if(!writeFile.isOkay())
|
||||
// {
|
||||
// std::cout << "Error creating " << fileName << std::endl;
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// while(true)
|
||||
// {
|
||||
// readLine(strLine);
|
||||
// strLine.makeBlock(subCommands, "|");
|
||||
// if(subCommands.size()!=2 || !(subCommands[0]=="PCKT"))
|
||||
// {
|
||||
// std::cout << "Unexpected command sequence" << std::endl;
|
||||
// break;
|
||||
// }
|
||||
// int bufferLength = subCommands[1].toLong();
|
||||
// if(0==bufferLength)
|
||||
// {
|
||||
// std::cout << "Client indicated end of data" << std::endl;
|
||||
// break;
|
||||
// }
|
||||
// receiveBuffer.size(bufferLength);
|
||||
// long bytes_read = read(receiveBuffer);
|
||||
// totalBytesRead+=bytes_read;
|
||||
// if(bufferLength!=bytes_read)
|
||||
// {
|
||||
// std::cout << "Send/Receive size mismatch. The client indicated a data length of " << bufferLength << " but a data length of " << bytes_read << " was received";
|
||||
// break;
|
||||
// }
|
||||
// writeFile.write(&receiveBuffer[0], receiveBuffer.size());
|
||||
// int percent = ((double)totalBytesRead / (double)fileLength)*100.00;
|
||||
// if(0==(percent%10))
|
||||
// {
|
||||
// std::cout << "Transferred " << totalBytesRead << " of " << fileLength << " " << percent << " percent" << std::endl;
|
||||
// }
|
||||
|
||||
// }
|
||||
// std::cout << "Transfer complete" << std::endl;
|
||||
// std::cout << "Received " << totalBytesRead << std::endl;
|
||||
// writeFile.close();
|
||||
// return totalBytesRead==fileLength;
|
||||
// }
|
||||
|
||||
// inline
|
||||
// int SocketConnectionReceiver::readLine(String &line)
|
||||
// {
|
||||
// int bytes_read = 0;
|
||||
// int total_bytes = 0;
|
||||
// char ch;
|
||||
|
||||
// char *lpLineBuffer = (char*)line;
|
||||
// while (total_bytes < line.lengthBytes() - 1)
|
||||
// {
|
||||
// bytes_read = ::recv(mSocket, &ch, 1, 0);
|
||||
// if (bytes_read <= 0)
|
||||
// {
|
||||
// return bytes_read;
|
||||
// }
|
||||
// if (ch=='\r') // Carriage return
|
||||
// {
|
||||
// recv(mSocket, &ch, 1, 0); // consume the line feed
|
||||
// break;
|
||||
// }
|
||||
// lpLineBuffer[total_bytes++] = ch;
|
||||
// }
|
||||
// lpLineBuffer[total_bytes] = '\0';
|
||||
// return total_bytes;
|
||||
// }
|
||||
|
||||
// inline
|
||||
// long SocketConnectionReceiver::read(Array<char> &buffer)
|
||||
// {
|
||||
// long bytes_read = 0;
|
||||
// long bytes_to_read = buffer.size();
|
||||
// long total_bytes_read =0;
|
||||
|
||||
// char *lpLineBuffer = (char*)&buffer[0];
|
||||
// while(bytes_to_read>0)
|
||||
// {
|
||||
// bytes_read = ::recv(mSocket, lpLineBuffer, bytes_to_read, 0);
|
||||
// lpLineBuffer+=bytes_read;
|
||||
// bytes_to_read -= bytes_read;
|
||||
// total_bytes_read += bytes_read;
|
||||
// }
|
||||
// return total_bytes_read;
|
||||
// }
|
||||
|
||||
// ***********************************************************************************************************************************************************
|
||||
// ***********************************************************************************************************************************************************
|
||||
// ***********************************************************************************************************************************************************
|
||||
|
||||
|
||||
// class SocketServer
|
||||
// {
|
||||
// public:
|
||||
// SocketServer(int port);
|
||||
// virtual ~SocketServer();
|
||||
// void listen(void);
|
||||
// void close(void);
|
||||
// bool isOkay(void);
|
||||
// private:
|
||||
|
||||
// static constexpr int MAX_CONNECTIONS=10; // The maximum connections to be queued at a time
|
||||
// bool mIsOkay;
|
||||
// int mListenPort;
|
||||
// int mSocketFileDescriptor;
|
||||
// struct sockaddr_in mInternalSocketAddress;
|
||||
// socklen_t mAddressLength = sizeof(mInternalSocketAddress);
|
||||
// std::vector<std::thread> mExecutionThreads;
|
||||
// };
|
||||
|
||||
// /// @brief This will construct the socket listener. You must then call listen() to listen for connections
|
||||
// /// @param port
|
||||
// inline
|
||||
// SocketServer::SocketServer(int port)
|
||||
// : mListenPort(port), mIsOkay(false), mSocketFileDescriptor(-1)
|
||||
// {
|
||||
// std::cout << "SocketServer()" << std::endl;
|
||||
// int opt=-1;
|
||||
// int result;
|
||||
|
||||
// // create socket file descriptor
|
||||
// mSocketFileDescriptor = ::socket(AF_INET,SOCK_STREAM,0);
|
||||
// if(0==mSocketFileDescriptor)return;
|
||||
|
||||
// // attach socket to port
|
||||
// result = ::setsockopt(mSocketFileDescriptor, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));
|
||||
// if(result)
|
||||
// {
|
||||
// close();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // bind socket to network address and port
|
||||
// mInternalSocketAddress.sin_family = AF_INET;
|
||||
// mInternalSocketAddress.sin_addr.s_addr=INADDR_ANY;
|
||||
|
||||
|
||||
// mInternalSocketAddress.sin_port = htons(mListenPort);
|
||||
// result = ::bind(mSocketFileDescriptor,(struct sockaddr*)&mInternalSocketAddress,sizeof(mInternalSocketAddress));
|
||||
// if(result)
|
||||
// {
|
||||
// close();
|
||||
// return;
|
||||
// }
|
||||
// mIsOkay=true;
|
||||
// }
|
||||
|
||||
// inline
|
||||
// SocketServer::~SocketServer()
|
||||
// {
|
||||
// std::cout << "~SocketServer()" << std::endl;
|
||||
// close();
|
||||
// }
|
||||
|
||||
// inline
|
||||
// bool SocketServer::isOkay(void)
|
||||
// {
|
||||
// return mIsOkay;
|
||||
// }
|
||||
|
||||
// inline
|
||||
// void SocketServer::listen(void)
|
||||
// {
|
||||
// while(isOkay())
|
||||
// {
|
||||
// std::cout << "Listening on port " << mListenPort << std::endl;
|
||||
// int result = ::listen(mSocketFileDescriptor, MAX_CONNECTIONS);
|
||||
// if(result)
|
||||
// {
|
||||
// std::cout << "Error listening on port " << mListenPort << std::endl;
|
||||
// close();
|
||||
// return;
|
||||
// }
|
||||
// struct sockaddr_in internalSocketAddress;
|
||||
// socklen_t addressLength = sizeof(internalSocketAddress);
|
||||
|
||||
// int socket = ::accept(mSocketFileDescriptor, (struct sockaddr*)&internalSocketAddress, &addressLength);
|
||||
// if(result)
|
||||
// {
|
||||
// std::cout << "Error accepting connection " << mListenPort << std::endl;
|
||||
// close();
|
||||
// return;
|
||||
// }
|
||||
// SocketConnectionReceiver socketConnectionReceiver(socket, internalSocketAddress);
|
||||
// mExecutionThreads.push_back(std::thread(&SocketConnectionReceiver::threadFunction, &socketConnectionReceiver, 0));
|
||||
// }
|
||||
// }
|
||||
|
||||
// inline
|
||||
// void SocketServer::close(void)
|
||||
// {
|
||||
// if(-1!=mSocketFileDescriptor)
|
||||
// {
|
||||
// mSocketFileDescriptor=-1;
|
||||
// }
|
||||
// }
|
||||
Reference in New Issue
Block a user