<commit_before>/**
    Copyright (c) 2009 James Wynn (james@jameswynn.com)

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
*/

#include <filesentry/FileWatcherWin32.h>

#if FILEWATCHER_PLATFORM == FILEWATCHER_PLATFORM_WIN32

//#define _WIN32_WINNT 0x0550
#include <windows.h>

#if defined(_MSC_VER)
#pragma comment(lib, "comctl32.lib")
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "ole32.lib")

// disable secure warnings
#pragma warning (disable: 4996)
#endif

namespace fs
{
    /// Internal watch data
    struct WatchStruct
    {
        OVERLAPPED mOverlapped;
        HANDLE mDirHandle;
        BYTE mBuffer[32 * 1024];
        LPARAM lParam;
        DWORD mNotifyFilter;
        bool mStopNow;
        FileWatcherImpl* mFileWatcher;
        std::function<void(
            WatchID watchid,
            const String& dir,
            const String& filename,
            Action action)> mFileWatchListener;
        char* mDirName;
        WatchID mWatchid;
        bool mIsRecursive;
    };

//#pragma region Internal Functions

    // forward decl
    bool RefreshWatch(WatchStruct* pWatch, bool _clear = false);

    /// Unpacks events and passes them to a user defined callback.
    void CALLBACK WatchCallback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped)
    {
        TCHAR szFile[MAX_PATH];
        PFILE_NOTIFY_INFORMATION pNotify;
        WatchStruct* pWatch = (WatchStruct*) lpOverlapped;
        size_t offset = 0;

        if(dwNumberOfBytesTransfered == 0)
            return;

        if (dwErrorCode == ERROR_SUCCESS)
        {
            do
            {
                pNotify = (PFILE_NOTIFY_INFORMATION) &pWatch->mBuffer[offset];
                offset += pNotify->NextEntryOffset;

#			if defined(UNICODE)
                {
                    lstrcpynW(szFile, pNotify->FileName,
                        min(MAX_PATH, pNotify->FileNameLength / sizeof(WCHAR) + 1));
                }
#			else
                {
                    int count = WideCharToMultiByte(CP_ACP, 0, pNotify->FileName,
                        pNotify->FileNameLength / sizeof(WCHAR),
                        szFile, MAX_PATH - 1, NULL, NULL);
                    szFile[count] = TEXT('\0');
                }
#			endif

                pWatch->mFileWatcher->handleAction(pWatch, szFile, pNotify->Action);

            } while (pNotify->NextEntryOffset != 0);
        }

        if (!pWatch->mStopNow)
        {
            RefreshWatch(pWatch);
        }
    }

    /// Refreshes the directory monitoring.
    bool RefreshWatch(WatchStruct* pWatch, bool _clear)
    {
        return ReadDirectoryChangesW(
            pWatch->mDirHandle, pWatch->mBuffer, sizeof(pWatch->mBuffer), pWatch->mIsRecursive,
            pWatch->mNotifyFilter, NULL, &pWatch->mOverlapped, _clear ? 0 : WatchCallback) != 0;
    }

    /// Stops monitoring a directory.
    void DestroyWatch(WatchStruct* pWatch)
    {
        if (pWatch)
        {
            pWatch->mStopNow = TRUE;

            CancelIo(pWatch->mDirHandle);

            RefreshWatch(pWatch, true);

            if (!HasOverlappedIoCompleted(&pWatch->mOverlapped))
            {
                SleepEx(5, TRUE);
            }

            CloseHandle(pWatch->mOverlapped.hEvent);
            CloseHandle(pWatch->mDirHandle);
            delete pWatch->mDirName;
            HeapFree(GetProcessHeap(), 0, pWatch);
        }
    }

    /// Starts monitoring a directory.
    WatchStruct* CreateWatch(LPCTSTR szDirectory, bool recursive, DWORD mNotifyFilter)
    {
        WatchStruct* pWatch;
        size_t ptrsize = sizeof(*pWatch);
        pWatch = static_cast<WatchStruct*>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptrsize));

        pWatch->mDirHandle = CreateFile(szDirectory, FILE_LIST_DIRECTORY,
            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
            OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL);

        if (pWatch->mDirHandle != INVALID_HANDLE_VALUE)
        {
            pWatch->mOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
            pWatch->mNotifyFilter = mNotifyFilter;
            pWatch->mIsRecursive = recursive;

            if (RefreshWatch(pWatch))
            {
                return pWatch;
            }
            else
            {
                CloseHandle(pWatch->mOverlapped.hEvent);
                CloseHandle(pWatch->mDirHandle);
            }
        }

        HeapFree(GetProcessHeap(), 0, pWatch);
        return nullptr;
    }

//#pragma endregion

    //--------
    FileWatcherWin32::FileWatcherWin32()
        : mLastWatchID(0)
    {
    }

    //--------
    FileWatcherWin32::~FileWatcherWin32()
    {
        WatchMap::iterator iter = mWatches.begin();
        WatchMap::iterator end = mWatches.end();
        for(; iter != end; ++iter)
        {
            DestroyWatch(iter->second);
        }
        mWatches.clear();
    }

    //--------
    WatchID FileWatcherWin32::addWatch(const String& directory, std::function<void(WatchID watchid, const String& dir, const String& filename, Action action)> watcher, bool recursive)
    {
        WatchID watchid = ++mLastWatchID;

        WatchStruct* watch = CreateWatch(directory.c_str(), recursive,
            FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_FILE_NAME);

        if(!watch)
            throw FileNotFoundException(directory);

        watch->mWatchid = watchid;
        watch->mFileWatcher = this;
        watch->mFileWatchListener = watcher;
        watch->mDirName = new char[directory.length()+1];
        strcpy(watch->mDirName, directory.c_str());

        mWatches.insert(std::make_pair(watchid, watch));

        return watchid;
    }

    //--------
    void FileWatcherWin32::removeWatch(const String& directory)
    {
        WatchMap::iterator iter = mWatches.begin();
        WatchMap::iterator end = mWatches.end();
        for(; iter != end; ++iter)
        {
            if(directory == iter->second->mDirName)
            {
                removeWatch(iter->first);
                return;
            }
        }
    }

    //--------
    void FileWatcherWin32::removeWatch(WatchID watchid)
    {
        WatchMap::iterator iter = mWatches.find(watchid);

        if(iter == mWatches.end())
            return;

        WatchStruct* watch = iter->second;
        mWatches.erase(iter);

        DestroyWatch(watch);
    }

    //--------
    void FileWatcherWin32::update()
    {
        MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, MWMO_ALERTABLE);
    }

    //--------
    void FileWatcherWin32::handleAction(WatchStruct* watch, const String& filename, unsigned long action)
    {
        Action fwAction;

        switch(action)
        {
        case FILE_ACTION_RENAMED_NEW_NAME:
        case FILE_ACTION_ADDED:
            fwAction = Actions::Add;
            break;
        case FILE_ACTION_RENAMED_OLD_NAME:
        case FILE_ACTION_REMOVED:
            fwAction = Actions::Delete;
            break;
        case FILE_ACTION_MODIFIED:
            fwAction = Actions::Modified;
            break;
        };

        watch->mFileWatchListener.operator()(watch->mWatchid, watch->mDirName, filename, fwAction);
    }

} //namespace fs

#endif//_WIN32
<commit_msg>Fix windows compiler warnings<commit_after>/**
    Copyright (c) 2009 James Wynn (james@jameswynn.com)

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
*/

#include <filesentry/FileWatcherWin32.h>

#if FILEWATCHER_PLATFORM == FILEWATCHER_PLATFORM_WIN32

//#define _WIN32_WINNT 0x0550
#include <windows.h>

#if defined(_MSC_VER)
#pragma comment(lib, "comctl32.lib")
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "ole32.lib")

// disable secure warnings
#pragma warning (disable: 4996)
#endif

namespace fs
{
    /// Internal watch data
    struct WatchStruct
    {
        OVERLAPPED mOverlapped;
        HANDLE mDirHandle;
        BYTE mBuffer[32 * 1024];
        LPARAM lParam;
        DWORD mNotifyFilter;
        bool mStopNow;
        FileWatcherImpl* mFileWatcher;
        std::function<void(
            WatchID watchid,
            const String& dir,
            const String& filename,
            Action action)> mFileWatchListener;
        char* mDirName;
        WatchID mWatchid;
        bool mIsRecursive;
    };

//#pragma region Internal Functions

    // forward decl
    bool RefreshWatch(WatchStruct* pWatch, bool _clear = false);

    /// Unpacks events and passes them to a user defined callback.
    void CALLBACK WatchCallback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped)
    {
        // TCHAR is wide char if UNICODE has been defined
        // otherwise it's just regular char
        TCHAR szFile[MAX_PATH];
        PFILE_NOTIFY_INFORMATION pNotify;
        WatchStruct* pWatch = (WatchStruct*) lpOverlapped;
        size_t offset = 0;

        if(dwNumberOfBytesTransfered == 0)
            return;

        if (dwErrorCode == ERROR_SUCCESS)
        {
            do
            {
                pNotify = (PFILE_NOTIFY_INFORMATION) &pWatch->mBuffer[offset];
                offset += pNotify->NextEntryOffset;

#			if defined(UNICODE)
                {
                    lstrcpynW(szFile, pNotify->FileName,
                        min(MAX_PATH, pNotify->FileNameLength / sizeof(WCHAR) + 1));
                }
#			else
                {
                    int count = WideCharToMultiByte(CP_ACP, 0, pNotify->FileName,
                        pNotify->FileNameLength / sizeof(WCHAR),
                        szFile, MAX_PATH - 1, NULL, NULL);
                    szFile[count] = TEXT('\0');
                }
#			endif

                pWatch->mFileWatcher->handleAction(pWatch, (const char*)szFile, pNotify->Action);

            } while (pNotify->NextEntryOffset != 0);
        }

        if (!pWatch->mStopNow)
        {
            RefreshWatch(pWatch);
        }
    }

    /// Refreshes the directory monitoring.
    bool RefreshWatch(WatchStruct* pWatch, bool _clear)
    {
        return ReadDirectoryChangesW(
            pWatch->mDirHandle, pWatch->mBuffer, sizeof(pWatch->mBuffer), pWatch->mIsRecursive,
            pWatch->mNotifyFilter, NULL, &pWatch->mOverlapped, _clear ? 0 : WatchCallback) != 0;
    }

    /// Stops monitoring a directory.
    void DestroyWatch(WatchStruct* pWatch)
    {
        if (pWatch)
        {
            pWatch->mStopNow = TRUE;

            CancelIo(pWatch->mDirHandle);

            RefreshWatch(pWatch, true);

            if (!HasOverlappedIoCompleted(&pWatch->mOverlapped))
            {
                SleepEx(5, TRUE);
            }

            CloseHandle(pWatch->mOverlapped.hEvent);
            CloseHandle(pWatch->mDirHandle);
            delete pWatch->mDirName;
            HeapFree(GetProcessHeap(), 0, pWatch);
        }
    }

    /// Starts monitoring a directory.
    WatchStruct* CreateWatch(LPCTSTR szDirectory, bool recursive, DWORD mNotifyFilter)
    {
        WatchStruct* pWatch;
        size_t ptrsize = sizeof(*pWatch);
        pWatch = static_cast<WatchStruct*>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptrsize));

        pWatch->mDirHandle = CreateFile(szDirectory, FILE_LIST_DIRECTORY,
            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
            OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL);

        if (pWatch->mDirHandle != INVALID_HANDLE_VALUE)
        {
            pWatch->mOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
            pWatch->mNotifyFilter = mNotifyFilter;
            pWatch->mIsRecursive = recursive;

            if (RefreshWatch(pWatch))
            {
                return pWatch;
            }
            else
            {
                CloseHandle(pWatch->mOverlapped.hEvent);
                CloseHandle(pWatch->mDirHandle);
            }
        }

        HeapFree(GetProcessHeap(), 0, pWatch);
        return nullptr;
    }

//#pragma endregion

    //--------
    FileWatcherWin32::FileWatcherWin32()
        : mLastWatchID(0)
    {
    }

    //--------
    FileWatcherWin32::~FileWatcherWin32()
    {
        WatchMap::iterator iter = mWatches.begin();
        WatchMap::iterator end = mWatches.end();
        for(; iter != end; ++iter)
        {
            DestroyWatch(iter->second);
        }
        mWatches.clear();
    }

    //--------
    WatchID FileWatcherWin32::addWatch(const String& directory, std::function<void(WatchID watchid, const String& dir, const String& filename, Action action)> watcher, bool recursive)
    {
        WatchID watchid = ++mLastWatchID;

        // LPCTSTR is a long (regular) const pointer to TCHAR string
        // TCHAR is a wide char if UNICODE has been defined (in which case std::wstring can be used as fs::String)
        WatchStruct* watch = CreateWatch((LPCTSTR)directory.c_str(), recursive,
            FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_FILE_NAME);

        if(!watch)
            throw FileNotFoundException(directory);

        watch->mWatchid = watchid;
        watch->mFileWatcher = this;
        watch->mFileWatchListener = watcher;
        watch->mDirName = new char[directory.length()+1];
        strcpy(watch->mDirName, directory.c_str());

        mWatches.insert(std::make_pair(watchid, watch));

        return watchid;
    }

    //--------
    void FileWatcherWin32::removeWatch(const String& directory)
    {
        WatchMap::iterator iter = mWatches.begin();
        WatchMap::iterator end = mWatches.end();
        for(; iter != end; ++iter)
        {
            if(directory == iter->second->mDirName)
            {
                removeWatch(iter->first);
                return;
            }
        }
    }

    //--------
    void FileWatcherWin32::removeWatch(WatchID watchid)
    {
        WatchMap::iterator iter = mWatches.find(watchid);

        if(iter == mWatches.end())
            return;

        WatchStruct* watch = iter->second;
        mWatches.erase(iter);

        DestroyWatch(watch);
    }

    //--------
    void FileWatcherWin32::update()
    {
        MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, MWMO_ALERTABLE);
    }

    //--------
    void FileWatcherWin32::handleAction(WatchStruct* watch, const String& filename, unsigned long action)
    {
        Action fwAction;

        switch(action)
        {
        case FILE_ACTION_RENAMED_NEW_NAME:
        case FILE_ACTION_ADDED:
            fwAction = Actions::Add;
            break;
        case FILE_ACTION_RENAMED_OLD_NAME:
        case FILE_ACTION_REMOVED:
            fwAction = Actions::Delete;
            break;
        case FILE_ACTION_MODIFIED:
            fwAction = Actions::Modified;
            break;
        };

        watch->mFileWatchListener.operator()(watch->mWatchid, watch->mDirName, filename, fwAction);
    }

} //namespace fs

#endif//_WIN32
<|endoftext|>


<commit_before>/*  ===========================================================================
#  This is the library for Hover.
#
#  Hover is a development kit that lets you control your hardware projects in a whole new way.
#  Wave goodbye to physical buttons. Hover detects hand movements in the air for touch-less interaction.
#  It also features five touch-sensitive regions for even more options.
#  Hover uses I2C and 2 digital pins. It is compatible with Arduino, Raspberry Pi and more.
#
#  Hover can be purchased here: http://www.hoverlabs.co
#
#  Written by Emran Mahbub and Jonathan Li for Hover Labs.
#  BSD license, all text above must be included in any redistribution
#  ===========================================================================
#
#  INSTALLATION
#  The 3 library files (Hover.cpp, Hover.h and keywords.txt) in the Hover folder should be placed in your Arduino Library folder.
#  Run the HoverDemo.ino file from your Arduino IDE.
#
#  SUPPORT
#  For questions and comments, email us at support@hoverlabs.co
#  v3.1
#  ===========================================================================*/

#include <Hover.h>
#include <Wire.h>

#ifdef __AVR__
 #define WIRE Wire
#endif

Hover::Hover(uint8_t ts, uint8_t rst, uint8_t gestmode, uint8_t touchmode, uint8_t tapmode, uint8_t posmode) {
  _i2caddr = 0x42;
  _ts = ts;
  _rst = rst;
  _gestmode = gestmode;
  _touchmode = touchmode;
  _tapmode = tapmode;
  _posmode = posmode;
}

void Hover::begin() {
	WIRE.begin();
	pinMode(_ts, INPUT);
	pinMode(_rst, OUTPUT);
	digitalWrite(_rst, LOW);
	delay(50);
	pinMode(_rst, INPUT);

	/*disable autocal for smoother operation*/
	uint8_t autoCal[] = {0x10, 0x00, 0x00, 0xA2, 0x80, 0x00 , 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF};
    Wire.beginTransmission(_i2caddr);
    Wire.write(autoCal, 16);
    Wire.endTransmission();

	Serial.println("Hover is ready");
}

void Hover::setRelease() {
    digitalWrite(_ts, HIGH);
    pinMode(_ts, INPUT);
}

boolean Hover::getStatus() {
	if (digitalRead(_ts) == 0) {
		pinMode(_ts, OUTPUT);
		digitalWrite(_ts, LOW);
		return 0;
	}
	return 1;
}

void Hover::readI2CData(void) {
	if (getStatus() == 0){
		int c = 0;
	    WIRE.requestFrom((uint8_t)_i2caddr, (uint8_t)26);    // request 26 bytes from slave device at 0x42
	    while(WIRE.available())    // slave may send less than requested
	    {
			_dat[c] = WIRE.read(); // receive a byte as character
			c++;
		}
		setRelease();
		_valid = 1;
		delay(6);
	} else {
		_valid = 0;
	}

}

Gesture::Gesture(){
	strcpy(gestureType, "none");
	gestureID = 0;
	gestureValue = 0;
}

Gesture::Gesture (char * type, uint8_t id, uint8_t value){
	strcpy(gestureType, type);
	gestureID = id;
	gestureValue = value;
}

Gesture Hover::getGesture(void) {
	char gtype[15];
	uint8_t gid;
	uint8_t gval;

	if (_valid == 1 && _gestmode == 0x01) {
		readGestureData(gtype, &gid, &gval);
	} else {
		strcpy(gtype, "none");
		gid = 0x00;
		gval = 0x00;
	}

	return Gesture(gtype, gid, gval);
}

void Hover::readGestureData(char * gtype, uint8_t * gid, uint8_t * gval) {

	switch (_dat[10]){
		case 2:
			strcpy(gtype, "Right Swipe");
			*gid = 0x01;
			*gval = 0x01;
		break;
		case 3:
			strcpy(gtype, "Left Swipe");
			*gid = 0x01;
			*gval = 0x02;
		break;
		case 4:
			strcpy(gtype, "Up Swipe");
			*gid = 0x01;
			*gval = 0x03;
		break;
		case 5:
			strcpy(gtype, "Down Swipe");
			*gid = 0x01;
			*gval = 0x04;
		break;
		default:
			strcpy(gtype, "None");
			*gid = 0x00;
			*gval = 0x00;
		break;
	}
	if (_dat[7] & 0x02){
		strcpy(gtype, "Airspin");
		*gid = 0x02;
		*gval = _dat[18];
	}
}

Touch::Touch(){
	strcpy(touchType, "none");
	touchID = 0;
	touchValue = 0;
}

Touch::Touch (char * type, uint8_t id, uint8_t value){
	strcpy(touchType, type);
	touchID = id;
	touchValue = value;
}

Touch Hover::getTouch(void) {
	char ttype[20];
	uint8_t tid;
	uint8_t tval;

	if (_valid == 1) {
		readTouchData(ttype, &tid, &tval);
	} else {
		strcpy(ttype, "None");
		tid = 0x00;
		tval = 0x00;
	}

	return Touch(ttype, tid, tval);
}

void Hover::readTouchData(char * ttype, uint8_t * tid, uint8_t * tval) {

	uint8_t touch, tap, doubleTap;

	touch = (_touchmode==0x01) ? (touch = (_dat[14] & 0x1F)) : (0);

	if (_tapmode!=0x00){
		if (_tapmode == 0x01){
			tap = (((_dat[15] & 0x03) << 3 ) | (_dat[14]>>5));
			doubleTap = ((_dat[15]>>2) & 0x1F);
		} else {
			tap = (_tapmode==0x02) ? (tap = (((_dat[15] & 0x03) << 3 ) | (_dat[14]>>5))) : (0);
			doubleTap = (_tapmode==0x03) ? (doubleTap = ((_dat[15]>>2) & 0x1F)) : (0);
		}
	} else {
		tap = 0;
		doubleTap = 0;
	}

	if (doubleTap != 0) {
		switch (doubleTap) {
			case 1:
				strcpy(ttype, "Double Tap South");
				*tid = 0x03;
				*tval = 0x04;
			break;
			case 2:
				strcpy(ttype, "Double Tap West");
				*tid = 0x03;
				*tval = 0x02;
			break;
			case 4:
				strcpy(ttype, "Double Tap North");
				*tid = 0x03;
				*tval = 0x03;
			break;
			case 8:
				strcpy(ttype, "Double Tap East");
				*tid = 0x03;
				*tval = 0x01;
			break;
			case 16:
				strcpy(ttype, "Double Tap Center");
				*tid = 0x03;
				*tval = 0x05;
			break;
			default:
				strcpy(ttype, "None");
				*tid = 0x00;
				*tval = 0x00;
			break;
		}

	} else if (tap != 0) {
		switch (tap){
			case 1:
				strcpy(ttype, "Tap South");
				*tid = 0x02;
				*tval = 0x04;
			break;
			case 2:
				strcpy(ttype, "Tap West");
				*tid = 0x02;
				*tval = 0x02;
			break;
			case 4:
				strcpy(ttype, "Tap North");
				*tid = 0x02;
				*tval = 0x03;
			break;
			case 8:
				strcpy(ttype, "Tap East");
				*tid = 0x02;
				*tval = 0x01;
			break;
			case 16:
				strcpy(ttype, "Tap Center");
				*tid = 0x02;
				*tval = 0x05;
			break;
			default:
				strcpy(ttype, "None");
				*tid = 0x00;
				*tval = 0x00;
			break;
		}

	} else if (touch!=0) {
		switch (touch){
			case 1:
				strcpy(ttype, "Touch South");
				*tid = 0x01;
				*tval = 0x04;
			break;
			case 2:
				strcpy(ttype, "Touch West");
				*tid = 0x01;
				*tval = 0x02;
			break;
			case 4:
				strcpy(ttype, "Touch North");
				*tid = 0x01;
				*tval = 0x03;
			break;
			case 8:
				strcpy(ttype, "Touch East");
				*tid = 0x01;
				*tval = 0x01;
			break;
			case 16:
				strcpy(ttype, "Touch Center");
				*tid = 0x01;
				*tval = 0x05;
			break;
			default:
				strcpy(ttype, "None");
				*tid = 0x00;
				*tval = 0x00;
			break;
		}

	}  else {

		strcpy(ttype, "None");
		*tid = 0x00;
		*tval = 0x00;

	}

}

Position::Position (uint16_t x0, uint16_t y0, uint16_t z0) {
	x = x0;
	y = y0;
	z = z0;
}

Position Hover::getPosition(void) {

	uint16_t x, y, z;

	if (_valid == 1 && _posmode == 0x01) {

		readPositionData(&x, &y, &z);

	} else {

		x = 0;
		y = 0;
		z = 0;

	}

	return Position(x, y, z);
}

void Hover::readPositionData(uint16_t *x, uint16_t *y, uint16_t *z) {

	if ((_dat[7] & 0x01) == 1){

		*x = ((_dat[21] << 8) | _dat[20]);
		*y = ((_dat[23] << 8) | _dat[22]);
		*z = ((_dat[25] << 8) | _dat[24]);

	} else {

		*x = 0;
		*y = 0;
		*z = 0;

	}

}

<commit_msg>fixing calibration typo<commit_after>/*  ===========================================================================
#  This is the library for Hover.
#
#  Hover is a development kit that lets you control your hardware projects in a whole new way.
#  Wave goodbye to physical buttons. Hover detects hand movements in the air for touch-less interaction.
#  It also features five touch-sensitive regions for even more options.
#  Hover uses I2C and 2 digital pins. It is compatible with Arduino, Raspberry Pi and more.
#
#  Hover can be purchased here: http://www.hoverlabs.co
#
#  Written by Emran Mahbub and Jonathan Li for Hover Labs.
#  BSD license, all text above must be included in any redistribution
#  ===========================================================================
#
#  INSTALLATION
#  The 3 library files (Hover.cpp, Hover.h and keywords.txt) in the Hover folder should be placed in your Arduino Library folder.
#  Run the HoverDemo.ino file from your Arduino IDE.
#
#  SUPPORT
#  For questions and comments, email us at support@hoverlabs.co
#  v3.1
#  ===========================================================================*/

#include <Hover.h>
#include <Wire.h>

#ifdef __AVR__
 #define WIRE Wire
#endif

Hover::Hover(uint8_t ts, uint8_t rst, uint8_t gestmode, uint8_t touchmode, uint8_t tapmode, uint8_t posmode) {
  _i2caddr = 0x42;
  _ts = ts;
  _rst = rst;
  _gestmode = gestmode;
  _touchmode = touchmode;
  _tapmode = tapmode;
  _posmode = posmode;
}

void Hover::begin() {
	WIRE.begin();
	pinMode(_ts, INPUT);
	pinMode(_rst, OUTPUT);
	digitalWrite(_rst, LOW);
	delay(50);
	pinMode(_rst, INPUT);

	/*disable autocal for smoother operation*/
	uint8_t autoCal[] = {0x10, 0x00, 0x00, 0xA2, 0x80, 0x00 , 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF};
    Wire.beginTransmission(_i2caddr);
    Wire.write(autoCal, 16);
    Wire.endTransmission();

	Serial.println("Hover is ready");
}

void Hover::setRelease() {
    digitalWrite(_ts, HIGH);
    pinMode(_ts, INPUT);
}

boolean Hover::getStatus() {
	if (digitalRead(_ts) == 0) {
		pinMode(_ts, OUTPUT);
		digitalWrite(_ts, LOW);
		return 0;
	}
	return 1;
}

void Hover::readI2CData(void) {
	if (getStatus() == 0){
		int c = 0;
	    WIRE.requestFrom((uint8_t)_i2caddr, (uint8_t)26);    // request 26 bytes from slave device at 0x42
	    while(WIRE.available())    // slave may send less than requested
	    {
			_dat[c] = WIRE.read(); // receive a byte as character
			c++;
		}
		setRelease();
		_valid = 1;
		delay(6);
	} else {
		_valid = 0;
	}

}

Gesture::Gesture(){
	strcpy(gestureType, "none");
	gestureID = 0;
	gestureValue = 0;
}

Gesture::Gesture (char * type, uint8_t id, uint8_t value){
	strcpy(gestureType, type);
	gestureID = id;
	gestureValue = value;
}

Gesture Hover::getGesture(void) {
	char gtype[15];
	uint8_t gid;
	uint8_t gval;

	if (_valid == 1 && _gestmode == 0x01) {
		readGestureData(gtype, &gid, &gval);
	} else {
		strcpy(gtype, "none");
		gid = 0x00;
		gval = 0x00;
	}

	return Gesture(gtype, gid, gval);
}

void Hover::readGestureData(char * gtype, uint8_t * gid, uint8_t * gval) {

	switch (_dat[10]){
		case 2:
			strcpy(gtype, "Right Swipe");
			*gid = 0x01;
			*gval = 0x01;
		break;
		case 3:
			strcpy(gtype, "Left Swipe");
			*gid = 0x01;
			*gval = 0x02;
		break;
		case 4:
			strcpy(gtype, "Up Swipe");
			*gid = 0x01;
			*gval = 0x03;
		break;
		case 5:
			strcpy(gtype, "Down Swipe");
			*gid = 0x01;
			*gval = 0x04;
		break;
		default:
			strcpy(gtype, "None");
			*gid = 0x00;
			*gval = 0x00;
		break;
	}
	if (_dat[7] & 0x02){
		strcpy(gtype, "Airspin");
		*gid = 0x02;
		*gval = _dat[18];
	}
}

Touch::Touch(){
	strcpy(touchType, "none");
	touchID = 0;
	touchValue = 0;
}

Touch::Touch (char * type, uint8_t id, uint8_t value){
	strcpy(touchType, type);
	touchID = id;
	touchValue = value;
}

Touch Hover::getTouch(void) {
	char ttype[20];
	uint8_t tid;
	uint8_t tval;

	if (_valid == 1) {
		readTouchData(ttype, &tid, &tval);
	} else {
		strcpy(ttype, "None");
		tid = 0x00;
		tval = 0x00;
	}

	return Touch(ttype, tid, tval);
}

void Hover::readTouchData(char * ttype, uint8_t * tid, uint8_t * tval) {

	uint8_t touch, tap, doubleTap;

	touch = (_touchmode==0x01) ? (touch = (_dat[14] & 0x1F)) : (0);

	if (_tapmode!=0x00){
		if (_tapmode == 0x01){
			tap = (((_dat[15] & 0x03) << 3 ) | (_dat[14]>>5));
			doubleTap = ((_dat[15]>>2) & 0x1F);
		} else {
			tap = (_tapmode==0x02) ? (tap = (((_dat[15] & 0x03) << 3 ) | (_dat[14]>>5))) : (0);
			doubleTap = (_tapmode==0x03) ? (doubleTap = ((_dat[15]>>2) & 0x1F)) : (0);
		}
	} else {
		tap = 0;
		doubleTap = 0;
	}

	if (doubleTap != 0) {
		switch (doubleTap) {
			case 1:
				strcpy(ttype, "Double Tap South");
				*tid = 0x03;
				*tval = 0x04;
			break;
			case 2:
				strcpy(ttype, "Double Tap West");
				*tid = 0x03;
				*tval = 0x02;
			break;
			case 4:
				strcpy(ttype, "Double Tap North");
				*tid = 0x03;
				*tval = 0x03;
			break;
			case 8:
				strcpy(ttype, "Double Tap East");
				*tid = 0x03;
				*tval = 0x01;
			break;
			case 16:
				strcpy(ttype, "Double Tap Center");
				*tid = 0x03;
				*tval = 0x05;
			break;
			default:
				strcpy(ttype, "None");
				*tid = 0x00;
				*tval = 0x00;
			break;
		}

	} else if (tap != 0) {
		switch (tap){
			case 1:
				strcpy(ttype, "Tap South");
				*tid = 0x02;
				*tval = 0x04;
			break;
			case 2:
				strcpy(ttype, "Tap West");
				*tid = 0x02;
				*tval = 0x02;
			break;
			case 4:
				strcpy(ttype, "Tap North");
				*tid = 0x02;
				*tval = 0x03;
			break;
			case 8:
				strcpy(ttype, "Tap East");
				*tid = 0x02;
				*tval = 0x01;
			break;
			case 16:
				strcpy(ttype, "Tap Center");
				*tid = 0x02;
				*tval = 0x05;
			break;
			default:
				strcpy(ttype, "None");
				*tid = 0x00;
				*tval = 0x00;
			break;
		}

	} else if (touch!=0) {
		switch (touch){
			case 1:
				strcpy(ttype, "Touch South");
				*tid = 0x01;
				*tval = 0x04;
			break;
			case 2:
				strcpy(ttype, "Touch West");
				*tid = 0x01;
				*tval = 0x02;
			break;
			case 4:
				strcpy(ttype, "Touch North");
				*tid = 0x01;
				*tval = 0x03;
			break;
			case 8:
				strcpy(ttype, "Touch East");
				*tid = 0x01;
				*tval = 0x01;
			break;
			case 16:
				strcpy(ttype, "Touch Center");
				*tid = 0x01;
				*tval = 0x05;
			break;
			default:
				strcpy(ttype, "None");
				*tid = 0x00;
				*tval = 0x00;
			break;
		}

	}  else {

		strcpy(ttype, "None");
		*tid = 0x00;
		*tval = 0x00;

	}

}

Position::Position (uint16_t x0, uint16_t y0, uint16_t z0) {
	x = x0;
	y = y0;
	z = z0;
}

Position Hover::getPosition(void) {

	uint16_t x, y, z;

	if (_valid == 1 && _posmode == 0x01) {

		readPositionData(&x, &y, &z);

	} else {

		x = 0;
		y = 0;
		z = 0;

	}

	return Position(x, y, z);
}

void Hover::readPositionData(uint16_t *x, uint16_t *y, uint16_t *z) {

	if ((_dat[7] & 0x01) == 1){

		*x = ((_dat[21] << 8) | _dat[20]);
		*y = ((_dat[23] << 8) | _dat[22]);
		*z = ((_dat[25] << 8) | _dat[24]);

	} else {

		*x = 0;
		*y = 0;
		*z = 0;

	}

}

<|endoftext|>


<commit_before>// $Id: nucleicAcid.C,v 1.9 2001/05/24 14:46:20 anker Exp $

#include <BALL/KERNEL/nucleicAcid.h>
#include <BALL/KERNEL/global.h>

using namespace std;

namespace BALL
{

	NucleicAcid::NucleicAcid()
		throw()
		:	Molecule(),
			id_(BALL_NUCLEICACID_DEFAULT_ID)
	{
	}

	NucleicAcid::NucleicAcid(const NucleicAcid& nucleic_acid, bool deep)
		throw()
		:	Molecule(nucleic_acid, deep),
			id_(nucleic_acid.id_)
	{
	}

	NucleicAcid::NucleicAcid(const String& name,const String& id)
		throw()
		:	Molecule(name),
			id_(id)
	{
	}

	NucleicAcid::~NucleicAcid()
		throw()
	{
		destroy();
	}

	void NucleicAcid::clear()
		throw()
	{
		Molecule::clear();
		id_ = BALL_NUCLEICACID_DEFAULT_ID;
	}

	void NucleicAcid::destroy()
		throw()
	{
		Molecule::destroy();
		id_ = BALL_NUCLEICACID_DEFAULT_ID;
	}

	void NucleicAcid::persistentWrite(PersistenceManager& pm, const char* name) const
		throw()
	{
		pm.writeObjectHeader(this, name);
			Molecule::persistentWrite(pm);
			pm.writePrimitive(id_, "id_");
		pm.writeObjectTrailer(name);
	}

	void NucleicAcid::persistentRead(PersistenceManager& pm)
		throw()
	{
		pm.checkObjectHeader(RTTI::getStreamName<Molecule>());
			Molecule::persistentRead(pm);
		pm.checkObjectTrailer(0);
		pm.readPrimitive(id_, "id_");
	}

	void NucleicAcid::set(const NucleicAcid& nucleic_acid, bool deep)
		throw()
	{
		Molecule::set(nucleic_acid, deep);
		id_ = nucleic_acid.id_;
	}

	const NucleicAcid& NucleicAcid::operator =(const NucleicAcid &nucleic_acid)
		throw()
	{
		set(nucleic_acid);
		return *this;
	}

	void NucleicAcid::get(NucleicAcid &nucleic_acid, bool deep) const
		throw()
	{
		nucleic_acid.set(*this, deep);
	}

	void NucleicAcid::swap(NucleicAcid& nucleic_acid)
		throw()
	{
		Molecule::swap(nucleic_acid);
		id_.swap(nucleic_acid.id_);
	}

	Nucleotide* NucleicAcid::getNucleotide(Position position)
		throw()
	{
		for (NucleotideIterator Nucleotide_it = beginNucleotide(); !Nucleotide_it.isEnd(); ++Nucleotide_it)
		{
			if (position-- == 0)
			{
				return &(*Nucleotide_it);
			}
		}

		return 0;
	}

	const Nucleotide* NucleicAcid::getNucleotide(Position position) const
		throw()
	{
		return ((NucleicAcid *)this)->getNucleotide(position);
	}

	Nucleotide* NucleicAcid::get3Prime()
		throw()
	{
		return getNucleotide(0);
	}

	const Nucleotide* NucleicAcid::get3Prime() const
		throw()
	{
		return getNucleotide(0);
	}

	Nucleotide* NucleicAcid::get5Prime()
		throw()
	{
		return getNucleotide(countNucleotides()-1);
	}

	const Nucleotide* NucleicAcid::get5Prime() const
		throw()
	{
		return getNucleotide(countNucleotides()-1);
	}

	void NucleicAcid::setID(const String& id)
		throw()
	{
		id_ = id;
	}

	const String& NucleicAcid::getID() const
		throw()
	{
		return id_;
	}

	Size NucleicAcid::countNucleotides() const
		throw()
	{
		Size size = 0;

		for (NucleotideIterator res_it = beginNucleotide(); !res_it.isEnd(); ++res_it)
		{
			++size;
		}

		return size;
	}

	bool NucleicAcid::isValid() const
		throw()
	{
		return (Molecule::isValid() && id_.isValid());
	}

	void	NucleicAcid::dump(ostream& s, Size depth) const
		throw()
	{
		BALL_DUMP_STREAM_PREFIX(s);

		Molecule::dump(s, depth);

		BALL_DUMP_DEPTH(s, depth);
		s << "  id: " << id_ << endl;

		BALL_DUMP_STREAM_SUFFIX(s);
	}

	void NucleicAcid::read(istream& /* s */)
		throw(Exception::NotImplemented)
	{
		throw Exception::NotImplemented(__FILE__, __LINE__);
	}

	void NucleicAcid::write(ostream&  /* s */) const
		throw(Exception::NotImplemented)
	{
		throw Exception::NotImplemented(__FILE__, __LINE__);
	}

	bool NucleicAcid::operator == (const NucleicAcid& nucleic_acid) const
		throw()
	{
		return(Object::operator == (nucleic_acid));
	}

	bool NucleicAcid::operator != (const NucleicAcid& nucleic_acid) const
		throw()
	{
		return ! (*this == nucleic_acid);
	}

} // namespace BALL
<commit_msg>fixed: removed NotImplemented from throw() again, added BAUSTELLE<commit_after>// $Id: nucleicAcid.C,v 1.10 2001/05/28 09:24:22 anker Exp $

#include <BALL/KERNEL/nucleicAcid.h>
#include <BALL/KERNEL/global.h>

using namespace std;

namespace BALL
{

	NucleicAcid::NucleicAcid()
		throw()
		:	Molecule(),
			id_(BALL_NUCLEICACID_DEFAULT_ID)
	{
	}

	NucleicAcid::NucleicAcid(const NucleicAcid& nucleic_acid, bool deep)
		throw()
		:	Molecule(nucleic_acid, deep),
			id_(nucleic_acid.id_)
	{
	}

	NucleicAcid::NucleicAcid(const String& name,const String& id)
		throw()
		:	Molecule(name),
			id_(id)
	{
	}

	NucleicAcid::~NucleicAcid()
		throw()
	{
		destroy();
	}

	void NucleicAcid::clear()
		throw()
	{
		Molecule::clear();
		id_ = BALL_NUCLEICACID_DEFAULT_ID;
	}

	void NucleicAcid::destroy()
		throw()
	{
		Molecule::destroy();
		id_ = BALL_NUCLEICACID_DEFAULT_ID;
	}

	void NucleicAcid::persistentWrite(PersistenceManager& pm, const char* name) const
		throw()
	{
		pm.writeObjectHeader(this, name);
			Molecule::persistentWrite(pm);
			pm.writePrimitive(id_, "id_");
		pm.writeObjectTrailer(name);
	}

	void NucleicAcid::persistentRead(PersistenceManager& pm)
		throw()
	{
		pm.checkObjectHeader(RTTI::getStreamName<Molecule>());
			Molecule::persistentRead(pm);
		pm.checkObjectTrailer(0);
		pm.readPrimitive(id_, "id_");
	}

	void NucleicAcid::set(const NucleicAcid& nucleic_acid, bool deep)
		throw()
	{
		Molecule::set(nucleic_acid, deep);
		id_ = nucleic_acid.id_;
	}

	const NucleicAcid& NucleicAcid::operator =(const NucleicAcid &nucleic_acid)
		throw()
	{
		set(nucleic_acid);
		return *this;
	}

	void NucleicAcid::get(NucleicAcid &nucleic_acid, bool deep) const
		throw()
	{
		nucleic_acid.set(*this, deep);
	}

	void NucleicAcid::swap(NucleicAcid& nucleic_acid)
		throw()
	{
		Molecule::swap(nucleic_acid);
		id_.swap(nucleic_acid.id_);
	}

	Nucleotide* NucleicAcid::getNucleotide(Position position)
		throw()
	{
		for (NucleotideIterator Nucleotide_it = beginNucleotide(); !Nucleotide_it.isEnd(); ++Nucleotide_it)
		{
			if (position-- == 0)
			{
				return &(*Nucleotide_it);
			}
		}

		return 0;
	}

	const Nucleotide* NucleicAcid::getNucleotide(Position position) const
		throw()
	{
		return ((NucleicAcid *)this)->getNucleotide(position);
	}

	Nucleotide* NucleicAcid::get3Prime()
		throw()
	{
		return getNucleotide(0);
	}

	const Nucleotide* NucleicAcid::get3Prime() const
		throw()
	{
		return getNucleotide(0);
	}

	Nucleotide* NucleicAcid::get5Prime()
		throw()
	{
		return getNucleotide(countNucleotides()-1);
	}

	const Nucleotide* NucleicAcid::get5Prime() const
		throw()
	{
		return getNucleotide(countNucleotides()-1);
	}

	void NucleicAcid::setID(const String& id)
		throw()
	{
		id_ = id;
	}

	const String& NucleicAcid::getID() const
		throw()
	{
		return id_;
	}

	Size NucleicAcid::countNucleotides() const
		throw()
	{
		Size size = 0;

		for (NucleotideIterator res_it = beginNucleotide(); !res_it.isEnd(); ++res_it)
		{
			++size;
		}

		return size;
	}

	bool NucleicAcid::isValid() const
		throw()
	{
		return (Molecule::isValid() && id_.isValid());
	}

	void	NucleicAcid::dump(ostream& s, Size depth) const
		throw()
	{
		BALL_DUMP_STREAM_PREFIX(s);

		Molecule::dump(s, depth);

		BALL_DUMP_DEPTH(s, depth);
		s << "  id: " << id_ << endl;

		BALL_DUMP_STREAM_SUFFIX(s);
	}

	void NucleicAcid::read(istream& /* s */)
		throw()
	{
		// BAUSTELLE
		throw Exception::NotImplemented(__FILE__, __LINE__);
	}

	void NucleicAcid::write(ostream&  /* s */) const
		throw()
	{
		// BAUSTELLE
		throw Exception::NotImplemented(__FILE__, __LINE__);
	}

	bool NucleicAcid::operator == (const NucleicAcid& nucleic_acid) const
		throw()
	{
		return(Object::operator == (nucleic_acid));
	}

	bool NucleicAcid::operator != (const NucleicAcid& nucleic_acid) const
		throw()
	{
		return ! (*this == nucleic_acid);
	}

} // namespace BALL
<|endoftext|>


<commit_before>#include "RRDTP/Connection.h"
#include "RRDTP/Platform.h"
#include "RRDTP/DataBuffer.h"
#include "RRDTP/Entry.h"
#include <sstream>
#include <cinttypes>
#ifdef RRDTP_PLATFORM_WINDOWS
#include <Winsock2.h>
#endif

using namespace rrdtp;

void Connection::dataRecieved(Socket* self, HostID sender, void* data, size_t dataSz)
{
	Connection* connection = (Connection*)self->GetUserData();

	if (data != NULL && dataSz > 0)
	{
		DataBuffer buffer((unsigned char*)data, dataSz);

		//Protocol version and event type are common to all packets.
		char protocolVersion = 0;
		buffer.Read<char>(protocolVersion);

		char eventType = 0;
		buffer.Read<char>(eventType);

		//Depending on the event type, different packets may have different contents.
		if (eventType == EET_SET)
		{
			//Length of value identifier
			char identifierLength = 0;
			buffer.Read<char>(identifierLength);

			//Value identifier string.
			char identifier[255];
			buffer.Read((unsigned char*)identifier, identifierLength);
			identifier[identifierLength] = '\0';

			//Data type
			char dataType = 0;
			buffer.Read<char>(dataType);

			//Create/retrieve the entry and let it deserialize itself.
			Entry* entry = connection->m_localDataStore.Create(sender, identifier, (E_DATA_TYPE)dataType);
			if (entry != NULL && entry->GetType() == dataType)
			{
				entry->Deserialize(buffer);

				//Trigger value change callback
				if (connection->m_valueChangedCallback)
				{
					connection->m_valueChangedCallback(connection, entry);
				}
			}
		}
	}
}

void Connection::clientConnected(Socket* self, HostID client)
{
	Connection* connection = (Connection*)self->GetUserData();

	//Once connected to the server, send it the client handshake packet.
	unsigned char packetData[2];
	DataBuffer buffer(packetData, 2);

	buffer.Write<char>(1);//Protocol version
	buffer.Write<char>(EET_SERVER_HANDSHAKE);//Event type

	self->Send(packetData, 2);

	//Send out update packet for all currently existing values.
	connection->SynchronizeAllEntries();
}

Connection::Connection()
	:m_socket(NULL),
	m_valueChangedCallback(NULL)
{
	m_socket = Socket::Create(&Connection::dataRecieved, this, &Connection::clientConnected);
}

Connection::~Connection()
{
	if (m_socket != NULL)
	{
		delete m_socket;
	}
}

void Connection::StartServer(unsigned int port)
{
	if (m_socket != NULL)
	{
		m_socket->Listen(port, ESP_TCP);
	}
}

bool Connection::StartClient(const char* ip, unsigned int port)
{
	if (m_socket != NULL)
	{
		if (m_socket->Connect(ip, port, ESP_TCP) == ESE_SUCCESS)
		{
			printf("Connected to server.\n");

			//Once connected to the server, send it the client handshake packet.
			unsigned char packetData[2];
			DataBuffer buffer(packetData, 2);

			buffer.Write<char>(1);//Protocol version
			buffer.Write<char>(EET_CLIENT_HANDSHAKE);//Event type

			m_socket->Send(packetData, 2);

			return true;
		}
	}

	return false;
}

void Connection::SendUpdatePacket(const char* identifier, Entry* entry)
{
	if (m_socket != NULL && entry != NULL)
	{
		int identifierLength = strlen(identifier);
		if (identifierLength >= 255)
		{
			return;
		}

		unsigned char* packetData = new unsigned char[512];
		DataBuffer buffer(packetData, 512);

		//Write header for set packet
		buffer.Write<char>(1);//Protocol version
		buffer.Write<char>(EET_SET);//Event type

		buffer.Write<char>((char)identifierLength);//Value identifier length
		buffer.Write((const unsigned char*)identifier, identifierLength);//Value identifier

		//Data type
		buffer.Write<char>((char)entry->GetType());

		//Let the entry write its data.
		//The entry will handle endianness conversion and tracking of data size.
		entry->Serialize(buffer);

		//Send update packet to all connected clients.
		m_socket->SendAll(packetData, buffer.GetPosition());

		delete[] packetData;
	}
}

void Connection::SynchronizeAllEntries()
{
	SynchronizeAllEntriesImplementation(m_localDataStore.GetRootCategory());
}

void Connection::SynchronizeAllEntriesImplementation(Category* start)
{
	//Send packet for each entry
	List<Entry*>::Node* n = start->GetEntries().Begin();
	while (n->HasNext())
	{
		SendUpdatePacket(n->GetValue()->GetIdentifier(), n->GetValue());

		n = n->GetNext();
	}
}

void Connection::SetInt(const char* identifier, int val)
{
	//Create/retrieve entry (id doesn't matter locally).
	IntEntry* entry = (IntEntry*)m_localDataStore.Create(-1, identifier, EDT_INT);
	if (entry != NULL)
	{
		//Update the entry
		entry->Set(val);

		SendUpdatePacket(identifier, entry);//TODO: Track changed entries and only send those in Poll
	}
}

int Connection::GetInt(const char* identifier, int defaultVal)
{
	//Retrieve entry
	Entry* entry = m_localDataStore.Get(identifier);
	if (entry != NULL && entry->GetType() == EDT_INT)
	{
		//Return the value
		return ((IntEntry*)entry)->Get();
	}

	return defaultVal;
}

void Connection::SetLong(const char* identifier, long val)
{
	//Create/retrieve entry (id doesn't matter locally).
	LongEntry* entry = (LongEntry*)m_localDataStore.Create(-1, identifier, EDT_LONG);
	if (entry != NULL)
	{
		//Update the entry
		entry->Set(val);

		SendUpdatePacket(identifier, entry);
	}
}

long Connection::GetLong(const char* identifier, long defaultVal)
{
	//Retrieve entry
	Entry* entry = m_localDataStore.Get(identifier);
	if (entry != NULL && entry->GetType() == EDT_LONG)
	{
		//Return the value
		return ((LongEntry*)entry)->Get();
	}

	return defaultVal;
}

void Connection::SetBool(const char* identifier, bool val)
{
	//Create/retrieve entry (id doesn't matter locally).
	BooleanEntry* entry = (BooleanEntry*)m_localDataStore.Create(-1, identifier, EDT_BOOLEAN);
	if (entry != NULL)
	{
		//Update the entry
		entry->Set(val);

		SendUpdatePacket(identifier, entry);
	}
}

bool Connection::GetBool(const char* identifier, bool defaultVal)
{
	//Retrieve entry
	Entry* entry = m_localDataStore.Get(identifier);
	if (entry != NULL && entry->GetType() == EDT_BOOLEAN)
	{
		//Return the value
		return ((BooleanEntry*)entry)->Get();
	}

	return defaultVal;
}

void Connection::SetString(const char* identifier, const char* str)
{
	int stringLength = strlen(str);

	//Create/retrieve entry (id doesn't matter locally).
	StringEntry* entry = (StringEntry*)m_localDataStore.Create(-1, identifier, EDT_STRING);
	if (entry != NULL)
	{
		//Update the entry
		entry->Set(str);

		SendUpdatePacket(identifier, entry);
	}
}

const char* Connection::GetString(const char* identifier, const char* defaultVal)
{
	//Retrieve entry
	Entry* entry = m_localDataStore.Get(identifier);
	if (entry != NULL && entry->GetType() == EDT_STRING)
	{
		//Return the value
		return ((StringEntry*)entry)->Get();
	}

	return defaultVal;
}

void Connection::Poll()
{
	if (m_socket != NULL)
	{
		if (m_socket->IsServer())
		{
			if (m_socket->Accept() != -1)
			{
				printf("Accepted connection.\n");
			}
		}

		m_socket->Poll();
	}
}<commit_msg>Connection synchronization<commit_after>#include "RRDTP/Connection.h"
#include "RRDTP/Platform.h"
#include "RRDTP/DataBuffer.h"
#include "RRDTP/Entry.h"
#include <sstream>
#include <cinttypes>
#ifdef RRDTP_PLATFORM_WINDOWS
#include <Winsock2.h>
#endif

using namespace rrdtp;

void Connection::dataRecieved(Socket* self, HostID sender, void* data, size_t dataSz)
{
	Connection* connection = (Connection*)self->GetUserData();

	if (data != NULL && dataSz > 0)
	{
		DataBuffer buffer((unsigned char*)data, dataSz);

		//Protocol version and event type are common to all packets.
		char protocolVersion = 0;
		buffer.Read<char>(protocolVersion);

		char eventType = 0;
		buffer.Read<char>(eventType);

		//Depending on the event type, different packets may have different contents.
		if (eventType == EET_SET)
		{
			//Length of value identifier
			char identifierLength = 0;
			buffer.Read<char>(identifierLength);

			//Value identifier string.
			char identifier[255];
			buffer.Read((unsigned char*)identifier, identifierLength);
			identifier[identifierLength] = '\0';

			//Data type
			char dataType = 0;
			buffer.Read<char>(dataType);

			//Create/retrieve the entry and let it deserialize itself.
			Entry* entry = connection->m_localDataStore.Create(sender, identifier, (E_DATA_TYPE)dataType);
			if (entry != NULL && entry->GetType() == dataType)
			{
				entry->Deserialize(buffer);

				//Trigger value change callback
				if (connection->m_valueChangedCallback)
				{
					connection->m_valueChangedCallback(connection, entry);
				}
			}
		}
	}
}

void Connection::clientConnected(Socket* self, HostID client)
{
	Connection* connection = (Connection*)self->GetUserData();

	//Once connected to the server, send it the client handshake packet.
	unsigned char packetData[2];
	DataBuffer buffer(packetData, 2);

	buffer.Write<char>(1);//Protocol version
	buffer.Write<char>(EET_SERVER_HANDSHAKE);//Event type

	self->Send(packetData, 2);

	//Send out update packet for all currently existing values.
	connection->SynchronizeAllEntries();
}

Connection::Connection()
	:m_socket(NULL),
	m_valueChangedCallback(NULL)
{
	m_socket = Socket::Create(&Connection::dataRecieved, this, &Connection::clientConnected);
}

Connection::~Connection()
{
	if (m_socket != NULL)
	{
		delete m_socket;
	}
}

void Connection::StartServer(unsigned int port)
{
	if (m_socket != NULL)
	{
		m_socket->Listen(port, ESP_TCP);
	}
}

bool Connection::StartClient(const char* ip, unsigned int port)
{
	if (m_socket != NULL)
	{
		if (m_socket->Connect(ip, port, ESP_TCP) == ESE_SUCCESS)
		{
			printf("Connected to server.\n");

			//Once connected to the server, send it the client handshake packet.
			unsigned char packetData[2];
			DataBuffer buffer(packetData, 2);

			buffer.Write<char>(1);//Protocol version
			buffer.Write<char>(EET_CLIENT_HANDSHAKE);//Event type

			m_socket->Send(packetData, 2);

			return true;
		}
	}

	return false;
}

void Connection::SendUpdatePacket(const char* identifier, Entry* entry)
{
	if (m_socket != NULL && entry != NULL)
	{
		int identifierLength = strlen(identifier);
		if (identifierLength >= 255)
		{
			return;
		}

		unsigned char* packetData = new unsigned char[512];
		DataBuffer buffer(packetData, 512);

		//Write header for set packet
		buffer.Write<char>(1);//Protocol version
		buffer.Write<char>(EET_SET);//Event type

		buffer.Write<char>((char)identifierLength);//Value identifier length
		buffer.Write((const unsigned char*)identifier, identifierLength);//Value identifier

		//Data type
		buffer.Write<char>((char)entry->GetType());

		//Let the entry write its data.
		//The entry will handle endianness conversion and tracking of data size.
		entry->Serialize(buffer);

		//Send update packet to all connected clients.
		m_socket->SendAll(packetData, buffer.GetPosition());

		delete[] packetData;
	}
}

void Connection::SynchronizeAllEntries()
{
	SynchronizeAllEntriesImplementation(m_localDataStore.GetRootCategory());
}

void Connection::SynchronizeAllEntriesImplementation(Category* start)
{
	//Send packet for each entry
	List<Entry*>::Node* n = start->GetEntries().Begin();
	while (n != NULL)
	{
		SendUpdatePacket(n->GetValue()->GetIdentifier(), n->GetValue());

		n = n->GetNext();
	}
}

void Connection::SetInt(const char* identifier, int val)
{
	//Create/retrieve entry (id doesn't matter locally).
	IntEntry* entry = (IntEntry*)m_localDataStore.Create(-1, identifier, EDT_INT);
	if (entry != NULL)
	{
		//Update the entry
		entry->Set(val);

		SendUpdatePacket(identifier, entry);//TODO: Track changed entries and only send those in Poll
	}
}

int Connection::GetInt(const char* identifier, int defaultVal)
{
	//Retrieve entry
	Entry* entry = m_localDataStore.Get(identifier);
	if (entry != NULL && entry->GetType() == EDT_INT)
	{
		//Return the value
		return ((IntEntry*)entry)->Get();
	}

	return defaultVal;
}

void Connection::SetLong(const char* identifier, long val)
{
	//Create/retrieve entry (id doesn't matter locally).
	LongEntry* entry = (LongEntry*)m_localDataStore.Create(-1, identifier, EDT_LONG);
	if (entry != NULL)
	{
		//Update the entry
		entry->Set(val);

		SendUpdatePacket(identifier, entry);
	}
}

long Connection::GetLong(const char* identifier, long defaultVal)
{
	//Retrieve entry
	Entry* entry = m_localDataStore.Get(identifier);
	if (entry != NULL && entry->GetType() == EDT_LONG)
	{
		//Return the value
		return ((LongEntry*)entry)->Get();
	}

	return defaultVal;
}

void Connection::SetBool(const char* identifier, bool val)
{
	//Create/retrieve entry (id doesn't matter locally).
	BooleanEntry* entry = (BooleanEntry*)m_localDataStore.Create(-1, identifier, EDT_BOOLEAN);
	if (entry != NULL)
	{
		//Update the entry
		entry->Set(val);

		SendUpdatePacket(identifier, entry);
	}
}

bool Connection::GetBool(const char* identifier, bool defaultVal)
{
	//Retrieve entry
	Entry* entry = m_localDataStore.Get(identifier);
	if (entry != NULL && entry->GetType() == EDT_BOOLEAN)
	{
		//Return the value
		return ((BooleanEntry*)entry)->Get();
	}

	return defaultVal;
}

void Connection::SetString(const char* identifier, const char* str)
{
	int stringLength = strlen(str);

	//Create/retrieve entry (id doesn't matter locally).
	StringEntry* entry = (StringEntry*)m_localDataStore.Create(-1, identifier, EDT_STRING);
	if (entry != NULL)
	{
		//Update the entry
		entry->Set(str);

		SendUpdatePacket(identifier, entry);
	}
}

const char* Connection::GetString(const char* identifier, const char* defaultVal)
{
	//Retrieve entry
	Entry* entry = m_localDataStore.Get(identifier);
	if (entry != NULL && entry->GetType() == EDT_STRING)
	{
		//Return the value
		return ((StringEntry*)entry)->Get();
	}

	return defaultVal;
}

void Connection::Poll()
{
	if (m_socket != NULL)
	{
		if (m_socket->IsServer())
		{
			if (m_socket->Accept() != -1)
			{
				printf("Accepted connection.\n");
			}
		}

		m_socket->Poll();
	}
}<|endoftext|>


<commit_before>// $Id: PeakList_test.C,v 1.4 2001/12/30 13:29:00 sturm Exp $
#include <BALL/CONCEPT/classTest.h>

///////////////////////////

// insert includes here

///////////////////////////

START_TEST(PeakList, "$Id: PeakList_test.C,v 1.4 2001/12/30 13:29:00 sturm Exp $")

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

using namespace BALL;

// tests for class PeakList::

CHECK(PeakList::BALL_CREATE(PeakList<PT>))
  //?????
RESULT

CHECK(PeakList::scale(float x))
  //?????
RESULT

CHECK(PeakList::getMaxIntensity() const )
  //?????
RESULT

CHECK(PeakList::getMinIntensity() const )
  //?????
RESULT

CHECK(PeakList::getMinPosition() const )
  //?????
RESULT

CHECK(PeakList::getMaxPosition() const )
  //?????
RESULT

CHECK(PeakList::PeakList::PeakList())
  //?????
RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
END_TEST
<commit_msg>initial implementation<commit_after>// $Id: PeakList_test.C,v 1.5 2002/01/05 02:54:59 oliver Exp $
#include <BALL/CONCEPT/classTest.h>

///////////////////////////

#include <BALL/NMR/peakList.h>

///////////////////////////

START_TEST(PeakList, "$Id: PeakList_test.C,v 1.5 2002/01/05 02:54:59 oliver Exp $")

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

using namespace BALL;

/// PeakList1D
PeakList1D* pl_ptr = 0;
CHECK(PeakList1D::PeakList())
	pl_ptr = new PeakList1D;
	TEST_NOT_EQUAL(pl_ptr, 0)
RESULT

CHECK(PeakList1D::~PeakList())
	delete pl_ptr;
RESULT

PeakList1D pl;
PeakList1D::PeakType p1;
PeakList1D::PeakType p2;
p1.setPosition(1.0);
p2.setPosition(4.0);
p1.setIntensity(2.0);
p2.setIntensity(8.0);
pl.push_back(p1);
pl.push_back(p2);

CHECK(PeakList1D::PeakList(const PeakList& peak_list))
	TEST_EQUAL(pl.size(), 2)
	PeakList1D pl_copy(pl);
	TEST_EQUAL(pl_copy.size(), 2)
	TEST_REAL_EQUAL(pl_copy.front().getPosition(), 1.0)
	TEST_REAL_EQUAL(pl_copy.back().getPosition(), 4.0)
	TEST_REAL_EQUAL(pl_copy.front().getIntensity(), 2.0)
	TEST_REAL_EQUAL(pl_copy.back().getIntensity(), 8.0)
RESULT

CHECK(PeakList1D::scale(float x))
	PeakList1D pl2(pl);
	pl2.scale(2.0);
	TEST_EQUAL(pl2.size(), 2)
	TEST_REAL_EQUAL(pl2.front().getPosition(), 1.0)
	TEST_REAL_EQUAL(pl2.back().getPosition(), 4.0)
	TEST_REAL_EQUAL(pl2.front().getIntensity(), 4.0)
	TEST_REAL_EQUAL(pl2.back().getIntensity(), 16.0)
RESULT

CHECK(PeakList1D::getMaxIntensity() const )
	PeakList1D pl2;
	TEST_REAL_EQUAL(pl2.getMaxIntensity(), -Limits<float>::max())
	TEST_REAL_EQUAL(pl.getMaxIntensity(), 8.0)
RESULT

CHECK(PeakList1D::getMinIntensity() const )
	PeakList1D pl2;
	TEST_REAL_EQUAL(pl2.getMinIntensity(), Limits<float>::max())
	TEST_REAL_EQUAL(pl.getMinIntensity(), 2.0)
RESULT

CHECK(PeakList1D::getMinPosition() const )
	PeakList1D pl2;
	TEST_REAL_EQUAL(pl2.getMinPosition(), Limits<float>::max())
	TEST_REAL_EQUAL(pl.getMinPosition(), 1.0)
RESULT

CHECK(PeakList1D::getMaxPosition() const )
	PeakList1D pl2;
	TEST_REAL_EQUAL(pl2.getMaxPosition(), -Limits<float>::max())
	TEST_REAL_EQUAL(pl.getMaxPosition(), 4.0)
RESULT

/// PeakList2D
PeakList2D* pl2D_ptr = 0;
CHECK(PeakList2D::PeakList())
	pl2D_ptr = new PeakList2D;
	TEST_NOT_EQUAL(pl2D_ptr, 0)
RESULT

CHECK(PeakList2D::~PeakList())
	delete pl2D_ptr;
RESULT

PeakList2D pl_2D;
PeakList2D::PeakType p_2D_1;
PeakList2D::PeakType p_2D_2;
p_2D_1.setPosition(Vector2(1.0, 2.0));
p_2D_2.setPosition(Vector2(4.0, 5.0));
p_2D_1.setIntensity(2.0);
p_2D_2.setIntensity(8.0);
pl_2D.push_back(p_2D_1);
pl_2D.push_back(p_2D_2);

CHECK(PeakList2D::PeakList(const PeakList& peak_list))
	TEST_EQUAL(pl_2D.size(), 2)
	PeakList2D pl_2D_copy(pl_2D);
	TEST_EQUAL(pl_2D_copy.size(), 2)
	TEST_REAL_EQUAL(pl_2D_copy.front().getPosition().x, 1.0)
	TEST_REAL_EQUAL(pl_2D_copy.front().getPosition().y, 2.0)
	TEST_REAL_EQUAL(pl_2D_copy.back().getPosition().x, 4.0)
	TEST_REAL_EQUAL(pl_2D_copy.back().getPosition().y, 5.0)
	TEST_REAL_EQUAL(pl_2D_copy.front().getIntensity(), 2.0)
	TEST_REAL_EQUAL(pl_2D_copy.back().getIntensity(), 8.0)
RESULT

CHECK(PeakList2D::scale(float x))
	PeakList2D pl_2D_2(pl_2D);
	pl_2D_2.scale(2.0);
	TEST_EQUAL(pl_2D_2.size(), 2)
	TEST_REAL_EQUAL(pl_2D_2.front().getPosition().x, 1.0)
	TEST_REAL_EQUAL(pl_2D_2.front().getPosition().y, 2.0)
	TEST_REAL_EQUAL(pl_2D_2.back().getPosition().x, 4.0)
	TEST_REAL_EQUAL(pl_2D_2.back().getPosition().y, 5.0)
	TEST_REAL_EQUAL(pl_2D_2.front().getIntensity(), 4.0)
	TEST_REAL_EQUAL(pl_2D_2.back().getIntensity(), 16.0)
RESULT

CHECK(PeakList2D::getMaxIntensity() const )
	PeakList2D pl_2D_2;
	TEST_REAL_EQUAL(pl_2D_2.getMaxIntensity(), -Limits<float>::max())
	TEST_REAL_EQUAL(pl_2D.getMaxIntensity(), 8.0)
RESULT

CHECK(PeakList2D::getMinIntensity() const )
	PeakList2D pl_2D_2;
	TEST_REAL_EQUAL(pl_2D_2.getMinIntensity(), Limits<float>::max())
	TEST_REAL_EQUAL(pl_2D.getMinIntensity(), 2.0)
RESULT

CHECK(PeakList2D::getMinPosition() const )
	PeakList2D pl_2D_2;
	TEST_REAL_EQUAL(pl_2D_2.getMinPosition().x, Limits<float>::max())
	TEST_REAL_EQUAL(pl_2D_2.getMinPosition().y, Limits<float>::max())
	TEST_REAL_EQUAL(pl_2D.getMinPosition().x, 1.0)
	TEST_REAL_EQUAL(pl_2D.getMinPosition().y, 2.0)
RESULT

CHECK(PeakList2D::getMaxPosition() const )
	PeakList2D pl_2D_2;
	TEST_REAL_EQUAL(pl_2D_2.getMaxPosition().x, -Limits<float>::max())
	TEST_REAL_EQUAL(pl_2D_2.getMaxPosition().y, -Limits<float>::max())
	TEST_REAL_EQUAL(pl_2D.getMaxPosition().x, 4.0)
	TEST_REAL_EQUAL(pl_2D.getMaxPosition().y, 5.0)
RESULT

/// PeakList3D
PeakList3D* pl3D_ptr = 0;
CHECK(PeakList3D::PeakList())
	pl3D_ptr = new PeakList3D;
	TEST_NOT_EQUAL(pl3D_ptr, 0)
RESULT

CHECK(PeakList3D::~PeakList())
	delete pl3D_ptr;
RESULT

PeakList3D pl_3D;
PeakList3D::PeakType p_3D_1;
PeakList3D::PeakType p_3D_2;
p_3D_1.setPosition(Vector3(1.0, 2.0, 3.0));
p_3D_2.setPosition(Vector3(4.0, 5.0, 6.0));
p_3D_1.setIntensity(2.0);
p_3D_2.setIntensity(8.0);
pl_3D.push_back(p_3D_1);
pl_3D.push_back(p_3D_2);

CHECK(PeakList3D::PeakList(const PeakList& peak_list))
	TEST_EQUAL(pl_3D.size(), 2)
	PeakList3D pl_3D_copy(pl_3D);
	TEST_EQUAL(pl_3D_copy.size(), 2)
	TEST_REAL_EQUAL(pl_3D_copy.front().getPosition().x, 1.0)
	TEST_REAL_EQUAL(pl_3D_copy.front().getPosition().y, 2.0)
	TEST_REAL_EQUAL(pl_3D_copy.front().getPosition().z, 3.0)
	TEST_REAL_EQUAL(pl_3D_copy.back().getPosition().x, 4.0)
	TEST_REAL_EQUAL(pl_3D_copy.back().getPosition().y, 5.0)
	TEST_REAL_EQUAL(pl_3D_copy.back().getPosition().z, 6.0)
	TEST_REAL_EQUAL(pl_3D_copy.front().getIntensity(), 2.0)
	TEST_REAL_EQUAL(pl_3D_copy.back().getIntensity(), 8.0)
RESULT

CHECK(PeakList3D::scale(float x))
	PeakList3D pl_3D_2(pl_3D);
	pl_3D_2.scale(2.0);
	TEST_EQUAL(pl_3D_2.size(), 2)
	TEST_REAL_EQUAL(pl_3D_2.front().getPosition().x, 1.0)
	TEST_REAL_EQUAL(pl_3D_2.front().getPosition().y, 2.0)
	TEST_REAL_EQUAL(pl_3D_2.front().getPosition().z, 3.0)
	TEST_REAL_EQUAL(pl_3D_2.back().getPosition().x, 4.0)
	TEST_REAL_EQUAL(pl_3D_2.back().getPosition().y, 5.0)
	TEST_REAL_EQUAL(pl_3D_2.back().getPosition().z, 6.0)
	TEST_REAL_EQUAL(pl_3D_2.front().getIntensity(), 4.0)
	TEST_REAL_EQUAL(pl_3D_2.back().getIntensity(), 16.0)
RESULT

CHECK(PeakList3D::getMaxIntensity() const )
	PeakList3D pl_3D_2;
	TEST_REAL_EQUAL(pl_3D_2.getMaxIntensity(), -Limits<float>::max())
	TEST_REAL_EQUAL(pl_3D.getMaxIntensity(), 8.0)
RESULT

CHECK(PeakList3D::getMinIntensity() const )
	PeakList3D pl_3D_2;
	TEST_REAL_EQUAL(pl_3D_2.getMinIntensity(), Limits<float>::max())
	TEST_REAL_EQUAL(pl_3D.getMinIntensity(), 2.0)
RESULT

CHECK(PeakList3D::getMinPosition() const )
	PeakList3D pl_3D_2;
	TEST_REAL_EQUAL(pl_3D_2.getMinPosition().x, Limits<float>::max())
	TEST_REAL_EQUAL(pl_3D_2.getMinPosition().y, Limits<float>::max())
	TEST_REAL_EQUAL(pl_3D_2.getMinPosition().z, Limits<float>::max())
	TEST_REAL_EQUAL(pl_3D.getMinPosition().x, 1.0)
	TEST_REAL_EQUAL(pl_3D.getMinPosition().y, 2.0)
	TEST_REAL_EQUAL(pl_3D.getMinPosition().z, 3.0)
RESULT

CHECK(PeakList3D::getMaxPosition() const )
	PeakList3D pl_3D_2;
	TEST_REAL_EQUAL(pl_3D_2.getMaxPosition().x, -Limits<float>::max())
	TEST_REAL_EQUAL(pl_3D_2.getMaxPosition().y, -Limits<float>::max())
	TEST_REAL_EQUAL(pl_3D_2.getMaxPosition().z, -Limits<float>::max())
	TEST_REAL_EQUAL(pl_3D.getMaxPosition().x, 4.0)
	TEST_REAL_EQUAL(pl_3D.getMaxPosition().y, 5.0)
	TEST_REAL_EQUAL(pl_3D.getMaxPosition().z, 6.0)
RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

END_TEST
<|endoftext|>


<commit_before>#include <stdlib.h>
#include <stdio.h>
#include "node.hpp"

using namespace std;

class Tree
{
    public:
        Tree();
        ~Tree();

        void insert(string key, int value);
        Node *search(string key);
        void destroy_tree();
        void print();

    private:
        int string_to_hash(string key);
        void destroy_tree(Node *leaf);
        void insert(int key, int value, Node *leaf);
        void print(Node *leaf);
        Node *search(int key, Node *leaf);

        Node *root;
};

Tree::Tree()
{
    root = NULL;
}

Tree::~Tree()
{
    destroy_tree();
}

int Tree::string_to_hash(string key)
{
    /* TODO: Use a more robust hashing algorithm */
    hash<string> str_hash;

    return str_hash(key);
}

/* Tree insert takes a key, a value, and a Node pointer
 * Returns void.
 *
 * This function is a tail recursive depth first insert
 * algorithm. The time complexity in the worst case is
 * O(N). On average it will be O(log(N)) assuming the
 * tree is reasonably balanced.
 */
void Tree::insert(int key, int value, Node *leaf)
{
    Node * new_node;

    if(key < leaf->get_key()) {
        if(leaf->get_left() != NULL) {
            return insert(key, value, leaf->get_left());
        } else {
            new_node = new Node();
            new_node->set_key(key);
            new_node->set_value(value);
            leaf->set_left(new_node);
        }
    } else if(key > leaf->get_key()) {
        if(leaf->get_right() != NULL) {
            return insert(key, value, leaf->get_right());
        } else {
            new_node = new Node();
            new_node->set_key(key);
            new_node->set_value(value);
            leaf->set_right(new_node);
        }
    } else if(key == leaf->get_key()) {
        leaf->set_value(value);
    }
}

/* Tree search takes a key, and a Node pointer
 * Returns a Node *.
 *
 * This function is a tail recursive depth first search
 * algorithm. The time complexity in the worst case is
 * O(N). On average it will be O(log(N)) assuming the
 * tree is reasonably balanced.
 */
Node *Tree::search(int key, Node *leaf)
{
    if(leaf != NULL) {

        if(key == leaf->get_key()) {
            return leaf;
        } else if (key < leaf->get_key()) {
            return search(key, leaf->get_left());
        }

        return search(key, leaf->get_right());

    }

    return NULL;
}

void Tree:: insert(string key, int value)
{
    int hash_key = string_to_hash(key);

    if(root != NULL) {
        insert(hash_key, value, root);
    } else {
        root = new Node();
        root->set_value(value);
        root->set_key(hash_key);
    }
}

Node *Tree::search(string key)
{
    int hash_key = string_to_hash(key);
    return search(hash_key, root);
}

void Tree::destroy_tree()
{
    delete root;
}

void Tree::print(Node *leaf)
{
    if(leaf->get_left() != NULL) {
        print(leaf->get_left());
    }

    if(leaf->get_right() != NULL) {
        print(leaf->get_right());
    }
}

void Tree::print()
{
    print(root);
}
<commit_msg>Whitespace<commit_after>#include <stdlib.h>
#include <stdio.h>
#include "node.hpp"

using namespace std;

class Tree
{
    public:
        Tree();
        ~Tree();

        void insert(string key, int value);
        Node *search(string key);
        void destroy_tree();
        void print();

    private:
        int string_to_hash(string key);
        void destroy_tree(Node *leaf);
        void insert(int key, int value, Node *leaf);
        void print(Node *leaf);
        Node *search(int key, Node *leaf);

        Node *root;
};

Tree::Tree()
{
    root = NULL;
}

Tree::~Tree()
{
    destroy_tree();
}

int Tree::string_to_hash(string key)
{
    /* TODO: Use a more robust hashing algorithm */
    hash<string> str_hash;

    return str_hash(key);
}

/* Tree insert takes a key, a value, and a Node pointer
 * Returns void.
 *
 * This function is a tail recursive depth first insert
 * algorithm. The time complexity in the worst case is
 * O(N). On average it will be O(log(N)) assuming the
 * tree is reasonably balanced.
 */
void Tree::insert(int key, int value, Node *leaf)
{
    Node * new_node;

    if(key < leaf->get_key()) {

        if(leaf->get_left() != NULL) {
            return insert(key, value, leaf->get_left());
        } else {
            new_node = new Node();
            new_node->set_key(key);
            new_node->set_value(value);
            leaf->set_left(new_node);
        }

    } else if(key > leaf->get_key()) {

        if(leaf->get_right() != NULL) {
            return insert(key, value, leaf->get_right());
        } else {
            new_node = new Node();
            new_node->set_key(key);
            new_node->set_value(value);
            leaf->set_right(new_node);
        }

    } else if(key == leaf->get_key()) {
        leaf->set_value(value);
    }
}

/* Tree search takes a key, and a Node pointer
 * Returns a Node *.
 *
 * This function is a tail recursive depth first search
 * algorithm. The time complexity in the worst case is
 * O(N). On average it will be O(log(N)) assuming the
 * tree is reasonably balanced.
 */
Node *Tree::search(int key, Node *leaf)
{
    if(leaf != NULL) {

        if(key == leaf->get_key()) {
            return leaf;
        } else if (key < leaf->get_key()) {
            return search(key, leaf->get_left());
        }

        return search(key, leaf->get_right());

    }

    return NULL;
}

void Tree:: insert(string key, int value)
{
    int hash_key = string_to_hash(key);

    if(root != NULL) {
        insert(hash_key, value, root);
    } else {
        root = new Node();
        root->set_value(value);
        root->set_key(hash_key);
    }
}

Node *Tree::search(string key)
{
    int hash_key = string_to_hash(key);
    return search(hash_key, root);
}

void Tree::destroy_tree()
{
    delete root;
}

void Tree::print(Node *leaf)
{
    if(leaf->get_left() != NULL) {
        print(leaf->get_left());
    }

    if(leaf->get_right() != NULL) {
        print(leaf->get_right());
    }
}

void Tree::print()
{
    print(root);
}
<|endoftext|>


<commit_before>/*
	This file is part of solidity.

	solidity is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	solidity is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with solidity.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file ConstantOptimiser.cpp
 * @author Christian <c@ethdev.com>
 * @date 2015
 */

#include <libevmasm/ConstantOptimiser.h>
#include <libevmasm/Assembly.h>
#include <libevmasm/GasMeter.h>
using namespace std;
using namespace dev;
using namespace dev::eth;

unsigned ConstantOptimisationMethod::optimiseConstants(
	bool _isCreation,
	size_t _runs,
	Assembly& _assembly,
	AssemblyItems& _items
)
{
	unsigned optimisations = 0;
	map<AssemblyItem, size_t> pushes;
	for (AssemblyItem const& item: _items)
		if (item.type() == Push)
			pushes[item]++;
	map<u256, AssemblyItems> pendingReplacements;
	for (auto it: pushes)
	{
		AssemblyItem const& item = it.first;
		if (item.data() < 0x100)
			continue;
		Params params;
		params.multiplicity = it.second;
		params.isCreation = _isCreation;
		params.runs = _runs;
		LiteralMethod lit(params, item.data());
		bigint literalGas = lit.gasNeeded();
		CodeCopyMethod copy(params, item.data());
		bigint copyGas = copy.gasNeeded();
		ComputeMethod compute(params, item.data());
		bigint computeGas = compute.gasNeeded();
		AssemblyItems replacement;
		if (copyGas < literalGas && copyGas < computeGas)
		{
			replacement = copy.execute(_assembly);
			optimisations++;
		}
		else if (computeGas < literalGas && computeGas <= copyGas)
		{
			replacement = compute.execute(_assembly);
			optimisations++;
		}
		if (!replacement.empty())
			pendingReplacements[item.data()] = replacement;
	}
	if (!pendingReplacements.empty())
		replaceConstants(_items, pendingReplacements);
	return optimisations;
}

bigint ConstantOptimisationMethod::simpleRunGas(AssemblyItems const& _items)
{
	bigint gas = 0;
	for (AssemblyItem const& item: _items)
		if (item.type() == Push)
			gas += GasMeter::runGas(Instruction::PUSH1);
		else if (item.type() == Operation)
			gas += GasMeter::runGas(item.instruction());
	return gas;
}

bigint ConstantOptimisationMethod::dataGas(bytes const& _data) const
{
	if (m_params.isCreation)
	{
		bigint gas;
		for (auto b: _data)
			gas += b ? GasCosts::txDataNonZeroGas : GasCosts::txDataZeroGas;
		return gas;
	}
	else
		return GasCosts::createDataGas * dataSize();
}

size_t ConstantOptimisationMethod::bytesRequired(AssemblyItems const& _items)
{
	size_t size = 0;
	for (AssemblyItem const& item: _items)
		size += item.bytesRequired(3); // assume 3 byte addresses
	return size;
}

void ConstantOptimisationMethod::replaceConstants(
	AssemblyItems& _items,
	map<u256, AssemblyItems> const& _replacements
)
{
	AssemblyItems replaced;
	for (AssemblyItem const& item: _items)
	{
		if (item.type() == Push)
		{
			auto it = _replacements.find(item.data());
			if (it != _replacements.end())
			{
				replaced += it->second;
				continue;
			}
		}
		replaced.push_back(item);
	}
	_items = std::move(replaced);
}

bigint LiteralMethod::gasNeeded()
{
	return combineGas(
		simpleRunGas({Instruction::PUSH1}),
		// PUSHX plus data
		(m_params.isCreation ? GasCosts::txDataNonZeroGas : GasCosts::createDataGas) + dataGas(),
		0
	);
}

CodeCopyMethod::CodeCopyMethod(Params const& _params, u256 const& _value):
	ConstantOptimisationMethod(_params, _value)
{
}

bigint CodeCopyMethod::gasNeeded()
{
	return combineGas(
		// Run gas: we ignore memory increase costs
		simpleRunGas(copyRoutine()) + GasCosts::copyGas,
		// Data gas for copy routines: Some bytes are zero, but we ignore them.
		bytesRequired(copyRoutine()) * (m_params.isCreation ? GasCosts::txDataNonZeroGas : GasCosts::createDataGas),
		// Data gas for data itself
		dataGas(toBigEndian(m_value))
	);
}

AssemblyItems CodeCopyMethod::execute(Assembly& _assembly)
{
	bytes data = toBigEndian(m_value);
	AssemblyItems actualCopyRoutine = copyRoutine();
	actualCopyRoutine[4] = _assembly.newData(data);
	return actualCopyRoutine;
}

AssemblyItems const& CodeCopyMethod::copyRoutine() const
{
	AssemblyItems static copyRoutine{
		u256(0),
		Instruction::DUP1,
		Instruction::MLOAD, // back up memory
		u256(32),
		AssemblyItem(PushData, u256(1) << 16), // has to be replaced
		Instruction::DUP4,
		Instruction::CODECOPY,
		Instruction::DUP2,
		Instruction::MLOAD,
		Instruction::SWAP2,
		Instruction::MSTORE
	};
	return copyRoutine;
}

AssemblyItems ComputeMethod::findRepresentation(u256 const& _value)
{
	if (_value < 0x10000)
		// Very small value, not worth computing
		return AssemblyItems{_value};
	else if (dev::bytesRequired(~_value) < dev::bytesRequired(_value))
		// Negated is shorter to represent
		return findRepresentation(~_value) + AssemblyItems{Instruction::NOT};
	else
	{
		// Decompose value into a * 2**k + b where abs(b) << 2**k
		// Is not always better, try literal and decomposition method.
		AssemblyItems routine{u256(_value)};
		bigint bestGas = gasNeeded(routine);
		for (unsigned bits = 255; bits > 8 && m_maxSteps > 0; --bits)
		{
			unsigned gapDetector = unsigned(_value >> (bits - 8)) & 0x1ff;
			if (gapDetector != 0xff && gapDetector != 0x100)
				continue;

			u256 powerOfTwo = u256(1) << bits;
			u256 upperPart = _value >> bits;
			bigint lowerPart = _value & (powerOfTwo - 1);
			if (powerOfTwo - lowerPart < lowerPart)
			{
				lowerPart = lowerPart - powerOfTwo; // make it negative
				upperPart++;
			}
			if (upperPart == 0)
				continue;
			if (abs(lowerPart) >= (powerOfTwo >> 8))
				continue;

			AssemblyItems newRoutine;
			if (lowerPart != 0)
				newRoutine += findRepresentation(u256(abs(lowerPart)));
			newRoutine += AssemblyItems{u256(bits), u256(2), Instruction::EXP};
			if (upperPart != 1)
				newRoutine += findRepresentation(upperPart) + AssemblyItems{Instruction::MUL};
			if (lowerPart > 0)
				newRoutine += AssemblyItems{Instruction::ADD};
			else if (lowerPart < 0)
				newRoutine.push_back(Instruction::SUB);

			if (m_maxSteps > 0)
				m_maxSteps--;
			bigint newGas = gasNeeded(newRoutine);
			if (newGas < bestGas)
			{
				bestGas = move(newGas);
				routine = move(newRoutine);
			}
		}
		return routine;
	}
}

bool ComputeMethod::checkRepresentation(u256 const& _value, AssemblyItems const& _routine)
{
	// This is a tiny EVM that can only evaluate some instructions.
	vector<u256> stack;
	for (AssemblyItem const& item: _routine)
	{
		switch (item.type())
		{
		case Operation:
		{
			if (stack.size() < size_t(item.arguments()))
				return false;
			u256* sp = &stack.back();
			switch (item.instruction())
			{
			case Instruction::MUL:
				sp[-1] = sp[0] * sp[-1];
				break;
			case Instruction::EXP:
				if (sp[-1] > 0xff)
					return false;
				sp[-1] = boost::multiprecision::pow(sp[0], unsigned(sp[-1]));
				break;
			case Instruction::ADD:
				sp[-1] = sp[0] + sp[-1];
				break;
			case Instruction::SUB:
				sp[-1] = sp[0] - sp[-1];
				break;
			case Instruction::NOT:
				sp[0] = ~sp[0];
				break;
			default:
				return false;
			}
			stack.resize(stack.size() + item.deposit());
			break;
		}
		case Push:
			stack.push_back(item.data());
			break;
		default:
			return false;
		}
	}
	return stack.size() == 1 && stack.front() == _value;
}

bigint ComputeMethod::gasNeeded(AssemblyItems const& _routine)
{
	size_t numExps = count(_routine.begin(), _routine.end(), Instruction::EXP);
	return combineGas(
		simpleRunGas(_routine) + numExps * (GasCosts::expGas + GasCosts::expByteGas),
		// Data gas for routine: Some bytes are zero, but we ignore them.
		bytesRequired(_routine) * (m_params.isCreation ? GasCosts::txDataNonZeroGas : GasCosts::createDataGas),
		0
	);
}
<commit_msg>Add parentheses for readability.<commit_after>/*
	This file is part of solidity.

	solidity is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	solidity is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with solidity.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file ConstantOptimiser.cpp
 * @author Christian <c@ethdev.com>
 * @date 2015
 */

#include <libevmasm/ConstantOptimiser.h>
#include <libevmasm/Assembly.h>
#include <libevmasm/GasMeter.h>
using namespace std;
using namespace dev;
using namespace dev::eth;

unsigned ConstantOptimisationMethod::optimiseConstants(
	bool _isCreation,
	size_t _runs,
	Assembly& _assembly,
	AssemblyItems& _items
)
{
	unsigned optimisations = 0;
	map<AssemblyItem, size_t> pushes;
	for (AssemblyItem const& item: _items)
		if (item.type() == Push)
			pushes[item]++;
	map<u256, AssemblyItems> pendingReplacements;
	for (auto it: pushes)
	{
		AssemblyItem const& item = it.first;
		if (item.data() < 0x100)
			continue;
		Params params;
		params.multiplicity = it.second;
		params.isCreation = _isCreation;
		params.runs = _runs;
		LiteralMethod lit(params, item.data());
		bigint literalGas = lit.gasNeeded();
		CodeCopyMethod copy(params, item.data());
		bigint copyGas = copy.gasNeeded();
		ComputeMethod compute(params, item.data());
		bigint computeGas = compute.gasNeeded();
		AssemblyItems replacement;
		if (copyGas < literalGas && copyGas < computeGas)
		{
			replacement = copy.execute(_assembly);
			optimisations++;
		}
		else if (computeGas < literalGas && computeGas <= copyGas)
		{
			replacement = compute.execute(_assembly);
			optimisations++;
		}
		if (!replacement.empty())
			pendingReplacements[item.data()] = replacement;
	}
	if (!pendingReplacements.empty())
		replaceConstants(_items, pendingReplacements);
	return optimisations;
}

bigint ConstantOptimisationMethod::simpleRunGas(AssemblyItems const& _items)
{
	bigint gas = 0;
	for (AssemblyItem const& item: _items)
		if (item.type() == Push)
			gas += GasMeter::runGas(Instruction::PUSH1);
		else if (item.type() == Operation)
			gas += GasMeter::runGas(item.instruction());
	return gas;
}

bigint ConstantOptimisationMethod::dataGas(bytes const& _data) const
{
	if (m_params.isCreation)
	{
		bigint gas;
		for (auto b: _data)
			gas += b ? GasCosts::txDataNonZeroGas : GasCosts::txDataZeroGas;
		return gas;
	}
	else
		return GasCosts::createDataGas * dataSize();
}

size_t ConstantOptimisationMethod::bytesRequired(AssemblyItems const& _items)
{
	size_t size = 0;
	for (AssemblyItem const& item: _items)
		size += item.bytesRequired(3); // assume 3 byte addresses
	return size;
}

void ConstantOptimisationMethod::replaceConstants(
	AssemblyItems& _items,
	map<u256, AssemblyItems> const& _replacements
)
{
	AssemblyItems replaced;
	for (AssemblyItem const& item: _items)
	{
		if (item.type() == Push)
		{
			auto it = _replacements.find(item.data());
			if (it != _replacements.end())
			{
				replaced += it->second;
				continue;
			}
		}
		replaced.push_back(item);
	}
	_items = std::move(replaced);
}

bigint LiteralMethod::gasNeeded()
{
	return combineGas(
		simpleRunGas({Instruction::PUSH1}),
		// PUSHX plus data
		(m_params.isCreation ? GasCosts::txDataNonZeroGas : GasCosts::createDataGas) + dataGas(),
		0
	);
}

CodeCopyMethod::CodeCopyMethod(Params const& _params, u256 const& _value):
	ConstantOptimisationMethod(_params, _value)
{
}

bigint CodeCopyMethod::gasNeeded()
{
	return combineGas(
		// Run gas: we ignore memory increase costs
		simpleRunGas(copyRoutine()) + GasCosts::copyGas,
		// Data gas for copy routines: Some bytes are zero, but we ignore them.
		bytesRequired(copyRoutine()) * (m_params.isCreation ? GasCosts::txDataNonZeroGas : GasCosts::createDataGas),
		// Data gas for data itself
		dataGas(toBigEndian(m_value))
	);
}

AssemblyItems CodeCopyMethod::execute(Assembly& _assembly)
{
	bytes data = toBigEndian(m_value);
	AssemblyItems actualCopyRoutine = copyRoutine();
	actualCopyRoutine[4] = _assembly.newData(data);
	return actualCopyRoutine;
}

AssemblyItems const& CodeCopyMethod::copyRoutine() const
{
	AssemblyItems static copyRoutine{
		u256(0),
		Instruction::DUP1,
		Instruction::MLOAD, // back up memory
		u256(32),
		AssemblyItem(PushData, u256(1) << 16), // has to be replaced
		Instruction::DUP4,
		Instruction::CODECOPY,
		Instruction::DUP2,
		Instruction::MLOAD,
		Instruction::SWAP2,
		Instruction::MSTORE
	};
	return copyRoutine;
}

AssemblyItems ComputeMethod::findRepresentation(u256 const& _value)
{
	if (_value < 0x10000)
		// Very small value, not worth computing
		return AssemblyItems{_value};
	else if (dev::bytesRequired(~_value) < dev::bytesRequired(_value))
		// Negated is shorter to represent
		return findRepresentation(~_value) + AssemblyItems{Instruction::NOT};
	else
	{
		// Decompose value into a * 2**k + b where abs(b) << 2**k
		// Is not always better, try literal and decomposition method.
		AssemblyItems routine{u256(_value)};
		bigint bestGas = gasNeeded(routine);
		for (unsigned bits = 255; bits > 8 && m_maxSteps > 0; --bits)
		{
			unsigned gapDetector = unsigned(_value >> (bits - 8)) & 0x1ff;
			if (gapDetector != 0xff && gapDetector != 0x100)
				continue;

			u256 powerOfTwo = u256(1) << bits;
			u256 upperPart = _value >> bits;
			bigint lowerPart = _value & (powerOfTwo - 1);
			if ((powerOfTwo - lowerPart) < lowerPart)
			{
				lowerPart = lowerPart - powerOfTwo; // make it negative
				upperPart++;
			}
			if (upperPart == 0)
				continue;
			if (abs(lowerPart) >= (powerOfTwo >> 8))
				continue;

			AssemblyItems newRoutine;
			if (lowerPart != 0)
				newRoutine += findRepresentation(u256(abs(lowerPart)));
			newRoutine += AssemblyItems{u256(bits), u256(2), Instruction::EXP};
			if (upperPart != 1)
				newRoutine += findRepresentation(upperPart) + AssemblyItems{Instruction::MUL};
			if (lowerPart > 0)
				newRoutine += AssemblyItems{Instruction::ADD};
			else if (lowerPart < 0)
				newRoutine.push_back(Instruction::SUB);

			if (m_maxSteps > 0)
				m_maxSteps--;
			bigint newGas = gasNeeded(newRoutine);
			if (newGas < bestGas)
			{
				bestGas = move(newGas);
				routine = move(newRoutine);
			}
		}
		return routine;
	}
}

bool ComputeMethod::checkRepresentation(u256 const& _value, AssemblyItems const& _routine)
{
	// This is a tiny EVM that can only evaluate some instructions.
	vector<u256> stack;
	for (AssemblyItem const& item: _routine)
	{
		switch (item.type())
		{
		case Operation:
		{
			if (stack.size() < size_t(item.arguments()))
				return false;
			u256* sp = &stack.back();
			switch (item.instruction())
			{
			case Instruction::MUL:
				sp[-1] = sp[0] * sp[-1];
				break;
			case Instruction::EXP:
				if (sp[-1] > 0xff)
					return false;
				sp[-1] = boost::multiprecision::pow(sp[0], unsigned(sp[-1]));
				break;
			case Instruction::ADD:
				sp[-1] = sp[0] + sp[-1];
				break;
			case Instruction::SUB:
				sp[-1] = sp[0] - sp[-1];
				break;
			case Instruction::NOT:
				sp[0] = ~sp[0];
				break;
			default:
				return false;
			}
			stack.resize(stack.size() + item.deposit());
			break;
		}
		case Push:
			stack.push_back(item.data());
			break;
		default:
			return false;
		}
	}
	return stack.size() == 1 && stack.front() == _value;
}

bigint ComputeMethod::gasNeeded(AssemblyItems const& _routine)
{
	size_t numExps = count(_routine.begin(), _routine.end(), Instruction::EXP);
	return combineGas(
		simpleRunGas(_routine) + numExps * (GasCosts::expGas + GasCosts::expByteGas),
		// Data gas for routine: Some bytes are zero, but we ignore them.
		bytesRequired(_routine) * (m_params.isCreation ? GasCosts::txDataNonZeroGas : GasCosts::createDataGas),
		0
	);
}
<|endoftext|>


<commit_before>// Report received data on the serial port.

#include "chip.h"
#include "uart.h"
#include <stdio.h>

#define chThdYield() // FIXME still used in rf69.h

// TODO #define RF69_SPI_BULK 1
#include "spi.h"
#include "rf69.h"

RF69<SpiDev0> rf;

uint8_t rxBuf[66];

int main () {
    // the device pin mapping is configured at run time based on its id
    uint16_t devId = LPC_SYSCON->DEVICEID;
    // choose different node id's, depending on the chip type
    uint8_t nodeId = 60;

    // SPI pin assignment:
    //  3: SPI0_SCK x         x         x
    //  4: x        SPI0_SSEL SPI0_MISO SPI0_MOSI

    switch (devId) {
        case 0x8100:
            nodeId = 10;
            // disable SWCLK/SWDIO and RESET
            LPC_SWM->PINENABLE0 |= (3<<2) | (1<<6);
            // lpc810 coin: sck=0p8, ssel=1p5, miso=2p4, mosi=5p1, tx=4p2
            // SPI0
            LPC_SWM->PINASSIGN[3] = 0x00FFFFFF;   // sck  -    -    -
            LPC_SWM->PINASSIGN[4] = 0xFF010205;   // -    nss  miso mosi
            // USART0
            LPC_SWM->PINASSIGN[0] = 0xFFFFFF04;
            break;
        case 0x8120:
            nodeId = 12;
            LPC_SWM->PINASSIGN[0] = 0xFFFF0004;
            // jnp v2: sck 6, ssel 8, miso 11, mosi 9, irq 10
            LPC_SWM->PINASSIGN[3] = 0x06FFFFFF;
            LPC_SWM->PINASSIGN[4] = 0xFF080B09;
            LPC_IOCON->PIO0[IOCON_PIO11] |= (1<<8); // std GPIO, not I2C pin
            // LPC_IOCON->PIO0[IOCON_PIO10] |= (1<<8); // std GPIO, not I2C pin
            break;
        case 0x8121:
            nodeId = 13;
            LPC_SWM->PINASSIGN[0] = 0xFFFF0004;
            // A not working, but B is fine
            // eb20soic A: sck 14, ssel 15, miso 12, mosi 13, irq 8
            //LPC_SWM->PINASSIGN[3] = 0x0EFFFFFF;
            //LPC_SWM->PINASSIGN[4] = 0xFF0F0C0D;
            // eb20soic B: sck 12, ssel 13, miso 15, mosi 14, irq 8
            LPC_SWM->PINASSIGN[3] = 0x0CFFFFFF;
            LPC_SWM->PINASSIGN[4] = 0xFF0D0F0E;
            break;
        case 0x8122:
            nodeId = 14;
            LPC_SWM->PINASSIGN[0] = 0xFFFF0106;
            // ea812: sck 12, ssel 13, miso 15, mosi 14
            LPC_SWM->PINASSIGN[3] = 0x0CFFFFFF;
            LPC_SWM->PINASSIGN[4] = 0xFF0D0F0E;
            break;
        case 0x8241:
            nodeId = 23;
            // ea824: sck 24, ssel 15, miso 25, mosi 26
            LPC_SWM->PINASSIGN[0] = 0xFFFF1207;
            LPC_SWM->PINASSIGN[3] = 0x18FFFFFF;
            LPC_SWM->PINASSIGN[4] = 0xFF0F191A;
            break;
        case 0x8242:
            nodeId = 24;
            // jnp v3: sck 17, ssel 23, miso 9, mosi 8, irq 1
            LPC_SWM->PINASSIGN[0] = 0xFFFF0004;
            LPC_SWM->PINASSIGN[3] = 0x11FFFFFF;
            LPC_SWM->PINASSIGN[4] = 0xFF170908;
            break;
    }

    uart0Init(115200);
    for (int i = 0; i < 10000; ++i) __ASM("");
    printf("\n[rf_ping] dev %x node %d\n", devId, nodeId);

    rf.init(nodeId, 42, 8683);
    rf.encrypt("mysecret");
    rf.txPower(0); // 0 = min .. 31 = max

    uint16_t cnt = 0;
    uint8_t txBuf[66];
    for (int i = 0; i < sizeof txBuf; ++i)
      txBuf[i] = i;
    txBuf[0] = 45; // FIXME start slightly before the problem with > 48 bytes

    while (true) {
        if (++cnt == 0) {
            int txLen = ++txBuf[0] % 64;
            printf(" > #%d, %db\n", txBuf[0], txLen);
            rf.send(0, txBuf, txLen);
        }

        int len = rf.receive(rxBuf, sizeof rxBuf);
        if (len >= 0) {
            printf("OK ");
            for (int i = 0; i < len; ++i)
                printf("%02x", rxBuf[i]);
            printf(" (%d%s%d:%d)\n",
                    rf.rssi, rf.afc < 0 ? "" : "+", rf.afc, rf.lna);
        }

        chThdYield()
    }
}
<commit_msg>add stdint header<commit_after>// Report received data on the serial port.

#include "chip.h"
#include "uart.h"
#include <stdio.h>
#include <stdint.h>

#define chThdYield() // FIXME still used in rf69.h

// TODO #define RF69_SPI_BULK 1
#include "spi.h"
#include "rf69.h"

RF69<SpiDev0> rf;

uint8_t rxBuf[66];

int main () {
    // the device pin mapping is configured at run time based on its id
    uint16_t devId = LPC_SYSCON->DEVICEID;
    // choose different node id's, depending on the chip type
    uint8_t nodeId = 60;

    // SPI pin assignment:
    //  3: SPI0_SCK x         x         x
    //  4: x        SPI0_SSEL SPI0_MISO SPI0_MOSI

    switch (devId) {
        case 0x8100:
            nodeId = 10;
            // disable SWCLK/SWDIO and RESET
            LPC_SWM->PINENABLE0 |= (3<<2) | (1<<6);
            // lpc810 coin: sck=0p8, ssel=1p5, miso=2p4, mosi=5p1, tx=4p2
            // SPI0
            LPC_SWM->PINASSIGN[3] = 0x00FFFFFF;   // sck  -    -    -
            LPC_SWM->PINASSIGN[4] = 0xFF010205;   // -    nss  miso mosi
            // USART0
            LPC_SWM->PINASSIGN[0] = 0xFFFFFF04;
            break;
        case 0x8120:
            nodeId = 12;
            LPC_SWM->PINASSIGN[0] = 0xFFFF0004;
            // jnp v2: sck 6, ssel 8, miso 11, mosi 9, irq 10
            LPC_SWM->PINASSIGN[3] = 0x06FFFFFF;
            LPC_SWM->PINASSIGN[4] = 0xFF080B09;
            LPC_IOCON->PIO0[IOCON_PIO11] |= (1<<8); // std GPIO, not I2C pin
            // LPC_IOCON->PIO0[IOCON_PIO10] |= (1<<8); // std GPIO, not I2C pin
            break;
        case 0x8121:
            nodeId = 13;
            LPC_SWM->PINASSIGN[0] = 0xFFFF0004;
            // A not working, but B is fine
            // eb20soic A: sck 14, ssel 15, miso 12, mosi 13, irq 8
            //LPC_SWM->PINASSIGN[3] = 0x0EFFFFFF;
            //LPC_SWM->PINASSIGN[4] = 0xFF0F0C0D;
            // eb20soic B: sck 12, ssel 13, miso 15, mosi 14, irq 8
            LPC_SWM->PINASSIGN[3] = 0x0CFFFFFF;
            LPC_SWM->PINASSIGN[4] = 0xFF0D0F0E;
            break;
        case 0x8122:
            nodeId = 14;
            LPC_SWM->PINASSIGN[0] = 0xFFFF0106;
            // ea812: sck 12, ssel 13, miso 15, mosi 14
            LPC_SWM->PINASSIGN[3] = 0x0CFFFFFF;
            LPC_SWM->PINASSIGN[4] = 0xFF0D0F0E;
            break;
        case 0x8241:
            nodeId = 23;
            // ea824: sck 24, ssel 15, miso 25, mosi 26
            LPC_SWM->PINASSIGN[0] = 0xFFFF1207;
            LPC_SWM->PINASSIGN[3] = 0x18FFFFFF;
            LPC_SWM->PINASSIGN[4] = 0xFF0F191A;
            break;
        case 0x8242:
            nodeId = 24;
            // jnp v3: sck 17, ssel 23, miso 9, mosi 8, irq 1
            LPC_SWM->PINASSIGN[0] = 0xFFFF0004;
            LPC_SWM->PINASSIGN[3] = 0x11FFFFFF;
            LPC_SWM->PINASSIGN[4] = 0xFF170908;
            break;
    }

    uart0Init(115200);
    for (int i = 0; i < 10000; ++i) __ASM("");
    printf("\n[rf_ping] dev %x node %d\n", devId, nodeId);

    rf.init(nodeId, 42, 8683);
    rf.encrypt("mysecret");
    rf.txPower(0); // 0 = min .. 31 = max

    uint16_t cnt = 0;
    uint8_t txBuf[66];
    for (int i = 0; i < sizeof txBuf; ++i)
      txBuf[i] = i;
    txBuf[0] = 45; // FIXME start slightly before the problem with > 48 bytes

    while (true) {
        if (++cnt == 0) {
            int txLen = ++txBuf[0] % 64;
            printf(" > #%d, %db\n", txBuf[0], txLen);
            rf.send(0, txBuf, txLen);
        }

        int len = rf.receive(rxBuf, sizeof rxBuf);
        if (len >= 0) {
            printf("OK ");
            for (int i = 0; i < len; ++i)
                printf("%02x", rxBuf[i]);
            printf(" (%d%s%d:%d)\n",
                    rf.rssi, rf.afc < 0 ? "" : "+", rf.afc, rf.lna);
        }

        chThdYield()
    }
}
<|endoftext|>